diff --git a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts index ef566777b..7825191a1 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/doc-tree.spec.ts @@ -5,6 +5,7 @@ import { createDoc, getOtherBrowserName, verifyDocName, + waitForTransitionsEnd, } from './utils-common'; import { addNewMember, connectOtherUserToDoc } from './utils-share'; import { addChild, createRootSubPage, getTreeRow } from './utils-sub-pages'; @@ -403,12 +404,16 @@ test.describe('Doc Tree', () => { await expect(rootMoreOptionsButton).toBeFocused(); await page.keyboard.press('F2'); await expect(rootAddDocButton).toBeFocused(); + await waitForTransitionsEnd(page); await page.keyboard.press('F2'); await expect(rootMoreOptionsButton).toBeFocused(); + await waitForTransitionsEnd(page); await page.keyboard.press('ArrowRight'); await expect(rootAddDocButton).toBeFocused(); + await waitForTransitionsEnd(page); await page.keyboard.press('ArrowLeft'); await expect(rootMoreOptionsButton).toBeFocused(); + await waitForTransitionsEnd(page); await page.keyboard.press('Enter'); await expect( page.getByRole('menuitem', { name: /Copy Link/i }), diff --git a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts index 7f5f239de..5aac4d57a 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/language.spec.ts @@ -5,6 +5,7 @@ import { createDoc, overrideConfig, waitForLanguageSwitch, + waitForTransitionsEnd, } from './utils-common'; import { openSuggestionMenu } from './utils-editor'; @@ -72,9 +73,12 @@ test.describe('Language', () => { await waitForLanguageSwitch(page, TestLanguage.French); await page.getByLabel('Menu utilisateur').click(); + await waitForTransitionsEnd(page); await page.keyboard.press('Tab'); + await waitForTransitionsEnd(page); await page.keyboard.press('Tab'); + await waitForTransitionsEnd(page); await page.keyboard.press('Enter'); await expect( diff --git a/src/frontend/apps/e2e/__tests__/app-impress/utils-common.ts b/src/frontend/apps/e2e/__tests__/app-impress/utils-common.ts index 1aa3f624f..eb2a5b697 100644 --- a/src/frontend/apps/e2e/__tests__/app-impress/utils-common.ts +++ b/src/frontend/apps/e2e/__tests__/app-impress/utils-common.ts @@ -413,6 +413,27 @@ export async function waitForLanguageSwitch( await page.keyboard.press('Escape'); } +/** + * Wait until no CSS transition runs on the page. + * + * Moving the focus with the keyboard starts the focus ring transitions of the + * buttons. Since Chromium 153, a button that loses the focus or becomes inert + * mid-transition gets them cancelled, and react-aria (`runAfterTransition`) + * then waits forever before focusing a menu or restoring the focus. + * Call it after a keyboard focus move, before the next key press. + */ +export const waitForTransitionsEnd = async (page: Page) => { + await page.waitForFunction(() => + document + .getAnimations() + .every( + (animation) => + !(animation instanceof CSSTransition) || + animation.playState !== 'running', + ), + ); +}; + export const clickInEditorShareButton = async (page: Page) => { await page .getByTestId('floating-bar') diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css index 3ff95ae7f..ebcbe90c3 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.css @@ -427,6 +427,12 @@ --c--contextuals--background--semantic--overlay--primary-hover: var( --c--globals--colors--black-100 ); + --c--contextuals--background--semantic--overlay--on-surface: var( + --c--globals--colors--white-650 + ); + --c--contextuals--background--semantic--overlay--transparent: var( + --c--globals--colors--white-000 + ); --c--contextuals--background--semantic--contextual--primary: var( --c--globals--colors--black-050 ); @@ -654,6 +660,9 @@ --c--contextuals--content--semantic--overlay--primary: var( --c--globals--colors--white-950 ); + --c--contextuals--content--semantic--overlay--secondary: var( + --c--globals--colors--white-800 + ); --c--contextuals--content--semantic--brand--primary: var( --c--globals--colors--brand-700 ); @@ -1781,6 +1790,12 @@ --c--contextuals--background--semantic--overlay--primary-hover: var( --c--globals--colors--white-100 ); + --c--contextuals--background--semantic--overlay--on-surface: var( + --c--globals--colors--black-650 + ); + --c--contextuals--background--semantic--overlay--transparent: var( + --c--globals--colors--black-000 + ); --c--contextuals--background--semantic--brand--primary: var( --c--globals--colors--brand-550 ); @@ -2002,6 +2017,9 @@ --c--contextuals--content--semantic--overlay--primary: var( --c--globals--colors--black-850 ); + --c--contextuals--content--semantic--overlay--secondary: var( + --c--globals--colors--black-700 + ); --c--contextuals--content--semantic--brand--primary: var( --c--globals--colors--brand-050 ); @@ -2588,6 +2606,12 @@ --c--contextuals--background--semantic--overlay--primary-hover: var( --c--globals--colors--black-100 ); + --c--contextuals--background--semantic--overlay--on-surface: var( + --c--globals--colors--white-650 + ); + --c--contextuals--background--semantic--overlay--transparent: var( + --c--globals--colors--white-000 + ); --c--contextuals--background--semantic--contextual--primary: var( --c--globals--colors--black-050 ); @@ -2815,6 +2839,9 @@ --c--contextuals--content--semantic--overlay--primary: var( --c--globals--colors--white-950 ); + --c--contextuals--content--semantic--overlay--secondary: var( + --c--globals--colors--white-800 + ); --c--contextuals--content--semantic--brand--primary: var( --c--globals--colors--brand-700 ); @@ -6212,6 +6239,18 @@ ); } +.bg-semantic-overlay-on-surface { + background-color: var( + --c--contextuals--background--semantic--overlay--on-surface + ); +} + +.bg-semantic-overlay-transparent { + background-color: var( + --c--contextuals--background--semantic--overlay--transparent + ); +} + .bg-semantic-contextual-primary { background-color: var( --c--contextuals--background--semantic--contextual--primary @@ -8125,6 +8164,10 @@ color: var(--c--contextuals--content--semantic--overlay--primary); } +.clr-content-semantic-overlay-secondary { + color: var(--c--contextuals--content--semantic--overlay--secondary); +} + .clr-content-semantic-brand-primary { color: var(--c--contextuals--content--semantic--brand--primary); } diff --git a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts index d51e2f87b..c5292f4a0 100644 --- a/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts +++ b/src/frontend/apps/impress/src/cunningham/cunningham-tokens.ts @@ -440,7 +440,12 @@ export const tokens = { tertiary: '#F8F8F9', }, semantic: { - overlay: { primary: '#1B1B230D', 'primary-hover': '#1B1B231A' }, + overlay: { + primary: '#1B1B230D', + 'primary-hover': '#1B1B231A', + 'on-surface': '#F8F8F9A6', + transparent: '#F8F8F900', + }, contextual: { primary: '#1B1B230D', 'primary-hover': '#1B1B231A' }, brand: { primary: '#5E5CD0', @@ -555,7 +560,7 @@ export const tokens = { logo2: '#4844AD', semantic: { contextual: { primary: '#F8F8F9F2' }, - overlay: { primary: '#F8F8F9F2' }, + overlay: { primary: '#F8F8F9F2', secondary: '#F8F8F9CC' }, brand: { primary: '#3E3B98', secondary: '#534FC2', @@ -1341,7 +1346,12 @@ export const tokens = { }, semantic: { contextual: { primary: '#F8F8F90D', 'primary-hover': '#F8F8F91A' }, - overlay: { primary: '#F8F8F90D', 'primary-hover': '#F8F8F91A' }, + overlay: { + primary: '#F8F8F90D', + 'primary-hover': '#F8F8F91A', + 'on-surface': '#1B1B23A6', + transparent: '#1B1B2300', + }, brand: { primary: '#5E5CD0', 'primary-hover': '#4844AD', @@ -1455,7 +1465,7 @@ export const tokens = { logo2: '#BEC5F0', semantic: { contextual: { primary: '#1B1B23D9' }, - overlay: { primary: '#1B1B23D9' }, + overlay: { primary: '#1B1B23D9', secondary: '#1B1B23B2' }, brand: { primary: '#EEF1FA', secondary: '#DDE2F5', @@ -1963,7 +1973,12 @@ export const tokens = { tertiary: '#F8F8F9', }, semantic: { - overlay: { primary: '#1B1B230D', 'primary-hover': '#1B1B231A' }, + overlay: { + primary: '#1B1B230D', + 'primary-hover': '#1B1B231A', + 'on-surface': '#F8F8F9A6', + transparent: '#F8F8F900', + }, contextual: { primary: '#1B1B230D', 'primary-hover': '#1B1B231A' }, brand: { primary: '#5E5CD0', @@ -2078,7 +2093,7 @@ export const tokens = { logo2: '#4844AD', semantic: { contextual: { primary: '#F8F8F9F2' }, - overlay: { primary: '#F8F8F9F2' }, + overlay: { primary: '#F8F8F9F2', secondary: '#F8F8F9CC' }, brand: { primary: '#3E3B98', secondary: '#534FC2',