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
183 changes: 183 additions & 0 deletions pages/visual-accent/simple.page.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<article>
<Box variant="h1" padding={{ bottom: 'l' }}>
VisualAccent component — Direction 5
</Box>

<Box variant="p" color="text-body-secondary" padding={{ bottom: 'xl' }}>
A standalone component with <code>content</code>, <code>iconName</code>, <code>color</code>, and{' '}
<code>shape</code> props. No visual context, no wrapper pattern.
</Box>

{/* ── Text with sharp shape ─────────────────────────────────────── */}
<Box variant="h2" padding={{ top: 'l', bottom: 'm' }}>
Text content (shape=&quot;sharp&quot;)
</Box>

<Box variant="h3" padding={{ bottom: 's' }}>
fontSize=&quot;heading-m&quot;
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_COLORS.map(color => (
<VisualAccent key={color} color={color} content="Heading 3" fontSize="heading-m" fontWeight="bold" />
))}
</SpaceBetween>

<Box variant="h3" padding={{ top: 'l', bottom: 's' }}>
fontSize=&quot;heading-s&quot;
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_COLORS.map(color => (
<VisualAccent key={color} color={color} content="Heading 4" fontSize="heading-s" fontWeight="bold" />
))}
</SpaceBetween>

<Box variant="h3" padding={{ top: 'l', bottom: 's' }}>
fontSize=&quot;body-m&quot;
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_COLORS.map(color => (
<VisualAccent key={color} color={color} content="Body paragraph text" />
))}
</SpaceBetween>

{/* ── Icons with circle shape ───────────────────────────────────── */}
<Box variant="h2" padding={{ top: 'xxxl', bottom: 'm' }}>
Icons (shape=&quot;circle&quot;)
</Box>
<SpaceBetween size="m" direction="horizontal">
{ALL_COLORS.map(color => (
<VisualAccent key={color} color={color} iconName="check" iconSize="medium" shape="circle" />
))}
</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: <VisualAccent color="indigo" content="E1WG1ZNPRXT0D4" />,
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: <VisualAccent color="green" content="Use only US, Canada, Europe" />,
},
{
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 visual accent icon badges"
items={LIST_ITEMS}
renderItem={item => ({
id: item.id,
content: item.content,
icon: <VisualAccent color={item.color} iconName={item.icon as any} iconSize="medium" shape="circle" />,
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>
);
}
46 changes: 46 additions & 0 deletions src/visual-accent/index.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<span {...baseProps} className={className} ref={__internalRootRef}>
{iconName ? <InternalIcon name={iconName} size={iconSize} /> : content}
</span>
);
}

applyDisplayName(VisualAccent, 'VisualAccent');
54 changes: 54 additions & 0 deletions src/visual-accent/interfaces.ts
Original file line number Diff line number Diff line change
@@ -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';
}
Loading
Loading