From 08d24680983acc1f80bd699b33eec33954dee180 Mon Sep 17 00:00:00 2001 From: at-susie Date: Tue, 23 Jun 2026 16:48:12 +0200 Subject: [PATCH] chore: Explore new VisualAccent component --- pages/visual-accent/simple.page.tsx | 183 ++++++++++++++++++++++++++++ src/visual-accent/index.tsx | 46 +++++++ src/visual-accent/interfaces.ts | 54 ++++++++ src/visual-accent/styles.scss | 147 ++++++++++++++++++++++ 4 files changed, 430 insertions(+) create mode 100644 pages/visual-accent/simple.page.tsx create mode 100644 src/visual-accent/index.tsx create mode 100644 src/visual-accent/interfaces.ts create mode 100644 src/visual-accent/styles.scss diff --git a/pages/visual-accent/simple.page.tsx b/pages/visual-accent/simple.page.tsx new file mode 100644 index 0000000000..9b03fb355b --- /dev/null +++ b/pages/visual-accent/simple.page.tsx @@ -0,0 +1,183 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React from 'react'; + +import Box from '~components/box'; +import ButtonDropdown from '~components/button-dropdown'; +import CopyToClipboard from '~components/copy-to-clipboard'; +import KeyValuePairs from '~components/key-value-pairs'; +import Link from '~components/link'; +import List from '~components/list'; +import ProgressBar from '~components/progress-bar'; +import SpaceBetween from '~components/space-between'; +import StatusIndicator from '~components/status-indicator'; +import VisualAccent, { VisualAccentProps } from '~components/visual-accent'; + +// ─── Data ────────────────────────────────────────────────────────────────────── + +const ALL_COLORS: VisualAccentProps.Color[] = [ + 'red', + 'yellow', + 'indigo', + 'green', + 'orange', + 'purple', + 'mint', + 'lime', + 'grey', +]; + +const LIST_ITEMS: { id: string; content: string; icon: string; color: VisualAccentProps.Color }[] = [ + { id: 'health', content: 'Health overview', icon: 'face-happy', color: 'green' }, + { id: 'functions', content: 'Functions', icon: 'script', color: 'indigo' }, + { id: 'network', content: 'Network configuration', icon: 'globe', color: 'grey' }, + { id: 'multi-session', content: 'Multi-session data', icon: 'multiscreen', color: 'purple' }, + { id: 'alert', content: 'Alert center', icon: 'security', color: 'red' }, + { id: 'communication', content: 'Communication', icon: 'contact', color: 'mint' }, +]; + +// ─── Page ────────────────────────────────────────────────────────────────────── + +export default function VisualAccentPage() { + return ( +
+ + VisualAccent component — Direction 5 + + + + A standalone component with content, iconName, color, and{' '} + shape props. No visual context, no wrapper pattern. + + + {/* ── Text with sharp shape ─────────────────────────────────────── */} + + Text content (shape="sharp") + + + + fontSize="heading-m" + + + {ALL_COLORS.map(color => ( + + ))} + + + + fontSize="heading-s" + + + {ALL_COLORS.map(color => ( + + ))} + + + + fontSize="body-m" + + + {ALL_COLORS.map(color => ( + + ))} + + + {/* ── Icons with circle shape ───────────────────────────────────── */} + + Icons (shape="circle") + + + {ALL_COLORS.map(color => ( + + ))} + + + {/* ── Application in components ──────────────────────────────────── */} + + Application in components + + + + KeyValuePairs + + , + info: ( + + Info + + ), + }, + { + label: 'ARN', + value: ( + + ), + }, + { + label: 'Status', + value: Available, + }, + { + label: 'SSL Certificate', + id: 'ssl-certificate-id', + value: ( + + ), + }, + { + label: 'Price class', + value: , + }, + { + label: 'CNAMEs', + value: ( + + abc.service23G24.xyz + + ), + }, + ]} + /> + + + List + + ({ + id: item.id, + content: item.content, + icon: , + actions: ( + + ), + })} + /> +
+ ); +} diff --git a/src/visual-accent/index.tsx b/src/visual-accent/index.tsx new file mode 100644 index 0000000000..2adcf3bfbe --- /dev/null +++ b/src/visual-accent/index.tsx @@ -0,0 +1,46 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +'use client'; +import React from 'react'; +import clsx from 'clsx'; + +import InternalIcon from '../icon/internal'; +import { getBaseProps } from '../internal/base-component'; +import useBaseComponent from '../internal/hooks/use-base-component'; +import { applyDisplayName } from '../internal/utils/apply-display-name'; +import { VisualAccentProps } from './interfaces'; + +import styles from './styles.css.js'; + +export { VisualAccentProps }; + +export default function VisualAccent({ + color, + content, + fontSize = 'body-m', + fontWeight = 'normal', + iconName, + iconSize = 'normal', + shape = 'sharp', + ...rest +}: VisualAccentProps) { + const { __internalRootRef } = useBaseComponent('VisualAccent', { props: { color, shape } }); + const baseProps = getBaseProps(rest); + + const className = clsx( + baseProps.className, + styles.root, + styles[`color-${color}`], + styles[`shape-${shape}`], + styles[`font-size-${fontSize}`], + styles[`font-weight-${fontWeight}`] + ); + + return ( + + {iconName ? : content} + + ); +} + +applyDisplayName(VisualAccent, 'VisualAccent'); diff --git a/src/visual-accent/interfaces.ts b/src/visual-accent/interfaces.ts new file mode 100644 index 0000000000..a07fe9b2dd --- /dev/null +++ b/src/visual-accent/interfaces.ts @@ -0,0 +1,54 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { IconProps } from '../icon/interfaces'; +import { BaseComponentProps } from '../internal/base-component'; + +export interface VisualAccentProps extends BaseComponentProps { + /** + * The accent color variant. + */ + color: VisualAccentProps.Color; + + /** + * Text content to display. When provided, renders a text accent element. + * Mutually exclusive with `iconName`. + */ + content?: string; + + /** + * Font size for text content. + * @defaultValue 'body-m' + */ + fontSize?: VisualAccentProps.FontSize; + + /** + * Font weight for text content. + * @defaultValue 'normal' + */ + fontWeight?: VisualAccentProps.FontWeight; + + /** + * Icon name to display. When provided, renders an icon accent element. + * Mutually exclusive with `content`. + */ + iconName?: IconProps.Name; + + /** + * Size of the icon. + * @defaultValue 'normal' + */ + iconSize?: IconProps.Size; + + /** + * Shape of the accent container. + * @defaultValue 'sharp' + */ + shape?: VisualAccentProps.Shape; +} + +export namespace VisualAccentProps { + export type Color = 'red' | 'yellow' | 'indigo' | 'green' | 'orange' | 'purple' | 'mint' | 'lime' | 'grey'; + export type FontSize = 'body-s' | 'body-m' | 'heading-xs' | 'heading-s' | 'heading-m'; + export type FontWeight = 'normal' | 'bold' | 'heavy'; + export type Shape = 'sharp' | 'circle'; +} diff --git a/src/visual-accent/styles.scss b/src/visual-accent/styles.scss new file mode 100644 index 0000000000..a558524479 --- /dev/null +++ b/src/visual-accent/styles.scss @@ -0,0 +1,147 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ + +@use '../internal/styles' as styles; +@use '../internal/styles/tokens' as awsui; +@use '../internal/styles/utils/theming' as theming; + +// ─── Base ──────────────────────────────────────────────────────────────────────── +.root { + display: inline-flex; + align-items: center; + justify-content: center; + font-family: awsui.$font-family-base; +} + +// ─── Shapes ────────────────────────────────────────────────────────────────────── +.shape-sharp { + padding-block: awsui.$space-xxs; + padding-inline: awsui.$space-xs; + border-start-start-radius: 2px; + border-start-end-radius: 2px; + border-end-start-radius: 2px; + border-end-end-radius: 2px; +} + +.shape-circle { + inline-size: 36px; + block-size: 36px; + flex-shrink: 0; + border-start-start-radius: 50%; + border-start-end-radius: 50%; + border-end-start-radius: 50%; + border-end-end-radius: 50%; +} + +// ─── Font sizes ────────────────────────────────────────────────────────────────── +.font-size-body-s { + @include styles.font(body-s); +} +.font-size-body-m { + @include styles.font(body-m); +} +.font-size-heading-xs { + @include styles.font(heading-xs); +} +.font-size-heading-s { + @include styles.font(heading-s); +} +.font-size-heading-m { + @include styles.font(heading-m); +} + +// ─── Font weights ──────────────────────────────────────────────────────────────── +.font-weight-normal { + font-weight: styles.$font-weight-normal; +} +.font-weight-bold { + font-weight: styles.$font-weight-bold; +} +.font-weight-heavy { + font-weight: styles.$font-weight-heavy; + @include styles.font-smoothing; +} + +// ─── Colors ────────────────────────────────────────────────────────────────────── +.color-red { + background-color: #fff5f5; + color: #db0000; + @include theming.dark-mode-only { + background-color: rgba(82, 0, 0, 0.8); + color: #ff7a7a; + } +} + +.color-yellow { + background-color: #fffef0; + color: #f2b100; + @include theming.dark-mode-only { + background-color: rgba(87, 58, 0, 0.8); + color: #ffe347; + } +} + +.color-indigo { + background-color: #f5f7ff; + color: #295eff; + @include theming.dark-mode-only { + background-color: rgba(0, 20, 117, 0.8); + color: #7598ff; + } +} + +.color-green { + background-color: #effff1; + color: #00802f; + @include theming.dark-mode-only { + background-color: rgba(0, 51, 17, 0.8); + color: #00e500; + } +} + +.color-orange { + background-color: #fff7f5; + color: #db3300; + @include theming.dark-mode-only { + background-color: rgba(71, 17, 0, 0.8); + color: #ff6a3d; + } +} + +.color-purple { + background-color: #faf5ff; + color: #962eff; + @include theming.dark-mode-only { + background-color: rgba(48, 0, 97, 0.8); + color: #bf80ff; + } +} + +.color-mint { + background-color: #ebfff6; + color: #008559; + @include theming.dark-mode-only { + background-color: rgba(0, 51, 34, 0.8); + color: #00e582; + } +} + +.color-lime { + background-color: #f7ffeb; + color: #008a00; + @include theming.dark-mode-only { + background-color: rgba(0, 46, 0, 0.8); + color: #7ae500; + } +} + +.color-grey { + background-color: #fcfcfc; + color: #6b6b6b; + @include theming.dark-mode-only { + background-color: rgba(21, 21, 21, 0.8); + color: #b7b7b7; + } +}