Skip to content

Commit 5f68a29

Browse files
committed
Add disabled SelectNext.Option example to pattern library
1 parent 756f809 commit 5f68a29

File tree

3 files changed

+99
-56
lines changed

3 files changed

+99
-56
lines changed

src/components/input/SelectNext.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,12 @@ function SelectOption<T>({
6464
return (
6565
<li
6666
className={classnames(
67-
'w-full ring-inset focus:ring outline-none rounded-none',
67+
'w-full ring-inset outline-none rounded-none',
6868
'border-t first:border-t-0 transition-colors whitespace-nowrap',
69-
{ 'cursor-pointer hover:bg-grey-1': !disabled },
69+
{
70+
'text-grey-4': disabled,
71+
'cursor-pointer focus:ring hover:bg-grey-1': !disabled,
72+
},
7073
classes,
7174
)}
7275
onClick={() => {
@@ -81,7 +84,7 @@ function SelectOption<T>({
8184
}
8285
}}
8386
role="option"
84-
disabled={disabled}
87+
aria-disabled={disabled}
8588
aria-selected={selected}
8689
// This is intended to be focused with arrow keys
8790
tabIndex={-1}
@@ -193,7 +196,7 @@ function SelectMain<T>({
193196
loop: false,
194197
autofocus: true,
195198
containerVisible: listboxOpen,
196-
selector: '[role="option"]',
199+
selector: '[role="option"]:not([aria-disabled="true"])',
197200
});
198201

199202
useLayoutEffect(() => {

src/components/input/test/SelectNext-test.js

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,17 @@ describe('SelectNext', () => {
1313
{ id: '5', name: 'Doris Evanescence' },
1414
];
1515

16-
const createComponent = (props = {}, paddingTop = 0) => {
16+
/**
17+
* @param {Object} [options]
18+
* @param {number} [options.paddingTop] - Extra padding top for the container.
19+
* Defaults to 0.
20+
* @param {boolean} [options.optionsChildrenAsCallback] -
21+
* Whether to renders SelectNext.Option children with callback notation.
22+
* Used primarily to test and cover both branches.
23+
* Defaults to true.
24+
*/
25+
const createComponent = (props = {}, options = {}) => {
26+
const { paddingTop = 0, optionsChildrenAsCallback = true } = options;
1727
const container = document.createElement('div');
1828
container.style.paddingTop = `${paddingTop}px`;
1929
document.body.append(container);
@@ -26,12 +36,16 @@ describe('SelectNext', () => {
2636
disabled={item.id === '4'}
2737
key={item.id}
2838
>
29-
{({ selected, disabled }) => (
30-
<span data-testid={`option-${item.id}`}>
31-
{item.name}
32-
{selected && <span data-testid="selected-option" />}
33-
{disabled && <span data-testid="disabled-option" />}
34-
</span>
39+
{!optionsChildrenAsCallback ? (
40+
<span data-testid={`option-${item.id}`}>{item.name}</span>
41+
) : (
42+
({ selected, disabled }) => (
43+
<span data-testid={`option-${item.id}`}>
44+
{item.name}
45+
{selected && <span data-testid="selected-option" />}
46+
{disabled && <span data-testid="disabled-option" />}
47+
</span>
48+
)
3549
)}
3650
</SelectNext.Option>
3751
))}
@@ -251,7 +265,7 @@ describe('SelectNext', () => {
251265
{ containerPaddingTop: 1000, shouldDropUp: true },
252266
].forEach(({ containerPaddingTop, shouldDropUp }) => {
253267
it('makes listbox drop up or down based on available space below', () => {
254-
const wrapper = createComponent({}, containerPaddingTop);
268+
const wrapper = createComponent({}, { paddingTop: containerPaddingTop });
255269
toggleListbox(wrapper);
256270

257271
assert.equal(listboxDidDropUp(wrapper), shouldDropUp);
@@ -273,12 +287,19 @@ describe('SelectNext', () => {
273287
checkAccessibility([
274288
{
275289
name: 'Closed Select listbox',
276-
content: () => createComponent({ buttonContent: 'Select' }),
290+
content: () =>
291+
createComponent(
292+
{ buttonContent: 'Select' },
293+
{ optionsChildrenAsCallback: false },
294+
),
277295
},
278296
{
279297
name: 'Open Select listbox',
280298
content: () => {
281-
const wrapper = createComponent({ buttonContent: 'Select' });
299+
const wrapper = createComponent(
300+
{ buttonContent: 'Select' },
301+
{ optionsChildrenAsCallback: false },
302+
);
282303
toggleListbox(wrapper);
283304

284305
return wrapper;

src/pattern-library/components/patterns/prototype/SelectNextPage.tsx

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import { IconButton, InputGroup } from '../../../../components/input';
66
import SelectNext from '../../../../components/input/SelectNext';
77
import Library from '../../Library';
88

9-
const defaultItems = [
9+
type ItemType = {
10+
id: string;
11+
name: string;
12+
disabled?: boolean;
13+
};
14+
15+
const defaultItems: ItemType[] = [
1016
{ id: '1', name: 'All students' },
1117
{ id: '2', name: 'Albert Banana' },
1218
{ id: '3', name: 'Bernard California' },
@@ -25,13 +31,14 @@ function SelectExample({
2531
classes?: string;
2632
items?: typeof defaultItems;
2733
}) {
28-
const [value, setValue] = useState<(typeof items)[number]>();
34+
const [value, setValue] = useState<ItemType>();
2935

3036
return (
3137
<SelectNext
3238
value={value}
3339
onChange={setValue}
3440
classes={classes}
41+
disabled={disabled}
3542
buttonContent={
3643
value ? (
3744
<>
@@ -51,21 +58,27 @@ function SelectExample({
5158
<>Select one...</>
5259
)
5360
}
54-
disabled={disabled}
5561
>
5662
{items.map(item => (
57-
<SelectNext.Option value={item} key={item.id}>
58-
{textOnly ? (
59-
item.name
60-
) : (
61-
<>
62-
{item.name}
63-
<div className="grow" />
64-
<div className="rounded px-2 ml-2 bg-grey-7 text-white">
65-
{item.id}
66-
</div>
67-
</>
68-
)}
63+
<SelectNext.Option value={item} key={item.id} disabled={item.disabled}>
64+
{({ disabled }) =>
65+
textOnly ? (
66+
item.name
67+
) : (
68+
<>
69+
{item.name}
70+
<div className="grow" />
71+
<div
72+
className={classnames('rounded px-2 ml-2 text-white', {
73+
'bg-grey-7': !disabled,
74+
'bg-grey-4': disabled,
75+
})}
76+
>
77+
{item.id}
78+
</div>
79+
</>
80+
)
81+
}
6982
</SelectNext.Option>
7083
))}
7184
</SelectNext>
@@ -215,14 +228,6 @@ export default function SelectNextPage() {
215228
</Library.Demo>
216229
</Library.Example>
217230

218-
<Library.Example title="Disabled Select">
219-
<Library.Demo title="Disabled Select">
220-
<div className="w-96 mx-auto">
221-
<SelectExample disabled />
222-
</div>
223-
</Library.Demo>
224-
</Library.Example>
225-
226231
<Library.Example title="Select with long content">
227232
<p>
228233
<code>SelectNext</code> makes sure the button content never
@@ -259,70 +264,75 @@ export default function SelectNextPage() {
259264
</Library.Example>
260265
</Library.Pattern>
261266

262-
<Library.Pattern title="Component API">
267+
<Library.Pattern title="SelectNext component API">
263268
<code>SelectNext</code> accepts all standard{' '}
264269
<Library.Link href="/using-components#presentational-components-api">
265270
presentational component props
266271
</Library.Link>
267-
<Library.Example title="buttonContent">
272+
<Library.Example title="value">
268273
<Library.Info>
269274
<Library.InfoItem label="description">
270-
The content to be displayed in the toggle button.
275+
Represents currently selected Option.
271276
</Library.InfoItem>
272277
<Library.InfoItem label="type">
273-
<code>ComponentChildren</code>
278+
<code>T</code>
274279
</Library.InfoItem>
275280
</Library.Info>
276281
</Library.Example>
277-
<Library.Example title="value">
282+
<Library.Example title="onChange">
278283
<Library.Info>
279284
<Library.InfoItem label="description">
280-
Represents currently selected Option.
285+
A callback invoked every time selected value changes.
281286
</Library.InfoItem>
282287
<Library.InfoItem label="type">
283-
<code>T</code>
288+
<code>(newValue: T) =&gt; void</code>
284289
</Library.InfoItem>
285290
</Library.Info>
286291
</Library.Example>
287-
<Library.Example title="onChange">
292+
<Library.Example title="buttonContent">
288293
<Library.Info>
289294
<Library.InfoItem label="description">
290-
A callback invoked every time selected value changes.
295+
The content to be displayed in the toggle button.
291296
</Library.InfoItem>
292297
<Library.InfoItem label="type">
293-
<code>(newValue: T) =&gt; void</code>
298+
<code>ComponentChildren</code>
294299
</Library.InfoItem>
295300
</Library.Info>
296301
</Library.Example>
297-
<Library.Example title="disabled">
302+
<Library.Example title="buttonId">
298303
<Library.Info>
299304
<Library.InfoItem label="description">
300-
Whether the Select is disabled or not.
305+
The toggle button{"'"}s <code>id</code>.
301306
</Library.InfoItem>
302307
<Library.InfoItem label="type">
303-
<code>boolean</code>
308+
<code>string</code>
304309
</Library.InfoItem>
305310
<Library.InfoItem label="default">
306311
<code>undefined</code>
307312
</Library.InfoItem>
308313
</Library.Info>
309314
</Library.Example>
310-
<Library.Example title="buttonId">
315+
<Library.Example title="disabled">
311316
<Library.Info>
312317
<Library.InfoItem label="description">
313-
The toggle button{"'"}s <code>id</code>.
318+
Whether the Select is disabled or not.
314319
</Library.InfoItem>
315320
<Library.InfoItem label="type">
316-
<code>string</code>
321+
<code>boolean</code>
317322
</Library.InfoItem>
318323
<Library.InfoItem label="default">
319324
<code>undefined</code>
320325
</Library.InfoItem>
321326
</Library.Info>
327+
<Library.Demo title="Disabled Select">
328+
<div className="w-96 mx-auto">
329+
<SelectExample disabled />
330+
</div>
331+
</Library.Demo>
322332
</Library.Example>
323-
<p>
324-
Every <code>SelectNext.Option</code> has its own set of props.
325-
</p>
333+
</Library.Pattern>
334+
335+
<Library.Pattern title="SelectNext.Option component API">
326336
<Library.Example title="children">
327337
<Library.Info>
328338
<Library.InfoItem label="description">
@@ -359,6 +369,15 @@ export default function SelectNextPage() {
359369
<code>undefined</code>
360370
</Library.InfoItem>
361371
</Library.Info>
372+
<Library.Demo title="Disabled options">
373+
<div className="w-96 mx-auto">
374+
<SelectExample
375+
items={defaultItems.map(item =>
376+
item.id !== '4' ? item : { ...item, disabled: true },
377+
)}
378+
/>
379+
</div>
380+
</Library.Demo>
362381
</Library.Example>
363382
</Library.Pattern>
364383

0 commit comments

Comments
 (0)