From a8fb6bddb63ea2d3bfa5aef12100e2b987ec433d Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:36:03 -0300 Subject: [PATCH 1/7] fix(onboarding): only show the code-card scrollbar on overflow The code card used overflow-x: scroll, rendering an empty scroll track even when the snippet fits. Switch to auto so the bar shows only on overflow; the webkit rule still forces it over the global dark-scroll mixin's hover toggle, so a long snippet's bar doesn't flicker. Co-Authored-By: Claude Opus 4.8 --- .../OnboardingConnectPanel.scss | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss index 55e5df84ecd0..80147b9e5daa 100644 --- a/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss +++ b/frontend/web/components/pages/onboarding/OnboardingConnectPanel/OnboardingConnectPanel.scss @@ -47,10 +47,10 @@ border: 0; border-radius: 0; color: var(--color-text-default); - // Reserve the scrollbar gutter permanently so hover doesn't shove the - // layout (the global dark-scroll mixin toggles display:none on a - // space-reserving webkit bar otherwise). - overflow-x: scroll; + // Scroll only when the snippet overflows. When it does, the webkit rule + // below forces the bar visible over the global dark-scroll mixin (which + // display:none-s it on hover), so a long snippet's bar doesn't flicker. + overflow-x: auto; overflow-y: hidden; &::-webkit-scrollbar, @@ -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 fd9d68a5f727e9c9b90639b793a8eb3e22c7b385 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:36:04 -0300 Subject: [PATCH 2/7] 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 ++++++++++++------- 1 file changed, 15 insertions(+), 8 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={} /> From 233b66164519c0004b267c666362b6ef9ba9a153 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:51:06 -0300 Subject: [PATCH 3/7] 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 8250b5d28e122ff27a7597a3e39705286374907d Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Wed, 8 Jul 2026 15:57:08 -0300 Subject: [PATCH 4/7] fix(code-help): correct the React init snippet The shared React init snippet was two files mashed into one - two 'export default function' (App and HomePage, invalid JS), duplicate imports, an unused useFlagsmith import, and an App that never rendered HomePage. Make it one coherent example: a named HomePage using useFlags, rendered inside the default App wrapped in FlagsmithProvider. Shared via codeHelp.INIT, so this fixes the snippet app-wide, including the onboarding wire step. Co-Authored-By: Claude Opus 4.8 --- frontend/common/code-help/init/init-react.js | 36 +++++++++----------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/frontend/common/code-help/init/init-react.js b/frontend/common/code-help/init/init-react.js index 6b1a3412cf0e..2791237c6b1f 100644 --- a/frontend/common/code-help/init/init-react.js +++ b/frontend/common/code-help/init/init-react.js @@ -3,9 +3,20 @@ import Constants from 'common/constants' export default ( envId, { FEATURE_NAME, FEATURE_NAME_ALT, LIB_NAME, NPM_CLIENT }, -) => `// App root -import ${LIB_NAME} from "${NPM_CLIENT}"; -import { FlagsmithProvider } from '@flagsmith/flagsmith/react'; +) => `import ${LIB_NAME} from "${NPM_CLIENT}"; +import { FlagsmithProvider, useFlags } from '${NPM_CLIENT}/react'; + +export function HomePage() { + const flags = useFlags(['${FEATURE_NAME}','${FEATURE_NAME_ALT}']); // only causes re-render if specified flag values / traits change + const ${FEATURE_NAME} = flags.${FEATURE_NAME}.enabled + const ${FEATURE_NAME_ALT} = flags.${FEATURE_NAME_ALT}.value + return ( + <> + {\`${FEATURE_NAME}: \${${FEATURE_NAME}}\`} + {\`${FEATURE_NAME_ALT}: \${${FEATURE_NAME_ALT}}\`} + </> + ); +} export default function App() { return ( @@ -17,21 +28,8 @@ export default function App() { : '' } }} - flagsmith={flagsmith}> - {...Your app} - </FlagsmithProvider> - ); -} - -// Home Page -import ${LIB_NAME} from '${NPM_CLIENT}'; -import { useFlags, useFlagsmith } from '${NPM_CLIENT}/react'; - -export default function HomePage() { - const flags = useFlags(['${FEATURE_NAME}','${FEATURE_NAME_ALT}']); // only causes re-render if specified flag values / traits change - const ${FEATURE_NAME} = flags.${FEATURE_NAME}.enabled - const ${FEATURE_NAME_ALT} = flags.${FEATURE_NAME_ALT}.value - return ( - <>{...}</> + flagsmith={${LIB_NAME}}> + <HomePage /> + </FlagsmithProvider> ); }` From 2cbe93a997eba2504bf4572b26aee3ef5bb2dd54 Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 15:05:43 -0300 Subject: [PATCH 5/7] 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 c16c0ad643db46c89ad9e5c724d1e23e2edd561d Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 15:13:16 -0300 Subject: [PATCH 6/7] 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 d1d43882b0ba02c5d0d584761324e56be336c7ac Mon Sep 17 00:00:00 2001 From: Talisson Costa Date: Fri, 10 Jul 2026 18:58:19 -0300 Subject: [PATCH 7/7] 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 = ({