Skip to content

Commit 4e4cdd5

Browse files
authored
feat: implement style api for progress bar component (#4022)
1 parent a63fb57 commit 4e4cdd5

File tree

9 files changed

+448
-27
lines changed

9 files changed

+448
-27
lines changed

build-tools/utils/custom-css-properties.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,5 +116,10 @@ const customCssPropertiesList = [
116116
'alertFocusRingBorderWidth',
117117
'alertFocusRingBoxShadow',
118118
'alertIconColor',
119+
// Progress bar style properties
120+
'progressBarBackgroundColor',
121+
'progressBarBorderRadius',
122+
'progressBarHeight',
123+
'progressValueBackgroundColor',
119124
];
120125
module.exports = customCssPropertiesList;
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
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, { ProgressBarProps } from '~components/progress-bar';
6+
7+
import createPermutations from '../utils/permutations';
8+
import PermutationsView from '../utils/permutations-view';
9+
import ScreenshotArea from '../utils/screenshot-area';
10+
11+
const permutations = createPermutations<ProgressBarProps>([
12+
{
13+
value: [45, 75, 99, 100],
14+
status: ['in-progress'],
15+
style: [
16+
{
17+
progressBar: {
18+
backgroundColor: '#ccfbf1',
19+
borderRadius: '8px',
20+
height: '8px',
21+
},
22+
progressValue: {
23+
backgroundColor: '#14b8a6',
24+
},
25+
progressPercentage: {
26+
color: 'light-dark(#0d5c54, #5eead4)',
27+
fontSize: '14px',
28+
fontWeight: '600',
29+
},
30+
},
31+
{
32+
progressBar: {
33+
backgroundColor: '#fee2e2',
34+
borderRadius: '4px',
35+
height: '10px',
36+
},
37+
progressValue: {
38+
backgroundColor: '#ef4444',
39+
},
40+
progressPercentage: {
41+
color: 'light-dark(#7f1d1d, #fca5a5)',
42+
fontSize: '14px',
43+
fontWeight: '600',
44+
},
45+
},
46+
{
47+
progressBar: {
48+
backgroundColor: '#fef3c7',
49+
borderRadius: '16px',
50+
height: '10px',
51+
},
52+
progressValue: {
53+
backgroundColor: '#f59e0b',
54+
},
55+
progressPercentage: {
56+
color: 'light-dark(#78350f, #fcd34d)',
57+
fontSize: '16px',
58+
fontWeight: '700',
59+
},
60+
},
61+
{
62+
progressBar: {
63+
backgroundColor: '#dbeafe',
64+
borderRadius: '4px',
65+
height: '6px',
66+
},
67+
progressValue: {
68+
backgroundColor: '#3b82f6',
69+
},
70+
progressPercentage: {
71+
color: 'light-dark(#1e40af, #93c5fd)',
72+
fontSize: '12px',
73+
fontWeight: '500',
74+
},
75+
},
76+
{
77+
progressBar: {
78+
backgroundColor: '#f3e8ff',
79+
borderRadius: '0px',
80+
height: '12px',
81+
},
82+
progressValue: {
83+
backgroundColor: '#a855f7',
84+
},
85+
progressPercentage: {
86+
color: 'light-dark(#6b21a8, #d8b4fe)',
87+
fontSize: '16px',
88+
fontWeight: '700',
89+
},
90+
},
91+
],
92+
},
93+
]);
94+
95+
export default function ProgressBarStylePermutations() {
96+
return (
97+
<>
98+
<h1>Progress Bar Style permutations</h1>
99+
<ScreenshotArea disableAnimations={true}>
100+
<PermutationsView permutations={permutations} render={permutation => <ProgressBar {...permutation} />} />
101+
</ScreenshotArea>
102+
</>
103+
);
104+
}

src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18391,6 +18391,88 @@ Add a button using the \`action\` property of the flashbar item instead.",
1839118391
"optional": true,
1839218392
"type": "string",
1839318393
},
18394+
{
18395+
"inlineType": {
18396+
"name": "ProgressBarProps.Style",
18397+
"properties": [
18398+
{
18399+
"inlineType": {
18400+
"name": "object",
18401+
"properties": [
18402+
{
18403+
"name": "backgroundColor",
18404+
"optional": true,
18405+
"type": "string",
18406+
},
18407+
{
18408+
"name": "borderRadius",
18409+
"optional": true,
18410+
"type": "string",
18411+
},
18412+
{
18413+
"name": "height",
18414+
"optional": true,
18415+
"type": "string",
18416+
},
18417+
],
18418+
"type": "object",
18419+
},
18420+
"name": "progressBar",
18421+
"optional": true,
18422+
"type": "{ backgroundColor?: string | undefined; borderRadius?: string | undefined; height?: string | undefined; }",
18423+
},
18424+
{
18425+
"inlineType": {
18426+
"name": "{ color?: string | undefined; fontSize?: string | undefined; fontWeight?: string | undefined; }",
18427+
"properties": [
18428+
{
18429+
"name": "color",
18430+
"optional": true,
18431+
"type": "string",
18432+
},
18433+
{
18434+
"name": "fontSize",
18435+
"optional": true,
18436+
"type": "string",
18437+
},
18438+
{
18439+
"name": "fontWeight",
18440+
"optional": true,
18441+
"type": "string",
18442+
},
18443+
],
18444+
"type": "object",
18445+
},
18446+
"name": "progressPercentage",
18447+
"optional": true,
18448+
"type": "{ color?: string | undefined; fontSize?: string | undefined; fontWeight?: string | undefined; }",
18449+
},
18450+
{
18451+
"inlineType": {
18452+
"name": "{ backgroundColor?: string | undefined; }",
18453+
"properties": [
18454+
{
18455+
"name": "backgroundColor",
18456+
"optional": true,
18457+
"type": "string",
18458+
},
18459+
],
18460+
"type": "object",
18461+
},
18462+
"name": "progressValue",
18463+
"optional": true,
18464+
"type": "{ backgroundColor?: string | undefined; }",
18465+
},
18466+
],
18467+
"type": "object",
18468+
},
18469+
"name": "style",
18470+
"optional": true,
18471+
"systemTags": [
18472+
"core",
18473+
],
18474+
"type": "ProgressBarProps.Style",
18475+
},
1839418476
{
1839518477
"defaultValue": "0",
1839618478
"description": "Indicates the current progress as a percentage. The value must be between 0 and 100. Decimals are rounded.",
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import customCssProps from '../../internal/generated/custom-css-properties';
5+
import { getProgressPercentageStyles, getProgressStyles, getProgressValueStyles } from '../styles';
6+
7+
// Mock the environment module
8+
jest.mock('../../internal/environment', () => ({
9+
SYSTEM: 'core',
10+
}));
11+
12+
describe('getProgressStyles', () => {
13+
afterEach(() => {
14+
jest.resetModules();
15+
});
16+
17+
test('returns undefined when no style is provided', () => {
18+
expect(getProgressStyles(undefined)).toBeUndefined();
19+
expect(getProgressStyles({})).toBeUndefined();
20+
});
21+
22+
test('returns progress bar styles when provided', () => {
23+
const style = {
24+
progressBar: {
25+
backgroundColor: '#e0e0e0',
26+
borderRadius: '8px',
27+
height: '8px',
28+
},
29+
};
30+
31+
expect(getProgressStyles(style)).toEqual({
32+
[customCssProps.progressBarBackgroundColor]: '#e0e0e0',
33+
[customCssProps.progressBarBorderRadius]: '8px',
34+
[customCssProps.progressBarHeight]: '8px',
35+
});
36+
});
37+
38+
test('returns undefined when SYSTEM is not core', async () => {
39+
jest.resetModules();
40+
jest.doMock('../../internal/environment', () => ({
41+
SYSTEM: 'visual-refresh',
42+
}));
43+
44+
const { getProgressStyles: getProgressStylesNonCore } = await import('../styles');
45+
46+
const style = {
47+
progressBar: {
48+
backgroundColor: '#e0e0e0',
49+
},
50+
};
51+
52+
expect(getProgressStylesNonCore(style)).toBeUndefined();
53+
});
54+
});
55+
56+
describe('getProgressValueStyles', () => {
57+
afterEach(() => {
58+
jest.resetModules();
59+
});
60+
61+
test('returns undefined when no style is provided', () => {
62+
expect(getProgressValueStyles(undefined)).toBeUndefined();
63+
expect(getProgressValueStyles({})).toBeUndefined();
64+
});
65+
66+
test('returns progress value styles when provided', () => {
67+
const style = {
68+
progressValue: {
69+
backgroundColor: '#0073bb',
70+
},
71+
};
72+
73+
expect(getProgressValueStyles(style)).toEqual({
74+
[customCssProps.progressValueBackgroundColor]: '#0073bb',
75+
});
76+
});
77+
78+
test('returns undefined when SYSTEM is not core', async () => {
79+
jest.resetModules();
80+
jest.doMock('../../internal/environment', () => ({
81+
SYSTEM: 'visual-refresh',
82+
}));
83+
84+
const { getProgressValueStyles: getProgressValueStylesNonCore } = await import('../styles');
85+
86+
const style = {
87+
progressValue: {
88+
backgroundColor: '#0073bb',
89+
},
90+
};
91+
92+
expect(getProgressValueStylesNonCore(style)).toBeUndefined();
93+
});
94+
});
95+
96+
describe('getProgressPercentageStyles', () => {
97+
afterEach(() => {
98+
jest.resetModules();
99+
});
100+
101+
test('returns undefined when no style is provided', () => {
102+
expect(getProgressPercentageStyles(undefined)).toBeUndefined();
103+
expect(getProgressPercentageStyles({})).toBeUndefined();
104+
});
105+
106+
test('returns progress percentage styles when provided', () => {
107+
const style = {
108+
progressPercentage: {
109+
color: '#0073bb',
110+
fontSize: '14px',
111+
fontWeight: '600',
112+
},
113+
};
114+
115+
expect(getProgressPercentageStyles(style)).toEqual({
116+
color: '#0073bb',
117+
fontSize: '14px',
118+
fontWeight: '600',
119+
});
120+
});
121+
122+
test('returns undefined when SYSTEM is not core', async () => {
123+
jest.resetModules();
124+
jest.doMock('../../internal/environment', () => ({
125+
SYSTEM: 'visual-refresh',
126+
}));
127+
128+
const { getProgressPercentageStyles: getProgressPercentageStylesNonCore } = await import('../styles');
129+
130+
const style = {
131+
progressPercentage: {
132+
color: '#0073bb',
133+
},
134+
};
135+
136+
expect(getProgressPercentageStylesNonCore(style)).toBeUndefined();
137+
});
138+
});

src/progress-bar/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export default function ProgressBar({
3535
additionalInfo,
3636
resultText,
3737
onResultButtonClick,
38+
style,
3839
...rest
3940
}: ProgressBarProps) {
4041
const { __internalRootRef } = useBaseComponent('ProgressBar', {
@@ -96,6 +97,7 @@ export default function ProgressBar({
9697
ariaDescribedby
9798
)}
9899
isInFlash={isInFlash}
100+
style={style}
99101
/>
100102
<InternalLiveRegion hidden={true} tagName="span" delay={0}>
101103
{label}

src/progress-bar/interfaces.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,30 @@ export interface ProgressBarProps extends BaseComponentProps {
8282
* Use the `buttonText` property and the `onButtonClick` event listener of the flashbar item instead.
8383
*/
8484
onResultButtonClick?: NonCancelableEventHandler;
85+
86+
/**
87+
* @awsuiSystem core
88+
*/
89+
style?: ProgressBarProps.Style;
8590
}
8691

8792
export namespace ProgressBarProps {
8893
export type Status = 'in-progress' | 'success' | 'error';
8994
export type Variant = 'standalone' | 'flash' | 'key-value';
95+
96+
export interface Style {
97+
progressBar?: {
98+
backgroundColor?: string;
99+
borderRadius?: string;
100+
height?: string;
101+
};
102+
progressValue?: {
103+
backgroundColor?: string;
104+
};
105+
progressPercentage?: {
106+
color?: string;
107+
fontSize?: string;
108+
fontWeight?: string;
109+
};
110+
}
90111
}

0 commit comments

Comments
 (0)