Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions pages/accent-classes/accent-classes.scss
Original file line number Diff line number Diff line change
@@ -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:
* <span className="awsui-accent-indigo awsui-accent-sharp">content</span>
* <span className="awsui-accent-green awsui-accent-circle"><Icon /></span>
*/

// 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);
}
}
190 changes: 190 additions & 0 deletions pages/accent-classes/simple.page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<article>
<Box variant="h1" padding={{ bottom: 'l' }}>
Accent utility classes — plain className usage
</Box>

<Box variant="p" color="text-body-secondary" padding={{ bottom: 'xl' }}>
No Cloudscape wrapper component. Builders apply <code>awsui-accent-&#123;variant&#125;</code> and{' '}
<code>awsui-accent-sharp</code> or <code>awsui-accent-circle</code> directly to any HTML element.
</Box>

{/* ── Box variants × color variants ─────────────────────────────── */}
<Box variant="h2" padding={{ top: 'l', bottom: 'm' }}>
awsui-accent-sharp
</Box>

{BOX_VARIANTS.map(({ variant, label, content }) => (
<section key={label}>
<Box variant="h3" padding={{ top: 'l', bottom: 's' }}>
Box variant=&quot;{label}&quot;
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_VARIANTS.map(v => (
<span key={v} className={`awsui-accent-${v} awsui-accent-sharp`}>
<Box variant={variant}>{content}</Box>
</span>
))}
</SpaceBetween>
</section>
))}

{/* ── Circle ────────────────────────────────────────────────────── */}
<Box variant="h2" padding={{ top: 'xxxl', bottom: 'm' }}>
awsui-accent-circle
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_VARIANTS.map(v => (
<span key={v} className={`awsui-accent-${v} awsui-accent-circle`}>
<Icon name="check" size="medium" variant="subtle" />
</span>
))}
</SpaceBetween>

{/* ── Application in components ──────────────────────────────────── */}
<Box variant="h2" padding={{ top: 'xxxl', bottom: 'm' }}>
Application in components
</Box>

<Box variant="h3" padding={{ bottom: 's' }}>
KeyValuePairs
</Box>
<KeyValuePairs
columns={3}
items={[
{
label: 'Distribution ID',
value: (
<span className="awsui-accent-indigo awsui-accent-sharp">
<Box variant="p">E1WG1ZNPRXT0D4</Box>
</span>
),
info: (
<Link variant="info" href="#">
Info
</Link>
),
},
{
label: 'ARN',
value: (
<CopyToClipboard
copyButtonAriaLabel="Copy ARN"
copyErrorText="ARN failed to copy"
copySuccessText="ARN copied"
textToCopy="arn:service23G24::111122223333:distribution/23E1WG1ZNPRXT0D4"
variant="inline"
/>
),
},
{
label: 'Status',
value: <StatusIndicator>Available</StatusIndicator>,
},
{
label: 'SSL Certificate',
id: 'ssl-certificate-id',
value: (
<ProgressBar
value={30}
additionalInfo="Additional information"
description="Progress bar description"
ariaLabelledby="ssl-certificate-id"
/>
),
},
{
label: 'Price class',
value: (
<span className="awsui-accent-green awsui-accent-sharp">
<Box variant="p">Use only US, Canada, Europe</Box>
</span>
),
},
{
label: 'CNAMEs',
value: (
<Link external={true} href="#">
abc.service23G24.xyz
</Link>
),
},
]}
/>

<Box variant="h3" padding={{ top: 'xl', bottom: 's' }}>
List
</Box>
<List
ariaLabel="List with circle icon badges"
items={LIST_ITEMS}
renderItem={item => ({
id: item.id,
content: item.content,
icon: (
<span className={`awsui-accent-${item.variant} awsui-accent-circle`}>
<Icon name={item.icon as any} size="medium" variant="subtle" />
</span>
),
actions: (
<ButtonDropdown
items={[
{ id: '1', text: 'Action one' },
{ id: '2', text: 'Action two' },
{ id: '3', text: 'Action three' },
]}
variant="icon"
ariaLabel={`Actions for ${item.content}`}
/>
),
})}
/>
</article>
);
}
35 changes: 35 additions & 0 deletions src/internal/styles/accent-classes.ts
Original file line number Diff line number Diff line change
@@ -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';
* <span className={`${accentClass.indigo} ${accentClass.sharp}`}>...</span>
*
* Or use the string literals directly:
* <span className="awsui-accent-indigo awsui-accent-sharp">...</span>
*/

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<AccentVariant | AccentShape, string>;
Loading