Skip to content

Commit eebe9a8

Browse files
avelinelaurkimkyledurand
authored
Update ChoiceList to use Layout primitives (#7751)
### WHY are these changes introduced? Resolves #7354 ### WHAT is this pull request doing? - Refactored `ChoiceList` to use primitive Layout components - Added support for `legend` element to `Box` - Add support for `fieldset` element to `AlphaStack` ### How to 🎩 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 34748dc commit eebe9a8

File tree

8 files changed

+100
-79
lines changed

8 files changed

+100
-79
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
@@ -39,6 +39,12 @@
3939
padding-inline-start: 0;
4040
}
4141

42+
.fieldsetReset {
43+
border: none;
44+
margin: 0;
45+
padding: 0;
46+
}
47+
4248
.fullWidth {
4349
> * {
4450
width: 100%;

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';
22+
type Element = 'div' | 'span' | 'section' | 'legend';
23+
2324
type Overflow = 'hidden' | 'scroll';
2425
type Position = 'relative' | 'absolute' | 'fixed' | 'sticky';
2526

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +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-
@media #{$p-breakpoints-md-down} {
11-
margin-bottom: var(--p-space-4);
12-
}
13-
}
14-
15-
.titleHidden > .Title {
16-
@include visually-hidden;
17-
}
18-
19-
.Choices {
20-
margin: 0;
21-
padding: 0;
22-
list-style: none;
23-
}
24-
253
.ChoiceChildren {
26-
@media #{$p-breakpoints-md-down} {
27-
margin-top: var(--p-space-4);
28-
}
29-
margin-bottom: var(--p-space-2);
304
padding-left: calc(var(--p-space-2) + var(--p-choice-size));
315
}
32-
33-
.ChoiceError {
34-
margin-top: var(--p-space-1);
35-
margin-bottom: var(--p-space-2);
36-
37-
@media #{$p-breakpoints-md-down} {
38-
margin-top: var(--p-space-4);
39-
}
40-
}
41-
42-
.Title {
43-
display: block;
44-
margin: 0 0 var(--p-space-1);
45-
padding: 0;
46-
47-
@media #{$p-breakpoints-md-down} {
48-
margin-bottom: var(--p-space-5);
49-
}
50-
}

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)