@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.
- package/.eslintrc.json +14 -6
- package/package.json +2 -3
- package/project.json +18 -7
- package/src/README.md +61 -0
- package/src/helpers/index.ts +2 -1
- package/src/helpers/playground.ts +16 -0
- package/src/lib/components/badge/badge.tsx +8 -17
- package/src/lib/components/badge/stories/badge.stories.mdx +44 -0
- package/src/lib/components/badge/stories/components.tsx +49 -0
- package/src/lib/components/card/card.test.tsx +4 -5
- package/src/lib/components/card/card.tsx +2 -2
- package/src/lib/components/card/components/card-section-slot.tsx +2 -2
- package/src/lib/components/card/storybook/card.stories.mdx +1 -1
- package/src/lib/components/card/storybook/components.tsx +6 -23
- package/src/lib/components/checkbox/checkbox.tsx +34 -95
- package/src/lib/components/checkbox/helpers.tsx +100 -0
- package/src/lib/components/checkbox/stories/checkbox.stories.mdx +27 -24
- package/src/lib/components/checkbox/stories/components.tsx +63 -15
- package/src/lib/components/divider/stories/divider.stories.mdx +7 -13
- package/src/lib/components/flag/flag-size-flags.tsx +55 -0
- package/src/lib/components/flag/flag.list.tsx +788 -0
- package/src/lib/components/flag/flag.test.tsx +65 -0
- package/src/lib/components/flag/flag.tsx +97 -0
- package/src/lib/components/flag/index.tsx +1 -0
- package/src/lib/components/flag/stories/components.tsx +403 -0
- package/src/lib/components/flag/stories/flag.stories.mdx +48 -0
- package/src/lib/components/flag/stories/playGround-select.tsx +145 -0
- package/src/lib/components/icon/icon-list.tsx +135 -0
- package/src/lib/components/icon/icon.test.tsx +48 -0
- package/src/lib/components/icon/icon.tsx +181 -0
- package/src/lib/components/icon/index.tsx +1 -0
- package/src/lib/components/icon/stories/components.tsx +282 -0
- package/src/lib/components/icon/stories/icon.stories.mdx +65 -0
- package/src/lib/components/index.ts +5 -0
- package/src/lib/components/input-field/components/labeled-input.tsx +7 -14
- package/src/lib/components/input-field/components/stepper.tsx +4 -3
- package/src/lib/components/input-field/input-field.test.tsx +5 -6
- package/src/lib/components/input-field/input-field.tsx +8 -8
- package/src/lib/components/input-field/storybook/components.tsx +9 -16
- package/src/lib/components/link/storybook/link.stories.mdx +1 -0
- package/src/lib/components/molecules/avatar/avatar-size-flags.tsx +3 -3
- package/src/lib/components/molecules/avatar/avatar.tsx +2 -2
- package/src/lib/components/molecules/avatar/stories/avatar.stories.mdx +18 -21
- package/src/lib/components/molecules/button/button-flags.tsx +120 -15
- package/src/lib/components/molecules/button/button.test.tsx +9 -9
- package/src/lib/components/molecules/button/button.tsx +61 -78
- package/src/lib/components/molecules/button/stories/button.stories.mdx +43 -42
- package/src/lib/components/molecules/button/stories/components.tsx +6 -8
- package/src/lib/components/molecules/input-checkbox/input-checkbox.tsx +23 -24
- package/src/lib/components/molecules/input-checkbox/stories/components.tsx +32 -15
- package/src/lib/components/molecules/input-checkbox/stories/input-checkbox.stories.mdx +6 -8
- package/src/lib/components/organisms/multi-choice-list/multi-choice-list.tsx +7 -8
- package/src/lib/components/organisms/multi-choice-list/stories/components.tsx +3 -5
- package/src/lib/components/organisms/multi-choice-list/stories/multi-choice-list.stories.mdx +4 -4
- package/src/lib/components/spinner/spinner.test.tsx +2 -2
- package/src/lib/components/spinner/spinner.tsx +15 -28
- package/src/lib/components/spinner/stories/components.tsx +33 -2
- package/src/lib/components/spinner/stories/spinner.stories.mdx +3 -10
- package/src/lib/components/tabs/components/index.ts +1 -0
- package/src/lib/components/tabs/components/tab.tsx +62 -0
- package/src/lib/components/tabs/index.tsx +1 -0
- package/src/lib/components/tabs/storybook/components.tsx +282 -0
- package/src/lib/components/tabs/storybook/tabs.stories.mdx +97 -0
- package/src/lib/components/tabs/tabs.test.tsx +86 -0
- package/src/lib/components/tabs/tabs.tsx +101 -0
- package/src/lib/components/tag/components/close-button.tsx +85 -0
- package/src/lib/components/tag/components/index.ts +2 -0
- package/src/lib/components/tag/components/tag-label.tsx +44 -0
- package/src/lib/components/tag/index.tsx +1 -0
- package/src/lib/components/tag/stories/components.tsx +86 -0
- package/src/lib/components/tag/stories/tag.stories.mdx +42 -0
- package/src/lib/components/tag/tag.test.tsx +36 -0
- package/src/lib/components/tag/tag.tsx +33 -0
- package/src/lib/components/thumbnail/thumbnail.tsx +7 -2
- package/src/lib/components/typography/storybook/components.tsx +47 -15
- package/src/lib/components/typography/storybook/typography.stories.mdx +6 -4
- package/src/lib/components/typography/typography.test.tsx +34 -30
- package/src/lib/components/typography/typography.tsx +61 -19
- package/src/lib/foundations/color-system/base-palette/base-palette.ts +0 -1
- package/src/lib/foundations/color-system/color-guidelines/color-guidelines.ts +5 -4
- package/src/lib/foundations/color-system/components/color-sample.tsx +3 -3
- package/src/lib/foundations/typography/fonts.ts +205 -0
- package/src/lib/foundations/typography/text-aspect-flags.ts +11 -4
- package/src/lib/foundations/typography/typography.tsx +38 -33
- package/src/lib/helpers/numbers.ts +14 -0
- package/src/lib/helpers/safe-navigation.ts +10 -0
- package/src/lib/helpers/slots.test.tsx +98 -0
- package/src/lib/helpers/slots.tsx +93 -12
- package/.storybook/preview-head.html +0 -1
- package/src/lib/components/badge/badge.stories.tsx +0 -16
- package/src/lib/components/checkbox/components/components.tsx +0 -59
- package/src/lib/components/checkbox/stories/index.tsx +0 -1
- package/src/lib/components/molecules/input-checkbox/stories/index.tsx +0 -1
- package/src/lib/components/organisms/multi-choice-list/stories/index.tsx +0 -1
package/.eslintrc.json
CHANGED
|
@@ -33,15 +33,19 @@
|
|
|
33
33
|
"message": "Use `import { forwardRef } from '@helpers'` instead"
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
|
-
"selector": "
|
|
36
|
+
"selector": "ImportDeclaration[source.value=/testing-library/i] ImportSpecifier[imported.name=/fireEvent/]",
|
|
37
|
+
"message": "Prefer `import userEvent from '@testing-library/user-event'` wherever possible.\n@see: https://edvisorio.atlassian.net/wiki/spaces/ENG/pages/235307017/First+contact+with+Testing+Library#Handling-Events"
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"selector": "Literal[value=/[^&]#[a-zA-Z0-9]{1,6}/i]",
|
|
37
41
|
"message": "No hex literals, please import constants from @foundations"
|
|
38
42
|
},
|
|
39
43
|
{
|
|
40
44
|
"selector": "Literal[value=/padding.*: ([0-9]|')/i]",
|
|
41
|
-
"message": "No
|
|
45
|
+
"message": "No string pixel values for css padding, please import Padding from @foundations"
|
|
42
46
|
},
|
|
43
47
|
{
|
|
44
|
-
"selector": "TemplateElement[value.cooked
|
|
48
|
+
"selector": "TemplateElement[value.cooked=/[^&]#[a-zA-Z0-9]{1,6}/i]",
|
|
45
49
|
"message": "No hex literals, please import constants from @foundations"
|
|
46
50
|
},
|
|
47
51
|
{
|
|
@@ -109,15 +113,19 @@
|
|
|
109
113
|
"message": "Use `import { forwardRef } from '@helpers'` instead"
|
|
110
114
|
},
|
|
111
115
|
{
|
|
112
|
-
"selector": "
|
|
116
|
+
"selector": "ImportDeclaration[source.value=/testing-library/i] ImportSpecifier[imported.name=/fireEvent/]",
|
|
117
|
+
"message": "Prefer `import userEvent from '@testing-library/user-event'` wherever possible.\n@see: https://edvisorio.atlassian.net/wiki/spaces/ENG/pages/235307017/First+contact+with+Testing+Library#Handling-Events"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"selector": "Literal[value=/[^&]#[a-zA-Z0-9]{1,6}/i]",
|
|
113
121
|
"message": "No hex literals, please import constants from @foundations"
|
|
114
122
|
},
|
|
115
123
|
{
|
|
116
124
|
"selector": "Literal[value=/padding.*: ([0-9]|')/i]",
|
|
117
|
-
"message": "No
|
|
125
|
+
"message": "No string pixel values for css padding, please import Padding from @foundations"
|
|
118
126
|
},
|
|
119
127
|
{
|
|
120
|
-
"selector": "TemplateElement[value.cooked
|
|
128
|
+
"selector": "TemplateElement[value.cooked=/[^&]#[a-zA-Z0-9]{1,6}/i]",
|
|
121
129
|
"message": "No hex literals, please import constants from @foundations"
|
|
122
130
|
},
|
|
123
131
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@edvisor/product-language",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "Edvisor.io product-language components",
|
|
6
6
|
"repository": "https://github.com/edvisor-io/front-end/",
|
|
@@ -8,8 +8,7 @@
|
|
|
8
8
|
"@types/jest-axe": "^3.5.4"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
|
-
"release": "release-it --disable-metrics"
|
|
12
|
-
"publish": "cd dist/packages/product-language & npm publish"
|
|
11
|
+
"release": "release-it --disable-metrics"
|
|
13
12
|
},
|
|
14
13
|
"peerDependencies": {
|
|
15
14
|
"release": "*"
|
package/project.json
CHANGED
|
@@ -20,14 +20,25 @@
|
|
|
20
20
|
"glob": "packages/product-language/README.md",
|
|
21
21
|
"input": ".",
|
|
22
22
|
"output": "."
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"dev": {
|
|
28
|
+
"executor": "@nrwl/web:rollup",
|
|
29
|
+
"outputs": ["{options.outputPath}"],
|
|
30
|
+
"options": {
|
|
31
|
+
"watch": true,
|
|
32
|
+
"outputPath": "../react-web-client/product-language",
|
|
33
|
+
"tsConfig": "packages/product-language/tsconfig.lib.json",
|
|
34
|
+
"project": "packages/product-language/package.json",
|
|
35
|
+
"entryFile": "packages/product-language/src/index.ts",
|
|
36
|
+
"external": ["react/jsx-runtime"],
|
|
37
|
+
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
|
|
38
|
+
"compiler": "babel",
|
|
39
|
+
"assets": [
|
|
29
40
|
{
|
|
30
|
-
"glob": "packages/product-language
|
|
41
|
+
"glob": "packages/product-language/README.md",
|
|
31
42
|
"input": ".",
|
|
32
43
|
"output": "."
|
|
33
44
|
}
|
package/src/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Directory Structure
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
Manifest Files (index.ts)
|
|
5
|
+
-------------------------
|
|
6
|
+
|
|
7
|
+
RWC, and now product-language, export components to be consumed by another system. Their API is a list of components that they export, and this API is declared in src/index.ts the “root manifest”.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
// src/index.ts
|
|
11
|
+
export * from 'src/components'
|
|
12
|
+
export * from 'src/foundations'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
And then things get… recursive.
|
|
16
|
+
|
|
17
|
+
The “components” directory is a module that exports components to be consumed by another system. It’s API is the list of components it exports, and this API is declared in src/components/index.ts
|
|
18
|
+
|
|
19
|
+
```ts
|
|
20
|
+
// src/components/index.ts
|
|
21
|
+
export * from 'src/components/atoms'
|
|
22
|
+
export * from 'src/components/molecules'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The “molecules” directory is a module that exports components to be consumed by another system. It’s API is the list of components it exports, and this API is declared in src/components/molecules/index.ts
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// src/components/molecules/index.ts
|
|
29
|
+
export * from 'src/components/molecules/button
|
|
30
|
+
export * from 'src/components/molecules/card
|
|
31
|
+
export * from 'src/components/molecules/input-field
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The “button” directory is a module that exports components to be consumed by another system. It’s API is the list of components it exports, and this API is declared in src/components/molecules/button/index.ts
|
|
35
|
+
|
|
36
|
+
This file, this index.ts file is the public API or public interface of the button module. A public interface should only expose public things. Private things should not be exported. So for example:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// src/components/molecules/button/index.ts
|
|
40
|
+
|
|
41
|
+
export * from './stories' // NOPE! this is not public
|
|
42
|
+
export * from './components' // Nope! don't expose implementation details
|
|
43
|
+
|
|
44
|
+
// in most cases, this is all you need
|
|
45
|
+
export * from './Button.tsx'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Within the Button module, we have to be careful to remember that these index files are the public api they are not to be consumed internally. So for example in a storybook file:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
// src/components/molecules/button/stories/button.stories.mdx
|
|
52
|
+
|
|
53
|
+
import { Button } from '../index' // Nope!
|
|
54
|
+
import { Button } from '../Button' // yes!
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Importing from the index file within the module that index file describes is a potential problem, it can cause cyclic dependencies which can be hard to debug.
|
|
58
|
+
|
|
59
|
+
On a similar note: your stories and tests folders don’t need index files at all. They are just there to provide a place to put helpers specific to the stories and tests for the component. They are not modules that export components for other systems to use, so they do not need an index.ts file.
|
|
60
|
+
|
|
61
|
+
On the other hand, the components folder in the Button module should have an index.ts file since it exposes a list of components that Button consumes. Doing this also makes it easier to lift a helper component from the Button module to a shared place if you discover you’ve created a helpful shared component.
|
package/src/helpers/index.ts
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import styled from 'styled-components'
|
|
2
|
+
import { Playground } from 'storybook-addon-jarle-monaco'
|
|
3
|
+
import { Margin, Surface, Text } from '@foundations'
|
|
4
|
+
export { Playground } from 'storybook-addon-jarle-monaco'
|
|
5
|
+
|
|
6
|
+
/** when using playground with a card inside we style it in night mode */
|
|
7
|
+
export const CardPlayground = styled(Playground)`
|
|
8
|
+
background: ${Surface.Neutral.Default};
|
|
9
|
+
|
|
10
|
+
margin-bottom: ${Margin.xxl};
|
|
11
|
+
|
|
12
|
+
> div:nth-of-type(2) {
|
|
13
|
+
background: ${Surface.Default.Inverse};
|
|
14
|
+
color: ${Text.OnPrimary};
|
|
15
|
+
}
|
|
16
|
+
`
|
|
@@ -2,30 +2,21 @@ import styled from 'styled-components'
|
|
|
2
2
|
import { Padding } from '@foundations'
|
|
3
3
|
import { BadgeTypeProps, getColor } from './badge-type-flags'
|
|
4
4
|
import { FC, PropsWithChildren } from '@helpers'
|
|
5
|
-
import {
|
|
5
|
+
import { Label } from 'components/typography'
|
|
6
6
|
|
|
7
|
-
const BadgeFrame = styled
|
|
7
|
+
const BadgeFrame = styled(Label)<{color: string}>`
|
|
8
8
|
background: ${props => props.color};
|
|
9
9
|
display: flex;
|
|
10
|
-
flex-direction: row;
|
|
11
10
|
align-items:center;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
width: fit-content;
|
|
11
|
+
padding: ${Padding.xxxs} ${Padding.xs};
|
|
12
|
+
border-radius:10px;
|
|
13
|
+
height: fit-content;
|
|
16
14
|
`
|
|
17
15
|
|
|
18
16
|
type IBadgeProps = BadgeTypeProps & PropsWithChildren
|
|
19
17
|
|
|
20
|
-
const
|
|
18
|
+
export const Badge: FC<IBadgeProps> = (props) => {
|
|
21
19
|
const color = getColor(props)
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<BadgeFrame color={color}>
|
|
26
|
-
<Label2>{props.children}</Label2>
|
|
27
|
-
</BadgeFrame>
|
|
28
|
-
)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export const Badge = Base
|
|
21
|
+
return <BadgeFrame color={color}>{props.children}</BadgeFrame>
|
|
22
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Badge } from '../badge'
|
|
2
|
+
import { Meta } from '@storybook/addon-docs'
|
|
3
|
+
import { BadgeExample } from './components'
|
|
4
|
+
|
|
5
|
+
<Meta
|
|
6
|
+
title="Components/Badge"
|
|
7
|
+
component={Badge}
|
|
8
|
+
/>
|
|
9
|
+
|
|
10
|
+
# Badge
|
|
11
|
+
|
|
12
|
+
This is an atom.
|
|
13
|
+
|
|
14
|
+
For more details, check out the component page on [Figma](https://www.figma.com/file/ue1CurHfZ426o2T2l8Dk64/Edvisor-Product-Language?node-id=1008%3A1257)
|
|
15
|
+
|
|
16
|
+
## How to use
|
|
17
|
+
|
|
18
|
+
```tsx
|
|
19
|
+
import { Badge } from '@edvisor/product-language'
|
|
20
|
+
|
|
21
|
+
<Badge>Contents</Badge>
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Attitudes
|
|
25
|
+
|
|
26
|
+
The badge can be rendered with various attitudes.
|
|
27
|
+
|
|
28
|
+
<BadgeExample />
|
|
29
|
+
|
|
30
|
+
## API
|
|
31
|
+
|
|
32
|
+
| Name | Type | Description |
|
|
33
|
+
| ----------- | --------- | ------------------------- |
|
|
34
|
+
| `neutral?` | `boolean` | renders the neutral badge |
|
|
35
|
+
| `info?` | `boolean` | renders the info badge |
|
|
36
|
+
| `warning?` | `boolean` | renders the info warning |
|
|
37
|
+
| `success?` | `boolean` | renders the info success |
|
|
38
|
+
| `critical?` | `boolean` | renders the info critical |
|
|
39
|
+
|
|
40
|
+
## Changelog
|
|
41
|
+
|
|
42
|
+
### [0.0.0]
|
|
43
|
+
- adopt the preferred storybook style
|
|
44
|
+
- removed a containing div, adjusted styles to match figma
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Margin } from '@foundations'
|
|
2
|
+
import { Flex } from 'components/layout'
|
|
3
|
+
import { Heading1 } from 'components/typography'
|
|
4
|
+
import { Playground } from 'storybook-addon-jarle-monaco'
|
|
5
|
+
import styled from 'styled-components'
|
|
6
|
+
import { Badge } from '../badge'
|
|
7
|
+
|
|
8
|
+
const Heading = styled(Heading1)`
|
|
9
|
+
margin-bottom: ${Margin.none};
|
|
10
|
+
margin-right: ${Margin.s};
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
const Header = styled(Flex)`
|
|
14
|
+
margin-bottom: ${Margin.l};
|
|
15
|
+
align-items: center;
|
|
16
|
+
`
|
|
17
|
+
|
|
18
|
+
export const BadgeExample = () => (
|
|
19
|
+
<Playground
|
|
20
|
+
code={`
|
|
21
|
+
<>
|
|
22
|
+
<Header>
|
|
23
|
+
<Heading>Booking #1123</Heading>
|
|
24
|
+
<Badge warning>Pending</Badge>
|
|
25
|
+
</Header>
|
|
26
|
+
<Header>
|
|
27
|
+
<Heading>Booking #1124</Heading>
|
|
28
|
+
<Badge success>Accepted</Badge>
|
|
29
|
+
</Header>
|
|
30
|
+
<Header>
|
|
31
|
+
<Heading>Booking #1125</Heading>
|
|
32
|
+
<Badge info>Processing</Badge>
|
|
33
|
+
</Header>
|
|
34
|
+
<Header>
|
|
35
|
+
<Heading>Booking #1126</Heading>
|
|
36
|
+
<Badge critical>Declined</Badge>
|
|
37
|
+
</Header>
|
|
38
|
+
</>
|
|
39
|
+
`}
|
|
40
|
+
providerProps={{
|
|
41
|
+
renderAsComponent: true,
|
|
42
|
+
scope: {
|
|
43
|
+
Badge,
|
|
44
|
+
Heading,
|
|
45
|
+
Header,
|
|
46
|
+
},
|
|
47
|
+
}}
|
|
48
|
+
/>
|
|
49
|
+
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Margin } from '@foundations'
|
|
2
|
-
import {
|
|
2
|
+
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import userEvent from '@testing-library/user-event'
|
|
3
4
|
import styled from 'styled-components'
|
|
4
5
|
|
|
5
6
|
import { Card } from './card'
|
|
@@ -141,7 +142,7 @@ describe('Card', () => {
|
|
|
141
142
|
expect(screen.getByRole('button')).toBeInTheDocument()
|
|
142
143
|
})
|
|
143
144
|
|
|
144
|
-
it('does not stop the user from clicking the controls', () => {
|
|
145
|
+
it('does not stop the user from clicking the controls', async () => {
|
|
145
146
|
const handleClick = jest.fn()
|
|
146
147
|
|
|
147
148
|
render(
|
|
@@ -153,9 +154,7 @@ describe('Card', () => {
|
|
|
153
154
|
</Card>
|
|
154
155
|
)
|
|
155
156
|
|
|
156
|
-
|
|
157
|
-
target: { value: 'JavaScript' },
|
|
158
|
-
})
|
|
157
|
+
await userEvent.click(screen.getByText('Click Me'))
|
|
159
158
|
|
|
160
159
|
expect(handleClick).toHaveBeenCalledTimes(1)
|
|
161
160
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import styled from 'styled-components'
|
|
2
|
-
import { isDefined, isEmpty, getSlots,
|
|
2
|
+
import { isDefined, isEmpty, getSlots, getOtherChildren, FC, PropsWithChildren, If, getSlot, toKebabCase } from '@helpers'
|
|
3
3
|
import { Padding, Margin, shadow } from '@foundations'
|
|
4
4
|
import { CardFrame as CardFrameBase } from './atoms'
|
|
5
5
|
import { Heading3 } from 'components/typography'
|
|
@@ -43,7 +43,7 @@ export const Card: FC<ICardProps, typeof SubComponents> = (props) => {
|
|
|
43
43
|
const controls = getSlot(CardControlsSlot, children)
|
|
44
44
|
const headingAction = getSlot(CardHeadingActionSlot, children)
|
|
45
45
|
const alertBanners = getSlots(CardAlertBannerSlot, children)
|
|
46
|
-
const otherChildren =
|
|
46
|
+
const otherChildren = getOtherChildren(children)
|
|
47
47
|
|
|
48
48
|
const headingId = isDefined(heading)
|
|
49
49
|
? toKebabCase(heading)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { HTMLAttributes } from 'react'
|
|
2
2
|
import styled from 'styled-components'
|
|
3
|
-
import { isDefined, Slot,
|
|
3
|
+
import { isDefined, Slot, getOtherChildren, PropsWithChildren, If, getSlot, toKebabCase } from '@helpers'
|
|
4
4
|
import { Borders, Padding, Margin } from '@foundations'
|
|
5
5
|
import { Heading4 } from 'components/typography'
|
|
6
6
|
import { SpaceBetween } from 'components/layout'
|
|
@@ -28,7 +28,7 @@ const SubheadingFrame = styled(SpaceBetween)`
|
|
|
28
28
|
export class CardSectionSlot extends Slot<ICardSectionProps> {
|
|
29
29
|
override render () {
|
|
30
30
|
const headingAction = getSlot(CardHeadingActionSlot, this.props.children)
|
|
31
|
-
const children =
|
|
31
|
+
const children = getOtherChildren(this.props.children)
|
|
32
32
|
const headingId = isDefined(this.props.heading)
|
|
33
33
|
? toKebabCase(this.props.heading)
|
|
34
34
|
: undefined
|
|
@@ -42,7 +42,7 @@ You can divide a card's body up into sections.
|
|
|
42
42
|
Any heading in a Card can have an action
|
|
43
43
|
|
|
44
44
|
<AlertBanner warning>
|
|
45
|
-
HeadingAction is a
|
|
45
|
+
HeadingAction is a slot, so its children will always render in the same place regardless of where you use it.
|
|
46
46
|
</AlertBanner>
|
|
47
47
|
|
|
48
48
|
<SectionsHeadingActionsExample />
|
|
@@ -1,43 +1,26 @@
|
|
|
1
1
|
import styled from 'styled-components'
|
|
2
|
-
|
|
3
|
-
import {
|
|
2
|
+
|
|
3
|
+
import { Surface } from '@foundations'
|
|
4
|
+
import { CardPlayground } from '@stories'
|
|
5
|
+
|
|
4
6
|
import { leftRightLayoutGenerator } from 'components/layout'
|
|
5
7
|
import { Body, Heading3 } from 'components/typography'
|
|
6
|
-
import { Divider } from 'components/divider'
|
|
7
|
-
import { Card } from '../card'
|
|
8
|
-
import { LeftRightCard } from '../molecules/left-right-card'
|
|
9
8
|
import { InputField } from 'components/input-field'
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
margin-bottom: ${Margin.xxl};
|
|
15
|
-
|
|
16
|
-
> div:nth-of-type(2) {
|
|
17
|
-
background: ${Surface.Default.Inverse}; // Surface.Inverse
|
|
18
|
-
color: ${Text.OnPrimary};
|
|
19
|
-
}
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
const Bar = styled(Divider)`
|
|
23
|
-
margin-bottom: ${Margin.l};
|
|
24
|
-
margin-top: ${Margin.l};
|
|
25
|
-
`
|
|
10
|
+
import { Card } from '../card'
|
|
11
|
+
import { LeftRightCard } from '../molecules/left-right-card'
|
|
26
12
|
|
|
27
13
|
export const CardExample = () => (
|
|
28
14
|
<CardPlayground
|
|
29
15
|
code={`
|
|
30
16
|
<Card heading='Heading'>
|
|
31
17
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
32
|
-
<Bar />
|
|
33
|
-
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
34
18
|
</Card>
|
|
35
19
|
`}
|
|
36
20
|
providerProps={{
|
|
37
21
|
renderAsComponent: true,
|
|
38
22
|
scope: {
|
|
39
23
|
Card,
|
|
40
|
-
Bar,
|
|
41
24
|
},
|
|
42
25
|
}}
|
|
43
26
|
/>
|
|
@@ -1,124 +1,63 @@
|
|
|
1
|
-
import { InputHTMLAttributes
|
|
2
|
-
import styled
|
|
3
|
-
import {
|
|
4
|
-
import { FC, is
|
|
1
|
+
import { InputHTMLAttributes } from 'react'
|
|
2
|
+
import styled from 'styled-components'
|
|
3
|
+
import { Margin, Padding, Focused } from '@foundations'
|
|
4
|
+
import { FC, is } from '@helpers'
|
|
5
5
|
import {
|
|
6
|
-
getHoverStyles,
|
|
7
6
|
getDisabledStyles,
|
|
8
7
|
getInvalidStyles,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
HiddenCheckbox,
|
|
12
|
-
Icon,
|
|
13
|
-
Wrapper,
|
|
14
|
-
} from './components/components'
|
|
8
|
+
getDefaultStyles,
|
|
9
|
+
} from './helpers'
|
|
15
10
|
|
|
16
|
-
const CustomizedCheckbox = styled.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}>`
|
|
21
|
-
display: inline-block;
|
|
11
|
+
const CustomizedCheckbox = styled.input<{ error?: boolean }>`
|
|
12
|
+
appearance: none;
|
|
13
|
+
position: relative;
|
|
14
|
+
box-sizing: content-box;
|
|
22
15
|
width: 18px;
|
|
23
16
|
height: 18px;
|
|
24
17
|
margin: ${Margin.none};
|
|
25
18
|
padding: ${Padding.none};
|
|
26
19
|
border-radius: 4px;
|
|
20
|
+
user-select: none;
|
|
21
|
+
vertical-align: bottom;
|
|
22
|
+
display: inline-block;
|
|
27
23
|
|
|
28
|
-
${
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
: css`
|
|
38
|
-
background: ${Surface.Default.Default};
|
|
39
|
-
border: 2px solid ${Interactive.Default.Disabled};
|
|
40
|
-
&:hover {
|
|
41
|
-
${getHoverStyles}
|
|
42
|
-
}
|
|
43
|
-
`
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
${props => is(props.disabled) ? getDisabledStyles() : ''}
|
|
47
|
-
${props => is(props.error)
|
|
48
|
-
? css`
|
|
49
|
-
${getInvalidStyles()}
|
|
50
|
-
&:hover {
|
|
51
|
-
background: ${({ checked }) => (is(checked)
|
|
52
|
-
? `${Actions.Critical.Pressed}`
|
|
53
|
-
: `${Surface.Default.Default}`
|
|
54
|
-
)};
|
|
55
|
-
border: 2px solid ${Borders.Critical.Default};
|
|
56
|
-
}
|
|
57
|
-
${HiddenCheckbox}:invalid {
|
|
58
|
-
${getInvalidStyles()}
|
|
59
|
-
}
|
|
60
|
-
`
|
|
61
|
-
: ''
|
|
62
|
-
}
|
|
24
|
+
${({ disabled, error }) => {
|
|
25
|
+
if (is(disabled)) {
|
|
26
|
+
return getDisabledStyles()
|
|
27
|
+
} else if (is(error)) {
|
|
28
|
+
return getInvalidStyles()
|
|
29
|
+
} else {
|
|
30
|
+
return getDefaultStyles()
|
|
31
|
+
}
|
|
32
|
+
}}
|
|
63
33
|
|
|
64
|
-
|
|
34
|
+
:focus-visible {
|
|
65
35
|
outline: 2px solid ${Focused.Default};
|
|
66
36
|
outline-offset: 1px;
|
|
67
37
|
}
|
|
68
|
-
${Icon} {
|
|
69
|
-
visibility: ${(props) => (is(props.checked) ? 'visible' : 'hidden')};
|
|
70
|
-
}
|
|
71
38
|
`
|
|
72
39
|
|
|
73
40
|
export interface ICheckboxProps {
|
|
74
|
-
disabled?: boolean
|
|
75
|
-
checked?: boolean
|
|
76
|
-
error?: boolean
|
|
77
|
-
className?: string
|
|
78
|
-
onChange?: (value: boolean) => void;
|
|
41
|
+
disabled?: boolean
|
|
42
|
+
checked?: boolean
|
|
43
|
+
error?: boolean
|
|
44
|
+
className?: string
|
|
79
45
|
}
|
|
80
46
|
|
|
81
47
|
export type IProps = ICheckboxProps & InputHTMLAttributes<HTMLInputElement>
|
|
82
48
|
|
|
83
49
|
export const Checkbox: FC<IProps> = (props: IProps) => {
|
|
84
50
|
const {
|
|
85
|
-
className,
|
|
86
|
-
onChange,
|
|
87
|
-
disabled = false,
|
|
88
51
|
error = false,
|
|
89
|
-
|
|
52
|
+
...htmlProps
|
|
90
53
|
} = props
|
|
91
|
-
const [isChecked, setIsChecked] = useState<boolean>(checked)
|
|
92
|
-
const handleOnChange = () => {
|
|
93
|
-
const newCheckedValue = !isChecked
|
|
94
|
-
setIsChecked(newCheckedValue)
|
|
95
|
-
if(isDefined(onChange)){
|
|
96
|
-
onChange(newCheckedValue)
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
54
|
|
|
100
55
|
return (
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
checked={isChecked}
|
|
108
|
-
disabled={disabled}
|
|
109
|
-
onChange={handleOnChange}
|
|
110
|
-
type='checkbox'
|
|
111
|
-
/>
|
|
112
|
-
<CustomizedCheckbox
|
|
113
|
-
{...props}
|
|
114
|
-
data-testid='checkbox-id'
|
|
115
|
-
checked={isChecked}
|
|
116
|
-
disabled={disabled}
|
|
117
|
-
error={error}
|
|
118
|
-
onClick={handleOnChange}
|
|
119
|
-
>
|
|
120
|
-
{getCheckedIcon()}
|
|
121
|
-
</CustomizedCheckbox>
|
|
122
|
-
</Wrapper>
|
|
56
|
+
<CustomizedCheckbox
|
|
57
|
+
{...htmlProps}
|
|
58
|
+
|
|
59
|
+
type='checkbox'
|
|
60
|
+
error={error}
|
|
61
|
+
/>
|
|
123
62
|
)
|
|
124
63
|
}
|