diff --git a/pages/progress-bar/style-api-v2.page.tsx b/pages/progress-bar/style-api-v2.page.tsx
new file mode 100644
index 0000000000..7d6cd0f858
--- /dev/null
+++ b/pages/progress-bar/style-api-v2.page.tsx
@@ -0,0 +1,21 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import React from 'react';
+
+import { ProgressBar } from '~components';
+
+import { SimplePage } from '../app/templates';
+
+import styles from './style-api-v2.scss';
+
+const brand = { styleClassNames: { progressBar: styles['bar-brand'], progressPercentage: styles['percentage-brand'] } };
+const genai = { styleClassNames: { progressBar: styles['bar-genai'], progressPercentage: styles['percentage-genai'] } };
+
+export default function () {
+ return (
+
+
+
+
+ );
+}
diff --git a/pages/progress-bar/style-api-v2.scss b/pages/progress-bar/style-api-v2.scss
new file mode 100644
index 0000000000..b314ec4b00
--- /dev/null
+++ b/pages/progress-bar/style-api-v2.scss
@@ -0,0 +1,37 @@
+/*
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ SPDX-License-Identifier: Apache-2.0
+*/
+
+@use '@cloudscape-design/component-toolkit/styling' as styling;
+@use '../style-api/palette' as palette;
+
+.bar-brand {
+ --awsui-style-track-color: #{palette.$subtle};
+ --awsui-style-value-color: #{palette.$accent};
+ --awsui-style-border-radius: 2px;
+ --awsui-style-block-size: 8px;
+}
+
+.bar-genai {
+ --awsui-style-track-color: #{palette.$genai-surface};
+ --awsui-style-value-color: #{palette.$genai};
+ --awsui-style-border-radius: 0;
+ --awsui-style-block-size: 12px;
+}
+
+.percentage-brand {
+ @include styling.override {
+ color: palette.$accent;
+ font-size: 14px;
+ font-weight: 700;
+ }
+}
+
+.percentage-genai {
+ @include styling.override {
+ color: palette.$genai-text;
+ font-size: 16px;
+ font-weight: 600;
+ }
+}
diff --git a/src/__tests__/snapshot-tests/__snapshots__/style-docs.test.ts.snap b/src/__tests__/snapshot-tests/__snapshots__/style-docs.test.ts.snap
index 0ec1499e58..2d38b568b1 100644
--- a/src/__tests__/snapshot-tests/__snapshots__/style-docs.test.ts.snap
+++ b/src/__tests__/snapshot-tests/__snapshots__/style-docs.test.ts.snap
@@ -174,6 +174,37 @@ exports[`Style API docs definition for link matches the snapshot: link 1`] = `
}
`;
+exports[`Style API docs definition for progress-bar matches the snapshot: progress-bar 1`] = `
+{
+ "slots": [
+ {
+ "name": "progressBar",
+ "properties": [],
+ "propertyDescriptions": {},
+ "tokenDescriptions": {},
+ "tokens": [
+ "track-color",
+ "value-color",
+ "border-radius",
+ "block-size",
+ ],
+ },
+ {
+ "name": "progressPercentage",
+ "properties": [
+ "color",
+ "font-family",
+ "font-size",
+ "font-weight",
+ ],
+ "propertyDescriptions": {},
+ "tokenDescriptions": {},
+ "tokens": [],
+ },
+ ],
+}
+`;
+
exports[`Style API docs definition for radio-button matches the snapshot: radio-button 1`] = `
{
"slots": [
@@ -245,6 +276,7 @@ exports[`Style API docs list of components with a Style API doc matches the snap
"checkbox",
"dropdown",
"link",
+ "progress-bar",
"radio-button",
"toggle",
]
diff --git a/src/internal/styles/style-api.scss b/src/internal/styles/style-api.scss
index a245639edf..8e3a8eddfd 100644
--- a/src/internal/styles/style-api.scss
+++ b/src/internal/styles/style-api.scss
@@ -51,9 +51,9 @@ $_focus-ring-carriers: toolkit.resolve($focus-ring, carrier);
}
}
-@mixin docs($name, $map) {
+@mixin docs($name, $tokens: null, $properties: null, $descriptions: null) {
@if enabled() {
- @include toolkit.docs($name, $map);
+ @include toolkit.docs($name, $tokens, $properties, $descriptions);
}
}
diff --git a/src/progress-bar/__tests__/style-api.test.tsx b/src/progress-bar/__tests__/style-api.test.tsx
new file mode 100644
index 0000000000..c1c4e3baf4
--- /dev/null
+++ b/src/progress-bar/__tests__/style-api.test.tsx
@@ -0,0 +1,38 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+import React from 'react';
+import { render } from '@testing-library/react';
+
+import ProgressBar, { ProgressBarProps } from '../../../lib/components/progress-bar';
+import createWrapper from '../../../lib/components/test-utils/dom';
+
+function renderProgressBar(props: Partial & Record = {}) {
+ const { container } = render();
+ return { container, wrapper: createWrapper(container).findProgressBar()! };
+}
+
+describe('ProgressBar Style API v2', () => {
+ test.each(['standalone', 'flash', 'key-value'])(
+ 'applies styleClassNames (variant=%s)',
+ variant => {
+ const { wrapper } = renderProgressBar({
+ variant,
+ styleClassNames: { progressBar: 'a', progressPercentage: 'b', unknown: 'c' },
+ });
+ const progress = wrapper.find('progress')!.getElement();
+ expect(progress).toHaveClass('a');
+ expect(progress).not.toHaveClass('b');
+ expect(progress).not.toHaveClass('c');
+
+ const percentage = wrapper.findPercentageText()!.getElement();
+ expect(percentage).not.toHaveClass('a');
+ expect(percentage).toHaveClass('b');
+ expect(percentage).not.toHaveClass('c');
+ }
+ );
+
+ test('does not leak the styleClassNames prop to the DOM', () => {
+ const { container } = renderProgressBar({ styleClassNames: { progressBar: 'a', progressPercentage: 'b' } });
+ expect(container.querySelector('[styleClassNames]')).toBeNull();
+ });
+});
diff --git a/src/progress-bar/index.tsx b/src/progress-bar/index.tsx
index 5c1737f059..437571e4f2 100644
--- a/src/progress-bar/index.tsx
+++ b/src/progress-bar/index.tsx
@@ -14,7 +14,7 @@ import { applyDisplayName } from '../internal/utils/apply-display-name';
import { joinStrings } from '../internal/utils/strings';
import InternalLiveRegion from '../live-region/internal';
import { ProgressBarProps } from './interfaces';
-import { Progress, ResultState, SmallText } from './internal';
+import { Progress, ResultState, SmallText, StyleClassNames } from './internal';
import styles from './styles.css.js';
@@ -41,7 +41,8 @@ export default function ProgressBar({
const { __internalRootRef } = useBaseComponent('ProgressBar', {
props: { variant },
});
- const baseProps = getBaseProps(rest);
+ const { styleClassNames, ...restProps } = rest as typeof rest & { styleClassNames?: StyleClassNames };
+ const baseProps = getBaseProps(restProps);
const generatedName = useUniqueId('awsui-progress-bar-');
const labelId = `${generatedName}-label`;
@@ -101,6 +102,7 @@ export default function ProgressBar({
)}
isInFlash={isInFlash}
style={style}
+ styleClassNames={styleClassNames}
/>
{label}
diff --git a/src/progress-bar/internal.tsx b/src/progress-bar/internal.tsx
index f8a0c785a8..c748541baf 100644
--- a/src/progress-bar/internal.tsx
+++ b/src/progress-bar/internal.tsx
@@ -26,9 +26,24 @@ interface ProgressProps {
ariaLabelledby?: string;
ariaDescribedby?: string;
style?: ProgressBarProps.Style;
+ styleClassNames?: StyleClassNames;
}
-export const Progress = ({ value, isInFlash, ariaLabel, ariaLabelledby, ariaDescribedby, style }: ProgressProps) => {
+// Style API v2
+export interface StyleClassNames {
+ progressBar?: string;
+ progressPercentage?: string;
+}
+
+export const Progress = ({
+ value,
+ isInFlash,
+ ariaLabel,
+ ariaLabelledby,
+ ariaDescribedby,
+ style,
+ styleClassNames,
+}: ProgressProps) => {
const roundedValue = Math.round(value);
const progressValue = clamp(roundedValue, 0, MAX_VALUE);
@@ -40,6 +55,7 @@ export const Progress = ({ value, isInFlash, ariaLabel, ariaLabelledby, ariaDesc
);
diff --git a/src/progress-bar/styles.scss b/src/progress-bar/styles.scss
index 49bd3e65c1..84ec1c4d2e 100644
--- a/src/progress-bar/styles.scss
+++ b/src/progress-bar/styles.scss
@@ -6,17 +6,43 @@
@use '../internal/styles/tokens' as awsui;
@use '../internal/styles' as styles;
@use '../internal/generated/custom-css-properties/index.scss' as custom-props;
+@use '../internal/styles/style-api' as style-api;
@use './motion';
-$progress-height: var(#{custom-props.$progressBarHeight}, 0.4 * styles.$base-size);
-$progress-border-radius: var(#{custom-props.$progressBarBorderRadius}, 10px);
-$progress-background-color: var(
- #{custom-props.$progressBarBackgroundColor},
- awsui.$color-background-progress-bar-default
+$progress-bar-tokens: style-api.resolve((track-color, value-color, border-radius, block-size), carrier);
+@include style-api.register($progress-bar-tokens);
+@include style-api.docs('progressBar', $progress-bar-tokens);
+@include style-api.docs('progressPercentage', $properties: (color, font-family, font-size, font-weight));
+
+$progress-height: style-api.value(
+ $progress-bar-tokens,
+ block-size,
+ var(#{custom-props.$progressBarHeight}, 0.4 * styles.$base-size)
+);
+$progress-border-radius: style-api.value(
+ $progress-bar-tokens,
+ border-radius,
+ var(#{custom-props.$progressBarBorderRadius}, 10px)
+);
+$progress-background-color: style-api.value(
+ $progress-bar-tokens,
+ track-color,
+ var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-default)
+);
+$progress-value-background-color: style-api.value(
+ $progress-bar-tokens,
+ value-color,
+ var(#{custom-props.$progressValueBackgroundColor}, awsui.$color-background-progress-bar-value-default)
);
-$progress-value-background-color: var(
- #{custom-props.$progressValueBackgroundColor},
- awsui.$color-background-progress-bar-value-default
+$progress-flash-background-color: style-api.value(
+ $progress-bar-tokens,
+ track-color,
+ var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash)
+);
+$progress-flash-value-background-color: style-api.value(
+ $progress-bar-tokens,
+ value-color,
+ var(#{custom-props.$progressValueBackgroundColor}, awsui.$color-background-progress-bar-value-flash)
);
.root {
@@ -79,7 +105,19 @@ $progress-value-background-color: var(
}
.percentage {
- /* used in test-utils */
+ display: inline-block;
+ font-family: awsui.$font-family-base;
+ -webkit-font-smoothing: auto;
+ -moz-osx-font-smoothing: auto;
+ line-height: awsui.$line-height-body-s;
+ letter-spacing: awsui.$letter-spacing-body-s;
+ color: awsui.$color-text-small;
+ font-size: awsui.$font-size-body-s;
+ font-weight: styles.$font-weight-normal;
+
+ &.percentage-flash {
+ color: currentColor;
+ }
}
@mixin general-progress-background-style {
@@ -101,6 +139,7 @@ $progress-value-background-color: var(
}
.progress {
+ @include style-api.carriers($progress-bar-tokens);
inline-size: 100%;
margin-inline-end: awsui.$space-s;
min-inline-size: 0;
@@ -131,22 +170,16 @@ $progress-value-background-color: var(
}
&.progress-flash {
- background-color: var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash);
+ background-color: $progress-flash-background-color;
&::-webkit-progress-bar {
- background-color: var(#{custom-props.$progressBarBackgroundColor}, awsui.$color-background-progress-bar-flash);
+ background-color: $progress-flash-background-color;
}
&::-webkit-progress-value {
- background-color: var(
- #{custom-props.$progressValueBackgroundColor},
- awsui.$color-background-progress-bar-value-flash
- );
+ background-color: $progress-flash-value-background-color;
}
&::-moz-progress-bar {
- background-color: var(
- #{custom-props.$progressValueBackgroundColor},
- awsui.$color-background-progress-bar-value-flash
- );
+ background-color: $progress-flash-value-background-color;
}
}
}