fix(docs): Fix SSR build errors by dynamically importing UI components and resolving other issues (#4991)

This commit is contained in:
Dan Rukas 2025-04-22 13:28:49 -04:00 committed by GitHub
parent d59828ab22
commit 09ac43f297
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 341 additions and 348 deletions

View File

@ -1,129 +1,142 @@
import React from 'react'; import React from 'react';
import '../css/custom.css'; import '../css/custom.css';
import Layout from '@theme/Layout'; import Layout from '@theme/Layout';
import { TooltipProvider } from '../../../../platform/ui-next/src/components/Tooltip'; import BrowserOnly from '@docusaurus/BrowserOnly';
// Navigation card components
import { Card, CardHeader, CardTitle, CardDescription } from '../../../../platform/ui-next/src/components/Card';
import { Icons } from '../../../../platform/ui-next/src/components/Icons';
/* Showcase components (alphabetical) */
// import AllinOneMenuShowcase from './components/AllinOneMenuShowcase';
import ButtonShowcase from './components/ButtonShowcase';
import CheckboxShowcase from './components/CheckboxShowcase';
// import CinePlayerShowcase from './components/CinePlayerShowcase';
import ComboboxShowcase from './components/ComboboxShowcase';
import DataRowShowcase from './components/DataRowShowcase';
import DialogShowcase from './components/DialogShowcase';
import DropdownMenuShowcase from './components/DropdownMenuShowcase';
import HoverCardShowcase from './components/HoverCardShowcase';
import InputShowcase from './components/InputShowcase';
import LabelShowcase from './components/LabelShowcase';
import NumericMetaShowcase from './components/NumericMetaShowcase';
import PanelSectionShowcase from './components/PanelSectionShowcase';
import PopoverShowcase from './components/PopoverShowcase';
import ScrollAreaShowcase from './components/ScrollAreaShowcase';
import SelectShowcase from './components/SelectShowcase';
import SliderShowcase from './components/SliderShowcase';
import SwitchShowcase from './components/SwitchShowcase';
import TabsShowcase from './components/TabsShowcase';
import ToastShowcase from './components/ToastShowcase';
import ToolButtonShowcase from './components/ToolButtonShowcase';
import ToolButtonListShowcase from './components/ToolButtonListShowcase';
import TooltipShowcase from './components/TooltipShowcase';
/** /**
* Components List page that displays all available UI components * Components List page that displays all available UI components
*/ */
export default function ComponentsList() { export default function ComponentsList() {
return ( return (
<Layout <Layout title="Components" description="OHIF Viewer Components">
title="Components" <BrowserOnly fallback={<></>}>
description="OHIF Viewer Components" {() => {
> // Dynamically require all sub-components to avoid SSR issues
<TooltipProvider> const { TooltipProvider } =
<div className="text-foreground min-h-screen bg-black"> require('../../../ui-next/src/components/Tooltip');
<div className="mx-auto my-4 max-w-5xl pt-4 pb-6">
{/* Navigation cards */}
<div className="mb-8 grid grid-cols-1 gap-5 md:grid-cols-3">
<a
href="/colors-and-type"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Colors & Typography
</CardTitle>
<CardDescription className="text-lg">
Color Palette and Typography Guidelines
</CardDescription>
</CardHeader>
</Card>
</a>
<a
href="/components-list"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Components
</CardTitle>
<CardDescription className="text-lg">
Essential UI Components with Variants
</CardDescription>
</CardHeader>
</Card>
</a>
<a
href="/patterns"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Patterns
</CardTitle>
<CardDescription className="text-lg">
Component-Based Layout Examples
</CardDescription>
</CardHeader>
</Card>
</a>
</div>
<h1 className="text-foreground ml-6 mb-6 text-5xl">Components</h1> const {
Card,
CardHeader,
CardTitle,
CardDescription,
} = require('../../../ui-next/src/components/Card');
const { Icons } = require('../../../ui-next/src/components/Icons');
{/* <AllinOneMenuShowcase /> */} // Showcase modules
<ButtonShowcase /> const AllinOneMenuShowcase = require('./components/AllinOneMenuShowcase').default;
<CheckboxShowcase /> const ButtonShowcase = require('./components/ButtonShowcase').default;
{/* <CinePlayerShowcase /> */} const CheckboxShowcase = require('./components/CheckboxShowcase').default;
<ComboboxShowcase /> const CinePlayerShowcase = require('./components/CinePlayerShowcase').default;
<DataRowShowcase /> const ComboboxShowcase = require('./components/ComboboxShowcase').default;
<DialogShowcase /> const DataRowShowcase = require('./components/DataRowShowcase').default;
<DropdownMenuShowcase /> const DialogShowcase = require('./components/DialogShowcase').default;
<HoverCardShowcase /> const DropdownMenuShowcase = require('./components/DropdownMenuShowcase').default;
<InputShowcase /> const HoverCardShowcase = require('./components/HoverCardShowcase').default;
<LabelShowcase /> const InputShowcase = require('./components/InputShowcase').default;
<NumericMetaShowcase /> const LabelShowcase = require('./components/LabelShowcase').default;
<PanelSectionShowcase /> const NumericMetaShowcase = require('./components/NumericMetaShowcase').default;
<PopoverShowcase /> const PanelSectionShowcase = require('./components/PanelSectionShowcase').default;
<ScrollAreaShowcase /> const PopoverShowcase = require('./components/PopoverShowcase').default;
<SelectShowcase /> const ScrollAreaShowcase = require('./components/ScrollAreaShowcase').default;
<SliderShowcase /> const SelectShowcase = require('./components/SelectShowcase').default;
<SwitchShowcase /> const SliderShowcase = require('./components/SliderShowcase').default;
<TabsShowcase /> const SwitchShowcase = require('./components/SwitchShowcase').default;
<ToastShowcase /> const TabsShowcase = require('./components/TabsShowcase').default;
<ToolButtonShowcase /> const ToastShowcase = require('./components/ToastShowcase').default;
<ToolButtonListShowcase /> const ToolButtonShowcase = require('./components/ToolButtonShowcase').default;
<TooltipShowcase /> const ToolButtonListShowcase = require('./components/ToolButtonListShowcase').default;
</div> const TooltipShowcase = require('./components/TooltipShowcase').default;
</div>
</TooltipProvider> return (
<TooltipProvider>
<div className="text-foreground min-h-screen bg-black">
<div className="mx-auto my-4 max-w-5xl pt-4 pb-6">
{/* Navigation cards */}
<div className="mb-8 grid grid-cols-1 gap-5 md:grid-cols-3">
<a
href="/colors-and-type"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Colors &amp; Typography
</CardTitle>
<CardDescription className="text-lg">
Color Palette and Typography Guidelines
</CardDescription>
</CardHeader>
</Card>
</a>
<a
href="/components-list"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Components
</CardTitle>
<CardDescription className="text-lg">
Essential UI Components with Variants
</CardDescription>
</CardHeader>
</Card>
</a>
<a
href="/patterns"
className="focus:ring-primary block rounded-lg text-inherit no-underline hover:no-underline focus:outline-none focus:ring-2"
>
<Card className="hover:bg-primary/30 w-full transition-colors">
<CardHeader>
<CardTitle className="text-foreground text-xl">
<Icons.ColorChange className="h-12 w-12" />
Patterns
</CardTitle>
<CardDescription className="text-lg">
ComponentBased Layout Examples
</CardDescription>
</CardHeader>
</Card>
</a>
</div>
<h1 className="text-foreground ml-6 mb-6 text-5xl">
Components
</h1>
<AllinOneMenuShowcase />
<ButtonShowcase />
<CheckboxShowcase />
<CinePlayerShowcase />
<ComboboxShowcase />
<DataRowShowcase />
<DialogShowcase />
<DropdownMenuShowcase />
<HoverCardShowcase />
<InputShowcase />
<LabelShowcase />
<NumericMetaShowcase />
<PanelSectionShowcase />
<PopoverShowcase />
<ScrollAreaShowcase />
<SelectShowcase />
<SliderShowcase />
<SwitchShowcase />
<TabsShowcase />
<ToastShowcase />
<ToolButtonShowcase />
<ToolButtonListShowcase />
<TooltipShowcase />
</div>
</div>
</TooltipProvider>
);
}}
</BrowserOnly>
</Layout> </Layout>
); );
} }

View File

@ -1,150 +1,119 @@
// import React from 'react'; import React from 'react';
// import * as AllInOneMenu from '../../../../../platform/ui-next/src/components/AllInOneMenu'; import useIsBrowser from '@docusaurus/useIsBrowser';
// import { Switch } from '../../../../../platform/ui-next/src/components/Switch'; import ShowcaseRow from './ShowcaseRow';
// import ShowcaseRow from './ShowcaseRow';
/** /**
* PureUI mock of the inapp Window/Level menu. * PureUI mock of the inapp Window/Level menu.
* Clickable, but all actions are inert. * Clickable, but all actions are inert.
*/ */
export default function AllinOneMenuShowcase() { export default function AllinOneMenuShowcase() {
return null; const isBrowser = useIsBrowser();
}
// /* Helpers to build common static items so the JSX stays concise */ if (!isBrowser) {
// const renderColorLUTItems = () => return null;
// [ }
// 'Grayscale',
// 'X Ray',
// 'HSV',
// 'Hot Iron',
// 'Red Hot',
// 'S PET',
// 'Perfusion',
// 'Rainbow',
// 'SUV',
// 'GE 256',
// 'GE',
// 'Siemens',
// ].map(name => (
// <AllInOneMenu.Item
// key={name}
// label={name}
// />
// ));
// const renderWindowPresetItems = () => const {
// [ default: AllInOneMenu,
// { desc: 'Soft tissue', wl: '400 / 40' }, IconMenu,
// { desc: 'Lung', wl: '1500 / -600' }, SubMenu,
// { desc: 'Liver', wl: '150 / 90' }, ItemPanel,
// { desc: 'Bone', wl: '2500 / 480' }, Item,
// { desc: 'Brain', wl: '80 / 40' }, DividerItem,
// ].map(p => ( HorizontalDirection,
// <AllInOneMenu.Item VerticalDirection,
// key={p.desc} } = require('../../../../ui-next/src/components/AllInOneMenu');
// label={p.desc} const { Switch } = require('../../../../ui-next/src/components/Switch');
// secondaryLabel={p.wl}
// />
// ));
// return ( const renderColorLUTItems = () =>
// <ShowcaseRow [
// title="All In One Menu" 'Grayscale',
// description="A structured, consolidated menu designed to reduce visual clutter, helping users keep their focus on the image. It supports various UI components—including Switches, Numeric Inputs, Tabs, and Sliders—for detailed settings, as well as text-based lists for actionable items." 'X Ray',
// code={`<AllInOneMenu.IconMenu icon="viewport-window-level" menuStyle={{ width: 212, maxHeight: 500 }}> 'HSV',
// <AllInOneMenu.ItemPanel label="Display"> 'Hot Iron',
// <AllInOneMenu.Item label="Display Color bar" rightIcon={<Switch disabled />} /> 'Red Hot',
// <AllInOneMenu.DividerItem /> 'S PET',
// <AllInOneMenu.SubMenu itemLabel="Color LUT" itemIcon="icon-color-lut"> 'Perfusion',
// <AllInOneMenu.ItemPanel label="Color LUTs"> 'Rainbow',
// <AllInOneMenu.Item label="Preview in viewport" rightIcon={<Switch disabled />} /> 'SUV',
// <AllInOneMenu.DividerItem /> 'GE 256',
// <AllInOneMenu.Item label="Grayscale" /> 'GE',
// <AllInOneMenu.Item label="X Ray" /> 'Siemens',
// <AllInOneMenu.Item label="HSV" /> ].map(name => <Item key={name} label={name} />);
// <AllInOneMenu.Item label="Hot Iron" />
// <AllInOneMenu.Item label="Red Hot" />
// <AllInOneMenu.Item label="S PET" />
// <AllInOneMenu.Item label="Perfusion" />
// <AllInOneMenu.Item label="Rainbow" />
// <AllInOneMenu.Item label="SUV" />
// <AllInOneMenu.Item label="GE 256" />
// <AllInOneMenu.Item label="GE" />
// <AllInOneMenu.Item label="Siemens" />
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.SubMenu>
// <AllInOneMenu.SubMenu itemLabel="Window Presets" itemIcon="viewport-window-level">
// <AllInOneMenu.ItemPanel label="CT Presets">
// <AllInOneMenu.Item label="Soft tissue" secondaryLabel="400 / 40" />
// <AllInOneMenu.Item label="Lung" secondaryLabel="1500 / 600" />
// <AllInOneMenu.Item label="Liver" secondaryLabel="150 / 90" />
// <AllInOneMenu.Item label="Bone" secondaryLabel="2500 / 480" />
// <AllInOneMenu.Item label="Brain" secondaryLabel="80 / 40" />
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.SubMenu>
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.IconMenu>`}
// >
// <div className="border-input/70 relative flex h-12 items-center rounded border bg-black px-4">
// <AllInOneMenu.IconMenu
// icon="viewport-window-level"
// iconClassName="text-xl text-highlight hover:bg-primary/30 cursor-pointer rounded"
// horizontalDirection={AllInOneMenu.HorizontalDirection.LeftToRight}
// verticalDirection={AllInOneMenu.VerticalDirection.TopToBottom}
// menuStyle={{ width: 212, maxHeight: 500 }}
// >
// <AllInOneMenu.ItemPanel label="Display">
// <AllInOneMenu.Item
// label="Display Color bar"
// rightIcon={
// <Switch
// checked={false}
// disabled
// className="pointer-events-none"
// />
// }
// useIconSpace={false}
// />
// <AllInOneMenu.DividerItem />
// <AllInOneMenu.SubMenu
// itemLabel="Color LUT"
// itemIcon="icon-color-lut"
// >
// <AllInOneMenu.ItemPanel
// label="Color LUTs"
// maxHeight="calc(100vh - 250px)"
// className="flex flex-col"
// >
// <AllInOneMenu.Item
// label="Preview in viewport"
// rightIcon={
// <Switch
// checked={false}
// disabled
// className="pointer-events-none"
// />
// }
// />
// <AllInOneMenu.DividerItem />
// {renderColorLUTItems()}
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.SubMenu>
// <AllInOneMenu.SubMenu
// itemLabel="Window Presets"
// itemIcon="viewport-window-level"
// >
// <AllInOneMenu.ItemPanel label="CT Presets">
// {renderWindowPresetItems()}
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.SubMenu>
// </AllInOneMenu.ItemPanel>
// </AllInOneMenu.IconMenu>
// <span className="text-muted-foreground ml-3 text-sm"> const renderWindowPresetItems = () =>
// Click the icon to explore an example [
// </span> { desc: 'Soft tissue', wl: '400 / 40' },
// </div> { desc: 'Lung', wl: '1500 / -600' },
// </ShowcaseRow> { desc: 'Liver', wl: '150 / 90' },
// ); { desc: 'Bone', wl: '2500 / 480' },
// } { desc: 'Brain', wl: '80 / 40' },
].map(p => (
<Item key={p.desc} label={p.desc} secondaryLabel={p.wl} />
));
return (
<ShowcaseRow
title="All In One Menu"
description="A structured menu that consolidates controls and actions."
code={`<IconMenu icon="viewport-window-level" menuStyle={{ width: 212, maxHeight: 500 }}>…</IconMenu>`}
>
<div className="border-input/70 relative flex h-12 items-center rounded border bg-black px-4">
<IconMenu
icon="viewport-window-level"
iconClassName="text-xl text-highlight hover:bg-primary/30 cursor-pointer rounded"
horizontalDirection={HorizontalDirection.LeftToRight}
verticalDirection={VerticalDirection.TopToBottom}
menuStyle={{ width: 212, maxHeight: 500 }}
>
<ItemPanel label="Display">
<Item
label="Display Color bar"
rightIcon={
<Switch
checked={false}
disabled
className="pointer-events-none"
/>
}
useIconSpace={false}
/>
<DividerItem />
<SubMenu itemLabel="Color LUT" itemIcon="icon-color-lut">
<ItemPanel
label="Color LUTs"
maxHeight="calc(100vh - 250px)"
className="flex flex-col"
>
<Item
label="Preview in viewport"
rightIcon={
<Switch
checked={false}
disabled
className="pointer-events-none"
/>
}
/>
<DividerItem />
{renderColorLUTItems()}
</ItemPanel>
</SubMenu>
<SubMenu
itemLabel="Window Presets"
itemIcon="viewport-window-level"
>
<ItemPanel label="CT Presets">
{renderWindowPresetItems()}
</ItemPanel>
</SubMenu>
</ItemPanel>
</IconMenu>
<span className="text-muted-foreground ml-3 text-sm">
Click the icon to explore an example
</span>
</div>
</ShowcaseRow>
);
}

View File

@ -1,39 +1,45 @@
// import React, { useState } from 'react'; import React, { useState } from 'react';
// import CinePlayer from '../../../../ui-next/src/components/CinePlayer/CinePlayer'; import useIsBrowser from '@docusaurus/useIsBrowser';
// import ShowcaseRow from './ShowcaseRow'; import ShowcaseRow from './ShowcaseRow';
/** /**
* CinePlayerShowcase displays a playable/pausable cine player with FPS control. * CinePlayerShowcase displays a playable/pausable cine player with FPS control.
*/ */
export default function CinePlayerShowcase() { export default function CinePlayerShowcase() {
return null; const [isPlaying, setIsPlaying] = useState(false);
} const [fps, setFps] = useState(24);
// const [isPlaying, setIsPlaying] = useState(false); const isBrowser = useIsBrowser();
// const [fps, setFps] = useState(24);
// return ( // If not browser, return null to avoid SSR parse errors
// <ShowcaseRow if (!isBrowser) {
// title="Cine Player" return null;
// description="Play, pause, scrub through dynamic image series and adjust FPS." }
// code={`
// <CinePlayer const { default: CinePlayer } = require('../../../../ui-next/src/components/CinePlayer/CinePlayer');
// className="w-[300px]"
// isPlaying={isPlaying} return (
// frameRate={fps} <ShowcaseRow
// onPlayPauseChange={setIsPlaying} title="Cine Player"
// onFrameRateChange={setFps} description="Play, pause, scrub through dynamic image series and adjust FPS."
// onClose={() => console.log('close clicked')} code={`
// /> <CinePlayer
// `} className="w-[300px]"
// > isPlaying={isPlaying}
// <CinePlayer frameRate={fps}
// className="w-[300px]" onPlayPauseChange={setIsPlaying}
// isPlaying={isPlaying} onFrameRateChange={setFps}
// frameRate={fps} onClose={() => console.log('close clicked')}
// onPlayPauseChange={setIsPlaying} />
// onFrameRateChange={setFps} `}
// onClose={() => console.log('close clicked')} >
// /> <CinePlayer
// </ShowcaseRow> className="w-[300px]"
// ); isPlaying={isPlaying}
// } frameRate={fps}
onPlayPauseChange={setIsPlaying}
onFrameRateChange={setFps}
onClose={() => console.log('close clicked')}
/>
</ShowcaseRow>
);
}

View File

@ -18,7 +18,7 @@ export default function DropdownMenuShowcase() {
description="Dropdown menu provides a flexible list of options that can open from buttons or other elements" description="Dropdown menu provides a flexible list of options that can open from buttons or other elements"
code={` code={`
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger> <DropdownMenuTrigger asChild>
<Button>Open Basic</Button> <Button>Open Basic</Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
@ -78,4 +78,4 @@ export default function DropdownMenuShowcase() {
</div> </div>
</ShowcaseRow> </ShowcaseRow>
); );
} }

View File

@ -1,47 +1,50 @@
import React from 'react'; import React from 'react';
import { import BrowserOnly from '@docusaurus/BrowserOnly';
Tooltip,
TooltipTrigger,
TooltipContent,
TooltipProvider,
} from '../../../../../platform/ui-next/src/components/Tooltip';
import { Button } from '../../../../../platform/ui-next/src/components/Button';
import ShowcaseRow from './ShowcaseRow'; import ShowcaseRow from './ShowcaseRow';
import { Button } from '../../../../ui-next/src/components/Button';
/** /**
* TooltipShowcase component displays Tooltip variants and examples * TooltipShowcase component displays Tooltip variants and examples
*/ */
export default function TooltipShowcase() { export default function TooltipShowcase() {
return ( return (
<ShowcaseRow <BrowserOnly fallback={<></>}>
title="Tooltip" {() => {
description="Tooltips reveal helper text when users hover, focus, or tap an element." const {
code={` Tooltip,
<TooltipProvider> TooltipTrigger,
<Tooltip> TooltipContent,
<TooltipTrigger asChild> TooltipProvider,
<Button variant="ghost" size="icon">?</Button> } = require('../../../../ui-next/src/components/Tooltip');
</TooltipTrigger>
<TooltipContent> return (
Tooltip content <TooltipProvider>
</TooltipContent> <ShowcaseRow
</Tooltip> title="Tooltip"
</TooltipProvider> description="Tooltips reveal helper text when users hover, focus, or tap an element."
`} code={`
> <Tooltip>
<TooltipProvider> <TooltipTrigger asChild>
<Tooltip> <Button variant="ghost" size="icon">?</Button>
<TooltipTrigger asChild> </TooltipTrigger>
<Button <TooltipContent>
variant="ghost" Tooltip content
size="icon" </TooltipContent>
</Tooltip>
`}
> >
? <Tooltip>
</Button> <TooltipTrigger asChild>
</TooltipTrigger> <Button variant="ghost" size="icon">
<TooltipContent>Tooltip content</TooltipContent> ?
</Tooltip> </Button>
</TooltipProvider> </TooltipTrigger>
</ShowcaseRow> <TooltipContent>Tooltip content</TooltipContent>
</Tooltip>
</ShowcaseRow>
</TooltipProvider>
);
}}
</BrowserOnly>
); );
} }

View File

@ -7,25 +7,27 @@ export default function Patterns() {
return ( return (
<Layout> <Layout>
<h1>Patterns</h1> <div>
<button <h1>Patterns</h1>
className="bg-slate-400" <button
onClick={() => history.push('/patterns/patterns-segmentation')} className="bg-slate-400"
> onClick={() => history.push('/patterns/patterns-segmentation')}
{'Segmentation Panel'} >
</button> {'Segmentation Panel'}
<button </button>
className="bg-slate-400" <button
onClick={() => history.push('/patterns/patterns-measurements')} className="bg-slate-400"
> onClick={() => history.push('/patterns/patterns-measurements')}
{'Measurements Panel'} >
</button> {'Measurements Panel'}
<button </button>
className="bg-slate-400" <button
onClick={() => history.push('/patterns/patterns-tmtv')} className="bg-slate-400"
> onClick={() => history.push('/patterns/patterns-tmtv')}
{'tmtv'} >
</button> {'tmtv'}
</button>
</div>
</Layout> </Layout>
); );
} }