diff --git a/packages/components/src/components/Table/Table.stories.tsx b/packages/components/src/components/Table/Table.stories.tsx index d5098601..ad6149f6 100644 --- a/packages/components/src/components/Table/Table.stories.tsx +++ b/packages/components/src/components/Table/Table.stories.tsx @@ -1,6 +1,10 @@ import { useState, useMemo } from 'react'; -import { IconArrowDownS16, IconArrowUpS16 } from '@koobiq/react-icons'; +import { + IconArrowDownS16, + IconArrowUpS16, + IconArrowUpArrowDown16, +} from '@koobiq/react-icons'; import type { Meta, StoryObj } from '@storybook/react'; import type { @@ -727,9 +731,16 @@ export const RenderSortIcon: Story = { aria-label="Fast animals" {...(sortDescriptor && { sortDescriptor })} onSortChange={handleSortChange} - renderSortIcon={({ direction }) => - direction === 'ascending' ? : - } + renderSortIcon={({ direction }) => { + if (!direction) + return ; + + return direction === 'ascending' ? ( + + ) : ( + + ); + }} selectionMode="multiple" {...args} > diff --git a/packages/components/src/components/Table/Table.test.tsx b/packages/components/src/components/Table/Table.test.tsx index 2de809ab..bec68562 100644 --- a/packages/components/src/components/Table/Table.test.tsx +++ b/packages/components/src/components/Table/Table.test.tsx @@ -203,4 +203,62 @@ describe('Table', () => { expect(onNavigate).toBeCalled(); }); + + it('should pass unsorted state to renderSortIcon for sortable column', () => { + const renderSortIcon = vi.fn(() => ); + + render( + + + + Name + + + + {(item) => ( + + {item.name} + + )} + +
+ ); + + expect(renderSortIcon).toBeCalledWith({ + direction: undefined, + isActive: false, + }); + + expect(screen.getByTestId('sort-icon')).toBeInTheDocument(); + }); + + it('should pass active sort direction to renderSortIcon', () => { + const renderSortIcon = vi.fn(() => ); + + render( + + + + Name + + + + {(item) => ( + + {item.name} + + )} + +
+ ); + + expect(renderSortIcon).toBeCalledWith({ + direction: 'ascending', + isActive: true, + }); + }); }); diff --git a/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.module.css b/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.module.css index d61424db..30be4205 100644 --- a/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.module.css +++ b/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.module.css @@ -97,6 +97,10 @@ .sortIcon { display: flex; visibility: hidden; + opacity: 1; + align-items: center; + justify-content: center; + inline-size: var(--kbq-size-l); &.active { visibility: visible; diff --git a/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.tsx b/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.tsx index a1ba5822..1f2b2683 100644 --- a/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.tsx +++ b/packages/components/src/components/Table/components/TableColumnHeader/TableColumnHeader.tsx @@ -2,7 +2,7 @@ import { useRef } from 'react'; -import { useFocusRing, mergeProps, clsx } from '@koobiq/react-core'; +import { useFocusRing, mergeProps, clsx, useHover } from '@koobiq/react-core'; import { IconChevronUpS16, IconChevronDownS16 } from '@koobiq/react-icons'; import type { TableState, @@ -58,18 +58,32 @@ export function TableColumnHeader({ }: ColumnProps = column.props; const { isFocusVisible, focusProps } = useFocusRing(); + const { isHovered, hoverProps } = useHover({ isDisabled: !allowsSorting }); const isActive = state.sortDescriptor?.column === column.key; const direction = isActive ? state.sortDescriptor?.direction : undefined; - const defaultIcon = - direction === 'ascending' ? : ; + const defaultIcon = () => { + if (direction === 'ascending') { + return ; + } - const iconToRender = renderSortIcon?.({ direction, isActive }) ?? defaultIcon; + if (direction === 'descending') { + return ; + } + + return null; + }; + + const iconToRender = + renderSortIcon?.({ direction, isActive }) ?? defaultIcon(); const columnSortIcon = allowsSorting && ( -