1- import cs from 'classnames' ;
2- import { useAtom , useAtomValue } from 'jotai' ;
1+ import { useAtom , useSetAtom } from 'jotai' ;
32import type { ReactNode } from 'react' ;
43import { useId , useRef } from 'react' ;
54import CrossSvg from '../assets/cross.svg' ;
65import DiscordIconSvg from '../assets/discord-icon.svg' ;
76import GithubIconSvg from '../assets/github-icon.svg' ;
87import HamburgerSvg from '../assets/hamburger.svg' ;
9- import { codeEditorShownMobileAtom } from '../utils/examples/codeEditorShownAtom.ts' ;
108import {
9+ codeEditorShownAtom ,
10+ experimentalExamplesShownAtom ,
1111 menuShownAtom ,
12- menuShownMobileAtom ,
13- } from '../utils/examples/menuShownAtom.ts' ;
12+ } from '../utils/examples/exampleViewStateAtoms.ts' ;
1413import { SearchableExampleList } from './SearchableExampleList.tsx' ;
1514import { Button } from './design/Button.tsx' ;
1615import { Toggle } from './design/Toggle.tsx' ;
17- import { experimentalExamplesShownAtom } from '../utils/examples/showExperimentalExamplesAtom .ts' ;
16+ import { useHydrated } from '../utils/useHydrated .ts' ;
1817
1918interface ExampleLayoutProps {
2019 children ?: ReactNode | undefined ;
2120}
2221
2322export function ExampleLayout ( props : ExampleLayoutProps ) {
24- const menuShown = useAtomValue ( menuShownAtom ) ;
25- const [ menuShownMobile , setMenuShownMobile ] = useAtom ( menuShownMobileAtom ) ;
26- const [ codeShownMobile , setCodeShownMobile ] = useAtom (
27- codeEditorShownMobileAtom ,
28- ) ;
23+ const [ menuShown , setMenuShown ] = useAtom ( menuShownAtom ) ;
24+ const [ codeShown , setCodeShown ] = useAtom ( codeEditorShownAtom ) ;
25+ const hydrated = useHydrated ( ) ;
2926
3027 return (
3128 < >
3229 < div className = 'absolute top-4 left-4 z-50 flex gap-2 text-sm md:hidden' >
33- { menuShownMobile
34- ? null
35- : (
36- < Button onClick = { ( ) => setMenuShownMobile ( true ) } >
37- < img src = { HamburgerSvg . src } alt = 'menu' className = '-m-2 h-6 w-6' />
38- </ Button >
39- ) }
30+ { ! menuShown && (
31+ < Button onClick = { ( ) => setMenuShown ( true ) } >
32+ < img src = { HamburgerSvg . src } alt = 'menu' className = '-m-2 h-6 w-6' />
33+ </ Button >
34+ ) }
4035
41- < Button
42- onClick = { ( ) =>
43- setCodeShownMobile ( ( codeShownMobile ) => ! codeShownMobile ) }
44- >
45- { codeShownMobile ? 'Preview' : 'Code' }
36+ < Button onClick = { ( ) => setCodeShown ( ( prev ) => ! prev ) } >
37+ { /* Applying the actual label only after the component has been hydrated */ }
38+ { codeShown && hydrated ? 'Preview' : 'Code' }
4639 </ Button >
4740 </ div >
4841
4942 < div className = 'box-border flex h-dvh gap-4 bg-tameplum-50 p-4' >
50- { menuShown || menuShownMobile ? < SideMenu /> : null }
43+ { menuShown && < SideMenu /> }
5144 { props . children }
5245 </ div >
5346 </ >
5447 ) ;
5548}
5649
5750function SideMenu ( ) {
58- const menuShown = useAtomValue ( menuShownAtom ) ;
59- const [ menuShownMobile , setMenuShownMobile ] = useAtom ( menuShownMobileAtom ) ;
51+ const setMenuShown = useSetAtom ( menuShownAtom ) ;
6052 const [ experimentalShowing , setExperimentalShowing ] = useAtom (
6153 experimentalExamplesShownAtom ,
6254 ) ;
6355 const scrollRef = useRef < HTMLDivElement > ( null ) ;
6456 const experimentalExamplesToggleId = useId ( ) ;
6557
6658 return (
67- < aside
68- className = { cs (
69- menuShown ? '' : 'md:hidden' ,
70- menuShownMobile
71- ? 'absolute inset-0 z-50 w-full md:static'
72- : 'hidden md:flex' ,
73- 'box-border flex flex-col bg-white md:w-75 md:rounded-2xl' ,
74- ) }
75- >
59+ < aside className = 'absolute inset-0 z-50 box-border flex w-full flex-col bg-white md:static md:w-75 md:rounded-2xl' >
7660 < header className = 'p-5' >
7761 < div className = 'grid place-items-center' >
7862 < a
@@ -87,11 +71,9 @@ function SideMenu() {
8771 </ a >
8872 </ div >
8973 < div className = 'absolute top-5 right-5 md:hidden' >
90- { menuShownMobile && (
91- < Button onClick = { ( ) => setMenuShownMobile ( false ) } >
92- < img src = { CrossSvg . src } alt = 'Close menu' className = 'h-3 w-3' />
93- </ Button >
94- ) }
74+ < Button onClick = { ( ) => setMenuShown ( false ) } >
75+ < img src = { CrossSvg . src } alt = 'Close menu' className = 'h-3 w-3' />
76+ </ Button >
9577 </ div >
9678 </ header >
9779
@@ -115,7 +97,7 @@ function SideMenu() {
11597 </ section >
11698
11799 < SearchableExampleList
118- excludeTags = { [ experimentalShowing ? [ ] : [ 'experimental' ] ] . flat ( ) }
100+ excludeTags = { experimentalShowing ? [ ] : [ 'experimental' ] }
119101 scrollContainerRef = { scrollRef }
120102 />
121103 </ div >
0 commit comments