@edvisor/product-language 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/.eslintrc.json +14 -6
  2. package/package.json +2 -3
  3. package/project.json +18 -7
  4. package/src/README.md +61 -0
  5. package/src/helpers/index.ts +2 -1
  6. package/src/helpers/playground.ts +16 -0
  7. package/src/lib/components/badge/badge.tsx +8 -17
  8. package/src/lib/components/badge/stories/badge.stories.mdx +44 -0
  9. package/src/lib/components/badge/stories/components.tsx +49 -0
  10. package/src/lib/components/card/card.test.tsx +4 -5
  11. package/src/lib/components/card/card.tsx +2 -2
  12. package/src/lib/components/card/components/card-section-slot.tsx +2 -2
  13. package/src/lib/components/card/storybook/card.stories.mdx +1 -1
  14. package/src/lib/components/card/storybook/components.tsx +6 -23
  15. package/src/lib/components/checkbox/checkbox.tsx +34 -95
  16. package/src/lib/components/checkbox/helpers.tsx +100 -0
  17. package/src/lib/components/checkbox/stories/checkbox.stories.mdx +27 -24
  18. package/src/lib/components/checkbox/stories/components.tsx +63 -15
  19. package/src/lib/components/divider/stories/divider.stories.mdx +7 -13
  20. package/src/lib/components/flag/flag-size-flags.tsx +55 -0
  21. package/src/lib/components/flag/flag.list.tsx +788 -0
  22. package/src/lib/components/flag/flag.test.tsx +65 -0
  23. package/src/lib/components/flag/flag.tsx +97 -0
  24. package/src/lib/components/flag/index.tsx +1 -0
  25. package/src/lib/components/flag/stories/components.tsx +403 -0
  26. package/src/lib/components/flag/stories/flag.stories.mdx +48 -0
  27. package/src/lib/components/flag/stories/playGround-select.tsx +145 -0
  28. package/src/lib/components/icon/icon-list.tsx +135 -0
  29. package/src/lib/components/icon/icon.test.tsx +48 -0
  30. package/src/lib/components/icon/icon.tsx +181 -0
  31. package/src/lib/components/icon/index.tsx +1 -0
  32. package/src/lib/components/icon/stories/components.tsx +282 -0
  33. package/src/lib/components/icon/stories/icon.stories.mdx +65 -0
  34. package/src/lib/components/index.ts +5 -0
  35. package/src/lib/components/input-field/components/labeled-input.tsx +7 -14
  36. package/src/lib/components/input-field/components/stepper.tsx +4 -3
  37. package/src/lib/components/input-field/input-field.test.tsx +5 -6
  38. package/src/lib/components/input-field/input-field.tsx +8 -8
  39. package/src/lib/components/input-field/storybook/components.tsx +9 -16
  40. package/src/lib/components/link/storybook/link.stories.mdx +1 -0
  41. package/src/lib/components/molecules/avatar/avatar-size-flags.tsx +3 -3
  42. package/src/lib/components/molecules/avatar/avatar.tsx +2 -2
  43. package/src/lib/components/molecules/avatar/stories/avatar.stories.mdx +18 -21
  44. package/src/lib/components/molecules/button/button-flags.tsx +120 -15
  45. package/src/lib/components/molecules/button/button.test.tsx +9 -9
  46. package/src/lib/components/molecules/button/button.tsx +61 -78
  47. package/src/lib/components/molecules/button/stories/button.stories.mdx +43 -42
  48. package/src/lib/components/molecules/button/stories/components.tsx +6 -8
  49. package/src/lib/components/molecules/input-checkbox/input-checkbox.tsx +23 -24
  50. package/src/lib/components/molecules/input-checkbox/stories/components.tsx +32 -15
  51. package/src/lib/components/molecules/input-checkbox/stories/input-checkbox.stories.mdx +6 -8
  52. package/src/lib/components/organisms/multi-choice-list/multi-choice-list.tsx +7 -8
  53. package/src/lib/components/organisms/multi-choice-list/stories/components.tsx +3 -5
  54. package/src/lib/components/organisms/multi-choice-list/stories/multi-choice-list.stories.mdx +4 -4
  55. package/src/lib/components/spinner/spinner.test.tsx +2 -2
  56. package/src/lib/components/spinner/spinner.tsx +15 -28
  57. package/src/lib/components/spinner/stories/components.tsx +33 -2
  58. package/src/lib/components/spinner/stories/spinner.stories.mdx +3 -10
  59. package/src/lib/components/tabs/components/index.ts +1 -0
  60. package/src/lib/components/tabs/components/tab.tsx +62 -0
  61. package/src/lib/components/tabs/index.tsx +1 -0
  62. package/src/lib/components/tabs/storybook/components.tsx +282 -0
  63. package/src/lib/components/tabs/storybook/tabs.stories.mdx +97 -0
  64. package/src/lib/components/tabs/tabs.test.tsx +86 -0
  65. package/src/lib/components/tabs/tabs.tsx +101 -0
  66. package/src/lib/components/tag/components/close-button.tsx +85 -0
  67. package/src/lib/components/tag/components/index.ts +2 -0
  68. package/src/lib/components/tag/components/tag-label.tsx +44 -0
  69. package/src/lib/components/tag/index.tsx +1 -0
  70. package/src/lib/components/tag/stories/components.tsx +86 -0
  71. package/src/lib/components/tag/stories/tag.stories.mdx +42 -0
  72. package/src/lib/components/tag/tag.test.tsx +36 -0
  73. package/src/lib/components/tag/tag.tsx +33 -0
  74. package/src/lib/components/thumbnail/thumbnail.tsx +7 -2
  75. package/src/lib/components/typography/storybook/components.tsx +47 -15
  76. package/src/lib/components/typography/storybook/typography.stories.mdx +6 -4
  77. package/src/lib/components/typography/typography.test.tsx +34 -30
  78. package/src/lib/components/typography/typography.tsx +61 -19
  79. package/src/lib/foundations/color-system/base-palette/base-palette.ts +0 -1
  80. package/src/lib/foundations/color-system/color-guidelines/color-guidelines.ts +5 -4
  81. package/src/lib/foundations/color-system/components/color-sample.tsx +3 -3
  82. package/src/lib/foundations/typography/fonts.ts +205 -0
  83. package/src/lib/foundations/typography/text-aspect-flags.ts +11 -4
  84. package/src/lib/foundations/typography/typography.tsx +38 -33
  85. package/src/lib/helpers/numbers.ts +14 -0
  86. package/src/lib/helpers/safe-navigation.ts +10 -0
  87. package/src/lib/helpers/slots.test.tsx +98 -0
  88. package/src/lib/helpers/slots.tsx +93 -12
  89. package/.storybook/preview-head.html +0 -1
  90. package/src/lib/components/badge/badge.stories.tsx +0 -16
  91. package/src/lib/components/checkbox/components/components.tsx +0 -59
  92. package/src/lib/components/checkbox/stories/index.tsx +0 -1
  93. package/src/lib/components/molecules/input-checkbox/stories/index.tsx +0 -1
  94. package/src/lib/components/organisms/multi-choice-list/stories/index.tsx +0 -1
@@ -0,0 +1,86 @@
1
+ import styled from 'styled-components'
2
+ import { Margin } from '@foundations'
3
+ import { render, screen } from '@testing-library/react'
4
+ import userEvent from '@testing-library/user-event'
5
+ import { Tabs, Tab } from './index'
6
+
7
+ describe('Tabs', () => {
8
+ it('renders both tabs and the currently selected content', async () => {
9
+ render(
10
+ <Tabs selected={0}>
11
+ <Tabs.TabList>
12
+ <Tab>One</Tab>
13
+ <Tab>Two</Tab>
14
+ </Tabs.TabList>
15
+ <Tabs.Content>ONE</Tabs.Content>
16
+ <Tabs.Content>TWO</Tabs.Content>
17
+ </Tabs>
18
+ )
19
+
20
+ expect(screen.getAllByRole('tab')).toHaveLength(2)
21
+ expect(screen.getAllByRole('tabpanel')).toHaveLength(1)
22
+ expect(screen.getByRole('tabpanel')).toHaveTextContent('ONE')
23
+ })
24
+
25
+ it('does not render the unselected tabs', async () => {
26
+ render(
27
+ <Tabs selected={2}>
28
+ <Tabs.TabList>
29
+ <Tab>One</Tab>
30
+ <Tab>Two</Tab>
31
+ <Tab>Three</Tab>
32
+ </Tabs.TabList>
33
+ <Tabs.Content>ONE</Tabs.Content>
34
+ <Tabs.Content>TWO</Tabs.Content>
35
+ <Tabs.Content>THREE</Tabs.Content>
36
+ </Tabs>
37
+ )
38
+
39
+ expect(screen.getAllByRole('tab')).toHaveLength(3)
40
+ expect(screen.getAllByRole('tabpanel', { hidden: true })).toHaveLength(3)
41
+
42
+ expect(screen.getByText('ONE')).toHaveAttribute('aria-hidden', 'true')
43
+ expect(screen.getByText('TWO')).toHaveAttribute('aria-hidden', 'true')
44
+ expect(screen.getByText('ONE')).not.toBeVisible()
45
+ expect(screen.getByText('TWO')).not.toBeVisible()
46
+ })
47
+
48
+ /**
49
+ * this test just ensures that the programmer did not
50
+ * forget to add className? to the props and then pass
51
+ * it to the wrapping element so that users downstream
52
+ * can style the component
53
+ */
54
+ it('accepts styles', () => {
55
+ const NiceTab = styled(Tab)`
56
+ margin-bottom: ${Margin.l};
57
+ `
58
+
59
+ const { container } = render(<NiceTab>Contents</NiceTab>)
60
+
61
+ expect(container.firstChild).toHaveStyle(`margin-bottom: ${Margin.l}`)
62
+ expect(screen.getByText('Contents')).toBeInTheDocument()
63
+ })
64
+
65
+ it('calls onChange when a tab is clicked', async () => {
66
+ const handleChange = jest.fn()
67
+
68
+ render(
69
+ <Tabs selected={0} onChange={handleChange}>
70
+ <Tabs.TabList>
71
+ <Tab>One</Tab>
72
+ <Tab>Two</Tab>
73
+ </Tabs.TabList>
74
+ <Tabs.Content>ONE</Tabs.Content>
75
+ <Tabs.Content>TWO</Tabs.Content>
76
+ </Tabs>
77
+ )
78
+
79
+ await userEvent.click(screen.getByText('Two'))
80
+
81
+ expect(handleChange).toHaveBeenCalledTimes(1)
82
+
83
+ expect(screen.getByText('ONE')).toBeVisible()
84
+ expect(screen.getByText('TWO')).not.toBeVisible()
85
+ })
86
+ })
@@ -0,0 +1,101 @@
1
+ import { Children, ReactElement } from 'react'
2
+ import styled from 'styled-components'
3
+
4
+ import { Borders, Margin, Padding } from '@foundations'
5
+ import { applyProps, applyStyle, FC, is, isReactElementOfType, PropsWithChildren, safeCallback, Slot, StylableSlot } from '@helpers'
6
+
7
+ import { Flex } from 'components/layout'
8
+ import { ITabProps, Tab as TabBase } from './components'
9
+
10
+ const Tab = styled(TabBase)``
11
+
12
+ const TabList = styled(Flex)`
13
+ padding-left: ${Padding.m};
14
+ border-bottom: 1px solid ${Borders.Default.Subdued};
15
+
16
+ ${Tab} {
17
+ margin-right: ${Margin.m};
18
+ margin-bottom: -1px;
19
+ flex-shrink: 0;
20
+ }
21
+ `
22
+
23
+ class Content extends StylableSlot {}
24
+ class Navigation extends Slot {}
25
+
26
+ type SubComponents = {
27
+ Content: typeof Content
28
+ TabList: typeof Navigation
29
+ }
30
+
31
+ interface ITabsProps extends PropsWithChildren {
32
+ selected: number
33
+ onChange?: (selected: number) => void
34
+ }
35
+
36
+ const isTab = isReactElementOfType(Tab)
37
+ const isTabList = isReactElementOfType(Navigation)
38
+ const isContent = isReactElementOfType(Content)
39
+
40
+ export const Tabs: FC<ITabsProps, SubComponents> = (props) => {
41
+ /** iterate over the children, wiring up the tabs and contents */
42
+ let contentCount = 0
43
+ let tabCount = 0
44
+ const children = Children.map(props.children, (child) => {
45
+ if (isContent(child)) {
46
+ return decorateContent(child, props, contentCount++)
47
+ } if (isTabList(child)) {
48
+ const tabs = Children.map(child.props.children, (tab) => {
49
+ return isTab(tab) ? decorateTab(tab, props, tabCount++) : tab
50
+ })
51
+
52
+ return <TabList>{tabs}</TabList>
53
+ } else {
54
+ return child
55
+ }
56
+ })
57
+
58
+ return <>{children}</>
59
+ }
60
+
61
+ function decorateTab(
62
+ tab: ReactElement<ITabProps>,
63
+ { selected, onChange = () => undefined }: ITabsProps,
64
+ index: number
65
+ ) {
66
+ return (
67
+ <Tab
68
+ {...tab.props}
69
+ selected={
70
+ is(tab.props.selected) ? tab.props.selected : index === selected
71
+ }
72
+ onFocus={(e) => {
73
+ safeCallback(tab.props.onFocus, e)
74
+
75
+ if (index !== selected) {
76
+ onChange(index)
77
+ }
78
+ }}
79
+ >
80
+ {tab.props.children}
81
+ </Tab>
82
+ )
83
+ }
84
+
85
+ /** content could be anything, but it needs to at least show and hide appropriately */
86
+ function decorateContent (child: ReactElement, props: ITabsProps, index: number) {
87
+ return applyProps(
88
+ applyStyle(child, {
89
+ display: index === props.selected ? 'inherit' : 'none',
90
+ }),
91
+ {
92
+ role: 'tabpanel',
93
+ 'aria-hidden': !(index === props.selected),
94
+ }
95
+ )
96
+ }
97
+
98
+ Tabs.Content = Content
99
+ Tabs.TabList = Navigation
100
+
101
+ export { Tab } from './components'
@@ -0,0 +1,85 @@
1
+ //close-button.tsx
2
+ import styled from 'styled-components'
3
+ import { Flex } from 'components/layout'
4
+ import { Surface, Padding, Icons } from '@foundations'
5
+ import { FC, is, isDefined, PropsWithChildren } from '@helpers'
6
+ import { HTMLAttributes } from 'react'
7
+
8
+ const ClosableWrapper = styled(Flex)<{
9
+ disabled: boolean
10
+ }>`
11
+ flex-direction: row;
12
+ align-items: center;
13
+ justify-content: center;
14
+ padding: ${Padding.xxxs} ${Padding.xxs};
15
+ gap: 8px;
16
+ width: 28px;
17
+
18
+ background: ${(props) =>
19
+ props.disabled ? Surface.Neutral.Subdued : Surface.Neutral.Default};
20
+ border-radius: 0px 4px 4px 0px;
21
+
22
+ ${(props) =>
23
+ !props.disabled
24
+ ? `
25
+ &:hover {
26
+ background: ${Surface.Neutral.Hover};
27
+ cursor: pointer;
28
+
29
+ svg {
30
+ path {
31
+ fill: ${Icons.Hover}
32
+ }
33
+ }
34
+ }
35
+
36
+ &:active {
37
+ background: ${Surface.Neutral.Pressed};
38
+
39
+ svg {
40
+ path {
41
+ fill: ${Icons.Pressed};
42
+ }
43
+ }
44
+ }
45
+ `
46
+ : `
47
+ svg {
48
+ path {
49
+ fill: ${Icons.Disabled};
50
+ }
51
+ }`}
52
+ `
53
+
54
+ const ClosableIcon = styled.svg`
55
+ path {
56
+ fill: ${Icons.Default};
57
+ }
58
+ `
59
+
60
+ interface IProps extends HTMLAttributes<HTMLDivElement>, PropsWithChildren {
61
+ disabled?: boolean
62
+ onClick?: () => void
63
+ }
64
+
65
+ export const CloseButton: FC<IProps> = (props) => {
66
+ const disabled = is(props.disabled)
67
+
68
+ const onClickHandler = () => {
69
+ if (!disabled && isDefined(props.onClick)) {
70
+ props.onClick()
71
+ }
72
+ }
73
+ return (
74
+ <ClosableWrapper disabled={disabled} onClick={onClickHandler} role="button">
75
+ <ClosableIcon
76
+ width="12.5"
77
+ height="12.5"
78
+ viewBox="0 0 16 16"
79
+ xmlns="http://www.w3.org/2000/svg"
80
+ >
81
+ <path d="M8.00451 6.79303L14.5439 0.251124C14.8798 -0.0837079 15.423 -0.0837079 15.7267 0.251124C16.0912 0.585955 16.0912 1.12912 15.7267 1.46395L9.21591 8.00442L15.7267 14.5438C16.0912 14.8797 16.0912 15.4229 15.7267 15.7266C15.423 16.0911 14.8798 16.0911 14.5439 15.7266L8.00451 9.21582L1.46404 15.7266C1.12921 16.0911 0.586045 16.0911 0.251177 15.7266C-0.0837258 15.4229 -0.0837258 14.8797 0.251177 14.5438L6.79312 8.00442L0.251177 1.46395C-0.0837258 1.12912 -0.0837258 0.585955 0.251177 0.251124C0.586045 -0.0837079 1.12921 -0.0837079 1.46404 0.251124L8.00451 6.79303Z" />
82
+ </ClosableIcon>
83
+ </ClosableWrapper>
84
+ )
85
+ }
@@ -0,0 +1,2 @@
1
+ export * from './close-button'
2
+ export * from './tag-label'
@@ -0,0 +1,44 @@
1
+ import styled from 'styled-components'
2
+ import { Flex } from 'components/layout'
3
+ import { Surface, Padding, Text } from '@foundations'
4
+ import { Label } from 'components/typography'
5
+ import { FC, is, PropsWithChildren } from '@helpers'
6
+ import { HTMLAttributes } from 'react'
7
+
8
+ const LabelFrame = styled(Flex)<{
9
+ disabled: boolean
10
+ closable: boolean
11
+ }>`
12
+ background: ${(props) =>
13
+ props.disabled ? Surface.Neutral.Subdued : Surface.Neutral.Default};
14
+ flex-direction: row;
15
+ align-items: center;
16
+ justify-content: center;
17
+ gap: 8px;
18
+ padding: ${Padding.xxxs} ${Padding.xs} ${Padding.xxxs} ${Padding.xs};
19
+ width: 100%;
20
+ min-height: 24px;
21
+ border-radius: ${(props) => (props.closable ? '4px 0px 0px 4px' : '4px')};
22
+ `
23
+
24
+ const LabelText = styled(Label)<{
25
+ disabled: boolean
26
+ }>`
27
+ color: ${(props) => (props.disabled ? Text.Light : Text.Default)};
28
+ `
29
+
30
+ interface IProps extends HTMLAttributes<HTMLLabelElement>, PropsWithChildren {
31
+ closable?: boolean
32
+ disabled?: boolean
33
+ }
34
+
35
+ export const TagLabel: FC<IProps> = (props) => {
36
+ const disabled = is(props.disabled)
37
+ const closable = is(props.closable)
38
+
39
+ return (
40
+ <LabelFrame disabled={disabled} closable={closable}>
41
+ <LabelText disabled={disabled}>{props.children}</LabelText>
42
+ </LabelFrame>
43
+ )
44
+ }
@@ -0,0 +1 @@
1
+ export * from './tag'
@@ -0,0 +1,86 @@
1
+ import { Playground } from 'storybook-addon-jarle-monaco'
2
+ import { Canvas } from '@storybook/addon-docs'
3
+ import { Tag } from '../tag'
4
+ import { Card } from 'components/card'
5
+ import styled from 'styled-components'
6
+ import { Margin, Padding, Surface } from '@foundations'
7
+
8
+ const WrapperStories = styled(Card)`
9
+ width: 240px;
10
+ height: 238px;
11
+ padding: ${Padding.l};
12
+ background: ${Surface.Default.Default};
13
+ `
14
+ const TagMarginBottom24 = styled(Tag)`
15
+ margin-bottom: ${Margin.l};
16
+ `
17
+
18
+ const onClickHandler = () => {
19
+ alert('Close button clicked')
20
+ }
21
+
22
+ export const SelectedTagHTMLExample = () => {
23
+ return (
24
+ <WrapperStories heading="Selected (2)">
25
+ <TagMarginBottom24 closable onClick={onClickHandler}>Toronto, ON, Canada</TagMarginBottom24>
26
+ <TagMarginBottom24 closable onClick={onClickHandler}>Melbourne NSW, Australia</TagMarginBottom24>
27
+ </WrapperStories>
28
+ )
29
+ }
30
+
31
+ export const TagExample = () => (
32
+ <Playground
33
+ code={`
34
+ /* Edit this code sample! */
35
+ <div style={{display:'flex', gap:'24px'}}>
36
+ <Tag >Label</Tag>
37
+ <Tag disabled >Label</Tag>
38
+ <Tag closable onClick={onClickHandler}>Label</Tag>
39
+ <Tag closable disabled>Label</Tag>
40
+ </div>
41
+ `}
42
+ providerProps={{
43
+ renderAsComponent: true,
44
+ scope: {
45
+ Tag,
46
+ Canvas,
47
+ onClickHandler
48
+ },
49
+ }}
50
+ />
51
+ )
52
+
53
+ export const WorkedExample = () => (
54
+ <Playground
55
+ code={`
56
+ const [selectedCities, setSelected] = useState([
57
+ { id: 1, name: 'Vancouver, BC', disabled: true },
58
+ { id: 2, name: 'Montreal, QC'},
59
+ { id: 3, name: 'Toronto, ON'},
60
+ ]);
61
+
62
+ <div style={{display:'flex', gap:'24px'}}>
63
+ {selectedCities.map((city, index) => {
64
+ return (
65
+ <Tag
66
+ closable
67
+ disabled={city.disabled}
68
+ key={city.id}
69
+ onClick={() => {
70
+ setSelected( prevCities => prevCities.filter( filteredCity => filteredCity.id !== city.id ) )
71
+ }}
72
+ >{city.name}</Tag>
73
+ )
74
+ })}
75
+ </div>
76
+ `}
77
+ providerProps={{
78
+ renderAsComponent: true,
79
+ scope: {
80
+ Tag,
81
+ Canvas,
82
+ onClickHandler
83
+ },
84
+ }}
85
+ />
86
+ )
@@ -0,0 +1,42 @@
1
+ import { Canvas, Meta, Story, ArgsTable } from '@storybook/addon-docs'
2
+ import { Tag } from '../index'
3
+ import { TagExample, SelectedTagHTMLExample, WorkedExample } from './components'
4
+
5
+ <Meta title="Components/Tag" component={Tag} />
6
+
7
+ # Tag
8
+
9
+ For more details, check out the component page on [Figma](https://www.figma.com/file/ue1CurHfZ426o2T2l8Dk64/Edvisor-Product-Language?node-id=1545%3A4278)
10
+
11
+ ## How to use
12
+
13
+ ```javascript
14
+ // Import the component
15
+ import { Tag } from '@edvisor/product-language'
16
+
17
+ // Render the default component
18
+ <Tag>Label</Tag>
19
+
20
+ ```
21
+
22
+ ## Properties
23
+
24
+ The available optional properties are as follows.
25
+
26
+ | Prop | Type | Description |
27
+ | ------------ | ---------- | ---------------------------------------------------- |
28
+ | `closable?` | `boolean` | Add a close button to the tag |
29
+ | `disabled?` | `boolean` | Disabled the tag |
30
+ | `className?` | `string` | Add the class to the tag |
31
+ | `onClick?` | `function` | Called when the close button is clicked |
32
+
33
+ ## Example
34
+
35
+ <SelectedTagHTMLExample />
36
+
37
+
38
+ ## Playground
39
+
40
+ Tags
41
+
42
+ <WorkedExample />
@@ -0,0 +1,36 @@
1
+ //tag.test
2
+ import { render, screen } from '@testing-library/react'
3
+ import userEvent from '@testing-library/user-event'
4
+ import { Tag } from './index'
5
+
6
+ describe('Tag Tests', () => {
7
+ it('should render Tag with given Text', async () => {
8
+ render(<Tag>Test</Tag>)
9
+ expect(screen.getByText('Test')).toBeInTheDocument()
10
+ expect(screen.queryByRole('button')).not.toBeInTheDocument()
11
+ })
12
+
13
+ it('should render a disabled Tag with the close button and with given Text', async () => {
14
+ render(
15
+ <Tag disabled closable>
16
+ Close
17
+ </Tag>
18
+ )
19
+ expect(screen.getByText('Close')).toBeInTheDocument()
20
+ expect(screen.queryByRole('button')).toBeInTheDocument()
21
+ })
22
+
23
+ it('should render the Tag with close button and handle event after click', async () => {
24
+ const spyOnClick = jest.fn()
25
+ render(
26
+ <Tag closable onClick={spyOnClick}>
27
+ Clicked
28
+ </Tag>
29
+ )
30
+ expect(screen.getByText('Clicked')).toBeInTheDocument()
31
+
32
+ const closeIcon = screen.queryByRole('button') as HTMLElement
33
+ await userEvent.click(closeIcon)
34
+ expect(spyOnClick).toHaveBeenCalled()
35
+ })
36
+ })
@@ -0,0 +1,33 @@
1
+ import { FC, PropsWithChildren, is } from '@helpers'
2
+ import { Padding } from '@foundations'
3
+ import styled from 'styled-components'
4
+ import { Flex } from 'components/layout'
5
+ import { CloseButton, TagLabel } from './components'
6
+ import { HTMLAttributes } from 'react'
7
+
8
+ const TagFrame = styled(Flex)`
9
+ flex-direction: row;
10
+ align-items: stretch;
11
+ padding: ${Padding.none};
12
+ width: fit-content;
13
+ `
14
+
15
+ interface IProps extends HTMLAttributes<HTMLDivElement>, PropsWithChildren {
16
+ closable?: boolean
17
+ disabled?: boolean
18
+ className?: string
19
+ onClick?: () => void
20
+ }
21
+
22
+ export const Tag: FC<IProps> = (props) => {
23
+ const { disabled, closable, onClick, ...domProps } = props
24
+
25
+ return (
26
+ <TagFrame {...domProps} className={props.className}>
27
+ <TagLabel disabled={disabled} closable={closable}>
28
+ {props.children}
29
+ </TagLabel>
30
+ {is(closable) && <CloseButton {...props} />}
31
+ </TagFrame>
32
+ )
33
+ }
@@ -21,11 +21,12 @@ const Image = styled.img`
21
21
  interface IThumbnailProps {
22
22
  imageUrl?: string;
23
23
  imageLabel?: string;
24
+ className?: string;
24
25
  }
25
26
  type IProps = IThumbnailProps & ThumbnailSizeProps
26
27
 
27
28
  export const Thumbnail: FC<IProps> = (props) => {
28
- const { imageUrl, imageLabel = imageUrl } = props
29
+ const { imageUrl, imageLabel = imageUrl, className = '' } = props
29
30
  const size = getValuesBySize(props)
30
31
 
31
32
  if (isNil(imageUrl)) {
@@ -33,7 +34,11 @@ export const Thumbnail: FC<IProps> = (props) => {
33
34
  }
34
35
 
35
36
  return (
36
- <Box size={size} data-testid="thumbnail-test">
37
+ <Box
38
+ size={size}
39
+ data-testid="thumbnail-test"
40
+ className={className}
41
+ >
37
42
  <Image src={imageUrl} alt={imageLabel}/>
38
43
  </Box>
39
44
  )
@@ -8,11 +8,10 @@ import {
8
8
  Heading2,
9
9
  Heading3,
10
10
  Heading4,
11
- BodyLarge,
12
11
  Body,
12
+ BodyLarge,
13
13
  Caption,
14
- Label1,
15
- Label2,
14
+ Label,
16
15
  } from '../typography'
17
16
  import { Typography } from '@foundations'
18
17
  import { Flex } from 'components/layout'
@@ -82,11 +81,11 @@ export const Button = styled.div<{ critical?: boolean, primary?: boolean }>`
82
81
 
83
82
  const Header = () => (
84
83
  <Row>
85
- <HeaderColumn><Label1 subdued>Typographic System</Label1></HeaderColumn>
86
- <HeaderColumn><Label1 subdued>Weight</Label1></HeaderColumn>
87
- <HeaderColumn><Label1 subdued>Size</Label1></HeaderColumn>
88
- <HeaderColumn><Label1 subdued>Line Height</Label1></HeaderColumn>
89
- <HeaderColumn><Label1 subdued>Spacing</Label1></HeaderColumn>
84
+ <HeaderColumn><Label subdued>Typographic System</Label></HeaderColumn>
85
+ <HeaderColumn><Label subdued>Weight</Label></HeaderColumn>
86
+ <HeaderColumn><Label subdued>Size</Label></HeaderColumn>
87
+ <HeaderColumn><Label subdued>Line Height</Label></HeaderColumn>
88
+ <HeaderColumn><Label subdued>Spacing</Label></HeaderColumn>
90
89
  </Row>
91
90
  )
92
91
 
@@ -198,10 +197,10 @@ export const TypographyTable: StoryComponent = () => {
198
197
  <Row gray>
199
198
  <Column>
200
199
  <Button {...toButtonProps(aspect)}>
201
- <BodyLarge {...toTextAspectProps(aspect)}>BodyLarge</BodyLarge>
200
+ <BodyLarge strong {...toTextAspectProps(aspect)}>BodyLarge/Strong</BodyLarge>
202
201
  </Button>
203
202
  </Column>
204
- <Column>Reg 400 / Semibold 600</Column>
203
+ <Column>Semibold 600</Column>
205
204
  <Column>18px (1.125rem)</Column>
206
205
  <Column>28px</Column>
207
206
  <Column>0 px</Column>
@@ -209,10 +208,32 @@ export const TypographyTable: StoryComponent = () => {
209
208
  <Row gray>
210
209
  <Column>
211
210
  <Button {...toButtonProps(aspect)}>
212
- <Body {...toTextAspectProps(aspect)}>Body</Body>
211
+ <BodyLarge {...toTextAspectProps(aspect)}>BodyLarge/Default</BodyLarge>
213
212
  </Button>
214
213
  </Column>
215
- <Column>Reg 400 / Medium 500</Column>
214
+ <Column>Regular 400</Column>
215
+ <Column>18px (1.125rem)</Column>
216
+ <Column>28px</Column>
217
+ <Column>0 px</Column>
218
+ </Row>
219
+ <Row gray>
220
+ <Column>
221
+ <Button {...toButtonProps(aspect)}>
222
+ <Body strong {...toTextAspectProps(aspect)}>Body Strong</Body>
223
+ </Button>
224
+ </Column>
225
+ <Column>Medium 500</Column>
226
+ <Column>14px (0.875rem)</Column>
227
+ <Column>20px</Column>
228
+ <Column>0 px</Column>
229
+ </Row>
230
+ <Row gray>
231
+ <Column>
232
+ <Button {...toButtonProps(aspect)}>
233
+ <Body {...toTextAspectProps(aspect)}>Body default</Body>
234
+ </Button>
235
+ </Column>
236
+ <Column>Regular 400</Column>
216
237
  <Column>14px (0.875rem)</Column>
217
238
  <Column>20px</Column>
218
239
  <Column>0 px</Column>
@@ -231,10 +252,21 @@ export const TypographyTable: StoryComponent = () => {
231
252
  <Row>
232
253
  <Column>
233
254
  <Button {...toButtonProps(aspect)}>
234
- <Label1 {...toTextAspectProps(aspect)}>Label1</Label1>
255
+ <Label strong {...toTextAspectProps(aspect)}>Label/Strong</Label>
256
+ </Button>
257
+ </Column>
258
+ <Column>Medium 500</Column>
259
+ <Column>14px (0.875rem)</Column>
260
+ <Column>20px</Column>
261
+ <Column>0 px</Column>
262
+ </Row>
263
+ <Row>
264
+ <Column>
265
+ <Button {...toButtonProps(aspect)}>
266
+ <Label {...toTextAspectProps(aspect)}>Label/Default</Label>
235
267
  </Button>
236
268
  </Column>
237
- <Column>Reg 400 / Medium 500</Column>
269
+ <Column>Regular 400</Column>
238
270
  <Column>14px (0.875rem)</Column>
239
271
  <Column>20px</Column>
240
272
  <Column>0 px</Column>
@@ -242,7 +274,7 @@ export const TypographyTable: StoryComponent = () => {
242
274
  <Row>
243
275
  <Column>
244
276
  <Button {...toButtonProps(aspect)}>
245
- <Label2 {...toTextAspectProps(aspect)}>Label2</Label2>
277
+ <Label subtle {...toTextAspectProps(aspect)}>Label/Subtle</Label>
246
278
  </Button>
247
279
  </Column>
248
280
  <Column>Regular 400</Column>