Skip to content

Commit 0130656

Browse files
committed
feat: Add radio button component to Core
1 parent 08da1c8 commit 0130656

File tree

31 files changed

+1327
-211
lines changed

31 files changed

+1327
-211
lines changed

build-tools/utils/pluralize.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const pluralizationMap = {
5959
ProgressBar: 'ProgressBars',
6060
PromptInput: 'PromptInputs',
6161
PropertyFilter: 'PropertyFilters',
62+
RadioButton: 'RadioButtons',
6263
RadioGroup: 'RadioGroups',
6364
S3ResourceSelector: 'S3ResourceSelectors',
6465
SegmentedControl: 'SegmentedControls',

pages/radio-button/cards.page.tsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React, { useContext, useRef, useState } from 'react';
4+
import clsx from 'clsx';
5+
6+
import Box from '~components/box';
7+
import Checkbox from '~components/checkbox';
8+
import FormField from '~components/form-field';
9+
import RadioButton, { RadioButtonProps } from '~components/radio-button';
10+
import SpaceBetween from '~components/space-between';
11+
12+
import AppContext, { AppContextType } from '../app/app-context';
13+
import ScreenshotArea from '../utils/screenshot-area';
14+
15+
import styles from './cards.scss';
16+
17+
type RadioButtonDemoContext = React.Context<
18+
AppContextType<{
19+
disabled?: boolean;
20+
readOnly?: boolean;
21+
}>
22+
>;
23+
24+
const Card = ({
25+
value,
26+
label,
27+
checked,
28+
setValue,
29+
description,
30+
disabled,
31+
readOnly,
32+
}: Omit<RadioButtonProps, 'name'> & { label: string; setValue: (_a: string) => void }) => {
33+
const ref = useRef<HTMLInputElement>(null);
34+
return (
35+
<li className={clsx(styles.card, checked && styles['card--selected'])}>
36+
<div>
37+
<h3 className={styles.heading}>
38+
<a href="#">{label}</a>
39+
</h3>
40+
<p className={styles.description}>{description}</p>
41+
</div>
42+
<label aria-label={`Select ${label}`}>
43+
<RadioButton
44+
value={value}
45+
name="quantity"
46+
checked={checked}
47+
disabled={disabled}
48+
readOnly={readOnly}
49+
onChange={({ detail }) => {
50+
setValue(detail.value);
51+
ref.current?.focus();
52+
}}
53+
ref={ref}
54+
/>
55+
</label>
56+
</li>
57+
);
58+
};
59+
60+
export default function RadioButtonsCardsPage() {
61+
const { urlParams, setUrlParams } = useContext(AppContext as RadioButtonDemoContext);
62+
63+
const [value, setValue] = useState<string>('');
64+
65+
return (
66+
<article>
67+
<h1>Radio button — custom card selection</h1>
68+
<Box margin={{ horizontal: 'm' }}>
69+
<SpaceBetween size="s">
70+
<FormField label="Options">
71+
<SpaceBetween size="s">
72+
<Checkbox
73+
checked={!!urlParams.disabled}
74+
onChange={({ detail }) => setUrlParams({ ...urlParams, disabled: detail.checked })}
75+
description="Make one of the radio buttons disabled"
76+
>
77+
Disabled
78+
</Checkbox>
79+
80+
<Checkbox
81+
checked={!!urlParams.readOnly}
82+
onChange={({ detail }) => setUrlParams({ ...urlParams, readOnly: detail.checked })}
83+
description="Make one of the radio buttons read-only"
84+
>
85+
Read-only
86+
</Checkbox>
87+
</SpaceBetween>
88+
</FormField>
89+
</SpaceBetween>
90+
</Box>
91+
<hr />
92+
<ScreenshotArea disableAnimations={true}>
93+
<ul className={styles.cards}>
94+
<Card value="one" checked={value === 'one'} setValue={setValue} label="One" description="First option">
95+
One
96+
</Card>
97+
<Card
98+
value="two"
99+
checked={value === 'two'}
100+
disabled={urlParams.disabled}
101+
readOnly={urlParams.readOnly}
102+
setValue={setValue}
103+
label="Two"
104+
description="Second option"
105+
>
106+
Two
107+
</Card>
108+
<Card value="three" checked={value === 'three'} setValue={setValue} label="Three" description="Third option">
109+
Three
110+
</Card>
111+
</ul>
112+
</ScreenshotArea>
113+
</article>
114+
);
115+
}

pages/radio-button/cards.scss

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
@use '~design-tokens' as awsui;
7+
8+
.cards {
9+
display: flex;
10+
flex-wrap: wrap;
11+
gap: awsui.$space-scaled-xs;
12+
list-style-type: none;
13+
margin-block: 0;
14+
margin-inline: 0;
15+
padding-block: 0;
16+
padding-inline: 0;
17+
}
18+
19+
.card {
20+
$border-radius: awsui.$space-scaled-s;
21+
align-items: start;
22+
border-color: awsui.$color-border-control-default;
23+
border-start-start-radius: $border-radius;
24+
border-start-end-radius: $border-radius;
25+
border-end-start-radius: $border-radius;
26+
border-end-end-radius: $border-radius;
27+
border-block-style: solid;
28+
border-inline-style: solid;
29+
border-block-width: 1px;
30+
border-inline-width: 1px;
31+
display: flex;
32+
gap: awsui.$space-scaled-s;
33+
inline-size: 300px;
34+
justify-content: space-between;
35+
padding-block: awsui.$space-scaled-l;
36+
padding-inline: awsui.$space-scaled-l;
37+
38+
&--selected {
39+
border-color: awsui.$color-border-item-focused;
40+
}
41+
}
42+
43+
.heading {
44+
margin-block: 0;
45+
}
46+
.description {
47+
margin-block: awsui.$space-scaled-xs 0;
48+
}

pages/radio-button/styles.scss

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
@use '~design-tokens' as awsui;
7+
8+
.radio-group {
9+
display: flex;
10+
column-gap: awsui.$space-scaled-m;
11+
row-gap: awsui.$space-scaled-xs;
12+
&--horizontal {
13+
flex-direction: row;
14+
flex-wrap: wrap;
15+
}
16+
&--vertical {
17+
flex-direction: column;
18+
}
19+
}

pages/radio-button/table.page.tsx

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React, { useContext, useRef, useState } from 'react';
4+
import clsx from 'clsx';
5+
6+
import Box from '~components/box';
7+
import Checkbox from '~components/checkbox';
8+
import FormField from '~components/form-field';
9+
import RadioButton, { RadioButtonProps } from '~components/radio-button';
10+
import SpaceBetween from '~components/space-between';
11+
12+
import AppContext, { AppContextType } from '../app/app-context';
13+
import ScreenshotArea from '../utils/screenshot-area';
14+
15+
import styles from './table.scss';
16+
17+
type RadioButtonDemoContext = React.Context<
18+
AppContextType<{
19+
disabled?: boolean;
20+
readOnly?: boolean;
21+
}>
22+
>;
23+
24+
const Row = ({
25+
value,
26+
label,
27+
checked,
28+
setValue,
29+
description,
30+
disabled,
31+
readOnly,
32+
}: Omit<RadioButtonProps, 'name'> & { label: string; setValue: (_a: string) => void }) => {
33+
const ref = useRef<HTMLInputElement>(null);
34+
return (
35+
<tr className={clsx(styles.row, checked && styles['row--selected'])}>
36+
<td className={styles.cell}>
37+
<label aria-label={`Select ${label}`}>
38+
<RadioButton
39+
value={value}
40+
name="quantity"
41+
checked={checked}
42+
disabled={disabled}
43+
readOnly={readOnly}
44+
onChange={({ detail }) => {
45+
setValue(detail.value);
46+
ref.current?.focus();
47+
}}
48+
ref={ref}
49+
/>
50+
</label>
51+
</td>
52+
<td className={styles.cell}>
53+
<a href="#">{label}</a>
54+
</td>
55+
<td className={styles.cell}>{description}</td>
56+
</tr>
57+
);
58+
};
59+
60+
export default function RadioButtonsTablePage() {
61+
const { urlParams, setUrlParams } = useContext(AppContext as RadioButtonDemoContext);
62+
63+
const [value, setValue] = useState<string>('');
64+
65+
return (
66+
<article>
67+
<h1>Radio button — custom table selection</h1>
68+
<Box margin={{ horizontal: 'm' }}>
69+
<SpaceBetween size="s">
70+
<FormField label="Options">
71+
<SpaceBetween size="s">
72+
<Checkbox
73+
checked={!!urlParams.disabled}
74+
onChange={({ detail }) => setUrlParams({ ...urlParams, disabled: detail.checked })}
75+
description="Make one of the radio buttons disabled"
76+
>
77+
Disabled
78+
</Checkbox>
79+
80+
<Checkbox
81+
checked={!!urlParams.readOnly}
82+
onChange={({ detail }) => setUrlParams({ ...urlParams, readOnly: detail.checked })}
83+
description="Make one of the radio buttons read-only"
84+
>
85+
Read-only
86+
</Checkbox>
87+
</SpaceBetween>
88+
</FormField>
89+
</SpaceBetween>
90+
</Box>
91+
<hr />
92+
<ScreenshotArea disableAnimations={true}>
93+
<table className={styles.table}>
94+
<thead className={styles.head}>
95+
<tr className={styles.row}>
96+
<th className={styles['header-cell']}></th>
97+
<th className={styles['header-cell']}>Name</th>
98+
<th className={styles['header-cell']}>Description</th>
99+
</tr>
100+
</thead>
101+
<tbody>
102+
<Row value="one" checked={value === 'one'} setValue={setValue} label="One" description="First option">
103+
One
104+
</Row>
105+
<Row
106+
value="two"
107+
checked={value === 'two'}
108+
disabled={urlParams.disabled}
109+
readOnly={urlParams.readOnly}
110+
setValue={setValue}
111+
label="Two"
112+
description="Second option"
113+
>
114+
Two
115+
</Row>
116+
<Row value="three" checked={value === 'three'} setValue={setValue} label="Three" description="Third option">
117+
Three
118+
</Row>
119+
</tbody>
120+
</table>
121+
</ScreenshotArea>
122+
</article>
123+
);
124+
}

pages/radio-button/table.scss

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
@use '~design-tokens' as awsui;
7+
8+
.table {
9+
border-collapse: collapse;
10+
}
11+
12+
.head {
13+
background-color: awsui.$color-background-cell-shaded;
14+
}
15+
16+
.cell,
17+
.header-cell {
18+
padding-inline: awsui.$space-scaled-s;
19+
}
20+
21+
.cell {
22+
padding-block: awsui.$space-scaled-xs;
23+
}
24+
25+
.header-cell,
26+
.row {
27+
border-block-style: solid;
28+
border-inline-style: solid;
29+
border-block-width: 1px;
30+
border-inline-width: 1px;
31+
border-color: awsui.$color-border-divider-default;
32+
}
33+
34+
.header-cell {
35+
padding-block: awsui.$space-scaled-xxs;
36+
text-align: start;
37+
}
38+
39+
.row {
40+
&--selected {
41+
outline: 1px solid awsui.$color-border-item-focused;
42+
}
43+
}

0 commit comments

Comments
 (0)