Skip to content

chore(List): swap List to container queries #3133

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 32 commits into from
Jul 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
a4003b4
feat(ContainerQueries): add container queries to responsive props api
dreamwasp Jul 8, 2025
1dc9300
test headerHeights
dreamwasp Jul 8, 2025
5dbe457
Merge branch 'main' into cass-gm-1218
dreamwasp Jul 8, 2025
d74bd7e
Merge branch 'main' into cass-gm-1218
dreamwasp Jul 8, 2025
c680236
Merge branch 'main' into cass-gm-1218
dreamwasp Jul 14, 2025
71595ed
swap everything over to container queries
dreamwasp Jul 14, 2025
1d34825
swap everything over to container queries
dreamwasp Jul 14, 2025
c5c6d7d
fix headerrow too
dreamwasp Jul 14, 2025
e24bd53
c_sm
dreamwasp Jul 14, 2025
fc9d3e3
start writing docs
dreamwasp Jul 16, 2025
2cab9b9
Merge branch 'main' into cass-gm-1218
dreamwasp Jul 16, 2025
308360a
tweak spacing
dreamwasp Jul 16, 2025
9fe1014
lint fix errors
dreamwasp Jul 16, 2025
959f5bd
add examples
dreamwasp Jul 16, 2025
a76e985
tweak to verbiage
dreamwasp Jul 16, 2025
55c213b
try splitting types to allow seperate container + media types
dreamwasp Jul 16, 2025
6ee24b4
Merge branch 'main' into cass-gm-1218
dreamwasp Jul 17, 2025
8cb08b3
Merge branch 'cass-gm-1218' into cass-gm-1231-1st
dreamwasp Jul 21, 2025
b96d347
fix list
dreamwasp Jul 21, 2025
10cdf62
merge main
dreamwasp Jul 22, 2025
281ebb7
test wrapper width
dreamwasp Jul 24, 2025
70e898d
fix build
dreamwasp Jul 24, 2025
a07214d
Merge branch 'main' into cass-gm-1231-1st
dreamwasp Jul 24, 2025
8c73563
adds test
dreamwasp Jul 24, 2025
84b9691
spacing fixes
aresnik11 Jul 24, 2025
1d3f626
dont show sticky header col wrapper when stacked
aresnik11 Jul 24, 2025
6a89b9e
remove html tests for now
dreamwasp Jul 24, 2025
84e37c0
fix first column
aresnik11 Jul 24, 2025
a64726d
fix failing tests
dreamwasp Jul 25, 2025
3e2ae9d
typo
dreamwasp Jul 25, 2025
dff152d
remove test code
dreamwasp Jul 25, 2025
825aa49
remove testing;
dreamwasp Jul 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/gamut/src/DataList/Controls/ExpandControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ export const ExpandControl: React.FC<ExpandColProps> = ({
expanded,
onExpand,
}) => (
<FlexBox center mt={{ _: 8, xs: 0 }} pl={{ _: 0, xs: 16 }} width={1}>
<FlexBox center mt={{ _: 8, c_sm: 0 }} pl={{ _: 0, c_sm: 16 }} width={1}>
<TextButton
aria-expanded={expanded}
aria-label={`Expand ${id} Row`}
disabled={disabled}
size="small"
variant="secondary"
width={{ _: 1, xs: 32 }}
width={{ _: 1, c_sm: 32 }}
onClick={() => {
onExpand?.({ rowId: id, toggle: expanded });
}}
Expand Down
4 changes: 4 additions & 0 deletions packages/gamut/src/DataList/DataGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ export function DataGrid<
hideSelectAll = false,
scrollToTopOnUpdate = false,
id,
wrapperWidth,
overflow,
} = props;

const empty = rows.length === 0;
Expand Down Expand Up @@ -117,11 +119,13 @@ export function DataGrid<
id={id}
loading={loading}
minHeight={minHeight}
overflow={overflow}
scrollToTopOnUpdate={scrollToTopOnUpdate}
scrollable={scrollable}
shadow={shadow}
spacing={spacing}
variant={variant}
wrapperWidth={wrapperWidth ?? undefined}
>
{renderedRows.map((row) => {
const rowId = row[idKey];
Expand Down
8 changes: 6 additions & 2 deletions packages/gamut/src/DataList/Tables/Rows/TableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export const TableRow: DataRow = ({
{selectable && (
<ListCol
{...listColProps}
display={{ _: 'flex', xs: 'flex' }}
display={{ _: 'flex', c_sm: 'flex' }}
size="content"
type="control"
>
Expand Down Expand Up @@ -136,7 +136,11 @@ export const TableRow: DataRow = ({
);
})}
{expandable && (
<ListCol {...listColProps} order={[1000, 'initial']} size="content">
<ListCol
{...listColProps}
order={{ _: 1000, c_sm: 'initial' }}
size="content"
>
<ExpandControl
disabled={loading}
expanded={expanded}
Expand Down
42 changes: 37 additions & 5 deletions packages/gamut/src/DataList/__tests__/DataGrid.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ describe('DataGrid', () => {
});

it("clicking the row's checkbox deselects the row when the row is already selected", () => {
renderView({ selected: [1] });
renderView({ selected: ['1'] });

const checkbox = screen.getByRole('checkbox', { name: 'Select 1' });

Expand All @@ -110,7 +110,7 @@ describe('DataGrid', () => {
});

it('selecting another row adds the row to the selection', () => {
renderView({ selected: [2] });
renderView({ selected: ['2'] });

const checkbox = screen.getByRole('checkbox', { name: 'Select 1' });

Expand Down Expand Up @@ -173,14 +173,14 @@ describe('DataGrid', () => {

describe('Expanding Rows', () => {
it('Renders an expanded row when passed the correct id', () => {
renderView({ expanded: [1] });
renderView({ expanded: ['1'] });

screen.getByText('Expanded 1');
screen.getByRole('button', { expanded: true });
});

it('allows multiple expanded rows by default', () => {
renderView({ expanded: [1, 2] });
renderView({ expanded: ['1', '2'] });

screen.getByText('Expanded 1');
screen.getByText('Expanded 2');
Expand All @@ -205,7 +205,7 @@ describe('DataGrid', () => {
});
});
it('calls the onRowExpand with the id omitted when an expanded row toggle is clicked', () => {
renderView({ expanded: [1] });
renderView({ expanded: ['1'] });

const expandButton = screen.getByRole('button', { name: `Expand 1 Row` });

Expand Down Expand Up @@ -516,4 +516,36 @@ describe('DataGrid', () => {
});
});
});

describe('wrapperWidth prop', () => {
it('applies wrapperWidth to the table container when provided', () => {
renderView({ wrapperWidth: '600px' });

const tableContainer = screen.getByTestId('scrollable-test');
expect(tableContainer).toHaveStyle({
maxWidth: '600px',
width: '600px',
});
});

it('uses default width when wrapperWidth is not provided', () => {
renderView();

const tableContainer = screen.getByTestId('scrollable-test');
expect(tableContainer).toHaveStyle({
maxWidth: '100%',
width: 'inherit',
});
});

it('passes wrapperWidth through to the underlying List component', () => {
renderView({ wrapperWidth: '750px' });

const tableContainer = screen.getByTestId('scrollable-test');
expect(tableContainer).toHaveStyle({
maxWidth: '750px',
width: '750px',
});
});
});
});
10 changes: 8 additions & 2 deletions packages/gamut/src/List/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ export interface ListProps extends AllListProps<ComponentProps<typeof ListEl>> {
* How the List container should handle overflow.
*/
overflow?: BoxProps['overflow'];
/**
* This is an override for the width of the wrapper element that contains the List.
* It is useful for custom scroll and breakpoint handling. Use with caution.
*/
wrapperWidth?: BoxProps['width'];
}

export const List = forwardRef<HTMLUListElement, ListProps>(
Expand All @@ -49,6 +54,7 @@ export const List = forwardRef<HTMLUListElement, ListProps>(
emptyMessage,
overflow = 'auto',
scrollToTopOnUpdate = false,
wrapperWidth,
...rest
},
ref
Expand Down Expand Up @@ -140,12 +146,12 @@ export const List = forwardRef<HTMLUListElement, ListProps>(
as={isTable && !isEmpty && !loading ? 'table' : 'div'}
data-testid={`scrollable-${id}`}
height={isEmpty ? height : 'fit-content'}
maxWidth={1}
maxWidth={wrapperWidth || 1}
minHeight={minHeight}
overflow="inherit"
position="relative"
ref={!isEmpty ? tableRef : undefined}
width="inherit"
width={wrapperWidth || 'inherit'}
>
{content}
</Box>
Expand Down
5 changes: 4 additions & 1 deletion packages/gamut/src/List/ListCol.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ export const ListCol = forwardRef<HTMLDivElement, ListColProps>(
);
if (sticky) {
return (
<StickyHeaderColWrapper data-testid="header-container">
<StickyHeaderColWrapper
as={isTable ? 'th' : 'div'}
data-testid="header-container"
>
{col}
</StickyHeaderColWrapper>
);
Expand Down
6 changes: 3 additions & 3 deletions packages/gamut/src/List/ListRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export type ListRowProps = ExpandableRowProps | SimpleRowProps;

const expandStyles = css({
overflow: 'hidden',
gridColumn: { _: 'span 2', xs: 'span 12' },
gridColumn: { _: 'span 2', c_sm: 'span 12' },
});

const DivExpand = styled(motion.div)(expandStyles);
Expand Down Expand Up @@ -124,10 +124,10 @@ export const ListRow = forwardRef<HTMLLIElement, ListRowProps>(
<RowEl
aria-live={renderExpanded ? 'polite' : undefined}
expanded={isTable ? undefined : !!renderExpanded}
gridAutoRows={{ _: undefined, xs: 'minmax(1.5rem, max-content) 6fr' }}
gridAutoRows={{ _: undefined, c_sm: 'minmax(1.5rem, max-content) 6fr' }}
gridTemplateColumns={{
_: 'minmax(0, 1fr) max-content',
xs: gridTemplateColumns,
c_sm: gridTemplateColumns,
}}
isOl={renderNumbering}
role={role}
Expand Down
36 changes: 27 additions & 9 deletions packages/gamut/src/List/__tests__/List.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { ListRow } from '../ListRow';
// Add the custom matchers provided by '@emotion/jest'
expect.extend(matchers);

// NOTE: We have removed the query styling tests here, they are to be replaced with visual tests: GM-1240

const renderView = setupRtl(List, {
children: (
<ListRow data-testid="row-el">
Expand Down Expand Up @@ -44,9 +46,6 @@ describe('List', () => {

expect(rowEl).toHaveStyle({ borderTop: 'none' });
expect(rowEl).toHaveStyle({ gap: theme.spacing[8] });
expect(rowEl).toHaveStyleRule('gap', theme.spacing[40], {
media: theme.breakpoints.xs,
});
});

it('configures columns with the correct variants', () => {
Expand All @@ -55,12 +54,8 @@ describe('List', () => {
const colEl = view.getByText('Hello');

expect(colEl).not.toHaveStyle({ py: 16 });
expect(colEl).toHaveStyleRule('padding-top', theme.spacing[16], {
media: theme.breakpoints.xs,
});
expect(colEl).toHaveStyleRule('padding-bottom', theme.spacing[16], {
media: theme.breakpoints.xs,
});
expect(colEl).toHaveStyleRule('padding-left', theme.spacing[8]);
expect(colEl).toHaveStyleRule('padding-right', theme.spacing[8]);

expect(colEl).not.toHaveStyle({ position: 'sticky' });
});
Expand Down Expand Up @@ -128,4 +123,27 @@ describe('List', () => {
});
expect(view.queryByText('Surprise!')).toBeNull();
});

describe('wrapperWidth prop', () => {
it('applies wrapperWidth to the table container when provided', () => {
const { view } = renderView({ wrapperWidth: '500px' });

const tableContainer = view.container.querySelector(
'[data-testid="scrollable-list-el"]'
);
expect(tableContainer).toHaveStyle({ maxWidth: '500px', width: '500px' });
});

it('uses inherit width when wrapperWidth is not provided', () => {
const { view } = renderView();

const tableContainer = view.container.querySelector(
'[data-testid="scrollable-list-el"]'
);
expect(tableContainer).toHaveStyle({
maxWidth: '100%',
width: 'inherit',
});
});
});
});
Loading
Loading