From 22a03652784b00f353b6519dd252f877502c5115 Mon Sep 17 00:00:00 2001 From: Maria Garcia Luque Date: Wed, 22 Jul 2026 14:09:23 +0200 Subject: [PATCH 1/5] [FIR-318] Move the playground e2e port from 4300 to 4310 Avoids colliding with dev servers commonly left running on 4300. --- apps/playground-e2e/playwright.config.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/playground-e2e/playwright.config.ts b/apps/playground-e2e/playwright.config.ts index 12115dd..37d8449 100644 --- a/apps/playground-e2e/playwright.config.ts +++ b/apps/playground-e2e/playwright.config.ts @@ -6,8 +6,10 @@ import { workspaceRoot } from '@nx/devkit'; * Dedicated port: 4200 is the default `nx serve playground` port, so a * developer's already-running dev server (of this app or any other) would be * silently reused and the suite would screenshot the wrong application. + * 4310 (not 4300) additionally keeps clear of other dev servers commonly + * left running on 4300 during local work. */ -const baseURL = process.env['BASE_URL'] || 'http://localhost:4300'; +const baseURL = process.env['BASE_URL'] || 'http://localhost:4310'; /** * Read environment variables from file. @@ -28,8 +30,8 @@ export default defineConfig({ }, /* Run your local dev server before starting the tests */ webServer: { - command: 'pnpm exec nx run playground:serve --port 4300', - url: 'http://localhost:4300', + command: 'pnpm exec nx run playground:serve --port 4310', + url: 'http://localhost:4310', reuseExistingServer: true, cwd: workspaceRoot, }, From 472ca1a5b237bc436aafa491a644f1c4fd1b01c1 Mon Sep 17 00:00:00 2001 From: Maria Garcia Luque Date: Wed, 22 Jul 2026 14:09:54 +0200 Subject: [PATCH 2/5] [FIR-318] Pin the flydocs input focus-ring token to the product's translucent halo ff-input already reads --ff-input-focus-ring for its wrapper box-shadow with a solid-color fallback; the flydocs theme previously left it unset, so focus fell back to a hard-edged outline instead of the product's translucent ring. Pin it to the product's own rgba value in light and dark, and record the resolved parity delta. --- .../src/app/themes/_flydocs-theme-dark.scss | 3 +- .../src/app/themes/_flydocs-theme.scss | 7 +++-- docs/flydocs-parity-report.md | 28 ++++++++++--------- docs/flydocs-theme-token-equivalence.md | 3 +- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/apps/playground/src/app/themes/_flydocs-theme-dark.scss b/apps/playground/src/app/themes/_flydocs-theme-dark.scss index 1dee954..dd7e042 100644 --- a/apps/playground/src/app/themes/_flydocs-theme-dark.scss +++ b/apps/playground/src/app/themes/_flydocs-theme-dark.scss @@ -19,8 +19,9 @@ --ff-color-surface: #161826; --ff-color-border: #363b4e; - /* Same alpha-drop reasoning as the light theme, over the dark ring hue. */ --ff-color-border-focus: #6378ff; + /* Dark counterpart of the light halo above, over the lifted dark ring hue. */ + --ff-input-focus-ring: rgba(99, 120, 255, 0.3); --ff-color-on-surface: #f6f7fa; --ff-text-primary: #f6f7fa; diff --git a/apps/playground/src/app/themes/_flydocs-theme.scss b/apps/playground/src/app/themes/_flydocs-theme.scss index 2be60a6..5b2ee52 100644 --- a/apps/playground/src/app/themes/_flydocs-theme.scss +++ b/apps/playground/src/app/themes/_flydocs-theme.scss @@ -27,10 +27,11 @@ /* ---- Surfaces / structure ---- */ --ff-color-surface: #ffffff; --ff-color-border: #e1e4ec; - /* Focus ring hue only: Flydocs models focus as a translucent ring - (rgba brand-blue at 25%); ff consumes it as a solid 2px outline, - so the hue is kept and the alpha dropped. */ + /* Focus border hue, consumed by ff-input as a solid 2px border-color. */ --ff-color-border-focus: #3b59f5; + /* Focus ring, consumed by ff-input as the wrapper's focus box-shadow + (translucent brand-blue halo, not a hard-edged outline). */ + --ff-input-focus-ring: rgba(59, 89, 245, 0.25); /* ---- Text-on-surface roles ---- `on-surface` has no named Flydocs counterpart; it plays the same diff --git a/docs/flydocs-parity-report.md b/docs/flydocs-parity-report.md index 6239050..0f65b6c 100644 --- a/docs/flydocs-parity-report.md +++ b/docs/flydocs-parity-report.md @@ -44,7 +44,7 @@ zoom**. | 4 | `ff-panel` | alert warning/danger, default with heading/footer | ✅ Pass | | 4 | `ff-card` | basic, md shadow | ✅ Pass | | 4 | `ff-tab-bar` | underline/pills, active not-first, badge+icon tabs | ✅ Pass | -| 5 | `ff-input` | rest / hover / **focus** / error / disabled | ⚠️ Pass with one flagged delta (focus-ring rendering) | +| 5 | `ff-input` | rest / hover / **focus** / error / disabled | ✅ Pass (focus-ring delta resolved, see FIR-318) | | 5 | `ff-checkbox` | unchecked / checked / disabled-checked | ✅ Pass | | 5 | `ff-radio` | group with selected option | ✅ Pass | @@ -52,21 +52,23 @@ zoom**. Per the gate's contract, components that fail the comparison are **not** fixed inside FF-CAT-20 — each perceptible delta generates its own issue. -One delta is flagged, borderline-perceptible and pre-documented in the -equivalence doc: - -1. **Input focus ring: solid outline vs translucent halo.** Flydocs models - focus as a translucent box-shadow ring (brand blue at 25% alpha); - `ff-input` consumes `--ff-color-border-focus` as a solid 2px outline on - the field wrapper (`:focus-within`, after the FIR-289 refactor moved it - off the native control). The hue matches; the rendering mechanism does - not. At 100% zoom the difference is visible on direct comparison - (hard edge vs soft glow). Changing it means teaching the component a - ring-style focus treatment — a component change, out of this gate's - scope. +No delta is currently flagged. ## Resolved deltas +- **Input focus ring: solid outline vs translucent halo — resolved (FIR-318).** + `ff-input`'s field wrapper already rendered its focus indicator through a + dedicated component token, `--ff-input-focus-ring` (falling back to + `--ff-color-border-focus` when unset). The Flydocs theme now pins that + token to the product's own translucent halo value + (`--hub-sys-focus-ring-color`, `rgba(59, 89, 245, 0.25)` in light, + `rgba(99, 120, 255, 0.3)` in dark), instead of leaving it to fall back to + the solid focus border color. The wrapper's `border-color` (driven by + `--ff-color-border-focus`) still changes on focus alongside the ring, so + the focus indicator carries two independent visual cues (border color + step-up + halo), keeping it perceptible at the reduced ring alpha. See + `docs/flydocs-theme-token-equivalence.md` for the full reasoning. + - **Neutral badge chip runs cool, Flydocs' runs warm — resolved (FIR-317).** `ff-badge`'s neutral chip background now resolves through its own component token, `--ff-badge-neutral-bg` (falling back to diff --git a/docs/flydocs-theme-token-equivalence.md b/docs/flydocs-theme-token-equivalence.md index d76eee6..adae51e 100644 --- a/docs/flydocs-theme-token-equivalence.md +++ b/docs/flydocs-theme-token-equivalence.md @@ -69,7 +69,8 @@ published theme. |---|---|---|---|---| | `--ff-color-surface` | Default component chrome background (card, header, nav, panel) | `--hub-sys-color-surface-default` (= `--hub-ref-color-neutral-0`) | `#ffffff` | Direct | | `--ff-color-border` | Default hairline border (cards, tables, dividers) | `--hub-sys-border-color-default` (= `--hub-ref-color-neutral-200`) | `#e1e4ec` | Direct | -| `--ff-color-border-focus` | Solid 2px focus outline | `--hub-sys-focus-ring-color` (`rgba(59,89,245,.25)`, i.e. brand blue) | `#3b59f5` | Derived — Flydocs models focus as a translucent ring meant for `box-shadow`; ff consumes it as a solid `outline`. The hue (brand blue = `--hub-ref-color-blue-500`) is kept, the alpha dropped so the stroke stays visible as a hard outline. | +| `--ff-color-border-focus` | Solid 2px focus border-color on the input wrapper | `--hub-sys-focus-ring-color` (`rgba(59,89,245,.25)`, i.e. brand blue) | `#3b59f5` | Derived — the border-color role only ever needs the ring's hue (brand blue = `--hub-ref-color-blue-500`); the alpha channel is not applicable to a `border-color` and is carried instead by `--ff-input-focus-ring` below. | +| `--ff-input-focus-ring` (component-scoped, `ff-input`) | Translucent focus halo on the input wrapper's `box-shadow` | `--hub-sys-focus-ring-color` | `rgba(59, 89, 245, 0.25)` (dark: `rgba(99, 120, 255, 0.3)`, `--hub-sys-focus-ring-color` re-pinned in `_theme-dark.scss`) | Direct — `ff-input` already renders its focus indicator as a `box-shadow` ring (`var(--ff-input-focus-ring, var(--ff-color-border-focus))`), so the full rgba value (hue + alpha) is ported as-is instead of being lossily collapsed into a solid color. | | `--ff-color-on-primary` | Text/icon color atop a primary-filled surface (button label, checked radio dot, checkbox mark) | `--hub-sys-color-primary-on` / `-on-default` | `#ffffff` | Direct | | `--ff-color-on-surface` | Text/icon color atop the default surface (menu item text) | no named counterpart | `#161826` | Derived — no Flydocs token is called "on-surface"; the role (primary reading text over the default surface) is identical to `text-primary`, so it takes that value. | From fbffc10e94420808d2dc80eacf3b0e351b15e4a7 Mon Sep 17 00:00:00 2001 From: Maria Garcia Luque Date: Wed, 22 Jul 2026 14:14:31 +0200 Subject: [PATCH 3/5] [FIR-318] Regenerate the input focused-state VR baseline for the ring halo Only the focused specimen's darwin baseline changes pixels; every other input state and wave-5 baseline is unaffected. Drops the stale linux baseline so CI reseeds it against the new rendering. --- .../input-default-focused-chromium-darwin.png | Bin 4511 -> 4547 bytes .../input-default-focused-chromium-linux.png | Bin 4555 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png diff --git a/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-darwin.png b/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-darwin.png index d6c4b6ffcb3f56ca380f39df524fd6e352dbff41..673d6b70ec7e1bfbc0828a377b3ad639016b6fcf 100644 GIT binary patch delta 4538 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 diff --git a/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png b/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png deleted file mode 100644 index 127c4e95e61a5e6dcc0d74d440b8c027c607a22a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4555 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 p00960Lj=J100006Nkl Date: Wed, 22 Jul 2026 14:19:03 +0200 Subject: [PATCH 4/5] [FIR-318] Trim the port and dark-ring comments to their contracts --- apps/playground-e2e/playwright.config.ts | 8 +++----- apps/playground/src/app/themes/_flydocs-theme-dark.scss | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/playground-e2e/playwright.config.ts b/apps/playground-e2e/playwright.config.ts index 37d8449..3ebf88d 100644 --- a/apps/playground-e2e/playwright.config.ts +++ b/apps/playground-e2e/playwright.config.ts @@ -3,11 +3,9 @@ import { nxE2EPreset } from '@nx/playwright/preset'; import { workspaceRoot } from '@nx/devkit'; /* - * Dedicated port: 4200 is the default `nx serve playground` port, so a - * developer's already-running dev server (of this app or any other) would be - * silently reused and the suite would screenshot the wrong application. - * 4310 (not 4300) additionally keeps clear of other dev servers commonly - * left running on 4300 during local work. + * Dedicated e2e port, distinct from common local dev-server ports: an + * already-running dev server (of this app or any other) would be silently + * reused and the suite would screenshot the wrong application. */ const baseURL = process.env['BASE_URL'] || 'http://localhost:4310'; diff --git a/apps/playground/src/app/themes/_flydocs-theme-dark.scss b/apps/playground/src/app/themes/_flydocs-theme-dark.scss index dd7e042..320aa49 100644 --- a/apps/playground/src/app/themes/_flydocs-theme-dark.scss +++ b/apps/playground/src/app/themes/_flydocs-theme-dark.scss @@ -20,7 +20,8 @@ --ff-color-surface: #161826; --ff-color-border: #363b4e; --ff-color-border-focus: #6378ff; - /* Dark counterpart of the light halo above, over the lifted dark ring hue. */ + /* Focus ring, consumed by ff-input as the wrapper's focus box-shadow + (translucent brand-blue halo, not a hard-edged outline). */ --ff-input-focus-ring: rgba(99, 120, 255, 0.3); --ff-color-on-surface: #f6f7fa; From 6a5673990070bde76233a4759d16b17cec174f32 Mon Sep 17 00:00:00 2001 From: Maria Garcia Luque Date: Wed, 22 Jul 2026 14:23:41 +0200 Subject: [PATCH 5/5] [FIR-318] Commit the reseeded focused-state linux baseline --- .../input-default-focused-chromium-linux.png | Bin 0 -> 4574 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png diff --git a/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png b/apps/playground-e2e/src/parity.spec.ts-snapshots/input-default-focused-chromium-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..a3cd7ba559d04be6ae1c2f4a772672afed20822d GIT binary patch literal 4574 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 IM6N<$f<2SVeE