@transferwise/components 46.150.0 → 46.151.1
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/build/main.css +155 -12
- package/build/styles/css/neptune.css +0 -11
- package/build/styles/main.css +155 -12
- package/build/styles/pocketSurface/PocketSurface.css +163 -0
- package/build/styles/sentimentSurface/SentimentSurface.css +0 -1
- package/build/styles/styles/less/neptune.css +0 -11
- package/build/types/index.d.ts +1 -1
- package/build/types/index.d.ts.map +1 -1
- package/build/types/pocketSurface/PocketSurface.d.ts +4 -0
- package/build/types/pocketSurface/PocketSurface.d.ts.map +1 -0
- package/build/types/pocketSurface/PocketSurface.types.d.ts +19 -0
- package/build/types/pocketSurface/PocketSurface.types.d.ts.map +1 -0
- package/build/types/pocketSurface/index.d.ts +3 -0
- package/build/types/pocketSurface/index.d.ts.map +1 -0
- package/package.json +6 -4
- package/src/index.ts +2 -0
- package/src/main.css +155 -12
- package/src/main.less +1 -0
- package/src/pocketSurface/PocketSurface.css +163 -0
- package/src/pocketSurface/PocketSurface.docs.mdx +64 -0
- package/src/pocketSurface/PocketSurface.less +6 -0
- package/src/pocketSurface/PocketSurface.story.tsx +278 -0
- package/src/pocketSurface/PocketSurface.test.tsx +107 -0
- package/src/pocketSurface/PocketSurface.tsx +41 -0
- package/src/pocketSurface/PocketSurface.types.ts +37 -0
- package/src/pocketSurface/index.ts +7 -0
- package/src/sentimentSurface/SentimentSurface.css +0 -1
- package/src/styles/less/neptune.css +0 -11
- package/src/tokens/tokens.story.tsx +0 -142
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Do not edit directly, this file was auto-generated.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
.wds-pocket-bright-blue {
|
|
7
|
+
--color-content-primary: #21231d;
|
|
8
|
+
--color-content-secondary: #0d0e0c;
|
|
9
|
+
--color-content-link: #21231d;
|
|
10
|
+
--color-content-link-hover: #354040;
|
|
11
|
+
--color-content-link-active: #4c5c5c;
|
|
12
|
+
--color-interactive-primary: #21231d;
|
|
13
|
+
--color-interactive-primary-hover: #354040;
|
|
14
|
+
--color-interactive-primary-active: #4c5c5c;
|
|
15
|
+
--color-interactive-accent: #21231d;
|
|
16
|
+
--color-interactive-accent-hover: #354040;
|
|
17
|
+
--color-interactive-accent-active: #4c5c5c;
|
|
18
|
+
--color-interactive-control: #a0e1e1;
|
|
19
|
+
--color-interactive-control-hover: #c5eded;
|
|
20
|
+
--color-interactive-control-active: #c5eded;
|
|
21
|
+
--color-background-screen: #a0e1e1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
.wds-pocket-bright-orange {
|
|
26
|
+
--color-content-primary: #260a2f;
|
|
27
|
+
--color-content-secondary: #110415;
|
|
28
|
+
--color-content-link: #260a2f;
|
|
29
|
+
--color-content-link-hover: #360e43;
|
|
30
|
+
--color-content-link-active: #471358;
|
|
31
|
+
--color-interactive-primary: #260a2f;
|
|
32
|
+
--color-interactive-primary-hover: #360e43;
|
|
33
|
+
--color-interactive-primary-active: #471358;
|
|
34
|
+
--color-interactive-accent: #260a2f;
|
|
35
|
+
--color-interactive-accent-hover: #360e43;
|
|
36
|
+
--color-interactive-accent-active: #471358;
|
|
37
|
+
--color-interactive-control: #ffc091;
|
|
38
|
+
--color-interactive-control-hover: #ffcda8;
|
|
39
|
+
--color-interactive-control-active: #ffdcc2;
|
|
40
|
+
--color-background-screen: #ffc091;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
.wds-pocket-bright-pink {
|
|
45
|
+
--color-content-primary: #320707;
|
|
46
|
+
--color-content-secondary: #160303;
|
|
47
|
+
--color-content-link: #320707;
|
|
48
|
+
--color-content-link-hover: #1f0404;
|
|
49
|
+
--color-content-link-active: #0d0202;
|
|
50
|
+
--color-interactive-primary: #320707;
|
|
51
|
+
--color-interactive-primary-hover: #1f0404;
|
|
52
|
+
--color-interactive-primary-active: #0d0202;
|
|
53
|
+
--color-interactive-accent: #320707;
|
|
54
|
+
--color-interactive-accent-hover: #1f0404;
|
|
55
|
+
--color-interactive-accent-active: #0d0202;
|
|
56
|
+
--color-interactive-control: #ffd7ef;
|
|
57
|
+
--color-interactive-control-hover: #ffbde4;
|
|
58
|
+
--color-interactive-control-active: #ffbde4;
|
|
59
|
+
--color-background-screen: #ffd7ef;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
.wds-pocket-bright-yellow {
|
|
64
|
+
--color-content-primary: #3a341c;
|
|
65
|
+
--color-content-secondary: #110f08;
|
|
66
|
+
--color-content-link: #3a341c;
|
|
67
|
+
--color-content-link-hover: #1b190d;
|
|
68
|
+
--color-content-link-active: #0a0a05;
|
|
69
|
+
--color-interactive-primary: #3a341c;
|
|
70
|
+
--color-interactive-primary-hover: #1b190d;
|
|
71
|
+
--color-interactive-primary-active: #0a0a05;
|
|
72
|
+
--color-interactive-accent: #3a341c;
|
|
73
|
+
--color-interactive-accent-hover: #1b190d;
|
|
74
|
+
--color-interactive-accent-active: #0a0a05;
|
|
75
|
+
--color-interactive-control: #ffeb69;
|
|
76
|
+
--color-interactive-control-hover: #ffef85;
|
|
77
|
+
--color-interactive-control-active: #fff29e;
|
|
78
|
+
--color-background-screen: #ffeb69;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
.wds-pocket-dark-charcoal {
|
|
83
|
+
--color-content-primary: #a0e1e1;
|
|
84
|
+
--color-content-secondary: #ecf9f9;
|
|
85
|
+
--color-content-link: #a0e1e1;
|
|
86
|
+
--color-content-link-hover: #77d4d4;
|
|
87
|
+
--color-content-link-active: #51c8c8;
|
|
88
|
+
--color-interactive-primary: #a0e1e1;
|
|
89
|
+
--color-interactive-primary-hover: #77d4d4;
|
|
90
|
+
--color-interactive-primary-active: #51c8c8;
|
|
91
|
+
--color-interactive-accent: #a0e1e1;
|
|
92
|
+
--color-interactive-accent-hover: #77d4d4;
|
|
93
|
+
--color-interactive-accent-active: #51c8c8;
|
|
94
|
+
--color-interactive-control: #21231d;
|
|
95
|
+
--color-interactive-control-hover: #181915;
|
|
96
|
+
--color-interactive-control-active: #0d0e0c;
|
|
97
|
+
--color-background-screen: #21231d;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
.wds-pocket-dark-gold {
|
|
102
|
+
--color-content-primary: #ffeb69;
|
|
103
|
+
--color-content-secondary: #fffce5;
|
|
104
|
+
--color-content-link: #ffeb69;
|
|
105
|
+
--color-content-link-hover: #ffe538;
|
|
106
|
+
--color-content-link-active: #ffde05;
|
|
107
|
+
--color-interactive-primary: #ffeb69;
|
|
108
|
+
--color-interactive-primary-hover: #ffe538;
|
|
109
|
+
--color-interactive-primary-active: #ffde05;
|
|
110
|
+
--color-interactive-accent: #ffeb69;
|
|
111
|
+
--color-interactive-accent-hover: #ffe538;
|
|
112
|
+
--color-interactive-accent-active: #ffde05;
|
|
113
|
+
--color-interactive-control: #3a341c;
|
|
114
|
+
--color-interactive-control-hover: #292514;
|
|
115
|
+
--color-interactive-control-active: #18160c;
|
|
116
|
+
--color-background-screen: #3a341c;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
.wds-pocket-dark-maroon {
|
|
121
|
+
--color-content-primary: #ffd7ef;
|
|
122
|
+
--color-content-secondary: #ffe5f5;
|
|
123
|
+
--color-content-link: #ffd7ef;
|
|
124
|
+
--color-content-link-hover: #ffe5f5;
|
|
125
|
+
--color-content-link-active: #fff5fb;
|
|
126
|
+
--color-interactive-primary: #ffd7ef;
|
|
127
|
+
--color-interactive-primary-hover: #ffe5f5;
|
|
128
|
+
--color-interactive-primary-active: #fff5fb;
|
|
129
|
+
--color-interactive-accent: #ffd7ef;
|
|
130
|
+
--color-interactive-accent-hover: #ffe5f5;
|
|
131
|
+
--color-interactive-accent-active: #fff5fb;
|
|
132
|
+
--color-interactive-control: #320707;
|
|
133
|
+
--color-interactive-control-hover: #480a0a;
|
|
134
|
+
--color-interactive-control-active: #5e0d0d;
|
|
135
|
+
--color-background-screen: #320707;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
.wds-pocket-dark-purple {
|
|
140
|
+
--color-content-primary: #ffc091;
|
|
141
|
+
--color-content-secondary: #fff0e5;
|
|
142
|
+
--color-content-link: #ffc091;
|
|
143
|
+
--color-content-link-hover: #ffdcc2;
|
|
144
|
+
--color-content-link-active: #fff9f5;
|
|
145
|
+
--color-interactive-primary: #ffc091;
|
|
146
|
+
--color-interactive-primary-hover: #ffdcc2;
|
|
147
|
+
--color-interactive-primary-active: #fff9f5;
|
|
148
|
+
--color-interactive-accent: #ffc091;
|
|
149
|
+
--color-interactive-accent-hover: #ffdcc2;
|
|
150
|
+
--color-interactive-accent-active: #fff9f5;
|
|
151
|
+
--color-interactive-control: #260a2f;
|
|
152
|
+
--color-interactive-control-hover: #360e43;
|
|
153
|
+
--color-interactive-control-active: #471358;
|
|
154
|
+
--color-background-screen: #260a2f;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
.wds-pocket-surface {
|
|
159
|
+
background-color: #ffffff;
|
|
160
|
+
background-color: var(--color-background-screen);
|
|
161
|
+
color: #37517e;
|
|
162
|
+
color: var(--color-content-primary);
|
|
163
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { Meta, Canvas } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as stories from './PocketSurface.story';
|
|
3
|
+
|
|
4
|
+
<Meta title="Internal/PocketSurface/Developer Guide" />
|
|
5
|
+
|
|
6
|
+
# PocketSurface
|
|
7
|
+
|
|
8
|
+
<div
|
|
9
|
+
style={{
|
|
10
|
+
backgroundColor: '#fff3cd',
|
|
11
|
+
border: '1px solid #ffb800',
|
|
12
|
+
borderRadius: '8px',
|
|
13
|
+
padding: '16px 20px',
|
|
14
|
+
marginBottom: '24px',
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
<strong>⚠️ Use under extrict design guidelines</strong>
|
|
18
|
+
<p style={{ margin: '8px 0 0' }}>
|
|
19
|
+
This component is <strong>not exposed in Figma</strong> and is
|
|
20
|
+
<strong>not intended for free use by product teams</strong>. It has strict design directions and
|
|
21
|
+
must only be used within approved Pocket-themed surfaces.
|
|
22
|
+
</p>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
`PocketSurface` is a polymorphic container that scopes pocket design tokens as CSS custom properties
|
|
26
|
+
and applies background and text colours for the selected pocket palette variant.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
import PocketSurface from '@transferwise/components/pocketSurface';
|
|
32
|
+
|
|
33
|
+
<PocketSurface pocket="dark-gold">
|
|
34
|
+
<p>Content inherits pocket palette colours</p>
|
|
35
|
+
</PocketSurface>;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Available Tokens
|
|
39
|
+
|
|
40
|
+
Each `PocketSurface` exposes the following CSS custom properties scoped to its variant:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
--color-content-primary
|
|
44
|
+
--color-content-secondary
|
|
45
|
+
--color-content-link
|
|
46
|
+
--color-content-link-hover
|
|
47
|
+
--color-content-link-active
|
|
48
|
+
|
|
49
|
+
--color-interactive-primary
|
|
50
|
+
--color-interactive-primary-hover
|
|
51
|
+
--color-interactive-primary-active
|
|
52
|
+
--color-interactive-accent
|
|
53
|
+
--color-interactive-accent-hover
|
|
54
|
+
--color-interactive-accent-active
|
|
55
|
+
--color-interactive-control
|
|
56
|
+
--color-interactive-control-hover
|
|
57
|
+
--color-interactive-control-active
|
|
58
|
+
|
|
59
|
+
--color-background-screen
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Variants
|
|
63
|
+
|
|
64
|
+
<Canvas of={stories.Variants} />
|
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
|
+
import { createSandboxStory, globalScope } from '../../.storybook/components/sandbox/SandboxEditor';
|
|
3
|
+
import Button from '../button';
|
|
4
|
+
import Link from '../link';
|
|
5
|
+
import PocketSurface from './PocketSurface';
|
|
6
|
+
import type { PocketVariant } from './PocketSurface.types';
|
|
7
|
+
|
|
8
|
+
const PocketCard = ({ variant }: { variant?: PocketVariant } = {}) => (
|
|
9
|
+
<div className="p-a-2 d-flex flex-column" style={{ gap: '0.75rem', maxWidth: '280px' }}>
|
|
10
|
+
{variant && (
|
|
11
|
+
<span
|
|
12
|
+
style={{
|
|
13
|
+
fontSize: '11px',
|
|
14
|
+
opacity: 0.7,
|
|
15
|
+
textTransform: 'uppercase',
|
|
16
|
+
letterSpacing: '0.5px',
|
|
17
|
+
}}
|
|
18
|
+
>
|
|
19
|
+
{variant}
|
|
20
|
+
</span>
|
|
21
|
+
)}
|
|
22
|
+
<strong className="np-text-title-screen" style={{ color: 'inherit' }}>
|
|
23
|
+
Some headline text
|
|
24
|
+
</strong>
|
|
25
|
+
<p style={{ margin: 0 }}>A bit of body copy</p>
|
|
26
|
+
<div className="d-flex" style={{ gap: '0.5rem', flexWrap: 'wrap' }}>
|
|
27
|
+
<Button v2 priority="primary" size="sm">
|
|
28
|
+
Primary
|
|
29
|
+
</Button>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* ⚠️ This component is not exposed in Figma and is not intended for use by product teams freely.
|
|
36
|
+
*
|
|
37
|
+
* PocketSurface is a polymorphic container component that scopes pocket design tokens
|
|
38
|
+
* as CSS custom properties and applies background and text colours for the selected
|
|
39
|
+
* pocket palette variant.
|
|
40
|
+
*/
|
|
41
|
+
const meta: Meta<typeof PocketSurface> = {
|
|
42
|
+
component: PocketSurface,
|
|
43
|
+
title: 'Internal/PocketSurface',
|
|
44
|
+
tags: ['early-access'],
|
|
45
|
+
argTypes: {
|
|
46
|
+
pocket: {
|
|
47
|
+
control: 'select',
|
|
48
|
+
options: [
|
|
49
|
+
'bright-blue',
|
|
50
|
+
'bright-orange',
|
|
51
|
+
'bright-pink',
|
|
52
|
+
'bright-yellow',
|
|
53
|
+
'dark-charcoal',
|
|
54
|
+
'dark-gold',
|
|
55
|
+
'dark-maroon',
|
|
56
|
+
'dark-purple',
|
|
57
|
+
],
|
|
58
|
+
description: 'The pocket palette variant that determines the colour scheme',
|
|
59
|
+
table: {
|
|
60
|
+
type: { summary: 'PocketVariant' },
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
as: {
|
|
64
|
+
control: 'text',
|
|
65
|
+
description: 'The underlying HTML element to render.',
|
|
66
|
+
table: {
|
|
67
|
+
defaultValue: { summary: '"div"' },
|
|
68
|
+
type: { summary: 'string' },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
className: {
|
|
72
|
+
table: { type: { summary: 'string' } },
|
|
73
|
+
control: 'text',
|
|
74
|
+
},
|
|
75
|
+
id: {
|
|
76
|
+
table: { type: { summary: 'string' } },
|
|
77
|
+
control: 'text',
|
|
78
|
+
},
|
|
79
|
+
'data-testid': {
|
|
80
|
+
control: 'text',
|
|
81
|
+
table: { type: { summary: 'string' } },
|
|
82
|
+
},
|
|
83
|
+
children: {
|
|
84
|
+
table: { type: { summary: 'ReactNode' } },
|
|
85
|
+
control: false,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
args: {
|
|
89
|
+
pocket: 'bright-blue',
|
|
90
|
+
as: undefined,
|
|
91
|
+
className: undefined,
|
|
92
|
+
id: undefined,
|
|
93
|
+
'data-testid': undefined,
|
|
94
|
+
children: 'This is a pocket surface',
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export default meta;
|
|
99
|
+
|
|
100
|
+
type Story = StoryObj<typeof PocketSurface>;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The Playground story allows you to experiment with all the props of the PocketSurface component.
|
|
104
|
+
* Use the controls below to customise the pocket variant and content.
|
|
105
|
+
*/
|
|
106
|
+
export const Playground: Story = {
|
|
107
|
+
args: {
|
|
108
|
+
pocket: 'bright-blue',
|
|
109
|
+
children: <PocketCard />,
|
|
110
|
+
},
|
|
111
|
+
parameters: {
|
|
112
|
+
docs: {
|
|
113
|
+
source: {
|
|
114
|
+
code: `<PocketSurface pocket="bright-blue">
|
|
115
|
+
<p>Content that inherits pocket palette colours</p>
|
|
116
|
+
<Button v2 priority="primary" size="sm">Primary</Button>
|
|
117
|
+
</PocketSurface>`,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export const Sandbox = createSandboxStory({
|
|
124
|
+
code: `<PocketSurface pocket="dark-gold" className="p-a-2">
|
|
125
|
+
<p>
|
|
126
|
+
This text and its <Link href="#">inline links</Link> use pocket-matched colour.
|
|
127
|
+
</p>
|
|
128
|
+
<Button v2 size="sm">Primary</Button>
|
|
129
|
+
</PocketSurface>`,
|
|
130
|
+
scope: { ...globalScope, Link, PocketSurface },
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const variants: PocketVariant[] = [
|
|
134
|
+
'bright-blue',
|
|
135
|
+
'bright-orange',
|
|
136
|
+
'bright-pink',
|
|
137
|
+
'bright-yellow',
|
|
138
|
+
'dark-charcoal',
|
|
139
|
+
'dark-gold',
|
|
140
|
+
'dark-maroon',
|
|
141
|
+
'dark-purple',
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* All 8 pocket palette variants, each applying its own background and text colours via
|
|
146
|
+
* CSS custom properties scoped to the `.wds-pocket-{variant}` class.
|
|
147
|
+
*/
|
|
148
|
+
export const Variants: Story = {
|
|
149
|
+
render: () => (
|
|
150
|
+
<div
|
|
151
|
+
style={{
|
|
152
|
+
display: 'grid',
|
|
153
|
+
gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))',
|
|
154
|
+
gap: '1rem',
|
|
155
|
+
width: '100%',
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
{variants.map((variant) => (
|
|
159
|
+
<PocketSurface key={variant} pocket={variant}>
|
|
160
|
+
<PocketCard variant={variant} />
|
|
161
|
+
</PocketSurface>
|
|
162
|
+
))}
|
|
163
|
+
</div>
|
|
164
|
+
),
|
|
165
|
+
parameters: {
|
|
166
|
+
controls: { disable: true },
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const tokenCategories = [
|
|
171
|
+
{
|
|
172
|
+
name: 'Content',
|
|
173
|
+
tokens: [
|
|
174
|
+
'--color-content-primary',
|
|
175
|
+
'--color-content-secondary',
|
|
176
|
+
'--color-content-link',
|
|
177
|
+
'--color-content-link-hover',
|
|
178
|
+
'--color-content-link-active',
|
|
179
|
+
],
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
name: 'Interactive',
|
|
183
|
+
tokens: [
|
|
184
|
+
'--color-interactive-primary',
|
|
185
|
+
'--color-interactive-primary-hover',
|
|
186
|
+
'--color-interactive-primary-active',
|
|
187
|
+
'--color-interactive-accent',
|
|
188
|
+
'--color-interactive-accent-hover',
|
|
189
|
+
'--color-interactive-accent-active',
|
|
190
|
+
'--color-interactive-control',
|
|
191
|
+
'--color-interactive-control-hover',
|
|
192
|
+
'--color-interactive-control-active',
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
name: 'Background',
|
|
197
|
+
tokens: ['--color-background-screen'],
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
const TokenSwatch = ({ token }: { token: string }) => (
|
|
202
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '12px', marginBottom: '4px' }}>
|
|
203
|
+
<div
|
|
204
|
+
style={{
|
|
205
|
+
width: '32px',
|
|
206
|
+
height: '32px',
|
|
207
|
+
borderRadius: '4px',
|
|
208
|
+
backgroundColor: `var(${token})`,
|
|
209
|
+
border: '1px solid rgba(0,0,0,0.1)',
|
|
210
|
+
flexShrink: 0,
|
|
211
|
+
}}
|
|
212
|
+
/>
|
|
213
|
+
<code style={{ fontSize: '12px', color: 'var(--color-content-primary)' }}>{token}</code>
|
|
214
|
+
</div>
|
|
215
|
+
);
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* All exposed CSS custom properties for each pocket variant.
|
|
219
|
+
*/
|
|
220
|
+
export const ExposedTokens: Story = {
|
|
221
|
+
render: () => (
|
|
222
|
+
<section style={{ display: 'flex', flexDirection: 'column', gap: '32px', maxWidth: '100%' }}>
|
|
223
|
+
{variants.map((variant) => (
|
|
224
|
+
<PocketSurface key={variant} pocket={variant}>
|
|
225
|
+
<div className="p-a-3">
|
|
226
|
+
<h4
|
|
227
|
+
className="d-block m-b-2 text-capitalize np-text-title-body"
|
|
228
|
+
style={{ color: 'inherit' }}
|
|
229
|
+
>
|
|
230
|
+
{variant}
|
|
231
|
+
</h4>
|
|
232
|
+
<div
|
|
233
|
+
style={{
|
|
234
|
+
display: 'grid',
|
|
235
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
|
|
236
|
+
gap: '24px',
|
|
237
|
+
}}
|
|
238
|
+
>
|
|
239
|
+
{tokenCategories.map((category) => (
|
|
240
|
+
<div key={category.name}>
|
|
241
|
+
<h5
|
|
242
|
+
style={{
|
|
243
|
+
color: 'inherit',
|
|
244
|
+
fontSize: '12px',
|
|
245
|
+
fontWeight: 600,
|
|
246
|
+
marginBottom: '8px',
|
|
247
|
+
textTransform: 'uppercase',
|
|
248
|
+
letterSpacing: '0.5px',
|
|
249
|
+
opacity: 0.8,
|
|
250
|
+
}}
|
|
251
|
+
>
|
|
252
|
+
{category.name}
|
|
253
|
+
</h5>
|
|
254
|
+
{category.tokens.map((token) => (
|
|
255
|
+
<TokenSwatch key={token} token={token} />
|
|
256
|
+
))}
|
|
257
|
+
</div>
|
|
258
|
+
))}
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</PocketSurface>
|
|
262
|
+
))}
|
|
263
|
+
</section>
|
|
264
|
+
),
|
|
265
|
+
parameters: {
|
|
266
|
+
controls: { disable: true },
|
|
267
|
+
docs: {
|
|
268
|
+
canvas: { sourceState: 'hidden' },
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
decorators: [
|
|
272
|
+
(Story: () => JSX.Element) => (
|
|
273
|
+
<div style={{ padding: '2rem', maxWidth: '1200px' }}>
|
|
274
|
+
<Story />
|
|
275
|
+
</div>
|
|
276
|
+
),
|
|
277
|
+
],
|
|
278
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { render, screen } from '../test-utils';
|
|
2
|
+
import PocketSurface from './PocketSurface';
|
|
3
|
+
import { PocketVariant } from './PocketSurface.types';
|
|
4
|
+
|
|
5
|
+
describe('PocketSurface', () => {
|
|
6
|
+
const testContent = 'Test content';
|
|
7
|
+
|
|
8
|
+
describe('rendering', () => {
|
|
9
|
+
it('renders with children', () => {
|
|
10
|
+
render(<PocketSurface pocket="bright-blue">{testContent}</PocketSurface>);
|
|
11
|
+
expect(screen.getByText(testContent)).toBeInTheDocument();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('renders as div by default', () => {
|
|
15
|
+
render(
|
|
16
|
+
<PocketSurface pocket="bright-blue" data-testid="surface">
|
|
17
|
+
{testContent}
|
|
18
|
+
</PocketSurface>,
|
|
19
|
+
);
|
|
20
|
+
expect(screen.getByTestId('surface').tagName).toBe('DIV');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders as custom element when as prop is provided', () => {
|
|
24
|
+
render(
|
|
25
|
+
<PocketSurface pocket="bright-blue" as="section" data-testid="surface">
|
|
26
|
+
{testContent}
|
|
27
|
+
</PocketSurface>,
|
|
28
|
+
);
|
|
29
|
+
expect(screen.getByTestId('surface').tagName).toBe('SECTION');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('pocket variants', () => {
|
|
34
|
+
const variants: PocketVariant[] = [
|
|
35
|
+
'bright-blue',
|
|
36
|
+
'bright-orange',
|
|
37
|
+
'bright-pink',
|
|
38
|
+
'bright-yellow',
|
|
39
|
+
'dark-charcoal',
|
|
40
|
+
'dark-gold',
|
|
41
|
+
'dark-maroon',
|
|
42
|
+
'dark-purple',
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
variants.forEach((variant) => {
|
|
46
|
+
it(`renders ${variant} variant with correct classes`, () => {
|
|
47
|
+
render(
|
|
48
|
+
<PocketSurface pocket={variant} data-testid="surface">
|
|
49
|
+
{testContent}
|
|
50
|
+
</PocketSurface>,
|
|
51
|
+
);
|
|
52
|
+
const element = screen.getByTestId('surface');
|
|
53
|
+
expect(element).toHaveClass('wds-pocket-surface');
|
|
54
|
+
expect(element).toHaveClass(`wds-pocket-${variant}`);
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('custom props', () => {
|
|
60
|
+
it('applies custom className', () => {
|
|
61
|
+
render(
|
|
62
|
+
<PocketSurface pocket="bright-blue" className="custom-class" data-testid="surface">
|
|
63
|
+
{testContent}
|
|
64
|
+
</PocketSurface>,
|
|
65
|
+
);
|
|
66
|
+
expect(screen.getByTestId('surface')).toHaveClass('custom-class');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('applies custom id', () => {
|
|
70
|
+
render(
|
|
71
|
+
<PocketSurface pocket="bright-blue" id="custom-id">
|
|
72
|
+
{testContent}
|
|
73
|
+
</PocketSurface>,
|
|
74
|
+
);
|
|
75
|
+
expect(screen.getByText(testContent)).toHaveAttribute('id', 'custom-id');
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('applies data-testid attribute', () => {
|
|
79
|
+
render(
|
|
80
|
+
<PocketSurface pocket="bright-blue" data-testid="test-surface">
|
|
81
|
+
{testContent}
|
|
82
|
+
</PocketSurface>,
|
|
83
|
+
);
|
|
84
|
+
expect(screen.getByTestId('test-surface')).toBeInTheDocument();
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe('HTML attributes', () => {
|
|
89
|
+
it('supports aria-label attribute', () => {
|
|
90
|
+
render(
|
|
91
|
+
<PocketSurface pocket="bright-blue" aria-label="Surface label" data-testid="surface">
|
|
92
|
+
{testContent}
|
|
93
|
+
</PocketSurface>,
|
|
94
|
+
);
|
|
95
|
+
expect(screen.getByTestId('surface')).toHaveAttribute('aria-label', 'Surface label');
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('supports role attribute', () => {
|
|
99
|
+
render(
|
|
100
|
+
<PocketSurface pocket="bright-blue" role="region" data-testid="surface">
|
|
101
|
+
{testContent}
|
|
102
|
+
</PocketSurface>,
|
|
103
|
+
);
|
|
104
|
+
expect(screen.getByTestId('surface')).toHaveAttribute('role', 'region');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { forwardRef, ElementType, ForwardedRef } from 'react';
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
|
|
4
|
+
import { PocketSurfaceComponentProps, PocketSurfaceComponent } from './PocketSurface.types';
|
|
5
|
+
|
|
6
|
+
// @ts-expect-error - Generic forwardRef limitation. See: https://fettblog.eu/typescript-react-generic-forward-refs/
|
|
7
|
+
const PocketSurface: PocketSurfaceComponent = forwardRef(function PocketSurface<
|
|
8
|
+
T extends ElementType = 'div',
|
|
9
|
+
>(
|
|
10
|
+
{
|
|
11
|
+
as,
|
|
12
|
+
pocket,
|
|
13
|
+
className,
|
|
14
|
+
children,
|
|
15
|
+
id,
|
|
16
|
+
'data-testid': dataTestId,
|
|
17
|
+
...props
|
|
18
|
+
}: PocketSurfaceComponentProps<T>,
|
|
19
|
+
ref: ForwardedRef<HTMLElement>,
|
|
20
|
+
) {
|
|
21
|
+
const Element = as ?? 'div';
|
|
22
|
+
|
|
23
|
+
const classNames = clsx('wds-pocket-surface', `wds-pocket-${pocket}`, className);
|
|
24
|
+
|
|
25
|
+
const pocketProps = {
|
|
26
|
+
ref,
|
|
27
|
+
id,
|
|
28
|
+
'data-testid': dataTestId,
|
|
29
|
+
className: classNames,
|
|
30
|
+
...props,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
// @ts-expect-error - Generic forwardRef limitation. See: https://fettblog.eu/typescript-react-generic-forward-refs/
|
|
35
|
+
<Element {...pocketProps}>{children}</Element>
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
PocketSurface.displayName = 'PocketSurface';
|
|
40
|
+
|
|
41
|
+
export default PocketSurface;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ReactNode, ElementType, ComponentPropsWithoutRef, HTMLAttributes } from 'react';
|
|
2
|
+
|
|
3
|
+
export type PocketVariant =
|
|
4
|
+
| 'bright-blue'
|
|
5
|
+
| 'bright-orange'
|
|
6
|
+
| 'bright-pink'
|
|
7
|
+
| 'bright-yellow'
|
|
8
|
+
| 'dark-charcoal'
|
|
9
|
+
| 'dark-gold'
|
|
10
|
+
| 'dark-maroon'
|
|
11
|
+
| 'dark-purple';
|
|
12
|
+
|
|
13
|
+
export interface CommonProps {
|
|
14
|
+
pocket: PocketVariant;
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
id?: string;
|
|
18
|
+
'data-testid'?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type PocketSurfaceDivProps<T extends ElementType = 'div'> = Omit<
|
|
22
|
+
HTMLAttributes<HTMLDivElement>,
|
|
23
|
+
keyof CommonProps
|
|
24
|
+
> &
|
|
25
|
+
CommonProps & {
|
|
26
|
+
as?: T;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export type PocketSurfaceProps<T extends ElementType = 'div'> = PocketSurfaceDivProps<T>;
|
|
30
|
+
|
|
31
|
+
export type PocketSurfaceComponentProps<T extends ElementType = 'div'> = PocketSurfaceProps<T> &
|
|
32
|
+
Omit<ComponentPropsWithoutRef<T>, keyof PocketSurfaceProps<T>>;
|
|
33
|
+
|
|
34
|
+
export interface PocketSurfaceComponent {
|
|
35
|
+
<T extends ElementType = 'div'>(props: PocketSurfaceComponentProps<T>): ReactNode;
|
|
36
|
+
displayName?: string;
|
|
37
|
+
}
|