-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat(web-react): Introduce Item component #DS-1049
- Loading branch information
1 parent
4d98af2
commit be86547
Showing
22 changed files
with
478 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import React, { ElementType } from 'react'; | ||
import classNames from 'classnames'; | ||
import { SpiritItemProps } from '../../types'; | ||
import { useStyleProps } from '../../hooks'; | ||
import { HelperText } from '../Field'; | ||
import { Icon } from '../Icon'; | ||
import { useItemStyleProps } from './useItemStyleProps'; | ||
|
||
const Item = <T extends ElementType = 'button'>(props: SpiritItemProps<T>): JSX.Element => { | ||
const { label, elementType: ElementTag = 'button', iconName, helperText, isSelected, ...restProps } = props; | ||
const { classProps, props: modifiedProps } = useItemStyleProps({ isSelected, ...restProps }); | ||
const { styleProps, props: otherProps } = useStyleProps(modifiedProps); | ||
|
||
return ( | ||
<ElementTag | ||
{...otherProps} | ||
{...styleProps} | ||
className={classNames(classProps.root, styleProps.className)} | ||
aria-selected={!!isSelected} | ||
> | ||
{iconName && ( | ||
<span className={classNames(classProps.icon.root, classProps.icon.start)}> | ||
<Icon name={iconName} /> | ||
</span> | ||
)} | ||
<span className={classProps.label}>{label}</span> | ||
<HelperText className={classProps.helperText} elementType="span" helperText={helperText} /> | ||
{isSelected && ( | ||
<span className={classNames(classProps.icon.root, classProps.icon.end)}> | ||
<Icon name="check-plain" /> | ||
</span> | ||
)} | ||
</ElementTag> | ||
); | ||
}; | ||
|
||
export default Item; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,94 @@ | ||
# Item | ||
|
||
To implement Item component with content of `Radio` or `Checkbox`, | ||
you need to use directly these components with prop `isItem`. | ||
The Item component is used to display a single item in a list. It can be used in Dropdown or similar. | ||
|
||
See `web` package [Item documentation][item-documentation] for more info. | ||
To use Item with checkbox or radio please use components [Checkbox][checkbox] or [Radio][radio] | ||
with `isItem` property. We do this to avoid repeating the same code and to simplify the API. | ||
|
||
[item-documentation]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web/src/scss/components/Item/README.md | ||
Simple Item example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" />; | ||
``` | ||
|
||
Item with icon example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" iconName="search" />; | ||
``` | ||
|
||
Item in selected state example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" isSelected />; | ||
``` | ||
|
||
Item with Helper text example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" helperText="Helper text" />; | ||
``` | ||
|
||
Item in disabled state example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" isDisabled />; | ||
``` | ||
|
||
Item with icon and helper text in selected state example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" iconName="search" helperText="Helper text" isSelected />; | ||
``` | ||
|
||
Item as a link example: | ||
|
||
```jsx | ||
import { Item } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Item label="Item" elementType="a" href="#" />; | ||
``` | ||
|
||
Radio as Item: | ||
|
||
```jsx | ||
import { Radio } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Radio id="radioItem" name="example" label="Radio Label" isItem />; | ||
``` | ||
|
||
Checkbox as Item: | ||
|
||
```jsx | ||
import { Checkbox } from '@lmc-eu/spirit-web-react'; | ||
|
||
<Checkbox id="checkboxItem" name="example" label="Checkbox Label" isItem />; | ||
``` | ||
|
||
## API | ||
|
||
| Name | Type | Default | Required | Description | | ||
| ------------------ | ------------------------- | -------- | -------- | ------------------------------- | | ||
| `elementType` | `ElementType` | `button` | ✕ | Type of element used as wrapper | | ||
| `helperText` | `string` | — | ✕ | Custom helper text | | ||
| `iconName` | `string` | — | ✕ | Icon used in item | | ||
| `isDisabled` | `bool` | `false` | ✕ | Whether is the item disabled | | ||
| `isSelected` | `bool` | `false` | ✕ | Whether is the item selected | | ||
| `label` | [`string` \| `ReactNode`] | - | ✔ | Label of the item | | ||
| `UNSAFE_className` | `string` | — | ✕ | Wrapper custom class name | | ||
| `UNSAFE_style` | `CSSProperties` | — | ✕ | Wrapper custom style | | ||
|
||
[checkbox]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Checkbox/README.md | ||
[radio]: https://github.com/lmc-eu/spirit-design-system/blob/main/packages/web-react/src/components/Radio/README.md |
60 changes: 60 additions & 0 deletions
60
packages/web-react/src/components/Item/__tests__/Item.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import React from 'react'; | ||
import '@testing-library/jest-dom'; | ||
import { render } from '@testing-library/react'; | ||
import { stylePropsTest } from '../../../../tests/providerTests/stylePropsTest'; | ||
import { restPropsTest } from '../../../../tests/providerTests/restPropsTest'; | ||
import { SpiritItemProps } from '../../../types'; | ||
import Item from '../Item'; | ||
|
||
describe('Item', () => { | ||
stylePropsTest(Item); | ||
|
||
restPropsTest((props: SpiritItemProps) => <Item {...props} />, 'button'); | ||
|
||
it('should render label', () => { | ||
const label = 'Item label'; | ||
const dom = render(<Item label={label} />); | ||
|
||
const element = dom.container.querySelector('.Item > .Item__label') as HTMLElement; | ||
expect(element).toHaveTextContent(label); | ||
}); | ||
|
||
it('should render helperText', () => { | ||
const helperText = 'Helper text'; | ||
const dom = render(<Item label="Item label" helperText={helperText} />); | ||
|
||
const element = dom.container.querySelector('.Item > .Item__helperText') as HTMLElement; | ||
expect(element).toHaveTextContent(helperText); | ||
}); | ||
|
||
it('should render icon', () => { | ||
const iconName = 'search'; | ||
const dom = render(<Item label="Item label" iconName={iconName} />); | ||
|
||
const element = dom.container.querySelector('.Item > .Item__icon') as HTMLElement; | ||
expect(element).toHaveClass('Item__icon--start'); | ||
}); | ||
|
||
it('should be selected and render end icon', () => { | ||
const dom = render(<Item label="Item label" isSelected />); | ||
|
||
const element = dom.container.querySelector('.Item') as HTMLElement; | ||
const iconElement = dom.container.querySelector('.Item > .Item__icon') as HTMLElement; | ||
expect(element).toHaveClass('Item--selected'); | ||
expect(iconElement).toHaveClass('Item__icon--end'); | ||
}); | ||
|
||
it('should be disabled', () => { | ||
const dom = render(<Item label="Item label" isDisabled />); | ||
|
||
const element = dom.container.querySelector('.Item') as HTMLElement; | ||
expect(element).toHaveClass('Item--disabled'); | ||
}); | ||
|
||
it('should render as anchor', () => { | ||
const dom = render(<Item label="Item label" elementType="a" />); | ||
|
||
const element = dom.container.querySelector('a') as HTMLElement; | ||
expect(element).toHaveClass('Item'); | ||
}); | ||
}); |
35 changes: 35 additions & 0 deletions
35
packages/web-react/src/components/Item/__tests__/useItemStyleProps.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
import { SpiritItemProps } from '../../../types'; | ||
import { useItemStyleProps } from '../useItemStyleProps'; | ||
|
||
describe('useItemStyleProps', () => { | ||
it('should return defaults', () => { | ||
const props = {}; | ||
const { result } = renderHook(() => useItemStyleProps(props)); | ||
|
||
expect(result.current.classProps).toEqual({ | ||
helperText: 'Item__helperText', | ||
icon: { | ||
root: 'Item__icon', | ||
start: 'Item__icon--start', | ||
end: 'Item__icon--end', | ||
}, | ||
label: 'Item__label', | ||
root: 'Item', | ||
}); | ||
}); | ||
|
||
it('should return selected item', () => { | ||
const props = { isSelected: true } as SpiritItemProps; | ||
const { result } = renderHook(() => useItemStyleProps(props)); | ||
|
||
expect(result.current.classProps.root).toBe('Item Item--selected'); | ||
}); | ||
|
||
it('should return disabled item', () => { | ||
const props = { isDisabled: true } as SpiritItemProps; | ||
const { result } = renderHook(() => useItemStyleProps(props)); | ||
|
||
expect(result.current.classProps.root).toBe('Item Item--disabled'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import React from 'react'; | ||
import { Checkbox } from '../../Checkbox'; | ||
|
||
const CheckboxItem = () => ( | ||
<Checkbox id="checkboxItemDefault" name="checkboxItemDefault" label="Checkbox Item" isItem /> | ||
); | ||
|
||
export default CheckboxItem; |
12 changes: 12 additions & 0 deletions
12
packages/web-react/src/components/Item/demo/ItemDefault.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import Item from '../Item'; | ||
|
||
const ItemDefault = () => ( | ||
<> | ||
<Item label="Item label" /> | ||
<Item elementType="a" label="Item label" href="https://www.example.com/" /> | ||
<Item elementType="div" label="Item label" /> | ||
</> | ||
); | ||
|
||
export default ItemDefault; |
13 changes: 13 additions & 0 deletions
13
packages/web-react/src/components/Item/demo/ItemDisabled.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react'; | ||
import Item from '../Item'; | ||
|
||
const ItemDisabled = () => { | ||
return ( | ||
<> | ||
<Item label="Item label" isDisabled /> | ||
<Item label="Item label" isDisabled isSelected /> | ||
</> | ||
); | ||
}; | ||
|
||
export default ItemDisabled; |
15 changes: 15 additions & 0 deletions
15
packages/web-react/src/components/Item/demo/ItemHelperText.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import React from 'react'; | ||
import Item from '../Item'; | ||
|
||
const ItemHelperText = () => { | ||
return ( | ||
<> | ||
<Item label="Item label" helperText="Helper text" /> | ||
<Item label="Item label" helperText="Helper text" isSelected /> | ||
<Item label="Item label" helperText="Helper text" isDisabled /> | ||
<Item label="Item label" helperText="Helper text" isSelected isDisabled /> | ||
</> | ||
); | ||
}; | ||
|
||
export default ItemHelperText; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import React from 'react'; | ||
import Item from '../Item'; | ||
|
||
const ItemIcon = () => { | ||
return ( | ||
<> | ||
<Item label="Item label" iconName="search" /> | ||
<Item label="Item label" iconName="search" isSelected /> | ||
</> | ||
); | ||
}; | ||
|
||
export default ItemIcon; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import React from 'react'; | ||
import Item from '../Item'; | ||
|
||
const ItemSelected = () => <Item label="Item label" isSelected />; | ||
|
||
export default ItemSelected; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import React from 'react'; | ||
import { Radio } from '../../Radio'; | ||
|
||
const RadioItem = () => <Radio id="radioItemDefault" isItem label="Radio Item" name="item" />; | ||
|
||
export default RadioItem; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import React from 'react'; | ||
import ReactDOM from 'react-dom/client'; | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment | ||
// @ts-ignore: No declaration file | ||
import icons from '@lmc-eu/spirit-icons/dist/icons'; | ||
import DocsSection from '../../../../docs/DocsSections'; | ||
import { IconsProvider } from '../../../context'; | ||
import ItemDefault from './ItemDefault'; | ||
import ItemSelected from './ItemSelected'; | ||
import ItemDisabled from './ItemDisabled'; | ||
import ItemHelperText from './ItemHelperText'; | ||
import ItemIcon from './ItemIcon'; | ||
import CheckboxItem from './CheckboxItem'; | ||
import RadioItem from './RadioItem'; | ||
|
||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( | ||
<React.StrictMode> | ||
<IconsProvider value={icons}> | ||
<DocsSection title="Default"> | ||
<ItemDefault /> | ||
</DocsSection> | ||
<DocsSection title="Selected"> | ||
<ItemSelected /> | ||
</DocsSection> | ||
<DocsSection title="Disabled"> | ||
<ItemDisabled /> | ||
</DocsSection> | ||
<DocsSection title="Helper Text"> | ||
<ItemHelperText /> | ||
</DocsSection> | ||
<DocsSection title="Icon"> | ||
<ItemIcon /> | ||
</DocsSection> | ||
<DocsSection title="Checkbox Item"> | ||
<CheckboxItem /> | ||
</DocsSection> | ||
<DocsSection title="Radio Item"> | ||
<RadioItem /> | ||
</DocsSection> | ||
</IconsProvider> | ||
</React.StrictMode>, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{{> demo}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from './Item'; | ||
export * from './useItemStyleProps'; | ||
export { default as Item } from './Item'; |
Oops, something went wrong.