From c7dd9d70458bd1cb4e9197546a36772f63709741 Mon Sep 17 00:00:00 2001 From: Ernst Kaese Date: Tue, 15 Jul 2025 17:20:02 +0200 Subject: [PATCH 01/73] Initial Token split-out --- .../custom.page.tsx => token/simple.page.tsx} | 6 +- pages/{token-group => token}/styles.scss | 0 src/file-token-group/file-token.tsx | 2 +- src/file-token-group/styles.scss | 2 +- .../components/button-trigger/styles.scss | 4 +- .../filtering-token/styles.scss | 2 +- src/token-group/internal.tsx | 6 +- src/token-group/styles.scss | 72 ----------------- src/{token-group => token}/constants.scss | 0 src/{token-group => token}/dismiss-button.tsx | 2 +- src/token/index.tsx | 31 ++++++++ src/token/interfaces.ts | 12 +++ .../token.tsx => token/internal.tsx} | 15 +--- src/{token-group => token}/mixins.scss | 0 src/token/styles.scss | 79 +++++++++++++++++++ 15 files changed, 140 insertions(+), 93 deletions(-) rename pages/{token-group/custom.page.tsx => token/simple.page.tsx} (94%) rename pages/{token-group => token}/styles.scss (100%) rename src/{token-group => token}/constants.scss (100%) rename src/{token-group => token}/dismiss-button.tsx (92%) create mode 100644 src/token/index.tsx create mode 100644 src/token/interfaces.ts rename src/{token-group/token.tsx => token/internal.tsx} (74%) rename src/{token-group => token}/mixins.scss (100%) create mode 100644 src/token/styles.scss diff --git a/pages/token-group/custom.page.tsx b/pages/token/simple.page.tsx similarity index 94% rename from pages/token-group/custom.page.tsx rename to pages/token/simple.page.tsx index 0d40977a92..a40b7d3a0b 100644 --- a/pages/token-group/custom.page.tsx +++ b/pages/token/simple.page.tsx @@ -7,8 +7,8 @@ import Box from '~components/box'; import Icon from '~components/icon'; import TokenList from '~components/internal/components/token-list'; import SpaceBetween from '~components/space-between'; +import Token from '~components/token'; import { TokenGroupProps } from '~components/token-group'; -import { Token } from '~components/token-group/token'; import styles from './styles.scss'; @@ -32,6 +32,10 @@ export default function GenericTokenGroupPage() { Standalone token + + Standalone readonly token + + Standalone disabled token diff --git a/pages/token-group/styles.scss b/pages/token/styles.scss similarity index 100% rename from pages/token-group/styles.scss rename to pages/token/styles.scss diff --git a/src/file-token-group/file-token.tsx b/src/file-token-group/file-token.tsx index e19d4e9940..1d59348de5 100644 --- a/src/file-token-group/file-token.tsx +++ b/src/file-token-group/file-token.tsx @@ -12,7 +12,7 @@ import { BaseComponentProps } from '../internal/base-component/index.js'; import Tooltip from '../internal/components/tooltip/index'; import InternalSpaceBetween from '../space-between/internal.js'; import InternalSpinner from '../spinner/internal.js'; -import DismissButton from '../token-group/dismiss-button'; +import DismissButton from '../token/dismiss-button.js'; import { TokenGroupProps } from '../token-group/interfaces.js'; import * as defaultFormatters from './default-formatters.js'; import { FileOptionThumbnail } from './thumbnail.js'; diff --git a/src/file-token-group/styles.scss b/src/file-token-group/styles.scss index 785ecf68b5..d8da57058e 100644 --- a/src/file-token-group/styles.scss +++ b/src/file-token-group/styles.scss @@ -6,7 +6,7 @@ @use '../internal/styles/tokens' as awsui; @use '../internal/styles' as styles; @use './constants' as constants; -@use '../token-group/mixins.scss' as mixins; +@use '../token/mixins.scss' as mixins; @use '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible; @mixin token-box-validation { diff --git a/src/internal/components/button-trigger/styles.scss b/src/internal/components/button-trigger/styles.scss index 30f785e579..60e35e5315 100644 --- a/src/internal/components/button-trigger/styles.scss +++ b/src/internal/components/button-trigger/styles.scss @@ -6,7 +6,7 @@ @use '../../styles' as styles; @use '../../styles/tokens' as awsui; @use '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible; -@use '../../../token-group/constants' as tokenGroup; +@use '../../../token/constants' as token; @use './motion'; @@ -40,7 +40,7 @@ $padding-block-inner-filtering-token: 0px; border-block-width: awsui.$border-width-token; border-inline-width: awsui.$border-width-token; - border-color: tokenGroup.$token-border-color; + border-color: token.$token-border-color; border-start-end-radius: 0; border-end-end-radius: 0; block-size: 100%; diff --git a/src/property-filter/filtering-token/styles.scss b/src/property-filter/filtering-token/styles.scss index 17f1462ba6..f96c3eda88 100644 --- a/src/property-filter/filtering-token/styles.scss +++ b/src/property-filter/filtering-token/styles.scss @@ -6,7 +6,7 @@ @use '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible; @use '../../internal/styles' as styles; @use '../../internal/styles/tokens' as awsui; -@use '../../token-group/constants' as constants; +@use '../../token/constants' as constants; $token-padding-block: styles.$control-padding-vertical; $token-padding-inline: styles.$control-padding-horizontal; diff --git a/src/token-group/internal.tsx b/src/token-group/internal.tsx index 531bcb8094..69ed561961 100644 --- a/src/token-group/internal.tsx +++ b/src/token-group/internal.tsx @@ -14,8 +14,8 @@ import checkControlled from '../internal/hooks/check-controlled'; import { InternalBaseComponentProps } from '../internal/hooks/use-base-component'; import { useListFocusController } from '../internal/hooks/use-list-focus-controller'; import { SomeRequired } from '../internal/types'; +import InternalToken from '../token/internal'; import { TokenGroupProps } from './interfaces'; -import { Token } from './token'; import tokenListStyles from '../internal/components/token-list/styles.css.js'; import styles from './styles.css.js'; @@ -71,7 +71,7 @@ export default function InternalTokenGroup({ items={items} limit={limit} renderItem={(item, itemIndex) => ( - { @@ -85,7 +85,7 @@ export default function InternalTokenGroup({ : getAnalyticsMetadataAttribute({ detail: { position: `${itemIndex + 1}` } }))} > + )} i18nStrings={i18nStrings} limitShowFewerAriaLabel={limitShowFewerAriaLabel} diff --git a/src/token-group/styles.scss b/src/token-group/styles.scss index b8c85efd43..42b7091738 100644 --- a/src/token-group/styles.scss +++ b/src/token-group/styles.scss @@ -5,9 +5,6 @@ @use '../internal/styles' as styles; @use '../internal/styles/tokens' as awsui; -@use '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible; -@use './constants' as constants; -@use './mixins.scss' as mixins; .root { @include styles.styles-reset; @@ -16,72 +13,3 @@ padding-block-start: awsui.$space-xs; } } - -.dismiss-button { - margin-block-start: -1px; - margin-block-end: 0; - margin-inline-start: awsui.$space-xxs; - margin-inline-end: -1px; - border-block: 1px solid transparent; - border-inline: 1px solid transparent; - padding-block: 0; - padding-inline: awsui.$space-xxs; - color: awsui.$color-text-button-inline-icon-default; - background-color: transparent; - - @include focus-visible.when-visible { - @include styles.focus-highlight(0px); - } - - &:focus { - outline: none; - text-decoration: none; - } - - &:hover { - cursor: pointer; - color: awsui.$color-text-button-inline-icon-hover; - } -} - -.token { - block-size: 100%; - display: flex; - flex-direction: column; - gap: awsui.$space-xxs; -} - -.token-box { - @include mixins.token-box-styles(); -} - -.token-box-readonly { - border-color: awsui.$color-border-input-disabled; - background-color: awsui.$color-background-container-content; - pointer-events: none; - - > .dismiss-button { - color: awsui.$color-text-button-inline-icon-disabled; - - &:hover { - /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ - cursor: initial; - color: awsui.$color-text-button-inline-icon-disabled; - } - } -} -.token-box-disabled.token-box-disabled { - border-color: awsui.$color-border-control-disabled; - background-color: awsui.$color-background-container-content; - color: awsui.$color-text-disabled; - pointer-events: none; - - > .dismiss-button { - color: awsui.$color-text-button-inline-icon-disabled; - - &:hover { - cursor: initial; - color: awsui.$color-text-button-inline-icon-disabled; - } - } -} diff --git a/src/token-group/constants.scss b/src/token/constants.scss similarity index 100% rename from src/token-group/constants.scss rename to src/token/constants.scss diff --git a/src/token-group/dismiss-button.tsx b/src/token/dismiss-button.tsx similarity index 92% rename from src/token-group/dismiss-button.tsx rename to src/token/dismiss-button.tsx index 91037853f6..f3fca74804 100644 --- a/src/token-group/dismiss-button.tsx +++ b/src/token/dismiss-button.tsx @@ -5,7 +5,7 @@ import React, { forwardRef, Ref } from 'react'; import { getAnalyticsMetadataAttribute } from '@cloudscape-design/component-toolkit/internal/analytics-metadata'; import InternalIcon from '../icon/internal'; -import { GeneratedAnalyticsMetadataTokenGroupDismiss } from './analytics-metadata/interfaces'; +import { GeneratedAnalyticsMetadataTokenGroupDismiss } from '../token-group/analytics-metadata/interfaces'; import styles from './styles.css.js'; diff --git a/src/token/index.tsx b/src/token/index.tsx new file mode 100644 index 0000000000..e5a158a2e0 --- /dev/null +++ b/src/token/index.tsx @@ -0,0 +1,31 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React from 'react'; + +// import { getAnalyticsMetadataAttribute } from '@cloudscape-design/component-toolkit/internal/analytics-metadata'; +import useBaseComponent from '../internal/hooks/use-base-component'; +import { applyDisplayName } from '../internal/utils/apply-display-name'; +// import { GeneratedAnalyticsMetadataTokenGroupComponent } from './analytics-metadata/interfaces'; +import { TokenProps } from './interfaces'; +import InternalToken from './internal'; + +export { TokenProps }; + +export default function Token(props: TokenProps) { + const baseComponentProps = useBaseComponent('TokenGroup'); + + // const componentAnalyticsMetadata: GeneratedAnalyticsMetadataTokenGroupComponent = { + // name: 'awsui.Token', + // label: 'invalid', + // }; + + return ( + + ); +} + +applyDisplayName(Token, 'Token'); diff --git a/src/token/interfaces.ts b/src/token/interfaces.ts new file mode 100644 index 0000000000..8252f0c55c --- /dev/null +++ b/src/token/interfaces.ts @@ -0,0 +1,12 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export interface TokenProps { + children: React.ReactNode; + ariaLabel?: string; + dismissLabel?: string; + onDismiss?: () => void; + disabled?: boolean; + readOnly?: boolean; + className?: string; +} diff --git a/src/token-group/token.tsx b/src/token/internal.tsx similarity index 74% rename from src/token-group/token.tsx rename to src/token/internal.tsx index 6d741da18f..f875b0fcf4 100644 --- a/src/token-group/token.tsx +++ b/src/token/internal.tsx @@ -6,20 +6,11 @@ import clsx from 'clsx'; import { getBaseProps } from '../internal/base-component'; import DismissButton from './dismiss-button'; +import { TokenProps } from './interfaces'; import styles from './styles.css.js'; -interface TokenProps { - children: React.ReactNode; - ariaLabel?: string; - dismissLabel?: string; - onDismiss?: () => void; - disabled?: boolean; - readOnly?: boolean; - className?: string; -} - -export function Token({ ariaLabel, disabled, readOnly, dismissLabel, onDismiss, children, ...restProps }: TokenProps) { +function InternalToken({ ariaLabel, disabled, readOnly, dismissLabel, onDismiss, children, ...restProps }: TokenProps) { const baseProps = getBaseProps(restProps); return ( @@ -45,3 +36,5 @@ export function Token({ ariaLabel, disabled, readOnly, dismissLabel, onDismiss, ); } + +export default InternalToken; diff --git a/src/token-group/mixins.scss b/src/token/mixins.scss similarity index 100% rename from src/token-group/mixins.scss rename to src/token/mixins.scss diff --git a/src/token/styles.scss b/src/token/styles.scss new file mode 100644 index 0000000000..531ef4374e --- /dev/null +++ b/src/token/styles.scss @@ -0,0 +1,79 @@ +/* + 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 '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible; +@use './constants' as constants; +@use './mixins.scss' as mixins; + +.dismiss-button { + margin-block-start: -1px; + margin-block-end: 0; + margin-inline-start: awsui.$space-xxs; + margin-inline-end: -1px; + border-block: 1px solid transparent; + border-inline: 1px solid transparent; + padding-block: 0; + padding-inline: awsui.$space-xxs; + color: awsui.$color-text-button-inline-icon-default; + background-color: transparent; + + @include focus-visible.when-visible { + @include styles.focus-highlight(0px); + } + + &:focus { + outline: none; + text-decoration: none; + } + + &:hover { + cursor: pointer; + color: awsui.$color-text-button-inline-icon-hover; + } +} + +.token { + block-size: 100%; + display: flex; + flex-direction: column; + gap: awsui.$space-xxs; +} + +.token-box { + @include mixins.token-box-styles(); +} + +.token-box-readonly { + border-color: awsui.$color-border-input-disabled; + background-color: awsui.$color-background-container-content; + pointer-events: none; + + > .dismiss-button { + color: awsui.$color-text-button-inline-icon-disabled; + + &:hover { + /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ + cursor: initial; + color: awsui.$color-text-button-inline-icon-disabled; + } + } +} +.token-box-disabled.token-box-disabled { + border-color: awsui.$color-border-control-disabled; + background-color: awsui.$color-background-container-content; + color: awsui.$color-text-disabled; + pointer-events: none; + + > .dismiss-button { + color: awsui.$color-text-button-inline-icon-disabled; + + &:hover { + cursor: initial; + color: awsui.$color-text-button-inline-icon-disabled; + } + } +} From 2f6420098df82ece81b51b8eaa4597d817009e94 Mon Sep 17 00:00:00 2001 From: Ernst Kaese Date: Tue, 5 Aug 2025 13:40:09 +0200 Subject: [PATCH 02/73] Initial inline token variant and styling --- pages/token/simple.page.tsx | 75 ++++++++++++++++++- .../__snapshots__/documenter.test.ts.snap | 71 ++++++++++++++++++ src/token/dismiss-button.tsx | 11 ++- src/token/index.tsx | 1 + src/token/interfaces.ts | 12 ++- src/token/internal.tsx | 22 +++++- src/token/mixins.scss | 28 +++++++ src/token/styles.scss | 8 ++ 8 files changed, 217 insertions(+), 11 deletions(-) diff --git a/pages/token/simple.page.tsx b/pages/token/simple.page.tsx index a40b7d3a0b..def86aaeb1 100644 --- a/pages/token/simple.page.tsx +++ b/pages/token/simple.page.tsx @@ -5,7 +5,9 @@ import { range } from 'lodash'; import Box from '~components/box'; import Icon from '~components/icon'; +import Input from '~components/input'; import TokenList from '~components/internal/components/token-list'; +import Popover from '~components/popover'; import SpaceBetween from '~components/space-between'; import Token from '~components/token'; import { TokenGroupProps } from '~components/token-group'; @@ -28,11 +30,80 @@ export default function GenericTokenGroupPage() { return ( -

Generic token group

+

Generic token

+

Inline

+ + + Inline token + + + D Inline token + + + A Inline token + + + tiny + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + Inline readonly token + + + Inline disabled token + + + {}}> + Inline dismissable token + + {}}> + Inline dismissable readonly token + + {}}> + Inline dismissable disabled token + + + {}}> + + + + }> + Inline dismissable token + + + {}}> + + + + Inline dismissable readonly token + + {}}> + + + + Inline dismissable disabled token + + + +

Normal

Standalone token - + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore + magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo + consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id + est laborum. + + + Standalone readonly token diff --git a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap index f383c5d49e..574123b7c9 100644 --- a/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap +++ b/src/__tests__/snapshot-tests/__snapshots__/documenter.test.ts.snap @@ -26341,6 +26341,77 @@ In most cases, they aren't needed, as the \`svg\` element inherits styles from t } `; +exports[`Components definition for token matches the snapshot: token 1`] = ` +{ + "dashCaseName": "token", + "events": [ + { + "cancelable": false, + "name": "onDismiss", + }, + ], + "functions": [], + "name": "Token", + "properties": [ + { + "name": "ariaLabel", + "optional": true, + "type": "string", + }, + { + "description": "Adds the specified classes to the root element of the component.", + "name": "className", + "optional": true, + "type": "string", + }, + { + "name": "disabled", + "optional": true, + "type": "boolean", + }, + { + "name": "dismissLabel", + "optional": true, + "type": "string", + }, + { + "deprecatedTag": "The usage of the \`id\` attribute is reserved for internal use cases. For testing and other use cases, +use [data attributes](https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes). If you must +use the \`id\` attribute, consider setting it on a parent element instead.", + "description": "Adds the specified ID to the root element of the component.", + "name": "id", + "optional": true, + "type": "string", + }, + { + "name": "readOnly", + "optional": true, + "type": "boolean", + }, + { + "inlineType": { + "name": "TokenProps.Variant", + "type": "union", + "values": [ + "inline", + "normal", + ], + }, + "name": "variant", + "optional": true, + "type": "string", + }, + ], + "regions": [ + { + "isDefault": true, + "name": "children", + }, + ], + "releaseStatus": "stable", +} +`; + exports[`Components definition for token-group matches the snapshot: token-group 1`] = ` { "dashCaseName": "token-group", diff --git a/src/token/dismiss-button.tsx b/src/token/dismiss-button.tsx index f3fca74804..53a3e28905 100644 --- a/src/token/dismiss-button.tsx +++ b/src/token/dismiss-button.tsx @@ -1,10 +1,12 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 import React, { forwardRef, Ref } from 'react'; +import clsx from 'clsx'; import { getAnalyticsMetadataAttribute } from '@cloudscape-design/component-toolkit/internal/analytics-metadata'; import InternalIcon from '../icon/internal'; +import { fireNonCancelableEvent, NonCancelableEventHandler } from '../internal/events'; import { GeneratedAnalyticsMetadataTokenGroupDismiss } from '../token-group/analytics-metadata/interfaces'; import styles from './styles.css.js'; @@ -12,14 +14,15 @@ import styles from './styles.css.js'; interface DismissButtonProps { disabled?: boolean; readOnly?: boolean; - onDismiss?: () => void; + onDismiss?: NonCancelableEventHandler; dismissLabel?: string; + inline?: boolean; } export default forwardRef(DismissButton); function DismissButton( - { disabled, dismissLabel, onDismiss, readOnly }: DismissButtonProps, + { disabled, dismissLabel, onDismiss, readOnly, inline }: DismissButtonProps, ref: Ref ) { const analyticsMetadata: GeneratedAnalyticsMetadataTokenGroupDismiss = { @@ -32,14 +35,14 @@ function DismissButton( ); } diff --git a/src/token/index.tsx b/src/token/index.tsx index 5f3deab79c..246c8d6324 100644 --- a/src/token/index.tsx +++ b/src/token/index.tsx @@ -13,7 +13,7 @@ import InternalToken from './internal'; export { TokenProps }; export default function Token(props: TokenProps) { - const baseComponentProps = useBaseComponent('TokenGroup'); + const baseComponentProps = useBaseComponent('Token'); // const componentAnalyticsMetadata: GeneratedAnalyticsMetadataTokenGroupComponent = { // name: 'awsui.Token', diff --git a/src/token/interfaces.ts b/src/token/interfaces.ts index a6130d503a..bce489c902 100644 --- a/src/token/interfaces.ts +++ b/src/token/interfaces.ts @@ -4,13 +4,11 @@ import { IconProps } from '../icon/interfaces'; import { BaseComponentProps } from '../internal/base-component'; import { NonCancelableEventHandler } from '../internal/events'; +import { PopoverProps } from '../popover/interfaces'; export interface TokenProps extends BaseComponentProps { /** @awsUiSystem core */ children?: React.ReactNode; - - onDismiss?: NonCancelableEventHandler; - label?: string; ariaLabel?: string; labelTag?: string; @@ -24,6 +22,9 @@ export interface TokenProps extends BaseComponentProps { iconSvg?: React.ReactNode; tags?: ReadonlyArray; dismissLabel?: string; + popoverProps?: PopoverProps; + + onDismiss?: NonCancelableEventHandler; } export namespace TokenProps { diff --git a/src/token/internal.tsx b/src/token/internal.tsx index 4cd967cae4..74b6614918 100644 --- a/src/token/internal.tsx +++ b/src/token/internal.tsx @@ -7,6 +7,7 @@ import clsx from 'clsx'; import { getBaseProps } from '../internal/base-component'; import Option from '../internal/components/option'; import { OptionDefinition } from '../internal/components/option/interfaces'; +import InternalPopover from '../popover/internal'; import DismissButton from './dismiss-button'; import { TokenProps } from './interfaces'; @@ -28,9 +29,11 @@ function InternalToken({ iconSvg, tags, dismissLabel, + popoverProps, ...restProps }: TokenProps) { const baseProps = getBaseProps(restProps); + const optionDefinition: OptionDefinition = { label, labelTag, @@ -43,10 +46,46 @@ function InternalToken({ tags, }; + const getTokenContent = () => { + const mainContent = children ??