diff --git a/src/__integ__/__snapshots__/themes.test.ts.snap b/src/__integ__/__snapshots__/themes.test.ts.snap index b50ed8fa34..34fa78068a 100644 --- a/src/__integ__/__snapshots__/themes.test.ts.snap +++ b/src/__integ__/__snapshots__/themes.test.ts.snap @@ -321,7 +321,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#ffffff", "color-shadow-default": "rgba(0, 28, 36, 0.5)", - "color-shadow-layout-toggle": "#d5dbdb", "color-stroke-chart-line": "#879596", "color-text-accent": "#0073bb", "color-text-body-default": "#16191f", @@ -931,7 +930,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#687078", "color-shadow-default": "rgba(0, 0, 0, 0.5)", - "color-shadow-layout-toggle": "#414750", "color-stroke-chart-line": "#879596", "color-text-accent": "#44b9d6", "color-text-body-default": "#d5dbdb", @@ -1541,7 +1539,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#ffffff", "color-shadow-default": "rgba(0, 28, 36, 0.5)", - "color-shadow-layout-toggle": "#d5dbdb", "color-stroke-chart-line": "#879596", "color-text-accent": "#0073bb", "color-text-body-default": "#16191f", @@ -2151,7 +2148,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#ffffff", "color-shadow-default": "rgba(0, 28, 36, 0.5)", - "color-shadow-layout-toggle": "#d5dbdb", "color-stroke-chart-line": "#879596", "color-text-accent": "#0073bb", "color-text-body-default": "#16191f", @@ -2761,7 +2757,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#ffffff", "color-shadow-default": "rgba(0, 7, 22, 0.12)", - "color-shadow-layout-toggle": "#d1d5db", "color-stroke-chart-line": "#7d8998", "color-text-accent": "#0972d3", "color-text-body-default": "#000716", @@ -3371,7 +3366,6 @@ Object { "color-foreground-control-default": "#ffffff", "color-foreground-control-disabled": "#ffffff", "color-shadow-default": "rgba(0, 7, 22, 0.12)", - "color-shadow-layout-toggle": "#d1d5db", "color-stroke-chart-line": "#7d8998", "color-text-accent": "#0972d3", "color-text-body-default": "#000716", @@ -3981,7 +3975,6 @@ Object { "color-foreground-control-default": "#000716", "color-foreground-control-disabled": "#0f1b2a", "color-shadow-default": "rgba(0, 7, 22, 1)", - "color-shadow-layout-toggle": "#354150", "color-stroke-chart-line": "#7d8998", "color-text-accent": "#539fe5", "color-text-body-default": "#d1d5db", @@ -4591,7 +4584,6 @@ Object { "color-foreground-control-default": "#000716", "color-foreground-control-disabled": "#0f1b2a", "color-shadow-default": "rgba(0, 7, 22, 1)", - "color-shadow-layout-toggle": "#354150", "color-stroke-chart-line": "#7d8998", "color-text-accent": "#539fe5", "color-text-body-default": "#d1d5db", diff --git a/src/app-layout/__integ__/app-layout-focus-delegation.test.ts b/src/app-layout/__integ__/app-layout-focus-delegation.test.ts index f03794c170..5d977f70a4 100644 --- a/src/app-layout/__integ__/app-layout-focus-delegation.test.ts +++ b/src/app-layout/__integ__/app-layout-focus-delegation.test.ts @@ -91,13 +91,14 @@ function setupTest( 'drawers focus toggles between open and close buttons', setupTest( async page => { - await page.click(wrapper.findDrawersTriggers().get(2).toSelector()); + const triggerSelector = wrapper.findDrawerTriggerById('pro-help').toSelector(); + await page.click(triggerSelector); await page.keys('Enter'); - await expect(page.isFocused(wrapper.findDrawersTriggers().get(2).toSelector())).resolves.toBe(true); + await expect(page.isFocused(triggerSelector)).resolves.toBe(true); await page.keys('Enter'); await expect(page.isFocused(wrapper.findActiveDrawerCloseButton().toSelector())).resolves.toBe(true); await page.keys('Enter'); - await expect(page.isFocused(wrapper.findDrawersTriggers().get(2).toSelector())).resolves.toBe(true); + await expect(page.isFocused(triggerSelector)).resolves.toBe(true); }, { pageName: 'with-drawers', visualRefresh, mobile } ) diff --git a/src/app-layout/__tests__/desktop.test.tsx b/src/app-layout/__tests__/desktop.test.tsx index 67cc70f5b7..cdfb01c7f9 100644 --- a/src/app-layout/__tests__/desktop.test.tsx +++ b/src/app-layout/__tests__/desktop.test.tsx @@ -171,7 +171,10 @@ describeEachThemeAppLayout(false, () => { test('Adds labels to toggle button and landmark when defined', () => { const { wrapper } = renderComponent(); - expect(wrapper.findDrawersTriggers()![0].getElement()).toHaveAttribute('aria-label', 'Security trigger button'); + expect(wrapper.findDrawersTriggerById('security')!.getElement()).toHaveAttribute( + 'aria-label', + 'Security trigger button' + ); expect(wrapper.findDrawersDesktopTriggersContainer()!.getElement()).toHaveAttribute('aria-label', 'Drawers'); }); diff --git a/src/app-layout/constants.scss b/src/app-layout/constants.scss index 4853aa2f8d..fd81fec8c6 100644 --- a/src/app-layout/constants.scss +++ b/src/app-layout/constants.scss @@ -8,14 +8,9 @@ // Toggle should have 40px width, whereas button is 26px wide. // 40 - 26 = 14px in total or 7px on each side -$toggle-padding-horizontal: 0.7 * styles.$base-size; -$toggle-padding-vertical: awsui.$space-xxs; -$toggle-padding: $toggle-padding-vertical $toggle-padding-horizontal; - -// New styles for when there are drawers -$drawers-padding-horizontal: 0.6 * styles.$base-size; -$drawers-padding-vertical: awsui.$space-scaled-xs; -$drawers-padding: $drawers-padding-vertical $drawers-padding-horizontal; +$_toggle-padding-horizontal: 0.7 * styles.$base-size; +$_toggle-padding-vertical: awsui.$space-xxs; +$toggle-padding: $_toggle-padding-vertical $_toggle-padding-horizontal; $sidebar-size-closed: 4 * styles.$base-size; diff --git a/src/app-layout/drawer/index.tsx b/src/app-layout/drawer/index.tsx index 3d897178db..c6fe84e947 100644 --- a/src/app-layout/drawer/index.tsx +++ b/src/app-layout/drawer/index.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import clsx from 'clsx'; import React, { useRef } from 'react'; -import { AppLayoutButton, CloseButton, togglesConfig } from '../toggles'; +import { ToggleButton, CloseButton, togglesConfig } from '../toggles'; import testutilStyles from '../test-classes/styles.css.js'; import styles from './styles.css.js'; @@ -63,7 +63,7 @@ export const Drawer = React.forwardRef( const regularOpenButton = ( -
{!isMobile && regularOpenButton} {resizeHandle} @@ -145,29 +145,29 @@ export function DrawerTriggersBar({ [styles['drawer-mobile']]: isMobile, })} > -
+
{!isMobile && ( - )} diff --git a/src/app-layout/mobile-toolbar/styles.scss b/src/app-layout/mobile-toolbar/styles.scss index 822851b038..fb3a2dacdf 100644 --- a/src/app-layout/mobile-toolbar/styles.scss +++ b/src/app-layout/mobile-toolbar/styles.scss @@ -12,7 +12,6 @@ } .mobile-bar { - /* stylelint-disable-next-line plugin/no-unsupported-browser-features */ position: sticky; display: flex; align-items: center; @@ -32,38 +31,25 @@ margin-right: awsui.$space-m; } -.mobile-trigger-with-drawers { - width: constants.$sidebar-size-closed; - display: flex; - justify-content: center; -} - .mobile-toggle { box-sizing: border-box; cursor: pointer; z-index: 1; padding: constants.$toggle-padding; width: constants.$sidebar-size-closed; - &:first-child { + &-type-navigation { border-right: 1px solid awsui.$color-border-layout; } - &:last-child:not(.mobile-toggle-with-drawers) { + &-type-tools, + &-type-drawer { border-left: 1px solid awsui.$color-border-layout; } - &:hover:not(.mobile-toggle-with-drawers) { + &:hover { background: awsui.$color-background-layout-panel-hover; } +} - &-with-drawers { - display: flex; - width: auto; - padding: 0; - height: 100%; - - > .mobile-trigger-with-drawers { - border-left: 1px solid awsui.$color-border-layout; - display: flex; - align-items: center; - } - } +.drawers-container { + display: flex; + align-items: stretch; } diff --git a/src/app-layout/toggles/index.tsx b/src/app-layout/toggles/index.tsx index e6bec2170d..e61c189af5 100644 --- a/src/app-layout/toggles/index.tsx +++ b/src/app-layout/toggles/index.tsx @@ -1,8 +1,10 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import clsx from 'clsx'; import React from 'react'; import { ButtonProps } from '../../button/interfaces'; import { InternalButton } from '../../button/internal'; +import InternalIcon from '../../icon/internal'; import { AppLayoutProps } from '../interfaces'; import { AppLayoutButtonProps } from './interfaces'; import styles from './styles.css.js'; @@ -28,25 +30,25 @@ export const togglesConfig = { }, } as const; -export const AppLayoutButton = React.forwardRef( +export const ToggleButton = React.forwardRef( ( - { className, ariaLabel, ariaExpanded, iconName, iconSvg, disabled, onClick }: AppLayoutButtonProps, - ref: React.Ref + { className, ariaLabel, ariaExpanded, iconName, iconSvg, disabled, testId, onClick }: AppLayoutButtonProps, + ref: React.Ref<{ focus(): void }> ) => { return ( - } + className={clsx(className, styles['toggle-button'])} + aria-label={ariaLabel} + type="button" onClick={onClick} - iconName={iconName} - iconSvg={iconSvg} disabled={disabled} - ariaExpanded={ariaExpanded ? undefined : false} - __nativeAttributes={{ 'aria-haspopup': ariaExpanded ? undefined : true }} - /> + aria-expanded={ariaExpanded ? undefined : false} + aria-haspopup={ariaExpanded ? undefined : true} + data-testid={testId} + > + + ); } ); @@ -61,11 +63,12 @@ export const CloseButton = React.forwardRef( ({ className, ariaLabel, onClick }: CloseButtonProps, ref: React.Ref) => { return ( - diff --git a/src/app-layout/toggles/interfaces.ts b/src/app-layout/toggles/interfaces.ts index 5007aeda6c..e1def475c5 100644 --- a/src/app-layout/toggles/interfaces.ts +++ b/src/app-layout/toggles/interfaces.ts @@ -1,5 +1,6 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 +import React from 'react'; import { IconProps } from '../../icon/interfaces'; export interface AppLayoutButtonProps { @@ -8,6 +9,7 @@ export interface AppLayoutButtonProps { ariaExpanded?: boolean; iconName?: IconProps.Name; iconSvg?: React.ReactNode; - onClick: () => void; + onClick?: () => void; disabled?: boolean; + testId?: string; } diff --git a/src/app-layout/toggles/styles.scss b/src/app-layout/toggles/styles.scss index 81c3eb6342..7fe0a008c6 100644 --- a/src/app-layout/toggles/styles.scss +++ b/src/app-layout/toggles/styles.scss @@ -7,6 +7,18 @@ @use '../../internal/styles' as styles; @use '../../internal/hooks/focus-visible' as focus-visible; +.toggle-button { + cursor: pointer; + border: 0; + // add up to 40px total height + padding: 5px awsui.$space-xxs; + background: transparent; + color: currentColor; + @include focus-visible.when-visible { + @include styles.focus-highlight(awsui.$space-button-inline-icon-focus-outline-gutter); + } +} + .close-button { position: absolute; outline: none; diff --git a/src/app-layout/visual-refresh/drawers.tsx b/src/app-layout/visual-refresh/drawers.tsx index c69a8fe478..386f0ea611 100644 --- a/src/app-layout/visual-refresh/drawers.tsx +++ b/src/app-layout/visual-refresh/drawers.tsx @@ -214,6 +214,7 @@ function DesktopTriggers() { }} ref={item.id === previousActiveDrawerId.current ? drawersRefs.toggle : undefined} selected={item.id === activeDrawerId} + testId={`awsui-app-layout-trigger-${item.id}`} /> ))} @@ -304,7 +305,7 @@ export function MobileTriggers() { onClick={() => handleDrawersClick(item.id)} ref={item.id === previousActiveDrawerId.current ? drawersRefs.toggle : undefined} variant="icon" - __nativeAttributes={{ 'aria-haspopup': true }} + __nativeAttributes={{ 'aria-haspopup': true, 'data-testid': `awsui-app-layout-trigger-${item.id}` }} /> ))} diff --git a/src/app-layout/visual-refresh/trigger-button.tsx b/src/app-layout/visual-refresh/trigger-button.tsx index c8dcc63e58..4689f39551 100644 --- a/src/app-layout/visual-refresh/trigger-button.tsx +++ b/src/app-layout/visual-refresh/trigger-button.tsx @@ -12,12 +12,13 @@ export interface TriggerButtonProps { className?: string; iconName?: IconProps.Name; iconSvg?: React.ReactNode; + testId?: string; onClick: React.MouseEventHandler; selected?: boolean; } function TriggerButton( - { ariaLabel, className, iconName, iconSvg, onClick, selected = false }: TriggerButtonProps, + { ariaLabel, className, iconName, iconSvg, onClick, testId, selected = false }: TriggerButtonProps, ref: React.Ref ) { return ( @@ -35,6 +36,7 @@ function TriggerButton( onClick={onClick} ref={ref as React.Ref} type="button" + data-testid={testId} > diff --git a/src/test-utils/dom/app-layout/index.ts b/src/test-utils/dom/app-layout/index.ts index c9ff7d6cc9..aae5ffe01a 100644 --- a/src/test-utils/dom/app-layout/index.ts +++ b/src/test-utils/dom/app-layout/index.ts @@ -67,6 +67,10 @@ export default class AppLayoutWrapper extends ComponentWrapper { return this.findAllByClassName(testutilStyles['drawers-trigger']); } + findDrawerTriggerById(id: string): ElementWrapper | null { + return this.find(`.${testutilStyles['drawers-trigger']}[data-testid="awsui-app-layout-trigger-${id}"]`); + } + findDrawersSlider(): ElementWrapper | null { return this.findByClassName(testutilStyles['drawers-slider']); } diff --git a/style-dictionary/utils/token-names.ts b/style-dictionary/utils/token-names.ts index 35eb975449..b9010614b3 100644 --- a/style-dictionary/utils/token-names.ts +++ b/style-dictionary/utils/token-names.ts @@ -331,7 +331,6 @@ export type ColorsTokenName = | 'colorForegroundControlDefault' | 'colorForegroundControlDisabled' | 'colorShadowDefault' - | 'colorShadowLayoutToggle' | 'colorShadowMedium' | 'colorShadowSide' | 'colorStrokeChartLine' diff --git a/style-dictionary/visual-refresh/colors.ts b/style-dictionary/visual-refresh/colors.ts index 6eb049e4b9..916ac60c1d 100644 --- a/style-dictionary/visual-refresh/colors.ts +++ b/style-dictionary/visual-refresh/colors.ts @@ -134,7 +134,6 @@ const tokens: StyleDictionary.ColorsDictionary = { colorForegroundControlDefault: { light: '{colorWhite}', dark: '{colorGrey900}' }, colorForegroundControlDisabled: { light: '{colorWhite}', dark: '{colorGrey800}' }, colorShadowDefault: '{colorGreyTransparentHeavy}', - colorShadowLayoutToggle: { light: '{colorGrey300}', dark: '{colorGrey650}' }, colorShadowMedium: '{colorGreyTransparent}', colorShadowSide: '{colorGreyTransparentLight}', colorStrokeChartLine: '{colorGrey500}',