Repository navigation
docs: replace FAB and Switch screenshots with live interactive examples - #5069
hristototov wants to merge 14 commits into
Conversation
satya164
left a comment
There was a problem hiding this comment.
Please avoid emdashes and claudism in text. Using LLM is fine but we shouldn't make our documentation look AI generated without human attention.
| 'tonalPrimary', | ||
| 'tonalSecondary', | ||
| 'tonalTertiary', | ||
| ] as const; |
There was a problem hiding this comment.
Remove the comment. Annotate the VARIANTS with a type based on the Variant so it actually stays in sync instead of the comment saying it does
| /** | ||
| * Every spec size accepted by the `size` prop. | ||
| */ | ||
| const SIZES = ['default', 'medium', 'large'] as const; |
| * Paper components depend on browser APIs through `react-native-web`, so the | ||
| * tree is only mounted on the client and a same-sized placeholder is rendered | ||
| * during SSR to avoid layout shift. The Paper theme is kept in sync with the | ||
| * active docs color mode so demos match the surrounding page. |
There was a problem hiding this comment.
The comment is wrong for the component's content. There's nothing related to SSR here.
But also why are we only rendering these on client and skipping on SSR? We need to render components both on SSR and client.
There was a problem hiding this comment.
updated
- Dropped
BrowserOnlyand thePlaceholder, then collapsedFrame+ the pass-throughInteractiveExampleinto a single component with no gate; the split had no purpose - Removed the now-dead
.paper-interactive-example--loadingclass - Rewrote the comment
There was a problem hiding this comment.
updated
- Dropped
BrowserOnlyand thePlaceholder, then collapsedFrame+ the pass-throughInteractiveExampleinto a single component with no gate; the split had no purpose - Removed the now-dead
.paper-interactive-example--loadingclass - Rewrote the comment
…into hristototov/revisit-docs
| const isDarkTheme = useColorMode().colorMode === 'dark'; | ||
|
|
||
| return ( | ||
| <Provider theme={isDarkTheme ? DarkTheme : LightTheme}> |
There was a problem hiding this comment.
Have you checked these in dark mode? I'm afraid they render with light-theme colors, so the caption under each switch ends up dark on dark and unreadable.
There was a problem hiding this comment.
Captions read fine now, thanks. The switches still come up light-themed on a first dark-mode load, though. They only turn dark after navigating away and back. Try a hard reload with a dark OS theme and nothing stored.
There was a problem hiding this comment.
Good catch - the theme lookup was fine, but Paper bakes colors into inline styles and hydration keeps whatever the server painted, which is always light. Remounting the Provider on the client forces a repaint.
The recording below is the built output with a dark OS theme and empty storage:
dark-mode-walkthrough.webm
|
|
||
| return ( | ||
| <InteractiveExample title="Extended"> | ||
| <FAB.Extended |
There was a problem hiding this comment.
Have you checked the extended FAB on the built page?
…into hristototov/revisit-docs
…into hristototov/revisit-docs
|
Review by Claude Web
|
satya164
left a comment
There was a problem hiding this comment.
Review by Claude
See the inline comments. (via Claude, verify if it makes sense)
| <Labelled label="selected"> | ||
| <Switch value={on} onValueChange={setOn} aria-label="Selected" /> | ||
| </Labelled> | ||
| <Labelled label="unselected"> | ||
| <Switch value={off} onValueChange={setOff} aria-label="Unselected" /> |
There was a problem hiding this comment.
The captions and aria-label values are fixed, but both switches toggle. After one click, the switch captioned "selected" is off, and a screen reader announces "Selected, switch, off".
Derive the caption from the value, and keep state words out of aria-label, because aria-checked already announces the state:
<Labelled label={first ? 'selected' : 'unselected'}>
<Switch value={first} onValueChange={setFirst} aria-label="First switch" />
</Labelled>The same applies to SwitchIconsExample. The disabled example can keep fixed captions, because those switches cannot change. (via Claude, verify if it makes sense)
| // The server always renders light colors, so remount to repaint in dark mode. | ||
| const [mounted, setMounted] = React.useState(false); | ||
|
|
||
| React.useEffect(() => { | ||
| setMounted(true); | ||
| }, []); | ||
|
|
||
| return ( | ||
| <Provider | ||
| key={String(mounted)} | ||
| theme={isDarkTheme ? DarkTheme : LightTheme} | ||
| > |
There was a problem hiding this comment.
The key remount hides a hydration mismatch instead of avoiding it. Rspress reads matchMedia and the stored appearance in its initial client state, so useColorMode() already returns dark during hydration. The first client render then uses DarkTheme while the server HTML uses LightTheme. React keeps the server attributes in that case, and the key change throws away the hydrated tree and mounts every example a second time, also in light mode where nothing changed.
Use the light theme until after mount. Hydration then matches the server, and the switch to dark is a normal update:
| // The server always renders light colors, so remount to repaint in dark mode. | |
| const [mounted, setMounted] = React.useState(false); | |
| React.useEffect(() => { | |
| setMounted(true); | |
| }, []); | |
| return ( | |
| <Provider | |
| key={String(mounted)} | |
| theme={isDarkTheme ? DarkTheme : LightTheme} | |
| > | |
| // The server always renders light colors, so use them until hydration is done. | |
| const [mounted, setMounted] = React.useState(false); | |
| React.useEffect(() => { | |
| setMounted(true); | |
| }, []); | |
| return ( | |
| <Provider theme={mounted && isDarkTheme ? DarkTheme : LightTheme}> |
(via Claude, verify if it makes sense)
| row: { | ||
| flexDirection: 'row', | ||
| flexWrap: 'wrap', | ||
| alignItems: 'center', |
There was a problem hiding this comment.
With center, each item is centered on the tallest item in the row. In the Sizes example the three FABs have different heights, so the "default", "medium" and "large" captions sit on three different lines.
flex-end puts the captions on one line and does not change rows where all items have the same height:
| alignItems: 'center', | |
| alignItems: 'flex-end', |
(via Claude, verify if it makes sense)
…into hristototov/revisit-docs






Motivation
Parts of the documentation have drifted out of sync with the v6 modernisation effort. The FAB and Switch pages were still illustrated with screenshots captured before those components were reworked for the latest Material Design 3 spec, so they showed outdated naming and token references:
modeprop — it'svariant(six role-color presets) andsize(three spec sizes) now.Android (enabled/disabled)/iOS (enabled/disabled)screenshot split, which no longer reflects reality: the modernised component renders the same MD3 visuals on both platforms.Static images also can't show what these components actually do - the Switch handle animation, the Extended FAB expand/collapse transition - and they silently rot every time a component changes.
This PR drops those screenshots and inlines the real components instead, so the docs render live from
Related issue
Closes #4991
Implementation notes
A general mechanism rather than a one-off, so the remaining outdated pages can follow:
docs/src/data/liveExamples.ts- new registry mapping a component title to the example module and named exports to render. Adding an entry here automatically removes that component's screenshot tabs, so a component is documented either with screenshots or with live examples, never both. The invariant is enforced in one place ingeneratePageMDX.ts.docs/src/components/InteractiveExample.tsx- shared shell for embedded demos. Paper components reach browser APIs throughreact-native-web, so the tree mounts client-only behindBrowserOnlywith a same-sized placeholder during SSR to avoid layout shift, and the Paper theme is kept in sync with the active docs color mode. Follows the existing pattern inBannerExample.tsx.FABExample.tsx/SwitchExample.tsx- the actual demos. The FAB variant and size lists mirror theVariantandSizeunions insrc/components/FAB/tokens.tsin order, so a spec change surfaces as a type error rather than a stale image.Also includes one small runtime fix surfaced while building the demos:
Switch'sabsoluteFillstyle was missingalignItems/justifyContent, so the unselected icon which is smaller than theSELECTED_ICON-sizediconWrapit sits in - was pinned to the top-left instead of centered. Snapshots updated accordingly.Images