Skip to content
Open
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
13 changes: 13 additions & 0 deletions pages/token/permutations.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import React from 'react';

import Icon from '~components/icon';
import Link from '~components/link';
import Popover from '~components/popover';
import Token, { TokenProps } from '~components/token';

import createPermutations from '../utils/permutations';
Expand Down Expand Up @@ -56,6 +58,17 @@ const permutations = createPermutations<TokenProps>([
disabled: [true, false],
variant: ['normal'],
},
{
label: [
<Link key="link" variant="primary" href="#test">
link
</Link>,
<Popover key="popover" content="Test" triggerType="text-inline">
popover
</Popover>,
],
variant: ['inline'],
},
]);

export default function TokenPermutations() {
Expand Down
5 changes: 4 additions & 1 deletion src/internal/context/reset-contexts-for-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CollectionLabelContext } from './collection-label-context';
import { FormFieldContext } from './form-field-context';
import { InfoLinkLabelContext } from './info-link-label-context';
import { defaultValue as linkDefaultValue, LinkDefaultVariantContext } from './link-default-variant-context';
import { defaultValue as tokenInlineDefaultValue, TokenInlineContext } from './token-inline-context';

/*
Use this context-resetter when creating a new modal-type context where typically the contents
Expand All @@ -20,7 +21,9 @@ const ResetContextsForModal = ({ children }: { children: React.ReactNode }) => (
<FormFieldContext.Provider value={{}}>
<InfoLinkLabelContext.Provider value="">
<LinkDefaultVariantContext.Provider value={linkDefaultValue}>
<SingleTabStopNavigationReset>{children}</SingleTabStopNavigationReset>
<TokenInlineContext.Provider value={tokenInlineDefaultValue}>
<SingleTabStopNavigationReset>{children}</SingleTabStopNavigationReset>
</TokenInlineContext.Provider>
</LinkDefaultVariantContext.Provider>
</InfoLinkLabelContext.Provider>
</FormFieldContext.Provider>
Expand Down
17 changes: 17 additions & 0 deletions src/internal/context/token-inline-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import { createContext, useContext } from 'react';

export interface TokenInlineContextProps {
isInlineToken: boolean;
}

export const defaultValue: TokenInlineContextProps = {
isInlineToken: false,
};

export const TokenInlineContext = createContext<TokenInlineContextProps>(defaultValue);

export function useTokenInlineContext() {
return useContext(TokenInlineContext);
}
5 changes: 4 additions & 1 deletion src/link/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { getBaseProps } from '../internal/base-component';
import { InfoLinkLabelContext } from '../internal/context/info-link-label-context';
import { LinkDefaultVariantContext } from '../internal/context/link-default-variant-context';
import { useTokenInlineContext } from '../internal/context/token-inline-context';
import { fireCancelableEvent, fireNonCancelableEvent, isPlainLeftClick } from '../internal/events';
import useForwardFocus from '../internal/hooks/forward-focus';
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
Expand Down Expand Up @@ -157,6 +158,7 @@ const InternalLink = React.forwardRef(

const linkRef = useRef<HTMLElement>(null);
const isVisualRefresh = useVisualRefresh();
const { isInlineToken } = useTokenInlineContext();
useForwardFocus(ref, linkRef);

// Visual refresh should only add styles to buttons that don't already have unique styles (e.g. primary/secondary variants)
Expand All @@ -172,7 +174,8 @@ const InternalLink = React.forwardRef(
applyButtonStyles ? styles.button : null,
styles[getVariantStyle(variant)],
styles[getFontSizeStyle(variant, fontSize)],
styles[getColorStyle(variant, color)]
styles[getColorStyle(variant, color)],
isInlineToken && styles['in-inline-token']
),
style: getLinkStyles(style),
'aria-label': ariaLabel,
Expand Down
4 changes: 4 additions & 0 deletions src/link/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@
@include styles.link-font-size-style(map.get(constants.$link-font-sizes, $font-size));
}
}

&.in-inline-token {
text-underline-offset: 0.15em;
}
}

.icon-wrapper {
Expand Down
4 changes: 3 additions & 1 deletion src/popover/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { getBaseProps } from '../internal/base-component';
import { getFirstFocusable } from '../internal/components/focus-lock/utils';
import { LinkDefaultVariantContext } from '../internal/context/link-default-variant-context';
import ResetContextsForModal from '../internal/context/reset-contexts-for-modal';
import { useTokenInlineContext } from '../internal/context/token-inline-context';
import { fireNonCancelableEvent, NonCancelableEventHandler } from '../internal/events/index';
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
import { usePortalModeClasses } from '../internal/hooks/use-portal-mode-classes';
Expand Down Expand Up @@ -131,13 +132,14 @@ function InternalPopover(
}, []);

const popoverClasses = usePortalModeClasses(triggerRef, { resetVisualContext: true });
const { isInlineToken } = useTokenInlineContext();

const triggerProps = {
// https://github.com/microsoft/TypeScript/issues/36659
ref: triggerRef as any,
onClick: onTriggerClick,
onKeyDown: onTriggerKeyDown,
className: clsx(styles.trigger, styles[`trigger-type-${triggerType}`]),
className: clsx(styles.trigger, styles[`trigger-type-${triggerType}`], isInlineToken && styles['in-inline-token']),
};
const { tabIndex: triggerTabIndex } = useSingleTabStopNavigation(triggerRef);

Expand Down
4 changes: 4 additions & 0 deletions src/popover/styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ $trigger-underline-offset: 0.25em;
*/
padding-block-end: calc(#{$trigger-underline-offset} + #{awsui.$border-divider-list-width});
}

&.in-inline-token {
text-underline-offset: 0.15em;
}
}

.trigger-type-text {
Expand Down
133 changes: 68 additions & 65 deletions src/token/internal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useResizeObserver, useUniqueId, warnOnce } from '@cloudscape-design/com

import { getBaseProps } from '../internal/base-component';
import Option from '../internal/components/option';
import { TokenInlineContext } from '../internal/context/token-inline-context';
import { InternalBaseComponentProps } from '../internal/hooks/use-base-component';
import LiveRegion from '../live-region/internal';
import Tooltip from '../tooltip/internal.js';
Expand Down Expand Up @@ -98,78 +99,80 @@ function InternalToken({
};

return (
<div
{...baseProps}
ref={__internalRootRef}
className={clsx(
styles.root,
legacyTestingStyles.token,
testUtilStyles.root,
!isInline ? styles['token-normal'] : styles['token-inline'],
analyticsSelectors.token,
baseProps.className
)}
aria-label={ariaLabel}
aria-labelledby={!ariaLabel ? ariaLabelledbyId : undefined}
aria-disabled={!!disabled}
role={role ?? 'group'}
onFocus={() => {
setShowTooltip(true);
}}
onBlur={() => {
setShowTooltip(false);
}}
onMouseEnter={() => {
setShowTooltip(true);
}}
onMouseLeave={() => {
setShowTooltip(false);
}}
tabIndex={!!tooltipContent && isInline && isEllipsisActive ? 0 : undefined}
>
<TokenInlineContext.Provider value={{ isInlineToken: isInline }}>
<div
{...baseProps}
ref={__internalRootRef}
className={clsx(
!isInline ? styles['token-box'] : styles['token-box-inline'],
disabled && styles['token-box-disabled'],
readOnly && styles['token-box-readonly'],
!isInline && !onDismiss && styles['token-box-without-dismiss'],
disableInnerPadding && styles['disable-padding']
styles.root,
legacyTestingStyles.token,
testUtilStyles.root,
!isInline ? styles['token-normal'] : styles['token-inline'],
analyticsSelectors.token,
baseProps.className
)}
aria-label={ariaLabel}
aria-labelledby={!ariaLabel ? ariaLabelledbyId : undefined}
aria-disabled={!!disabled}
role={role ?? 'group'}
onFocus={() => {
setShowTooltip(true);
}}
onBlur={() => {
setShowTooltip(false);
}}
onMouseEnter={() => {
setShowTooltip(true);
}}
onMouseLeave={() => {
setShowTooltip(false);
}}
tabIndex={!!tooltipContent && isInline && isEllipsisActive ? 0 : undefined}
>
<Option
className={clsx(isInline && styles['token-option-inline'])}
triggerVariant={isInline}
option={buildOptionDefinition()}
disableTitleTooltip={!!tooltipContent}
labelContainerRef={labelContainerRef}
labelRef={labelRef}
labelId={ariaLabelledbyId}
/>
{onDismiss && (
<DismissButton
disabled={disabled}
dismissLabel={dismissLabel}
onDismiss={onDismiss}
readOnly={readOnly}
inline={isInline}
<div
className={clsx(
!isInline ? styles['token-box'] : styles['token-box-inline'],
disabled && styles['token-box-disabled'],
readOnly && styles['token-box-readonly'],
!isInline && !onDismiss && styles['token-box-without-dismiss'],
disableInnerPadding && styles['disable-padding']
)}
>
<Option
className={clsx(isInline && styles['token-option-inline'])}
triggerVariant={isInline}
option={buildOptionDefinition()}
disableTitleTooltip={!!tooltipContent}
labelContainerRef={labelContainerRef}
labelRef={labelRef}
labelId={ariaLabelledbyId}
/>
{onDismiss && (
<DismissButton
disabled={disabled}
dismissLabel={dismissLabel}
onDismiss={onDismiss}
readOnly={readOnly}
inline={isInline}
/>
)}
</div>
{!!tooltipContent && isInline && isEllipsisActive && showTooltip && (
<Tooltip
data-testid="token-tooltip"
getTrack={() => labelContainerRef.current}
content={
<LiveRegion>
<span data-testid="tooltip-live-region-content">{tooltipContent}</span>
</LiveRegion>
}
onEscape={() => {
setShowTooltip(false);
}}
/>
)}
</div>
{!!tooltipContent && isInline && isEllipsisActive && showTooltip && (
<Tooltip
data-testid="token-tooltip"
getTrack={() => labelContainerRef.current}
content={
<LiveRegion>
<span data-testid="tooltip-live-region-content">{tooltipContent}</span>
</LiveRegion>
}
onEscape={() => {
setShowTooltip(false);
}}
/>
)}
</div>
</TokenInlineContext.Provider>
);
}

Expand Down
Loading