Skip to content

Commit fa4c1d5

Browse files
avelinelaurkimkyledurand
committed
Update ChoiceList to use Layout primitives (#7751)
Resolves #7354 - Refactored `ChoiceList` to use primitive Layout components - Added support for `legend` element to `Box` - Add support for `fieldset` element to `AlphaStack` There should be no visual changes. Co-authored-by: Lo Kim <lo.kim@shopify.com> Co-authored-by: Kyle Durand <kyledurand@users.noreply.github.com>
1 parent 80f72f3 commit fa4c1d5

File tree

8 files changed

+100
-86
lines changed

8 files changed

+100
-86
lines changed

.changeset/cold-keys-raise.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@shopify/polaris': minor
3+
---
4+
5+
- Refactored `ChoiceList` to use primitive Layout components
6+
- Added support for `legend` element to `Box`
7+
- Added support for `fieldset` element to `AlphaStack`

polaris-react/src/components/AlphaStack/AlphaStack.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@
5555
padding-inline-start: 0;
5656
}
5757

58+
.fieldsetReset {
59+
border: none;
60+
margin: 0;
61+
padding: 0;
62+
}
63+
5864
.fullWidth {
5965
> * {
6066
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY

polaris-react/src/components/AlphaStack/AlphaStack.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export const AlphaStack = ({
5151
styles.AlphaStack,
5252
fullWidth && styles.fullWidth,
5353
as === 'ul' && styles.listReset,
54+
as === 'fieldset' && styles.fieldsetReset,
5455
);
5556

5657
const style = {

polaris-react/src/components/Box/Box.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {
1919

2020
import styles from './Box.scss';
2121

22-
type Element = 'div' | 'span' | 'section' | 'ul' | 'li';
22+
type Element = 'div' | 'span' | 'section' | 'legend' | 'ul' | 'li';
23+
2324
type Overflow = 'hidden' | 'scroll';
2425
type Position = 'relative' | 'absolute' | 'fixed' | 'sticky';
2526

Lines changed: 0 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,5 @@
11
@import '../../styles/common';
22

3-
.ChoiceList {
4-
margin: 0;
5-
padding: 0;
6-
border: none;
7-
}
8-
9-
.ChoiceItem:not(:last-child) {
10-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
11-
@media #{$p-breakpoints-md-down} {
12-
margin-bottom: var(--p-space-4);
13-
}
14-
}
15-
16-
.titleHidden > .Title {
17-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
18-
@include visually-hidden;
19-
}
20-
21-
.Choices {
22-
margin: 0;
23-
padding: 0;
24-
list-style: none;
25-
}
26-
273
.ChoiceChildren {
28-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
29-
@media #{$p-breakpoints-md-down} {
30-
margin-top: var(--p-space-4);
31-
}
32-
margin-bottom: var(--p-space-2);
33-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
344
padding-left: calc(var(--p-space-2) + var(--p-choice-size));
355
}
36-
37-
.ChoiceError {
38-
margin-top: var(--p-space-1);
39-
margin-bottom: var(--p-space-2);
40-
41-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
42-
@media #{$p-breakpoints-md-down} {
43-
margin-top: var(--p-space-4);
44-
}
45-
}
46-
47-
.Title {
48-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
49-
display: block;
50-
margin: 0 0 var(--p-space-1);
51-
padding: 0;
52-
53-
// stylelint-disable-next-line -- generated by polaris-migrator DO NOT COPY
54-
@media #{$p-breakpoints-md-down} {
55-
margin-bottom: var(--p-space-5);
56-
}
57-
}

polaris-react/src/components/ChoiceList/ChoiceList.tsx

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import React from 'react';
22

3-
import {classNames} from '../../utilities/css';
43
import {useUniqueId} from '../../utilities/unique-id';
54
import type {Error} from '../../types';
65
import {Checkbox} from '../Checkbox';
76
import {RadioButton} from '../RadioButton';
87
import {InlineError, errorTextID} from '../InlineError';
98
import {Text} from '../Text';
9+
import {AlphaStack} from '../AlphaStack';
10+
import {Box} from '../Box';
11+
import {Bleed} from '../Bleed';
1012

1113
import styles from './ChoiceList.scss';
1214

@@ -66,17 +68,16 @@ export function ChoiceList({
6668
const name = useUniqueId('ChoiceList', nameProp);
6769
const finalName = allowMultiple ? `${name}[]` : name;
6870

69-
const className = classNames(
70-
styles.ChoiceList,
71-
titleHidden && styles.titleHidden,
72-
);
73-
7471
const titleMarkup = title ? (
75-
<legend className={styles.Title}>
72+
<Box
73+
as="legend"
74+
paddingBlockEnd={{xs: '5', md: '1'}}
75+
visuallyHidden={titleHidden}
76+
>
7677
<Text as="span" variant="bodyMd">
7778
{title}
7879
</Text>
79-
</legend>
80+
</Box>
8081
) : null;
8182

8283
const choicesMarkup = choices.map((choice) => {
@@ -101,41 +102,57 @@ export function ChoiceList({
101102
? choice.renderChildren(isSelected)
102103
: null;
103104
const children = renderedChildren ? (
104-
<div className={styles.ChoiceChildren}>{renderedChildren}</div>
105+
<div className={styles.ChoiceChildren}>
106+
<Box paddingBlockStart={{xs: '4', md: '0'}} paddingBlockEnd="2">
107+
{renderedChildren}
108+
</Box>
109+
</div>
105110
) : null;
106-
107111
return (
108-
<li key={value} className={styles.ChoiceItem}>
109-
<ControlComponent
110-
name={finalName}
111-
value={value}
112-
id={id}
113-
label={label}
114-
disabled={choiceDisabled || disabled}
115-
checked={choiceIsSelected(choice, selected)}
116-
helpText={helpText}
117-
onChange={handleChange}
118-
ariaDescribedBy={
119-
error && describedByError ? errorTextID(finalName) : null
120-
}
121-
/>
122-
{children}
112+
<li key={value}>
113+
<Bleed
114+
marginInline="0"
115+
marginBlockEnd={helpText ? {xs: '1', md: '0'} : {xs: '0'}}
116+
>
117+
<ControlComponent
118+
name={finalName}
119+
value={value}
120+
id={id}
121+
label={label}
122+
disabled={choiceDisabled || disabled}
123+
checked={choiceIsSelected(choice, selected)}
124+
helpText={helpText}
125+
onChange={handleChange}
126+
ariaDescribedBy={
127+
error && describedByError ? errorTextID(finalName) : null
128+
}
129+
/>
130+
{children}
131+
</Bleed>
123132
</li>
124133
);
125134
});
126135

127136
const errorMarkup = error && (
128-
<div className={styles.ChoiceError}>
137+
<Box paddingBlockStart={{xs: '0', md: '1'}} paddingBlockEnd="2">
129138
<InlineError message={error} fieldID={finalName} />
130-
</div>
139+
</Box>
131140
);
132141

133142
return (
134-
<fieldset className={className} id={finalName} aria-invalid={error != null}>
143+
<AlphaStack
144+
as="fieldset"
145+
gap={{xs: '4', md: '0'}}
146+
fullWidth
147+
aria-invalid={error != null}
148+
id={finalName}
149+
>
135150
{titleMarkup}
136-
<ul className={styles.Choices}>{choicesMarkup}</ul>
151+
<AlphaStack as="ul" gap={{xs: '4', md: '0'}} fullWidth>
152+
{choicesMarkup}
153+
</AlphaStack>
137154
{errorMarkup}
138-
</fieldset>
155+
</AlphaStack>
139156
);
140157
}
141158

polaris-react/src/components/ChoiceList/tests/ChoiceList.test.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import {mountWithApp} from 'tests/utilities';
33

4+
import {Bleed} from '../../Bleed';
45
import {Checkbox} from '../../Checkbox';
56
import {InlineError} from '../../InlineError';
67
import {RadioButton} from '../../RadioButton';
@@ -241,10 +242,14 @@ describe('<ChoiceList />', () => {
241242
/>,
242243
);
243244

245+
const listItemWithChildren =
246+
choiceElements.findAll('li')[indexWithChildren];
247+
const listItemBleedChild = listItemWithChildren
248+
.find(Bleed)
249+
?.find('div');
250+
244251
expect(renderChildrenSpy).toHaveBeenCalled();
245-
expect(
246-
choiceElements.findAll('li')[indexWithChildren],
247-
).not.toContainReactComponent('div');
252+
expect(listItemBleedChild).not.toContainReactComponent('div');
248253
});
249254
});
250255

polaris-react/src/components/Modal/components/Header/Header.tsx

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,33 @@ export function Header({
5555
</Columns>
5656
</Box>
5757
);
58+
59+
if (titleHidden || !children) {
60+
return titleHiddenMarkup;
61+
}
62+
63+
return (
64+
<Box
65+
paddingBlockStart="4"
66+
paddingBlockEnd="4"
67+
paddingInlineStart="5"
68+
paddingInlineEnd="5"
69+
borderBlockEnd="divider"
70+
>
71+
<Columns columns={{xs: '1fr auto'}}>
72+
<Inline>
73+
<Text id={id} as="h2" variant="headingLg" breakWord>
74+
{children}
75+
</Text>
76+
</Inline>
77+
<Inline>
78+
<CloseButton
79+
pressed={closing}
80+
titleHidden={titleHidden}
81+
onClick={onClose}
82+
/>
83+
</Inline>
84+
</Columns>
85+
</Box>
86+
);
5887
}

0 commit comments

Comments
 (0)