Skip to content

Commit 56db88d

Browse files
committed
chore: Styling v2 for slider and progress bar
1 parent 1f35242 commit 56db88d

13 files changed

Lines changed: 505 additions & 142 deletions

File tree

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React from 'react';
4+
5+
import { ProgressBar } from '~components';
6+
7+
import { SimplePage } from '../app/templates';
8+
9+
import styles from './style-api-v2.scss';
10+
11+
const brand = { styleClassNames: { bar: styles['bar-brand'], percentage: styles['percentage-brand'] } };
12+
const genai = { styleClassNames: { bar: styles['bar-genai'], percentage: styles['percentage-genai'] } };
13+
14+
export default function () {
15+
return (
16+
<SimplePage title="Progress bar - Style API v2" screenshotArea={{}}>
17+
<ProgressBar value={45} label="Attachments" description="Files are uploading" {...brand} />
18+
<ProgressBar value={72} label="Attachments" additionalInfo="You can add more files at any time" {...genai} />
19+
</SimplePage>
20+
);
21+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
@use '~components/styling/progress-bar';
7+
@use '../style-api/palette' as palette;
8+
9+
.bar-brand {
10+
@include progress-bar.bar(
11+
$track-color: palette.$subtle,
12+
$value-color: palette.$accent,
13+
$border-radius: 2px,
14+
$block-size: 8px
15+
);
16+
}
17+
18+
.bar-genai {
19+
@include progress-bar.bar(
20+
$track-color: palette.$genai-surface,
21+
$value-color: palette.$genai,
22+
$border-radius: 0,
23+
$block-size: 12px
24+
);
25+
}
26+
27+
.percentage-brand {
28+
@include progress-bar.percentage($color: palette.$accent, $font-size: 14px, $font-weight: 700);
29+
}
30+
31+
.percentage-genai {
32+
@include progress-bar.percentage($color: palette.$genai-text, $font-size: 16px, $font-weight: 600);
33+
}

‎pages/slider/style-api-v2.page.tsx‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React, { useState } from 'react';
4+
5+
import { KeyValuePairs, Slider } from '~components';
6+
7+
import { SimplePage } from '../app/templates';
8+
9+
import styles from './style-api-v2.scss';
10+
11+
const styleClassNames = { root: styles.slider, handle: styles.handle };
12+
13+
export default function () {
14+
const [value, setValue] = useState(40);
15+
return (
16+
<SimplePage title="Slider - Style API v2" screenshotArea={{}}>
17+
<KeyValuePairs
18+
items={[
19+
{
20+
type: 'pair',
21+
label: 'With tick marks',
22+
value: (
23+
<Slider
24+
value={value}
25+
onChange={({ detail }) => setValue(detail.value)}
26+
min={0}
27+
max={100}
28+
step={20}
29+
tickMarks={true}
30+
ariaLabel="With tick marks"
31+
{...{ styleClassNames }}
32+
/>
33+
),
34+
},
35+
{
36+
type: 'pair',
37+
label: 'Disabled',
38+
value: (
39+
<Slider
40+
value={value}
41+
onChange={({ detail }) => setValue(detail.value)}
42+
min={0}
43+
max={100}
44+
disabled={true}
45+
ariaLabel="Disabled"
46+
{...{ styleClassNames }}
47+
/>
48+
),
49+
},
50+
{
51+
type: 'pair',
52+
label: 'Read-only',
53+
value: (
54+
<Slider
55+
value={value}
56+
onChange={({ detail }) => setValue(detail.value)}
57+
min={0}
58+
max={100}
59+
readOnly={true}
60+
ariaLabel="Read-only"
61+
{...{ styleClassNames }}
62+
/>
63+
),
64+
},
65+
]}
66+
/>
67+
</SimplePage>
68+
);
69+
}

‎pages/slider/style-api-v2.scss‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
/* stylelint-disable selector-combinator-disallowed-list */
7+
8+
@use '~components/styling/slider';
9+
@use '../style-api/palette' as palette;
10+
11+
.slider {
12+
@include slider.root($track-color: palette.$surface-alt, $value-color: palette.$accent);
13+
}
14+
15+
// The handle is the native <input type="range">, so its states are regular selectors.
16+
.handle {
17+
@include slider.handle($fill-color: palette.$accent, $halo-color: palette.$genai, $border-radius: 4px);
18+
19+
&:hover {
20+
@include slider.handle($fill-color: palette.$accent-hover);
21+
}
22+
23+
&:is(:focus, :active) {
24+
@include slider.handle($fill-color: palette.$accent-active);
25+
}
26+
27+
&:disabled,
28+
&[aria-disabled='true'] {
29+
@include slider.handle($fill-color: palette.$control-bg-disabled, $halo-color: palette.$control-bg-disabled);
30+
}
31+
}
32+
33+
// The value fill follows the handle state through :has() on the root slot.
34+
.slider:has(.handle:is(:focus, :active)) {
35+
@include slider.root($value-color: palette.$accent-active);
36+
}
37+
38+
// After the focus rule: a read-only slider stays focusable, and both rules have the same specificity.
39+
.slider:has(.handle:disabled, .handle[aria-disabled='true']) {
40+
@include slider.root($value-color: palette.$control-bg-disabled);
41+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
import React from 'react';
4+
import { render } from '@testing-library/react';
5+
6+
import ProgressBar, { ProgressBarProps } from '../../../lib/components/progress-bar';
7+
import createWrapper from '../../../lib/components/test-utils/dom';
8+
9+
function renderProgressBar(props: Partial<ProgressBarProps> & Record<string, unknown> = {}) {
10+
const { container } = render(<ProgressBar value={40} label="Label" {...props} />);
11+
return { container, wrapper: createWrapper(container).findProgressBar()! };
12+
}
13+
14+
describe('ProgressBar Style API v2', () => {
15+
test.each<ProgressBarProps.Variant>(['standalone', 'flash', 'key-value'])(
16+
'applies styleClassNames (variant=%s)',
17+
variant => {
18+
const { wrapper } = renderProgressBar({
19+
variant,
20+
styleClassNames: { bar: 'a', percentage: 'b', unknown: 'c' },
21+
});
22+
const progress = wrapper.find('progress')!.getElement();
23+
expect(progress).toHaveClass('a');
24+
expect(progress).not.toHaveClass('b');
25+
expect(progress).not.toHaveClass('c');
26+
27+
const percentage = wrapper.findPercentageText()!.getElement();
28+
expect(percentage).not.toHaveClass('a');
29+
expect(percentage).toHaveClass('b');
30+
expect(percentage).not.toHaveClass('c');
31+
}
32+
);
33+
34+
test('does not leak the styleClassNames prop to the DOM', () => {
35+
const { container } = renderProgressBar({ styleClassNames: { bar: 'a', percentage: 'b' } });
36+
expect(container.querySelector('[styleClassNames]')).toBeNull();
37+
});
38+
});

‎src/progress-bar/index.tsx‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { applyDisplayName } from '../internal/utils/apply-display-name';
1414
import { joinStrings } from '../internal/utils/strings';
1515
import InternalLiveRegion from '../live-region/internal';
1616
import { ProgressBarProps } from './interfaces';
17-
import { Progress, ResultState, SmallText } from './internal';
17+
import { Progress, ResultState, SmallText, StyleClassNames } from './internal';
1818

1919
import styles from './styles.css.js';
2020

@@ -41,7 +41,8 @@ export default function ProgressBar({
4141
const { __internalRootRef } = useBaseComponent('ProgressBar', {
4242
props: { variant },
4343
});
44-
const baseProps = getBaseProps(rest);
44+
const { styleClassNames, ...restProps } = rest as typeof rest & { styleClassNames?: StyleClassNames };
45+
const baseProps = getBaseProps(restProps);
4546
const generatedName = useUniqueId('awsui-progress-bar-');
4647

4748
const labelId = `${generatedName}-label`;
@@ -101,6 +102,7 @@ export default function ProgressBar({
101102
)}
102103
isInFlash={isInFlash}
103104
style={style}
105+
styleClassNames={styleClassNames}
104106
/>
105107
<InternalLiveRegion hidden={true} tagName="span" delay={0}>
106108
{label}

‎src/progress-bar/internal.tsx‎

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,24 @@ interface ProgressProps {
2626
ariaLabelledby?: string;
2727
ariaDescribedby?: string;
2828
style?: ProgressBarProps.Style;
29+
styleClassNames?: StyleClassNames;
2930
}
3031

31-
export const Progress = ({ value, isInFlash, ariaLabel, ariaLabelledby, ariaDescribedby, style }: ProgressProps) => {
32+
// Style API v2
33+
export interface StyleClassNames {
34+
bar?: string;
35+
percentage?: string;
36+
}
37+
38+
export const Progress = ({
39+
value,
40+
isInFlash,
41+
ariaLabel,
42+
ariaLabelledby,
43+
ariaDescribedby,
44+
style,
45+
styleClassNames,
46+
}: ProgressProps) => {
3247
const roundedValue = Math.round(value);
3348
const progressValue = clamp(roundedValue, 0, MAX_VALUE);
3449

@@ -40,6 +55,7 @@ export const Progress = ({ value, isInFlash, ariaLabel, ariaLabelledby, ariaDesc
4055
<div className={styles['progress-container']}>
4156
<progress
4257
className={clsx(
58+
styleClassNames?.bar,
4359
styles.progress,
4460
progressValue >= MAX_VALUE && styles.complete,
4561
isInFlash && styles['progress-flash']
@@ -56,14 +72,12 @@ export const Progress = ({ value, isInFlash, ariaLabel, ariaLabelledby, ariaDesc
5672
}}
5773
/>
5874
<span aria-hidden="true" className={styles['percentage-container']}>
59-
<InternalBox
60-
className={styles.percentage}
61-
variant="small"
62-
color={isInFlash ? 'inherit' : undefined}
63-
nativeAttributes={progressPercentageStyles ? { style: progressPercentageStyles } : undefined}
75+
<small
76+
className={clsx(styleClassNames?.percentage, styles.percentage, isInFlash && styles['percentage-flash'])}
77+
style={progressPercentageStyles}
6478
>
6579
{`${progressValue}%`}
66-
</InternalBox>
80+
</small>
6781
</span>
6882
</div>
6983
);

‎src/progress-bar/styles.scss‎

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,43 @@
66
@use '../internal/styles/tokens' as awsui;
77
@use '../internal/styles' as styles;
88
@use '../internal/generated/custom-css-properties/index.scss' as custom-props;
9+
@use '../internal/styles/style-api' as style-api;
910
@use './motion';
1011

11-
$progress-height: var(#{custom-props.$progressBarHeight}, 0.4 * styles.$base-size);
12-
$progress-border-radius: var(#{custom-props.$progressBarBorderRadius}, 10px);
13-
$progress-background-color: var(
14-
#{custom-props.$progressBarBackgroundColor},
15-
awsui.$color-background-progress-bar-default
12+
$progress-bar-tokens: style-api.resolve((track-color, value-color, border-radius, block-size), carrier);
13+
@include style-api.register($progress-bar-tokens);
14+
@include style-api.docs('bar', $progress-bar-tokens);
15+
@include style-api.docs('percentage', $properties: (color, font-family, font-size, font-weight));
16+
17+
$progress-height: style-api.value(
18+
$progress-bar-tokens,
19+
block-size,
20+
var(#{custom-props.$progressBarHeight}, 0.4 * styles.$base-size)
21+
);
22+
$progress-border-radius: style-api.value(
23+
$progress-bar-tokens,
24+
border-radius,
25+
var(#{custom-props.$progressBarBorderRadius}, 10px)
26+
);
27+
$progress-background-color: style-api.value(
28+
$progress-bar-tokens,
29+
track-color,
30+
var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-default)
31+
);
32+
$progress-value-background-color: style-api.value(
33+
$progress-bar-tokens,
34+
value-color,
35+
var(#{custom-props.$progressValueBackgroundColor}, awsui.$color-background-progress-bar-value-default)
1636
);
17-
$progress-value-background-color: var(
18-
#{custom-props.$progressValueBackgroundColor},
19-
awsui.$color-background-progress-bar-value-default
37+
$progress-flash-background-color: style-api.value(
38+
$progress-bar-tokens,
39+
track-color,
40+
var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash)
41+
);
42+
$progress-flash-value-background-color: style-api.value(
43+
$progress-bar-tokens,
44+
value-color,
45+
var(#{custom-props.$progressValueBackgroundColor}, awsui.$color-background-progress-bar-value-flash)
2046
);
2147

2248
.root {
@@ -79,7 +105,19 @@ $progress-value-background-color: var(
79105
}
80106

81107
.percentage {
82-
/* used in test-utils */
108+
display: inline-block;
109+
font-family: awsui.$font-family-base;
110+
-webkit-font-smoothing: auto;
111+
-moz-osx-font-smoothing: auto;
112+
line-height: awsui.$line-height-body-s;
113+
letter-spacing: awsui.$letter-spacing-body-s;
114+
color: awsui.$color-text-small;
115+
font-size: awsui.$font-size-body-s;
116+
font-weight: styles.$font-weight-normal;
117+
118+
&.percentage-flash {
119+
color: currentColor;
120+
}
83121
}
84122

85123
@mixin general-progress-background-style {
@@ -101,6 +139,7 @@ $progress-value-background-color: var(
101139
}
102140

103141
.progress {
142+
@include style-api.carriers($progress-bar-tokens);
104143
inline-size: 100%;
105144
margin-inline-end: awsui.$space-s;
106145
min-inline-size: 0;
@@ -131,22 +170,16 @@ $progress-value-background-color: var(
131170
}
132171

133172
&.progress-flash {
134-
background-color: var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash);
173+
background-color: $progress-flash-background-color;
135174

136175
&::-webkit-progress-bar {
137-
background-color: var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash);
176+
background-color: $progress-flash-background-color;
138177
}
139178
&::-webkit-progress-value {
140-
background-color: var(
141-
#{custom-props.$progressValueBackgroundColor},
142-
awsui.$color-background-progress-bar-value-flash
143-
);
179+
background-color: $progress-flash-value-background-color;
144180
}
145181
&::-moz-progress-bar {
146-
background-color: var(
147-
#{custom-props.$progressValueBackgroundColor},
148-
awsui.$color-background-progress-bar-value-flash
149-
);
182+
background-color: $progress-flash-value-background-color;
150183
}
151184
}
152185
}

0 commit comments

Comments
 (0)