Skip to content

Commit 86e81d5

Browse files
authored
fix: App layout toolbar trigger alignment in Safari (#3547)
1 parent 4fcfe74 commit 86e81d5

File tree

4 files changed

+35
-86
lines changed

4 files changed

+35
-86
lines changed

src/app-layout/__tests__/mobile.test.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import visualRefreshRefactoredStyles from '../../../lib/components/app-layout/vi
2626
import toolbarNotificationsStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/notifications/styles.css.js';
2727
import toolbarSkeletonStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/skeleton/styles.css.js';
2828
import toolbarStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/styles.css.js';
29-
import toolbarTriggerButtonStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/trigger-button/styles.css.js';
30-
import iconStyles from '../../../lib/components/icon/styles.css.js';
3129

3230
function AppLayoutWithControlledNavigation({
3331
initialNavigationOpen,
@@ -77,8 +75,6 @@ describeEachAppLayout({ sizes: ['mobile'] }, ({ theme }) => {
7775
classic: `.${styles['notifications-sticky']}`,
7876
};
7977

80-
const triggerBadgeClassName =
81-
theme === 'refresh-toolbar' ? toolbarTriggerButtonStyles['trigger-badge-wrapper'] : iconStyles.badge;
8278
const isUnfocusable = (element: HTMLElement) =>
8379
!!findUpUntil(element, current => current.classList.contains(unfocusableClassName));
8480

@@ -577,7 +573,8 @@ describeEachAppLayout({ sizes: ['mobile'] }, ({ theme }) => {
577573

578574
test('should render badge when defined', () => {
579575
const { wrapper } = renderComponent(<AppLayout drawers={manyDrawers} />);
580-
expect(wrapper.findDrawerTriggerById('security')!.getElement().children[0]).toHaveClass(triggerBadgeClassName);
576+
expect(wrapper.findDrawerTriggerById('security')).toBeTruthy();
577+
expect(wrapper.findDrawerTriggerById('security', { hasBadge: true })).toBeTruthy();
581578
});
582579

583580
test('renders roles only when aria labels are not provided', () => {

src/app-layout/__tests__/runtime-drawers.test.tsx

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,9 @@ import {
2222
testDrawer,
2323
} from './utils';
2424

25-
import triggerStyles from '../../../lib/components/app-layout/visual-refresh/styles.selectors.js';
2625
import skeletonStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/skeleton/styles.selectors.js';
2726
import toolbarStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/styles.selectors.js';
2827
import toolbarTriggerStyles from '../../../lib/components/app-layout/visual-refresh-toolbar/toolbar/trigger-button/styles.selectors.js';
29-
import iconStyles from '../../../lib/components/icon/styles.selectors.js';
3028

3129
beforeEach(() => {
3230
awsuiPluginsInternal.appLayout.clearRegisteredDrawers();
@@ -64,7 +62,7 @@ const drawerDefaults: DrawerConfig = {
6462
unmountContent: () => {},
6563
};
6664

67-
describeEachAppLayout(({ theme, size }) => {
65+
describeEachAppLayout(({ size }) => {
6866
test('does not render runtime drawers when it is explicitly disabled', async () => {
6967
awsuiPlugins.appLayout.registerDrawer(drawerDefaults);
7068
const { wrapper } = await renderComponent(<AppLayout {...({ __disableRuntimeDrawers: true } as any)} />);
@@ -111,33 +109,21 @@ describeEachAppLayout(({ theme, size }) => {
111109
const { wrapper } = await renderComponent(<AppLayout />);
112110
// the 2nd trigger is for tools
113111
expect(wrapper.findDrawersTriggers()).toHaveLength(2);
114-
const drawerTrigger = wrapper.findDrawerTriggerById(drawerDefaults.id);
115-
116-
const triggerParent = drawerTrigger!.getElement().parentElement;
117-
const triggerParentWrapper = createWrapper(triggerParent!);
118112

119113
awsuiPlugins.appLayout.updateDrawer({
120114
id: drawerDefaults.id,
121115
badge: true,
122116
});
123117
await delay();
124-
const badgeSelector =
125-
theme === 'refresh-toolbar'
126-
? toolbarTriggerStyles.badge
127-
: theme === 'refresh' && size === 'desktop'
128-
? triggerStyles.badge
129-
: iconStyles.badge;
130-
131-
expect(triggerParentWrapper!.findByClassName(badgeSelector)!.getElement()).toBeInTheDocument();
118+
expect(wrapper.findDrawerTriggerById(drawerDefaults.id, { hasBadge: true })).toBeTruthy();
132119

133120
awsuiPlugins.appLayout.updateDrawer({
134121
id: drawerDefaults.id,
135122
badge: false,
136123
});
137124
await delay();
138125

139-
// re-querying the dot element
140-
expect(triggerParentWrapper!.findByClassName(badgeSelector)).toBeNull();
126+
expect(wrapper.findDrawerTriggerById(drawerDefaults.id, { hasBadge: false })).toBeTruthy();
141127
});
142128

143129
(size === 'desktop' ? test : test.skip)('update runtime drawers config resizable validation', async () => {

src/app-layout/visual-refresh-toolbar/toolbar/trigger-button/index.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,9 @@ function TriggerButton(
217217
disabled={disabled}
218218
className={clsx(
219219
styles.trigger,
220-
styles['trigger-button-styles'],
221220
{
222221
[styles.selected]: selected,
223-
[styles.badge]: badge,
222+
[styles['trigger-with-badge']]: badge,
224223
[testutilStyles['drawers-trigger-with-badge']]: badge,
225224
},
226225
className
@@ -232,9 +231,7 @@ function TriggerButton(
232231
data-shift-focus="awsui-layout-drawer-trigger"
233232
{...getAnalyticsMetadataAttribute(triggerEventMetadata)}
234233
>
235-
<span className={clsx(badge && clsx(styles['trigger-badge-wrapper'], styles['trigger-button-styles']))}>
236-
{(iconName || iconSvg) && <Icon name={iconName} svg={iconSvg} />}
237-
</span>
234+
{(iconName || iconSvg) && <Icon name={iconName} svg={iconSvg} />}
238235
</button>
239236
{badge && <div className={styles.dot} />}
240237
{tooltipVisible && (

src/app-layout/visual-refresh-toolbar/toolbar/trigger-button/styles.scss

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,31 @@
77
@use '../../../../internal/styles/tokens' as awsui;
88
@use '@cloudscape-design/component-toolkit/internal/focus-visible' as focus-visible;
99

10-
@mixin trigger-selected-styles {
11-
background: awsui.$color-background-layout-toggle-selected-default;
12-
color: awsui.$color-text-layout-toggle-selected;
13-
14-
&:hover {
15-
background: awsui.$color-background-layout-toggle-selected-hover;
16-
}
17-
&:active {
18-
background: awsui.$color-background-layout-toggle-selected-active;
19-
}
20-
}
10+
.trigger {
11+
// reset native <button> tag styles
12+
all: initial;
2113

22-
.trigger-button-styles {
23-
background: transparent;
14+
cursor: pointer;
2415
color: awsui.$color-text-interactive-default;
2516
border-start-start-radius: 50%;
2617
border-start-end-radius: 50%;
2718
border-end-start-radius: 50%;
2819
border-end-end-radius: 50%;
2920
block-size: 30px;
3021
inline-size: 30px;
31-
display: flex;
32-
align-items: center;
33-
justify-content: center;
34-
box-sizing: border-box;
22+
text-align: center;
23+
24+
&-with-badge {
25+
clip-path: path(
26+
'M29.2862 10.4145C28.7243 10.5998 28.1238 10.7 27.4999 10.7C24.3519 10.7 21.7999 8.14803 21.7999 5C21.7999 3.92883 22.0954 2.92667 22.6093 2.07057C20.3785 0.754846 17.7774 0 15 0C6.71573 0 0 6.71573 0 15C0 23.2843 6.71573 30 15 30C23.2843 30 30 23.2843 30 15C30 13.4007 29.7497 11.8599 29.2862 10.4145Z'
27+
);
28+
29+
@include styles.with-direction('rtl') {
30+
clip-path: path(
31+
'M2.21384 10.4145C2.77569 10.5998 3.37617 10.7 4.00007 10.7C7.1481 10.7 9.70007 8.14803 9.70007 5C9.70007 3.92883 9.4046 2.92667 8.89071 2.07057C11.1215 0.754846 13.7226 0 16.5 0C24.7843 0 31.5 6.71573 31.5 15C31.5 23.2843 24.7843 30 16.5 30C8.21573 30 1.5 23.2843 1.5 15C1.5 13.4007 1.75029 11.8599 2.21384 10.4145Z'
32+
);
33+
}
34+
}
3535

3636
&:hover {
3737
background: awsui.$color-background-input-disabled;
@@ -42,61 +42,30 @@
4242
background: awsui.$color-background-control-disabled;
4343
color: awsui.$color-text-interactive-hover;
4444
}
45-
}
46-
47-
.trigger-badge-wrapper {
48-
position: absolute;
49-
inset-block-start: 0;
50-
inset-inline-start: 0;
51-
display: flex;
52-
justify-content: center;
53-
align-items: center;
54-
clip-path: path(
55-
'M29.2862 10.4145C28.7243 10.5998 28.1238 10.7 27.4999 10.7C24.3519 10.7 21.7999 8.14803 21.7999 5C21.7999 3.92883 22.0954 2.92667 22.6093 2.07057C20.3785 0.754846 17.7774 0 15 0C6.71573 0 0 6.71573 0 15C0 23.2843 6.71573 30 15 30C23.2843 30 30 23.2843 30 15C30 13.4007 29.7497 11.8599 29.2862 10.4145Z'
56-
);
57-
58-
@include styles.with-direction('rtl') {
59-
clip-path: path(
60-
'M2.21384 10.4145C2.77569 10.5998 3.37617 10.7 4.00007 10.7C7.1481 10.7 9.70007 8.14803 9.70007 5C9.70007 3.92883 9.4046 2.92667 8.89071 2.07057C11.1215 0.754846 13.7226 0 16.5 0C24.7843 0 31.5 6.71573 31.5 15C31.5 23.2843 24.7843 30 16.5 30C8.21573 30 1.5 23.2843 1.5 15C1.5 13.4007 1.75029 11.8599 2.21384 10.4145Z'
61-
);
62-
}
63-
}
64-
65-
.trigger {
66-
border-block: none;
67-
border-inline: none;
68-
cursor: pointer;
69-
pointer-events: auto;
70-
71-
@include focus-visible.when-visible {
72-
@include styles.focus-highlight(3px);
73-
}
7445

7546
&:focus {
47+
// custom outline attached on the wrapping element
7648
outline: none;
7749
}
7850

7951
&.selected {
80-
@include trigger-selected-styles();
52+
background: awsui.$color-background-layout-toggle-selected-default;
53+
color: awsui.$color-text-layout-toggle-selected;
8154

82-
> .trigger-badge-wrapper {
83-
@include trigger-selected-styles();
55+
&:hover {
56+
background: awsui.$color-background-layout-toggle-selected-hover;
57+
}
58+
&:active {
59+
background: awsui.$color-background-layout-toggle-selected-active;
8460
}
85-
}
86-
87-
&.badge,
88-
&.badge:hover,
89-
&.badge:active {
90-
background: transparent;
9161
}
9262
}
9363

9464
.trigger-wrapper {
9565
position: relative;
96-
border-start-start-radius: 50%;
97-
border-start-end-radius: 50%;
98-
border-end-start-radius: 50%;
99-
border-end-end-radius: 50%;
66+
&:has(:focus-visible) {
67+
@include styles.focus-highlight(3px);
68+
}
10069
}
10170

10271
.dot {

0 commit comments

Comments
 (0)