From c713a30931b987fdaaf76833cc8dd58dd08b1c24 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:36:04 -0300 Subject: [PATCH 01/12] style(onboarding): show the selected SDK as a badge in the code card Replace the plain text language label in the code card header with the same accent badge (logo + label) the SDK picker uses for the selected chip, in semibold. Reuses the Chip primitive rather than the bespoke label style. Co-Authored-By: Claude Opus 4.8 --- .../ConnectYourCodePanel.tsx | 23 ++++++++++++------- .../OnboardingConnectPanel.scss | 6 ----- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx index b66882d24569..b73ec452890c 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx @@ -1,5 +1,6 @@ import React, { FC, useState } from 'react' import classNames from 'classnames' +import Chip from 'components/base/Chip' import CodeCard from './CodeCard' import SdkPicker from './SdkPicker' import { getSdkSnippet } from './sdkSnippets' @@ -9,6 +10,18 @@ type PackageManager = 'npm' | 'yarn' const PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn'] +// The chosen SDK as an accent badge (logo + label), matching the picker's +// selected chip - the code card labels its language with this. +const SdkBadge: FC<{ lang: SdkLang }> = ({ lang }) => { + const Logo = lang.logo + return ( + + + {lang.label} + + ) +} + export type ConnectYourCodePanelProps = { environmentKey: string featureName: string @@ -64,9 +77,7 @@ const ConnectYourCodePanel: FC = ({ ))} ) : ( - - {sdkLang.label} - + ) } /> @@ -83,11 +94,7 @@ const ConnectYourCodePanel: FC = ({ language={sdkSnippet.language} onCopy={onCopyWire} copyLabel='Copy code snippet' - headerLeft={ - - {sdkLang.label} - - } + headerLeft={} /> diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss index 55e5df84ecd0..bd7ad277621a 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss @@ -100,12 +100,6 @@ border-bottom: 1px solid var(--color-border-default); } - &__codecard-lang { - font-size: 0.75rem; - font-weight: 600; - color: var(--color-text-secondary); - } - &__pm { border-radius: 6px; overflow: hidden; From 140cc85a190ce1447205d2a56c29225a6382110e Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:51:06 -0300 Subject: [PATCH 02/12] fix(onboarding): make the JavaScript SDK logo legible on light mode The JS logo hole-punched the letters out of the yellow square, so they showed the chip behind them and washed out on a light chip. Draw it as the brand badge instead - solid black JS on a rounded yellow square - so it reads on both light and dark. Co-Authored-By: Claude Opus 4.8 --- .../logos/javascript-logo.tsx | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/logos/javascript-logo.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/logos/javascript-logo.tsx index f7299f0ae2f8..dca252b249f8 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/logos/javascript-logo.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/logos/javascript-logo.tsx @@ -1,8 +1,16 @@ import React from 'react' -import Svg from './svg' +// Two-tone on purpose: the other logos are single-fill glyphs, but JS is a +// filled badge. Drawing the "JS" as solid black over the yellow square (rather +// than the shared wrapper's hole-punch, which shows the chip through it and +// washes out on a light chip) keeps it readable on both light and dark. Rounded +// so it reads as a badge. export const JavascriptLogo = () => ( - - - + + + + ) From 4ed30e285b4b32d8a1e6ed52378f6fff648c4922 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 15:05:43 -0300 Subject: [PATCH 03/12] style(onboarding): match SDK picker chips to the badge weight Apply fw-semibold to the selectable SDK chips (and the More/Less chip) so they match the selected-SDK badge in the code card. Co-Authored-By: Claude Opus 4.8 --- .../pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx index e3f4ea0a3772..a0c4241e0420 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx @@ -69,6 +69,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => { ref={(el) => { refs.current[lang.label] = el }} + className='fw-semibold' role='radio' aria-checked={isSelected} tabIndex={lang.label === tabStopLabel ? 0 : -1} @@ -91,6 +92,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => {
{popularLangs.map(renderOption)} setMoreOpen((open) => !open)} aria-expanded={moreOpen} > From 722c461b933dae9b23344650986f34f9f3f61e98 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 15:13:16 -0300 Subject: [PATCH 04/12] style(onboarding): add breathing room above the theme toggle Review nit: bump the flow's top padding (4px -> 24px) so the theme-toggle row isn't flush to the top edge. Co-Authored-By: Claude Opus 4.8 --- .../pages/onboarding/OnboardingFlow/OnboardingFlow.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.scss b/frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.scss index 8b923ee20edd..9bee42832fe9 100644 --- a/frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.scss +++ b/frontend/web/components/pages/onboarding/OnboardingFlow/OnboardingFlow.scss @@ -4,7 +4,7 @@ // Centring is the `mx-auto` utility on the element. .onboarding-flow { max-width: 1100px; - // Minimal top padding so the theme-toggle row isn't flush to the very edge; + // Top padding gives the theme-toggle row room to breathe from the very edge; // sides + bottom keep the reading column off the edges. - padding: 4px 24px 40px; + padding: 24px 24px 40px; } From faf2a37cd88a70a07305b1ae116a20401caa9d7f Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 18:58:19 -0300 Subject: [PATCH 05/12] style(onboarding): make inline-edit fields read as editable at rest Review feedback (Matt): the org/project fields only showed a fill on hover, so they read as plain text until clicked. Give them a resting fill (matching the flag pill) and a full-opacity pencil, deepening on hover for feedback. Co-Authored-By: Claude Opus 4.8 --- .../onboarding/InlineInput/InlineInput.scss | 18 ++++-------------- .../onboarding/InlineInput/InlineInput.tsx | 4 ++-- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss index 80fb93e7b9da..1032d4ffac12 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss @@ -1,5 +1,3 @@ -// Inline editable value in the welcome sentence: an action underline + pencil, -// with a faint highlight on hover/focus. Rationale lives in InlineInput.tsx. .inline-input { display: inline-flex; align-items: center; @@ -8,25 +6,17 @@ padding: 0 4px; border-radius: var(--radius-xs); border-bottom: 1px solid var(--color-border-action); + // Resting fill so it reads as editable, not only on hover. + background-color: var(--color-surface-subtle); cursor: text; transition: background-color var(--duration-fast) var(--easing-standard); - svg { - opacity: 0.8; - transition: opacity var(--duration-fast) var(--easing-standard); - } - &:hover, &:focus-within { - background-color: var(--color-surface-subtle); - - svg { - opacity: 1; - } + background-color: var(--color-surface-muted); } - // The hero value (flag name): a filled soft-purple pill instead of an - // underline, so it reads as the thing the user will reference in code. + // Flag name: a filled pill rather than an underline (it's referenced in code). &--accent { padding: 1px 8px; border-bottom: none; diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx index 82ac5f2b173e..3e66caaf6db2 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx @@ -23,8 +23,8 @@ export type InlineInputProps = { } // Onboarding-local inline editable value (GhostInput + pencil) for the welcome -// sentence: an action underline + pencil mark it editable, it commits on -// blur/Enter, and an empty value reverts. Shares the VariationKeyLabel inline +// sentence: a resting fill, action underline and pencil mark it editable; it +// commits on blur/Enter, and an empty value reverts. Shares the VariationKeyLabel inline // edit's visual language but drops its buttons/validation to stay prose-like; // feature-local for now, both should converge on one primitive. const InlineInput: FC = ({ From 8c3e7ea6e00ff7e69b34c0f8a0a462014c9fd63f Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Mon, 13 Jul 2026 15:10:22 -0300 Subject: [PATCH 06/12] fix(onboarding): avoid Safari contact autofill on inline-edit fields Safari AutoFill read the " name" aria-label as a contact-name field and showed its person icon on the project field. Label the fields "Edit " instead: a clear accessible name Safari doesn't classify as a contact. Co-Authored-By: Claude Opus 4.8 --- .../web/components/pages/onboarding/InlineInput/InlineInput.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx index 3e66caaf6db2..2a4d6082fdc6 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.tsx @@ -67,7 +67,7 @@ const InlineInput: FC = ({ value={draft} placeholder={label} maxLength={maxLength} - aria-label={`${label} name`} + aria-label={`Edit ${label.toLowerCase()}`} onChange={(e) => { const raw = e.target.value setDraft(transform ? transform(raw) : raw) From 3c80f00e4c0eb34a26dc50fbf3a2331c41787bae Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Tue, 14 Jul 2026 09:02:07 -0300 Subject: [PATCH 07/12] test(onboarding): match e2e to the Edit- aria-label The flag rename step located the field via getByLabel('Flag name'); the field is now labelled 'Edit flag' (Safari autofill fix), so point the selector there. Co-Authored-By: Claude Opus 4.8 --- frontend/e2e/tests/onboarding-tests.pw.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/e2e/tests/onboarding-tests.pw.ts b/frontend/e2e/tests/onboarding-tests.pw.ts index a59d0e4ae944..2bada321f222 100644 --- a/frontend/e2e/tests/onboarding-tests.pw.ts +++ b/frontend/e2e/tests/onboarding-tests.pw.ts @@ -101,7 +101,7 @@ test.describe('Onboarding', () => { // Rename the flag. Names are immutable, so this delete + recreates; the // Onboarding tag must survive (the recreate carries the old flag's tags). log('Rename the flag'); - const flagInput = page.getByLabel('Flag name'); + const flagInput = page.getByLabel('Edit flag'); await flagInput.fill('renamed_demo_flag'); await flagInput.press('Enter'); @@ -114,7 +114,7 @@ test.describe('Onboarding', () => { // Reload to prove it persisted (bootstrap reuses the renamed flag). await page.reload(); await flowReady(); - await expect(page.getByLabel('Flag name')).toHaveValue('renamed_demo_flag'); + await expect(page.getByLabel('Edit flag')).toHaveValue('renamed_demo_flag'); await expect( page .getByRole('region', { name: 'Your flags' }) From f489ef0928cd540f546f67c9a7034d463bcf9441 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 15 Jul 2026 09:46:12 -0300 Subject: [PATCH 08/12] fix(onboarding): use font-weight-semibold, fw-semibold is a no-op here Review (Kyle): the chips/badge weren't rendering semibold. The project's working weight class is .font-weight-semibold (token + !important); Bootstrap's .fw-semibold has no effect here. Swap it across the connect panel. Co-Authored-By: Claude Opus 4.8 --- .../OnboardingConnectPanel/ConnectWithAiPanel.tsx | 6 ++++-- .../OnboardingConnectPanel/ConnectYourCodePanel.tsx | 8 +++++--- .../pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectWithAiPanel.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectWithAiPanel.tsx index 626a1000f44e..f16683da39c6 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectWithAiPanel.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectWithAiPanel.tsx @@ -32,7 +32,7 @@ Detect my stack, install the SDK, and wire ${featureName} into one place. Then r return ( <> - + Paste this into your AI coding agent’s chat
@@ -50,7 +50,9 @@ Detect my stack, install the SDK, and wire ${featureName} into one place. Then r
- What happens next + + What happens next +
  • Detects your stack: language, framework and package manager.
  • Installs the Flagsmith SDK and wires it into your code.
  • diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx index b73ec452890c..d2477881a1ca 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx @@ -15,7 +15,7 @@ const PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn'] const SdkBadge: FC<{ lang: SdkLang }> = ({ lang }) => { const Logo = lang.logo return ( - + {lang.label} @@ -53,7 +53,9 @@ const ConnectYourCodePanel: FC = ({
    1 - Install the SDK + + Install the SDK +
    = ({
    2 - + Wire it in & take instant control of what users see
    diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx index a0c4241e0420..2c0b7e81a4dc 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx @@ -69,7 +69,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => { ref={(el) => { refs.current[lang.label] = el }} - className='fw-semibold' + className='font-weight-semibold' role='radio' aria-checked={isSelected} tabIndex={lang.label === tabStopLabel ? 0 : -1} @@ -92,7 +92,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => {
    {popularLangs.map(renderOption)} setMoreOpen((open) => !open)} aria-expanded={moreOpen} > From b0bbf5bb6420d6cfa93ece7fe9281c3b8cf1f452 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 15 Jul 2026 09:46:15 -0300 Subject: [PATCH 09/12] style(onboarding): soften inline-edit radius and spacing Review (Kyle): the resting-fill fields felt cramped. Bump the radius to --radius-sm and the padding to 1px 8px, matching the flag pill. Co-Authored-By: Claude Opus 4.8 --- .../components/pages/onboarding/InlineInput/InlineInput.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss index 1032d4ffac12..e1dec31ac08b 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss @@ -3,8 +3,8 @@ align-items: center; vertical-align: baseline; gap: 4px; - padding: 0 4px; - border-radius: var(--radius-xs); + padding: 1px 8px; + border-radius: var(--radius-sm); border-bottom: 1px solid var(--color-border-action); // Resting fill so it reads as editable, not only on hover. background-color: var(--color-surface-subtle); From 8be8e039ec06406c63df0861eed6d1d6183073ff Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 15 Jul 2026 09:49:02 -0300 Subject: [PATCH 10/12] style(onboarding): round only the top of the inline-edit fields Rounded bottom corners fought the action underline. Square the bottom so it sits flush; the flag pill (no underline) keeps its full radius. Co-Authored-By: Claude Opus 4.8 --- .../components/pages/onboarding/InlineInput/InlineInput.scss | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss index e1dec31ac08b..68285be954db 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss @@ -4,7 +4,9 @@ vertical-align: baseline; gap: 4px; padding: 1px 8px; - border-radius: var(--radius-sm); + // Round the top only; the bottom stays square so it sits flush with the + // action underline (rounded bottom corners fight the border). + border-radius: var(--radius-sm) var(--radius-sm) 0 0; border-bottom: 1px solid var(--color-border-action); // Resting fill so it reads as editable, not only on hover. background-color: var(--color-surface-subtle); From 1202aefafa58064a8ca6aef5bc081b7d48cd03af Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 15 Jul 2026 09:52:03 -0300 Subject: [PATCH 11/12] style(onboarding): medium weight on the SDK badges Semibold read too heavy on the chips; use font-weight-medium for the SDK badge and picker chips. Section headings stay semibold. Co-Authored-By: Claude Opus 4.8 --- .../OnboardingConnectPanel/ConnectYourCodePanel.tsx | 2 +- .../pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx index d2477881a1ca..a32a58387b42 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/ConnectYourCodePanel.tsx @@ -15,7 +15,7 @@ const PACKAGE_MANAGERS: PackageManager[] = ['npm', 'yarn'] const SdkBadge: FC<{ lang: SdkLang }> = ({ lang }) => { const Logo = lang.logo return ( - + {lang.label} diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx index 2c0b7e81a4dc..fb477210edc1 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/SdkPicker.tsx @@ -69,7 +69,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => { ref={(el) => { refs.current[lang.label] = el }} - className='font-weight-semibold' + className='font-weight-medium' role='radio' aria-checked={isSelected} tabIndex={lang.label === tabStopLabel ? 0 : -1} @@ -92,7 +92,7 @@ const SdkPicker: FC = ({ onSelect, selected }) => {
    {popularLangs.map(renderOption)} setMoreOpen((open) => !open)} aria-expanded={moreOpen} > From a08c5c004a2427304dddf2a0f70f428b11b5ef8f Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 15 Jul 2026 10:13:16 -0300 Subject: [PATCH 12/12] style(onboarding): tighten inline-edit radius to 2px Co-Authored-By: Claude Opus 4.8 --- .../components/pages/onboarding/InlineInput/InlineInput.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss index 68285be954db..045c13b15612 100644 --- a/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss +++ b/frontend/web/components/pages/onboarding/InlineInput/InlineInput.scss @@ -6,7 +6,7 @@ padding: 1px 8px; // Round the top only; the bottom stays square so it sits flush with the // action underline (rounded bottom corners fight the border). - border-radius: var(--radius-sm) var(--radius-sm) 0 0; + border-radius: var(--radius-xs) var(--radius-xs) 0 0; border-bottom: 1px solid var(--color-border-action); // Resting fill so it reads as editable, not only on hover. background-color: var(--color-surface-subtle);