From 68d1ed34f58e25f5f63a880c628906b364cc8b53 Mon Sep 17 00:00:00 2001 From: at-susie Date: Mon, 22 Jun 2026 17:48:11 +0200 Subject: [PATCH] chore: Explore utility class approach --- pages/accent-classes/accent-classes.scss | 160 +++++++++++++++++++ pages/accent-classes/simple.page.tsx | 190 +++++++++++++++++++++++ src/internal/styles/accent-classes.ts | 35 +++++ 3 files changed, 385 insertions(+) create mode 100644 pages/accent-classes/accent-classes.scss create mode 100644 pages/accent-classes/simple.page.tsx create mode 100644 src/internal/styles/accent-classes.ts diff --git a/pages/accent-classes/accent-classes.scss b/pages/accent-classes/accent-classes.scss new file mode 100644 index 0000000000..e29ecbc2e2 --- /dev/null +++ b/pages/accent-classes/accent-classes.scss @@ -0,0 +1,160 @@ +/* + Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + SPDX-License-Identifier: Apache-2.0 +*/ + +/* stylelint-disable selector-class-pattern */ + +/* + * Accent utility classes — Direction 3 exploration + * + * NOTE: This stylesheet is experimental. Class names and values may change without notice. + * + * Usage: + * content + * + */ + +// Dark mode detection — awsui-dark-mode and awsui-polaris-dark-mode are the +// class names Cloudscape places on an ancestor element to signal dark mode. +@mixin dark-mode-only { + @media not print { + /* stylelint-disable selector-combinator-disallowed-list */ + :global(.awsui-polaris-dark-mode) &, + :global(.awsui-dark-mode) & { + @content; + } + } +} + +// ─── Content color mixin ─────────────────────────────────────────────────────── +// Overrides CSS custom properties consumed by Box text variants and Icon (subtle). +// $light: 600-level | $dark: 400-level + +@mixin accent-content($light, $dark) { + --color-text-body-default-a7br70: #{$light}; + --color-text-heading-default-5p4ugs: #{$light}; + --color-text-body-secondary-6zl7e0: #{$light}; + --color-text-heading-secondary-c1zwy4: #{$light}; + --color-text-icon-subtle-xnb03v: #{$light}; + --color-text-small-ldm4or: #{$light}; + + @include dark-mode-only { + --color-text-body-default-a7br70: #{$dark}; + --color-text-heading-default-5p4ugs: #{$dark}; + --color-text-body-secondary-6zl7e0: #{$dark}; + --color-text-heading-secondary-c1zwy4: #{$dark}; + --color-text-icon-subtle-xnb03v: #{$dark}; + --color-text-small-ldm4or: #{$dark}; + } +} + +// ─── Base ────────────────────────────────────────────────────────────────────── + +:global([class*='awsui-accent-']) { + display: inline-flex; +} + +// ─── Shape classes ───────────────────────────────────────────────────────────── +// Spacing values match the SCSS token equivalents: +// awsui.$space-xxs = 4px | awsui.$space-xs = 8px +// awsui.$size-icon-medium = 20px | awsui.$space-scaled-xs = 8px comfortable + +:global(.awsui-accent-sharp) { + padding-block: 4px; /* spaceXxs */ + padding-inline: 8px; /* spaceXs */ + border-start-start-radius: 2px; + border-start-end-radius: 2px; + border-end-start-radius: 2px; + border-end-end-radius: 2px; +} + +:global(.awsui-accent-circle) { + /* (spaceScaledXs * 2) + sizeIconMedium = 8*2 + 20 = 36px */ + inline-size: 36px; + block-size: 36px; + align-items: center; + justify-content: center; + flex-shrink: 0; + border-start-start-radius: 50%; + border-start-end-radius: 50%; + border-end-start-radius: 50%; + border-end-end-radius: 50%; +} + +// ─── Color classes ───────────────────────────────────────────────────────────── +// Background: 50-level (light) / 950-level @ 80% opacity (dark) +// Content: 600-level (light) / 400-level (dark) +// Source: style-dictionary/core/color-palette.ts + +:global(.awsui-accent-red) { + background-color: #fff5f5; + @include accent-content(#db0000, #ff7a7a); + @include dark-mode-only { + background-color: rgba(82, 0, 0, 0.8); + } +} + +:global(.awsui-accent-yellow) { + background-color: #fffef0; + @include accent-content(#f2b100, #ffe347); + @include dark-mode-only { + background-color: rgba(87, 58, 0, 0.8); + } +} + +:global(.awsui-accent-indigo) { + background-color: #f5f7ff; + @include accent-content(#295eff, #7598ff); + @include dark-mode-only { + background-color: rgba(0, 20, 117, 0.8); + } +} + +:global(.awsui-accent-green) { + background-color: #effff1; + @include accent-content(#00802f, #00e500); + @include dark-mode-only { + background-color: rgba(0, 51, 17, 0.8); + } +} + +:global(.awsui-accent-orange) { + background-color: #fff7f5; + @include accent-content(#db3300, #ff6a3d); + @include dark-mode-only { + background-color: rgba(71, 17, 0, 0.8); + } +} + +:global(.awsui-accent-purple) { + background-color: #faf5ff; + @include accent-content(#962eff, #bf80ff); + @include dark-mode-only { + background-color: rgba(48, 0, 97, 0.8); + } +} + +:global(.awsui-accent-mint) { + background-color: #ebfff6; + @include accent-content(#008559, #00e582); + @include dark-mode-only { + background-color: rgba(0, 51, 34, 0.8); + } +} + +:global(.awsui-accent-lime) { + background-color: #f7ffeb; + @include accent-content(#008a00, #7ae500); + @include dark-mode-only { + background-color: rgba(0, 46, 0, 0.8); + } +} + +:global(.awsui-accent-grey) { + background-color: #fcfcfc; + @include accent-content(#6b6b6b, #b7b7b7); + @include dark-mode-only { + background-color: rgba(21, 21, 21, 0.8); + } +} diff --git a/pages/accent-classes/simple.page.tsx b/pages/accent-classes/simple.page.tsx new file mode 100644 index 0000000000..8772d5e4ed --- /dev/null +++ b/pages/accent-classes/simple.page.tsx @@ -0,0 +1,190 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/* + * NOTE: This page imports accent-classes.scss globally via a style import. + * In a real integration the stylesheet would be included once in the app bundle. + * Here we import it at the page level for demonstration. + */ +import React from 'react'; + +import Box, { BoxProps } from '~components/box'; +import ButtonDropdown from '~components/button-dropdown'; +import CopyToClipboard from '~components/copy-to-clipboard'; +import Icon from '~components/icon'; +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 './accent-classes.scss'; + +// ─── Data ────────────────────────────────────────────────────────────────────── + +const ALL_VARIANTS = ['red', 'yellow', 'indigo', 'green', 'orange', 'purple', 'mint', 'lime', 'grey'] as const; +type Variant = (typeof ALL_VARIANTS)[number]; + +const BOX_VARIANTS: { variant: BoxProps['variant']; label: string; content: string }[] = [ + { variant: 'h3', label: 'h3', content: 'Heading 3' }, + { variant: 'h4', label: 'h4', content: 'Heading 4' }, + { variant: 'p', label: 'p', content: 'Body paragraph text' }, +]; + +const LIST_ITEMS: { id: string; content: string; icon: string; variant: Variant }[] = [ + { id: 'health', content: 'Health overview', icon: 'face-happy', variant: 'green' }, + { id: 'functions', content: 'Functions', icon: 'script', variant: 'indigo' }, + { id: 'network', content: 'Network configuration', icon: 'globe', variant: 'grey' }, + { id: 'multi-session', content: 'Multi-session data', icon: 'multiscreen', variant: 'purple' }, + { id: 'alert', content: 'Alert center', icon: 'security', variant: 'red' }, + { id: 'communication', content: 'Communication', icon: 'contact', variant: 'mint' }, +]; + +// ─── Page ────────────────────────────────────────────────────────────────────── + +export default function AccentClassesPage() { + return ( +
+ + Accent utility classes — plain className usage + + + + No Cloudscape wrapper component. Builders apply awsui-accent-{variant} and{' '} + awsui-accent-sharp or awsui-accent-circle directly to any HTML element. + + + {/* ── Box variants × color variants ─────────────────────────────── */} + + awsui-accent-sharp + + + {BOX_VARIANTS.map(({ variant, label, content }) => ( +
+ + Box variant="{label}" + + + {ALL_VARIANTS.map(v => ( + + {content} + + ))} + +
+ ))} + + {/* ── Circle ────────────────────────────────────────────────────── */} + + awsui-accent-circle + + + {ALL_VARIANTS.map(v => ( + + + + ))} + + + {/* ── Application in components ──────────────────────────────────── */} + + Application in components + + + + KeyValuePairs + + + E1WG1ZNPRXT0D4 + + ), + info: ( + + Info + + ), + }, + { + label: 'ARN', + value: ( + + ), + }, + { + label: 'Status', + value: Available, + }, + { + label: 'SSL Certificate', + id: 'ssl-certificate-id', + value: ( + + ), + }, + { + label: 'Price class', + value: ( + + Use only US, Canada, Europe + + ), + }, + { + label: 'CNAMEs', + value: ( + + abc.service23G24.xyz + + ), + }, + ]} + /> + + + List + + ({ + id: item.id, + content: item.content, + icon: ( + + + + ), + actions: ( + + ), + })} + /> +
+ ); +} diff --git a/src/internal/styles/accent-classes.ts b/src/internal/styles/accent-classes.ts new file mode 100644 index 0000000000..3007b78dda --- /dev/null +++ b/src/internal/styles/accent-classes.ts @@ -0,0 +1,35 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +/** + * @experimental Accent utility class names. Available to selected builders only. + * These names may change without notice. + * + * Usage: + * import { accentClass } from '.../accent-classes'; + * ... + * + * Or use the string literals directly: + * ... + */ + +export type AccentVariant = 'red' | 'yellow' | 'indigo' | 'green' | 'orange' | 'purple' | 'mint' | 'lime' | 'grey'; +export type AccentShape = 'sharp' | 'circle'; + +/** Typed accent class name constants. */ +export const accentClass = { + // Color variants + red: 'awsui-accent-red', + yellow: 'awsui-accent-yellow', + indigo: 'awsui-accent-indigo', + green: 'awsui-accent-green', + orange: 'awsui-accent-orange', + purple: 'awsui-accent-purple', + mint: 'awsui-accent-mint', + lime: 'awsui-accent-lime', + grey: 'awsui-accent-grey', + + // Shape modifiers + sharp: 'awsui-accent-sharp', + circle: 'awsui-accent-circle', +} as const satisfies Record;