@charcoal-ui/react 3.9.1 → 3.10.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/dist/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.d.ts.map +1 -1
- package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts +2 -1
- package/dist/components/DropdownSelector/MenuList/MenuListContext.d.ts.map +1 -1
- package/dist/components/DropdownSelector/MenuList/index.d.ts.map +1 -1
- package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts +2 -1
- package/dist/components/DropdownSelector/MenuList/internals/getValuesRecursive.d.ts.map +1 -1
- package/dist/components/DropdownSelector/index.d.ts +4 -0
- package/dist/components/DropdownSelector/index.d.ts.map +1 -1
- package/dist/components/DropdownSelector/index.story.d.ts +12 -5
- package/dist/components/DropdownSelector/index.story.d.ts.map +1 -1
- package/dist/components/LoadingSpinner/LoadingSpinnerIcon.story.d.ts.map +1 -1
- package/dist/components/LoadingSpinner/index.story.d.ts.map +1 -1
- package/dist/index.cjs.js +44 -23
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +54 -33
- package/dist/index.esm.js.map +1 -1
- package/package.json +9 -7
- package/src/components/DropdownSelector/ListItem/__snapshots__/index.story.storyshot +5 -3
- package/src/components/DropdownSelector/ListItem/index.tsx +5 -1
- package/src/components/DropdownSelector/MenuItem/internals/useMenuItemHandleKeyDown.tsx +29 -18
- package/src/components/DropdownSelector/MenuList/MenuListContext.ts +3 -2
- package/src/components/DropdownSelector/MenuList/__snapshots__/index.story.storyshot +15 -9
- package/src/components/DropdownSelector/MenuList/index.tsx +6 -4
- package/src/components/DropdownSelector/MenuList/internals/getValuesRecursive.tsx +11 -8
- package/src/components/DropdownSelector/__snapshots__/index.story.storyshot +2666 -396
- package/src/components/DropdownSelector/index.story.tsx +264 -103
- package/src/components/DropdownSelector/index.tsx +35 -7
- package/src/components/LoadingSpinner/LoadingSpinnerIcon.story.tsx +1 -0
- package/src/components/LoadingSpinner/index.story.tsx +1 -0
- package/src/components/Modal/__snapshots__/index.story.storyshot +76 -0
|
@@ -1,93 +1,210 @@
|
|
|
1
1
|
import { useState } from 'react'
|
|
2
|
-
import DropdownSelector
|
|
2
|
+
import DropdownSelector from '.'
|
|
3
3
|
import { Divider } from './Divider'
|
|
4
4
|
import MenuItemGroup from './MenuItemGroup'
|
|
5
5
|
import DropdownMenuItem from './DropdownMenuItem'
|
|
6
6
|
import Modal from '../Modal'
|
|
7
7
|
import { ModalBody, ModalHeader } from '../Modal/ModalPlumbing'
|
|
8
|
-
import styled from 'styled-components'
|
|
9
|
-
import Button from '../Button'
|
|
10
8
|
import { Meta, StoryObj } from '@storybook/react'
|
|
9
|
+
import TextField from '../TextField'
|
|
10
|
+
import TextArea from '../TextArea'
|
|
11
|
+
import Button from '../Button'
|
|
11
12
|
|
|
12
13
|
export default {
|
|
13
14
|
title: 'DropdownSelector',
|
|
14
15
|
component: DropdownSelector,
|
|
15
16
|
} as Meta<typeof DropdownSelector>
|
|
16
17
|
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
export const Default: StoryObj<typeof DropdownSelector> = {
|
|
19
|
+
render: function Render(args) {
|
|
20
|
+
const [selected, setSelected] = useState('')
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<div style={{ width: 288 }}>
|
|
24
|
+
<DropdownSelector
|
|
25
|
+
{...args}
|
|
26
|
+
onChange={setSelected}
|
|
27
|
+
value={args.value ? args.value : selected}
|
|
28
|
+
placeholder="Placeholder"
|
|
29
|
+
label="Label"
|
|
30
|
+
>
|
|
31
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
32
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
33
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
34
|
+
</DropdownSelector>
|
|
35
|
+
</div>
|
|
36
|
+
)
|
|
23
37
|
},
|
|
24
|
-
children: <DropdownMenuItem value="item" />,
|
|
25
38
|
}
|
|
26
39
|
|
|
27
|
-
export const
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
export const Label: StoryObj<typeof DropdownSelector> = {
|
|
41
|
+
render: function Render() {
|
|
42
|
+
const [selected, setSelected] = useState('1')
|
|
43
|
+
return (
|
|
44
|
+
<div style={{ width: 288 }}>
|
|
45
|
+
<DropdownSelector
|
|
46
|
+
value={selected}
|
|
47
|
+
onChange={setSelected}
|
|
48
|
+
label="Label"
|
|
49
|
+
showLabel
|
|
50
|
+
>
|
|
51
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
52
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
53
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
54
|
+
</DropdownSelector>
|
|
55
|
+
</div>
|
|
56
|
+
)
|
|
30
57
|
},
|
|
31
|
-
|
|
32
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
33
|
-
const [selected, setSelected] = useState('50')
|
|
58
|
+
}
|
|
34
59
|
|
|
60
|
+
export const Disabled: StoryObj<typeof DropdownSelector> = {
|
|
61
|
+
render: function Render() {
|
|
62
|
+
const [selected, setSelected] = useState('1')
|
|
35
63
|
return (
|
|
36
64
|
<div style={{ width: 288 }}>
|
|
37
|
-
<Button></Button>
|
|
38
65
|
<DropdownSelector
|
|
39
|
-
{...props}
|
|
40
|
-
onChange={(value) => {
|
|
41
|
-
setSelected(value)
|
|
42
|
-
}}
|
|
43
66
|
value={selected}
|
|
44
|
-
|
|
67
|
+
disabled
|
|
68
|
+
onChange={setSelected}
|
|
69
|
+
label="Label"
|
|
70
|
+
>
|
|
71
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
72
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
73
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
74
|
+
</DropdownSelector>
|
|
75
|
+
</div>
|
|
76
|
+
)
|
|
77
|
+
},
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export const DisabledItem: StoryObj<typeof DropdownSelector> = {
|
|
81
|
+
render: function Render() {
|
|
82
|
+
const [selected, setSelected] = useState('2')
|
|
83
|
+
return (
|
|
84
|
+
<div style={{ width: 288 }}>
|
|
85
|
+
<DropdownSelector value={selected} onChange={setSelected} label="Label">
|
|
86
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
87
|
+
<DropdownMenuItem value="2" disabled>
|
|
88
|
+
Option 2 (disabled)
|
|
89
|
+
</DropdownMenuItem>
|
|
90
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
91
|
+
<DropdownMenuItem value="4">Option 4</DropdownMenuItem>
|
|
92
|
+
<DropdownMenuItem value="5">Option 5</DropdownMenuItem>
|
|
93
|
+
</DropdownSelector>
|
|
94
|
+
</div>
|
|
95
|
+
)
|
|
96
|
+
},
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export const Invalid: StoryObj<typeof DropdownSelector> = {
|
|
100
|
+
render: function Render() {
|
|
101
|
+
const [selected, setSelected] = useState('1')
|
|
102
|
+
return (
|
|
103
|
+
<div style={{ width: 288 }}>
|
|
104
|
+
<DropdownSelector
|
|
105
|
+
value={selected}
|
|
106
|
+
invalid
|
|
107
|
+
onChange={setSelected}
|
|
108
|
+
label="Label"
|
|
109
|
+
>
|
|
110
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
111
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
112
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
113
|
+
</DropdownSelector>
|
|
114
|
+
</div>
|
|
115
|
+
)
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export const AssistiveText: StoryObj<typeof DropdownSelector> = {
|
|
120
|
+
render: function Render() {
|
|
121
|
+
const [selected, setSelected] = useState('1')
|
|
122
|
+
return (
|
|
123
|
+
<div style={{ width: 288 }}>
|
|
124
|
+
<DropdownSelector
|
|
125
|
+
value={selected}
|
|
126
|
+
onChange={setSelected}
|
|
127
|
+
label="Label"
|
|
128
|
+
assistiveText="assistiveText"
|
|
45
129
|
>
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
{i}
|
|
50
|
-
</DropdownMenuItem>
|
|
51
|
-
)
|
|
52
|
-
})}
|
|
130
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
131
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
132
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
53
133
|
</DropdownSelector>
|
|
54
134
|
</div>
|
|
55
135
|
)
|
|
56
136
|
},
|
|
57
137
|
}
|
|
58
138
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
139
|
+
export const InvalidAssistiveText: StoryObj<typeof DropdownSelector> = {
|
|
140
|
+
render: function Render() {
|
|
141
|
+
const [selected, setSelected] = useState('1')
|
|
142
|
+
return (
|
|
143
|
+
<div style={{ width: 288 }}>
|
|
144
|
+
<DropdownSelector
|
|
145
|
+
value={selected}
|
|
146
|
+
onChange={setSelected}
|
|
147
|
+
label="Label"
|
|
148
|
+
invalid
|
|
149
|
+
assistiveText="assistiveText"
|
|
150
|
+
>
|
|
151
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
152
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
153
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
154
|
+
</DropdownSelector>
|
|
155
|
+
</div>
|
|
156
|
+
)
|
|
157
|
+
},
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export const RequiredText: StoryObj<typeof DropdownSelector> = {
|
|
161
|
+
render: function Render() {
|
|
162
|
+
const [selected, setSelected] = useState('1')
|
|
163
|
+
return (
|
|
164
|
+
<div style={{ width: 288 }}>
|
|
165
|
+
<DropdownSelector
|
|
166
|
+
value={selected}
|
|
167
|
+
invalid
|
|
168
|
+
onChange={setSelected}
|
|
169
|
+
label="Label"
|
|
170
|
+
showLabel
|
|
171
|
+
required
|
|
172
|
+
requiredText="required"
|
|
173
|
+
>
|
|
174
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
175
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
176
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
177
|
+
</DropdownSelector>
|
|
178
|
+
</div>
|
|
179
|
+
)
|
|
180
|
+
},
|
|
75
181
|
}
|
|
76
182
|
|
|
77
|
-
export const
|
|
78
|
-
|
|
79
|
-
|
|
183
|
+
export const SubLabel: StoryObj<typeof DropdownSelector> = {
|
|
184
|
+
render: function Render() {
|
|
185
|
+
const [selected, setSelected] = useState('1')
|
|
186
|
+
return (
|
|
187
|
+
<div style={{ width: 288 }}>
|
|
188
|
+
<DropdownSelector
|
|
189
|
+
value={selected}
|
|
190
|
+
invalid
|
|
191
|
+
onChange={setSelected}
|
|
192
|
+
label="Label"
|
|
193
|
+
showLabel
|
|
194
|
+
subLabel="SubLabel"
|
|
195
|
+
>
|
|
196
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
197
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
198
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
199
|
+
</DropdownSelector>
|
|
200
|
+
</div>
|
|
201
|
+
)
|
|
80
202
|
},
|
|
81
|
-
render: (props) => (
|
|
82
|
-
<div style={{ width: 288 }}>
|
|
83
|
-
<PlaygroundDropdownSelector {...props} />
|
|
84
|
-
</div>
|
|
85
|
-
),
|
|
86
203
|
}
|
|
87
204
|
|
|
88
205
|
export const LongNames: StoryObj<typeof DropdownSelector> = {
|
|
89
206
|
render: function Render(args) {
|
|
90
|
-
const [selected, setSelected] = useState('
|
|
207
|
+
const [selected, setSelected] = useState('1')
|
|
91
208
|
return (
|
|
92
209
|
<div
|
|
93
210
|
style={{
|
|
@@ -102,13 +219,13 @@ export const LongNames: StoryObj<typeof DropdownSelector> = {
|
|
|
102
219
|
value={selected}
|
|
103
220
|
label="label"
|
|
104
221
|
>
|
|
105
|
-
<DropdownMenuItem value={'
|
|
222
|
+
<DropdownMenuItem value={'1'}>
|
|
106
223
|
Lorem ipsum dolor sit amet, consectetur adipisicing elit,
|
|
107
224
|
</DropdownMenuItem>
|
|
108
|
-
<DropdownMenuItem value={'
|
|
225
|
+
<DropdownMenuItem value={'2'}>
|
|
109
226
|
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
|
110
227
|
</DropdownMenuItem>
|
|
111
|
-
<DropdownMenuItem value={'
|
|
228
|
+
<DropdownMenuItem value={'3'}>
|
|
112
229
|
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
|
|
113
230
|
nisi ut aliquip ex ea commodo consequat.
|
|
114
231
|
</DropdownMenuItem>
|
|
@@ -118,17 +235,11 @@ export const LongNames: StoryObj<typeof DropdownSelector> = {
|
|
|
118
235
|
},
|
|
119
236
|
}
|
|
120
237
|
|
|
121
|
-
const DummyBox = styled.div`
|
|
122
|
-
border: solid 1px ${({ theme }) => theme.border.default.color};
|
|
123
|
-
display: flex;
|
|
124
|
-
justify-content: center;
|
|
125
|
-
align-items: center;
|
|
126
|
-
height: 256px;
|
|
127
|
-
`
|
|
128
|
-
|
|
129
238
|
export const InModal: StoryObj<typeof DropdownSelector> = {
|
|
130
239
|
render: function Render() {
|
|
131
240
|
const [open, setOpen] = useState(true)
|
|
241
|
+
const [selected1, setSelected1] = useState('1')
|
|
242
|
+
const [selected2, setSelected2] = useState('2')
|
|
132
243
|
return (
|
|
133
244
|
<div
|
|
134
245
|
style={{
|
|
@@ -149,14 +260,57 @@ export const InModal: StoryObj<typeof DropdownSelector> = {
|
|
|
149
260
|
<ModalBody>
|
|
150
261
|
<div
|
|
151
262
|
style={{
|
|
152
|
-
padding:
|
|
263
|
+
padding: 16,
|
|
264
|
+
display: 'grid',
|
|
265
|
+
gap: 40,
|
|
153
266
|
}}
|
|
154
267
|
>
|
|
155
|
-
<
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
268
|
+
<DropdownSelector
|
|
269
|
+
value={selected1}
|
|
270
|
+
onChange={setSelected1}
|
|
271
|
+
label="DropdownSelector1"
|
|
272
|
+
showLabel
|
|
273
|
+
required
|
|
274
|
+
requiredText="required"
|
|
275
|
+
placeholder="placeholder"
|
|
276
|
+
assistiveText="assistiveText"
|
|
277
|
+
>
|
|
278
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
279
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
280
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
281
|
+
</DropdownSelector>
|
|
282
|
+
|
|
283
|
+
<TextField
|
|
284
|
+
label="TextField"
|
|
285
|
+
showLabel
|
|
286
|
+
required
|
|
287
|
+
requiredText="required"
|
|
288
|
+
placeholder="placeholder"
|
|
289
|
+
assistiveText="assistiveText"
|
|
290
|
+
/>
|
|
291
|
+
<TextArea
|
|
292
|
+
label="TextArea"
|
|
293
|
+
showLabel
|
|
294
|
+
required
|
|
295
|
+
requiredText="required"
|
|
296
|
+
placeholder="placeholder"
|
|
297
|
+
assistiveText="assistiveText"
|
|
298
|
+
/>
|
|
299
|
+
|
|
300
|
+
<DropdownSelector
|
|
301
|
+
value={selected2}
|
|
302
|
+
onChange={setSelected2}
|
|
303
|
+
label="DropdownSelector2"
|
|
304
|
+
showLabel
|
|
305
|
+
required
|
|
306
|
+
requiredText="required"
|
|
307
|
+
placeholder="placeholder"
|
|
308
|
+
assistiveText="assistiveText"
|
|
309
|
+
>
|
|
310
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
311
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
312
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
313
|
+
</DropdownSelector>
|
|
160
314
|
</div>
|
|
161
315
|
</ModalBody>
|
|
162
316
|
</Modal>
|
|
@@ -167,9 +321,19 @@ export const InModal: StoryObj<typeof DropdownSelector> = {
|
|
|
167
321
|
|
|
168
322
|
export const InFormTag: StoryObj<typeof DropdownSelector> = {
|
|
169
323
|
render: function Render(props) {
|
|
170
|
-
const [selected, setSelected] = useState('')
|
|
324
|
+
const [selected, setSelected] = useState('1')
|
|
171
325
|
return (
|
|
172
|
-
<form
|
|
326
|
+
<form
|
|
327
|
+
style={{ width: 288, display: 'flex' }}
|
|
328
|
+
onSubmit={(e) => {
|
|
329
|
+
const target = e.target as HTMLFormElement
|
|
330
|
+
const select = target.elements.namedItem(
|
|
331
|
+
'exampleOption'
|
|
332
|
+
) as HTMLSelectElement
|
|
333
|
+
alert(`selected value: Option ${select.value}`)
|
|
334
|
+
e.preventDefault()
|
|
335
|
+
}}
|
|
336
|
+
>
|
|
173
337
|
<DropdownSelector
|
|
174
338
|
{...props}
|
|
175
339
|
onChange={(value) => {
|
|
@@ -177,20 +341,29 @@ export const InFormTag: StoryObj<typeof DropdownSelector> = {
|
|
|
177
341
|
}}
|
|
178
342
|
value={selected}
|
|
179
343
|
label="label"
|
|
344
|
+
name="exampleOption"
|
|
180
345
|
>
|
|
181
|
-
<DropdownMenuItem value=
|
|
182
|
-
<DropdownMenuItem value=
|
|
183
|
-
<DropdownMenuItem value=
|
|
346
|
+
<DropdownMenuItem value="1">Option 1</DropdownMenuItem>
|
|
347
|
+
<DropdownMenuItem value="2">Option 2</DropdownMenuItem>
|
|
348
|
+
<DropdownMenuItem value="3">Option 3</DropdownMenuItem>
|
|
184
349
|
</DropdownSelector>
|
|
350
|
+
<Button
|
|
351
|
+
variant="Primary"
|
|
352
|
+
type="submit"
|
|
353
|
+
style={{
|
|
354
|
+
marginLeft: 16,
|
|
355
|
+
}}
|
|
356
|
+
>
|
|
357
|
+
submit
|
|
358
|
+
</Button>
|
|
185
359
|
</form>
|
|
186
360
|
)
|
|
187
361
|
},
|
|
188
362
|
}
|
|
189
363
|
|
|
190
364
|
export const CustomChildren: StoryObj<typeof DropdownSelector> = {
|
|
191
|
-
args: { ...baseProps },
|
|
192
365
|
render: function Render(props) {
|
|
193
|
-
const [selected, setSelected] = useState('
|
|
366
|
+
const [selected, setSelected] = useState('bold')
|
|
194
367
|
return (
|
|
195
368
|
<div style={{ width: 288 }}>
|
|
196
369
|
<DropdownSelector
|
|
@@ -201,34 +374,23 @@ export const CustomChildren: StoryObj<typeof DropdownSelector> = {
|
|
|
201
374
|
value={selected}
|
|
202
375
|
label="label"
|
|
203
376
|
>
|
|
204
|
-
<DropdownMenuItem value={'
|
|
377
|
+
<DropdownMenuItem value={'normal'}>Normal</DropdownMenuItem>
|
|
378
|
+
<DropdownMenuItem value={'bold'}>
|
|
205
379
|
<div
|
|
206
380
|
style={{
|
|
207
|
-
color: 'pink',
|
|
208
381
|
fontWeight: 'bold',
|
|
209
382
|
}}
|
|
210
383
|
>
|
|
211
|
-
|
|
384
|
+
Bold
|
|
212
385
|
</div>
|
|
213
386
|
</DropdownMenuItem>
|
|
214
|
-
<DropdownMenuItem value={'
|
|
387
|
+
<DropdownMenuItem value={'italic'}>
|
|
215
388
|
<div
|
|
216
389
|
style={{
|
|
217
|
-
color: 'yellowgreen',
|
|
218
390
|
fontStyle: 'italic',
|
|
219
391
|
}}
|
|
220
392
|
>
|
|
221
|
-
|
|
222
|
-
</div>
|
|
223
|
-
</DropdownMenuItem>
|
|
224
|
-
<DropdownMenuItem value={'30'}>
|
|
225
|
-
<div
|
|
226
|
-
style={{
|
|
227
|
-
color: 'orange',
|
|
228
|
-
fontSize: '24px',
|
|
229
|
-
}}
|
|
230
|
-
>
|
|
231
|
-
Orange
|
|
393
|
+
Italic
|
|
232
394
|
</div>
|
|
233
395
|
</DropdownMenuItem>
|
|
234
396
|
</DropdownSelector>
|
|
@@ -237,10 +399,9 @@ export const CustomChildren: StoryObj<typeof DropdownSelector> = {
|
|
|
237
399
|
},
|
|
238
400
|
}
|
|
239
401
|
|
|
240
|
-
export const
|
|
241
|
-
args: { ...baseProps },
|
|
402
|
+
export const Section: StoryObj<typeof DropdownSelector> = {
|
|
242
403
|
render: function Render(props) {
|
|
243
|
-
const [selected, setSelected] = useState('
|
|
404
|
+
const [selected, setSelected] = useState('banana')
|
|
244
405
|
return (
|
|
245
406
|
<div style={{ width: 288 }}>
|
|
246
407
|
<DropdownSelector
|
|
@@ -252,15 +413,15 @@ export const SectionList: StoryObj<typeof DropdownSelector> = {
|
|
|
252
413
|
label="label"
|
|
253
414
|
>
|
|
254
415
|
<MenuItemGroup text="fruits">
|
|
255
|
-
<DropdownMenuItem value={'
|
|
256
|
-
<DropdownMenuItem value={'
|
|
257
|
-
<DropdownMenuItem value={'
|
|
416
|
+
<DropdownMenuItem value={'apple'}>Apple</DropdownMenuItem>
|
|
417
|
+
<DropdownMenuItem value={'banana'}>Banana</DropdownMenuItem>
|
|
418
|
+
<DropdownMenuItem value={'orange'}>Orange</DropdownMenuItem>
|
|
258
419
|
</MenuItemGroup>
|
|
259
420
|
<Divider />
|
|
260
421
|
<MenuItemGroup text="vehicle">
|
|
261
|
-
<DropdownMenuItem value={'
|
|
262
|
-
<DropdownMenuItem value={'
|
|
263
|
-
<DropdownMenuItem value={'
|
|
422
|
+
<DropdownMenuItem value={'bicycle'}>bicycle</DropdownMenuItem>
|
|
423
|
+
<DropdownMenuItem value={'car'}>car</DropdownMenuItem>
|
|
424
|
+
<DropdownMenuItem value={'train'}>train</DropdownMenuItem>
|
|
264
425
|
</MenuItemGroup>
|
|
265
426
|
</DropdownSelector>
|
|
266
427
|
</div>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReactNode, useState, useRef } from 'react'
|
|
1
|
+
import { ReactNode, useState, useRef, useMemo } from 'react'
|
|
2
2
|
import styled, { css } from 'styled-components'
|
|
3
3
|
import { disabledSelector } from '@charcoal-ui/utils'
|
|
4
4
|
import Icon from '../Icon'
|
|
@@ -7,6 +7,8 @@ import { DropdownPopover } from './DropdownPopover'
|
|
|
7
7
|
import { findPreviewRecursive } from './utils/findPreviewRecursive'
|
|
8
8
|
import MenuList, { MenuListChildren } from './MenuList'
|
|
9
9
|
import { focusVisibleFocusRingCss } from '@charcoal-ui/styled'
|
|
10
|
+
import { getValuesRecursive } from './MenuList/internals/getValuesRecursive'
|
|
11
|
+
import { useVisuallyHidden } from '@react-aria/visually-hidden'
|
|
10
12
|
|
|
11
13
|
export type DropdownSelectorProps = {
|
|
12
14
|
label: string
|
|
@@ -19,6 +21,10 @@ export type DropdownSelectorProps = {
|
|
|
19
21
|
required?: boolean
|
|
20
22
|
requiredText?: string
|
|
21
23
|
subLabel?: ReactNode
|
|
24
|
+
/**
|
|
25
|
+
* the name of hidden `<select />`
|
|
26
|
+
*/
|
|
27
|
+
name?: string
|
|
22
28
|
children: MenuListChildren
|
|
23
29
|
onChange: (value: string) => void
|
|
24
30
|
}
|
|
@@ -30,6 +36,15 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
30
36
|
const [isOpen, setIsOpen] = useState(false)
|
|
31
37
|
const preview = findPreviewRecursive(props.children, props.value)
|
|
32
38
|
|
|
39
|
+
const isPlaceholder = useMemo(
|
|
40
|
+
() => props.placeholder !== undefined && preview === undefined,
|
|
41
|
+
[preview, props.placeholder]
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const propsArray = getValuesRecursive(props.children)
|
|
45
|
+
|
|
46
|
+
const { visuallyHiddenProps } = useVisuallyHidden()
|
|
47
|
+
|
|
33
48
|
return (
|
|
34
49
|
<DropdownSelectorRoot aria-disabled={props.disabled}>
|
|
35
50
|
{props.showLabel === true && (
|
|
@@ -40,6 +55,21 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
40
55
|
subLabel={props.subLabel}
|
|
41
56
|
/>
|
|
42
57
|
)}
|
|
58
|
+
<div {...visuallyHiddenProps} aria-hidden="true">
|
|
59
|
+
<select name={props.name} value={props.value} tabIndex={-1}>
|
|
60
|
+
{propsArray.map((itemProps) => {
|
|
61
|
+
return (
|
|
62
|
+
<option
|
|
63
|
+
key={itemProps.value}
|
|
64
|
+
value={itemProps.value}
|
|
65
|
+
disabled={itemProps.disabled}
|
|
66
|
+
>
|
|
67
|
+
{itemProps.value}
|
|
68
|
+
</option>
|
|
69
|
+
)
|
|
70
|
+
})}
|
|
71
|
+
</select>
|
|
72
|
+
</div>
|
|
43
73
|
<DropdownButton
|
|
44
74
|
invalid={props.invalid}
|
|
45
75
|
disabled={props.disabled}
|
|
@@ -51,10 +81,8 @@ export default function DropdownSelector(props: DropdownSelectorProps) {
|
|
|
51
81
|
type="button"
|
|
52
82
|
$active={isOpen}
|
|
53
83
|
>
|
|
54
|
-
<DropdownButtonText>
|
|
55
|
-
{props.placeholder
|
|
56
|
-
? props.placeholder
|
|
57
|
-
: preview}
|
|
84
|
+
<DropdownButtonText $isText3={isPlaceholder}>
|
|
85
|
+
{isPlaceholder ? props.placeholder : preview}
|
|
58
86
|
</DropdownButtonText>
|
|
59
87
|
<DropdownButtonIcon name="16/Menu" />
|
|
60
88
|
</DropdownButton>
|
|
@@ -151,12 +179,12 @@ const DropdownButton = styled.button<{ invalid?: boolean; $active?: boolean }>`
|
|
|
151
179
|
`}
|
|
152
180
|
`
|
|
153
181
|
|
|
154
|
-
const DropdownButtonText = styled.span
|
|
182
|
+
const DropdownButtonText = styled.span<{ $isText3: boolean }>`
|
|
155
183
|
text-align: left;
|
|
156
184
|
font-size: 14px;
|
|
157
185
|
line-height: 22px;
|
|
158
186
|
display: flow-root;
|
|
159
|
-
color: var(--charcoal
|
|
187
|
+
color: var(--charcoal-${(p) => (p.$isText3 ? 'text3' : 'text2')});
|
|
160
188
|
overflow: hidden;
|
|
161
189
|
text-overflow: ellipsis;
|
|
162
190
|
white-space: nowrap;
|