Skip to content

Commit

Permalink
Merge pull request #48 from MetroStar/CSG-717
Browse files Browse the repository at this point in the history
CSG-717: Add USWDS List component to USWDS Comet package.
  • Loading branch information
jbouder committed Jun 7, 2023
2 parents 581e3db + 2be22ce commit ffaf79a
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/comet-uswds/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export { default as Header } from './header';
export { default as Icon } from './icon';
export { default as TextInput } from './text-input';
export { default as Label } from './label';
export { default as List } from './list';
export { default as MemorableDate } from './memorable-date';
export { default as Modal } from './modal';
export { default as Pagination } from './pagination';
Expand Down
1 change: 1 addition & 0 deletions packages/comet-uswds/src/components/list/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './list';
32 changes: 32 additions & 0 deletions packages/comet-uswds/src/components/list/list.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';
import { StoryFn, Meta } from '@storybook/react';
import { List } from '../../index';
import { ListItem, ListProps } from './list';

const meta: Meta<typeof List> = {
title: 'USWDS/List',
component: List,
argTypes: {
id: { required: true },
type: { control: 'select' },
variant: { control: 'select' },
},
};
export default meta;

const Template: StoryFn<typeof List> = (args: ListProps) => <List {...args}>Button</List>;

const items = [
{ id: 'item-1', value: 'Item 1' },
{ id: 'item-2', value: 'Item 2' },
{ id: 'item-3', value: 'Item 3' },
] as ListItem[];

export const Default = Template.bind({});
Default.args = {
id: 'list-1',
type: 'unordered',
variant: 'default',
items,
className: '',
};
39 changes: 39 additions & 0 deletions packages/comet-uswds/src/components/list/list.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from 'react';
import '@testing-library/jest-dom';
import { render } from '@testing-library/react';
import List, { ListItem } from './list';

describe('List', () => {
const items = [
{ id: 'item-1', value: 'Item 1' },
{ id: 'item-2', value: 'Item 2' },
{ id: 'item-3', value: 'Item 3' },
] as ListItem[];

test('should render the default component', () => {
const { baseElement } = render(<List id="list-1" items={items} />);
expect(baseElement.querySelector('#list-1')).toBeTruthy();
expect(baseElement.querySelector('ul')).toBeTruthy();
expect(baseElement.querySelectorAll('li')).toHaveLength(3);
});

test('should render the component as ordered', () => {
const { baseElement } = render(<List id="list-1" type="ordered" items={items} />);
expect(baseElement.querySelector('#list-1')).toBeTruthy();
expect(baseElement.querySelector('ol')).toBeTruthy();
});

test('should render the component as unstyled', () => {
const { baseElement } = render(<List id="list-1" variant="unstyled" items={items} />);
expect(baseElement.querySelector('#list-1')).toBeTruthy();
expect(baseElement.querySelector('ul')).toBeTruthy();
expect(baseElement.querySelector('#list-1')).toHaveClass('usa-list--unstyled');
});

test('should render the component with custom class', () => {
const { baseElement } = render(<List id="list-1" className="some-class" items={items} />);
expect(baseElement.querySelector('#list-1')).toBeTruthy();
expect(baseElement.querySelector('ul')).toBeTruthy();
expect(baseElement.querySelector('#list-1')).toHaveClass('some-class');
});
});
71 changes: 71 additions & 0 deletions packages/comet-uswds/src/components/list/list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { ReactNode } from 'react';
import classnames from 'classnames';

export interface ListItem {
id: string;
value: ReactNode;
}

export interface ListProps {
/**
* The unique identifier for this component
*/
id: string;
/**
* The type of list to display
*/
type?: 'ordered' | 'unordered';
/**
* The style variant of list to display
*/
variant?: 'default' | 'unstyled';
/**
* A custom class to apply to the component
*/
className?: string;
/**
* The list of items to display
*/
items: ListItem[];
}

/**
* A list organizes information into discrete sequential sections.
*/
export const List = ({
id,
type = 'unordered',
variant = 'default',
className,
items,
...listProps
}: ListProps): React.ReactElement => {
const classes = classnames(
'usa-list',
{
'usa-list--unstyled': variant === 'unstyled',
},
className,
);

const getChildren = (items: ListItem[]): React.ReactNode =>
items.map((item) => {
return (
<li id={item.id} key={item.id}>
{item.value}
</li>
);
});

return type === 'unordered' ? (
<ul id={id} className={classes} {...listProps}>
{getChildren(items)}
</ul>
) : (
<ol id={id} className={classes} {...listProps}>
{getChildren(items)}
</ol>
);
};

export default List;

0 comments on commit ffaf79a

Please sign in to comment.