💩(frontend) introduce an official footer
Based on Florian's feedbacks, this is mandatory as the project is getting attention. Bad code, needs a refactor.
This commit is contained in:
committed by
aleb_the_flash
parent
819d3784f7
commit
e7e7bb0d09
3
src/frontend/public/assets/link-grey.svg
Normal file
3
src/frontend/public/assets/link-grey.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.66667 4.00098V5.33431H3.33333V12.6676H10.6667V9.33431H12V13.3343C12 13.7025 11.7015 14.001 11.3333 14.001H2.66667C2.29848 14.001 2 13.7025 2 13.3343V4.66764C2 4.29945 2.29848 4.00098 2.66667 4.00098H6.66667ZM14 2.00098V7.33431H12.6667V4.27631L7.47133 9.47231L6.52867 8.52964L11.7233 3.33431H8.66667V2.00098H14Z" fill="#666666"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 484 B |
@@ -7,6 +7,7 @@ import { Center } from '@/styled-system/jsx'
|
|||||||
export const LoadingScreen = ({
|
export const LoadingScreen = ({
|
||||||
delay = 500,
|
delay = 500,
|
||||||
header = undefined,
|
header = undefined,
|
||||||
|
footer = undefined,
|
||||||
layout = 'centered',
|
layout = 'centered',
|
||||||
}: {
|
}: {
|
||||||
delay?: number
|
delay?: number
|
||||||
@@ -15,7 +16,7 @@ export const LoadingScreen = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DelayedRender delay={delay}>
|
<DelayedRender delay={delay}>
|
||||||
<Screen layout={layout} header={header}>
|
<Screen layout={layout} header={header} footer={footer}>
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
<Center>
|
<Center>
|
||||||
<p>{t('loading')}</p>
|
<p>{t('loading')}</p>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export const QueryAware = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status === 'pending') {
|
if (status === 'pending') {
|
||||||
return <LoadingScreen header={undefined} />
|
return <LoadingScreen header={undefined} footer={undefined} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return children
|
return children
|
||||||
|
|||||||
@@ -15,6 +15,6 @@ export const UserAware = ({ children }: { children: React.ReactNode }) => {
|
|||||||
return isLoggedIn !== undefined ? (
|
return isLoggedIn !== undefined ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<LoadingScreen header={false} delay={1000} />
|
<LoadingScreen header={false} footer={false} delay={1000} />
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ export const Conference = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryAware status={isFetchError ? createStatus : fetchStatus}>
|
<QueryAware status={isFetchError ? createStatus : fetchStatus}>
|
||||||
<Screen header={false}>
|
<Screen header={false} footer={false}>
|
||||||
<LiveKitRoom
|
<LiveKitRoom
|
||||||
room={room}
|
room={room}
|
||||||
serverUrl={data?.livekit?.url}
|
serverUrl={data?.livekit?.url}
|
||||||
|
|||||||
276
src/frontend/src/layout/Footer.tsx
Normal file
276
src/frontend/src/layout/Footer.tsx
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
import { styled } from '@/styled-system/jsx'
|
||||||
|
import { css } from '@/styled-system/css'
|
||||||
|
import { A } from '@/primitives'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
|
const StyledLi = styled('li', {
|
||||||
|
base: {},
|
||||||
|
variants: {
|
||||||
|
divider: {
|
||||||
|
true: {
|
||||||
|
_after: {
|
||||||
|
content: '""',
|
||||||
|
display: 'inline-block',
|
||||||
|
marginX: '.75rem',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
boxShadow: 'inset 0 0 0 1px #ddd',
|
||||||
|
height: '1rem',
|
||||||
|
width: '1px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const InnerContainer = styled('div', {
|
||||||
|
base: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'start',
|
||||||
|
margin: 'auto',
|
||||||
|
maxWidth: '1200px',
|
||||||
|
paddingX: { base: '0.5rem', xs: '1rem', sm: '2rem' },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const MainLinkList = styled('ul', {
|
||||||
|
base: {
|
||||||
|
display: 'flex',
|
||||||
|
gap: '0.5rem 1rem',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
flexBasis: { base: '100%', md: '50%' },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const FirstRow = styled('div', {
|
||||||
|
base: {
|
||||||
|
display: 'flex',
|
||||||
|
gap: '2rem',
|
||||||
|
flexWrap: { base: 'wrap', md: 'nowrap' },
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '100%',
|
||||||
|
alignItems: 'flex-start',
|
||||||
|
marginBottom: '1.5rem',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const SecondRow = styled('ul', {
|
||||||
|
base: {
|
||||||
|
display: 'flex',
|
||||||
|
borderTop: '1px solid rgb(217 217 217)',
|
||||||
|
paddingTop: '0.5rem',
|
||||||
|
width: '100%',
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const ThirdRow = styled('p', {
|
||||||
|
base: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
color: 'rgb(77 77 77)',
|
||||||
|
fontFamily: 'Marianne',
|
||||||
|
textWrap: 'wrap',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
marginTop: { base: '1rem', xs: '0.5rem' },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const Marianne = () => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={css({
|
||||||
|
_before: {
|
||||||
|
content: '""',
|
||||||
|
display: 'block',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
backgroundImage: 'url(/assets/marianne.svg)',
|
||||||
|
height: '1.25rem',
|
||||||
|
marginBottom: '.2rem',
|
||||||
|
width: '3rem',
|
||||||
|
},
|
||||||
|
_after: {
|
||||||
|
content: '""',
|
||||||
|
display: 'block',
|
||||||
|
backgroundImage: 'url(/assets/devise.svg)',
|
||||||
|
backgroundRepeat: 'no-repeat',
|
||||||
|
backgroundSize: 'contain',
|
||||||
|
height: '2.313rem',
|
||||||
|
marginTop: '.2rem',
|
||||||
|
width: '3.25rem',
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<p
|
||||||
|
className={css({
|
||||||
|
letterSpacing: '-.01em',
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
fontWeight: '600',
|
||||||
|
fontFamily: 'Marianne',
|
||||||
|
fontSize: '1.25rem',
|
||||||
|
lineHeight: '1.75rem',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
gouvernement
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Footer = () => {
|
||||||
|
const { t } = useTranslation('global', { keyPrefix: 'footer' })
|
||||||
|
|
||||||
|
return (
|
||||||
|
<footer
|
||||||
|
className={css({
|
||||||
|
borderTop: '2px solid rgb(0 0 145)',
|
||||||
|
paddingY: '2rem',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<InnerContainer>
|
||||||
|
<FirstRow>
|
||||||
|
<div
|
||||||
|
className={css({
|
||||||
|
display: 'flex',
|
||||||
|
paddingBottom: '1.5rem',
|
||||||
|
paddingX: '1.5rem',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: '1.5rem',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<Marianne />
|
||||||
|
<span
|
||||||
|
className={css({
|
||||||
|
height: '80px',
|
||||||
|
backgroundColor: 'rgb(77 77 77)',
|
||||||
|
width: '1px',
|
||||||
|
display: { base: 'none', xs: 'block' },
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<p
|
||||||
|
className={css({
|
||||||
|
display: 'none',
|
||||||
|
fontWeight: '700',
|
||||||
|
fontFamily: 'Marianne',
|
||||||
|
xs: {
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
},
|
||||||
|
xsm: {
|
||||||
|
display: 'block',
|
||||||
|
fontSize: '1rem',
|
||||||
|
lineHeight: '1.5rem',
|
||||||
|
},
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
Direction
|
||||||
|
<br />
|
||||||
|
interministérielle
|
||||||
|
<br />
|
||||||
|
du numérique
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<MainLinkList>
|
||||||
|
<li>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="important"
|
||||||
|
href="https://legifrance.gouv.fr"
|
||||||
|
aria-label={
|
||||||
|
t('links.legifrance') + ' - ' + t('links.ariaLabel')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('links.legifrance')}
|
||||||
|
</A>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="important"
|
||||||
|
href="https://info.gouv.fr"
|
||||||
|
aria-label={t('links.infogouv') + ' - ' + t('links.ariaLabel')}
|
||||||
|
>
|
||||||
|
{t('links.infogouv')}
|
||||||
|
</A>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="important"
|
||||||
|
href="https://www.service-public.fr/"
|
||||||
|
aria-label={
|
||||||
|
t('links.servicepublic') + ' - ' + t('links.ariaLabel')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('links.servicepublic')}
|
||||||
|
</A>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="important"
|
||||||
|
href="https://data.gouv.fr"
|
||||||
|
aria-label={t('links.datagouv') + ' - ' + t('links.ariaLabel')}
|
||||||
|
>
|
||||||
|
{t('links.datagouv')}
|
||||||
|
</A>
|
||||||
|
</li>
|
||||||
|
</MainLinkList>
|
||||||
|
</FirstRow>
|
||||||
|
<SecondRow>
|
||||||
|
<StyledLi divider>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="minor"
|
||||||
|
href="https://docs.numerique.gouv.fr/docs/f88a2eb0-7ce7-4016-b6ee-9f1fd1771951/"
|
||||||
|
aria-label={t('links.legalsTerms') + ' - ' + t('links.ariaLabel')}
|
||||||
|
>
|
||||||
|
{t('links.legalsTerms')}
|
||||||
|
</A>
|
||||||
|
</StyledLi>
|
||||||
|
<StyledLi divider>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="minor"
|
||||||
|
href="https://docs.numerique.gouv.fr/docs/168d7e8e-3f09-462d-8bbc-ea95dedd3889/"
|
||||||
|
aria-label={t('links.data') + ' - ' + t('links.ariaLabel')}
|
||||||
|
>
|
||||||
|
{t('links.data')}
|
||||||
|
</A>
|
||||||
|
</StyledLi>
|
||||||
|
<StyledLi>
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
underline={false}
|
||||||
|
footer="minor"
|
||||||
|
href="https://docs.numerique.gouv.fr/docs/94bd1e3b-a44d-4cf5-b7ee-708a5386a111/"
|
||||||
|
aria-label={
|
||||||
|
t('links.accessibility') + ' - ' + t('links.ariaLabel')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('links.accessibility')}
|
||||||
|
</A>
|
||||||
|
</StyledLi>
|
||||||
|
</SecondRow>
|
||||||
|
<ThirdRow>
|
||||||
|
{t('mentions')}{' '}
|
||||||
|
<A
|
||||||
|
externalIcon
|
||||||
|
footer="minor"
|
||||||
|
href="https://github.com/etalab/licence-ouverte/blob/master/LO.md"
|
||||||
|
>
|
||||||
|
{t('license')}
|
||||||
|
</A>
|
||||||
|
</ThirdRow>
|
||||||
|
</InnerContainer>
|
||||||
|
</footer>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import { css } from '@/styled-system/css'
|
|||||||
import { Header } from './Header'
|
import { Header } from './Header'
|
||||||
import { layoutStore } from '@/stores/layout'
|
import { layoutStore } from '@/stores/layout'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { Footer } from '@/layout/Footer'
|
||||||
|
|
||||||
export type Layout = 'fullpage' | 'centered'
|
export type Layout = 'fullpage' | 'centered'
|
||||||
|
|
||||||
@@ -15,28 +16,33 @@ export type Layout = 'fullpage' | 'centered'
|
|||||||
export const Layout = ({ children }: { children: ReactNode }) => {
|
export const Layout = ({ children }: { children: ReactNode }) => {
|
||||||
const layoutSnap = useSnapshot(layoutStore)
|
const layoutSnap = useSnapshot(layoutStore)
|
||||||
const showHeader = layoutSnap.showHeader
|
const showHeader = layoutSnap.showHeader
|
||||||
|
const showFooter = layoutSnap.showFooter
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<>
|
||||||
className={css({
|
<div
|
||||||
height: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
backgroundColor: 'white',
|
|
||||||
color: 'default.text',
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{showHeader && <Header />}
|
|
||||||
<main
|
|
||||||
className={css({
|
className={css({
|
||||||
flexGrow: 1,
|
height: '100%',
|
||||||
overflow: 'auto',
|
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
|
minHeight: 'fit-content',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
backgroundColor: 'white',
|
||||||
|
color: 'default.text',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{children}
|
{showHeader && <Header />}
|
||||||
</main>
|
<main
|
||||||
</div>
|
className={css({
|
||||||
|
flexGrow: 1,
|
||||||
|
overflow: 'auto',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
{showFooter && <Footer />}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,18 +13,23 @@ export type ScreenProps = {
|
|||||||
* True by default. Pass undefined to render the screen without modifying current header visibility
|
* True by default. Pass undefined to render the screen without modifying current header visibility
|
||||||
*/
|
*/
|
||||||
header?: boolean
|
header?: boolean
|
||||||
|
footer?: boolean
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Screen = ({
|
export const Screen = ({
|
||||||
layout = 'fullpage',
|
layout = 'fullpage',
|
||||||
header = true,
|
header = true,
|
||||||
|
footer = true,
|
||||||
children,
|
children,
|
||||||
}: ScreenProps) => {
|
}: ScreenProps) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (header !== undefined) {
|
if (header !== undefined) {
|
||||||
layoutStore.showHeader = header
|
layoutStore.showHeader = header
|
||||||
}
|
}
|
||||||
}, [header])
|
if (footer !== undefined) {
|
||||||
|
layoutStore.showFooter = footer
|
||||||
|
}
|
||||||
|
}, [header, footer])
|
||||||
return layout === 'centered' ? <Centered>{children}</Centered> : children
|
return layout === 'centered' ? <Centered>{children}</Centered> : children
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,19 @@
|
|||||||
"notFound": {
|
"notFound": {
|
||||||
"heading": ""
|
"heading": ""
|
||||||
},
|
},
|
||||||
"submit": "OK"
|
"submit": "OK",
|
||||||
|
"footer": {
|
||||||
|
"links": {
|
||||||
|
"legifrance": "",
|
||||||
|
"infogouv": "",
|
||||||
|
"servicepublic": "",
|
||||||
|
"datagouv": "",
|
||||||
|
"legalsTerms": "",
|
||||||
|
"data": "",
|
||||||
|
"accessibility": "",
|
||||||
|
"ariaLabel": ""
|
||||||
|
},
|
||||||
|
"mentions": "",
|
||||||
|
"license": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,19 @@
|
|||||||
"notFound": {
|
"notFound": {
|
||||||
"heading": "Page not found"
|
"heading": "Page not found"
|
||||||
},
|
},
|
||||||
"submit": "OK"
|
"submit": "OK",
|
||||||
|
"footer": {
|
||||||
|
"links": {
|
||||||
|
"legifrance": "legifrance.gouv.fr",
|
||||||
|
"infogouv": "info.gouv.fr",
|
||||||
|
"servicepublic": "service-public.fr",
|
||||||
|
"datagouv": "data.gouv.fr",
|
||||||
|
"legalsTerms": "Legal Notice",
|
||||||
|
"data": "Personal Data and Cookies",
|
||||||
|
"accessibility": "Accessibility: audit in progress",
|
||||||
|
"ariaLabel": "new window"
|
||||||
|
},
|
||||||
|
"mentions": "Unless otherwise stated, the contents of this site are available under",
|
||||||
|
"license": "etalab 2.0 license"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,5 +24,19 @@
|
|||||||
"notFound": {
|
"notFound": {
|
||||||
"heading": "Page introuvable"
|
"heading": "Page introuvable"
|
||||||
},
|
},
|
||||||
"submit": "OK"
|
"submit": "OK",
|
||||||
|
"footer": {
|
||||||
|
"links": {
|
||||||
|
"legifrance": "legifrance.gouv.fr",
|
||||||
|
"infogouv": "info.gouv.fr",
|
||||||
|
"servicepublic": "service-public.fr",
|
||||||
|
"datagouv": "data.gouv.fr",
|
||||||
|
"legalsTerms": "Mentions légales",
|
||||||
|
"data": "Données personnelles et cookie",
|
||||||
|
"accessibility": "Accessibilités : audit en cours",
|
||||||
|
"ariaLabel": "nouvelle fenêtre"
|
||||||
|
},
|
||||||
|
"mentions": "Sauf mention contraire, les contenus de ce site sont disponibles sous",
|
||||||
|
"license": "licence etalab 2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,36 @@ const link = cva({
|
|||||||
textStyle: 'sm',
|
textStyle: 'sm',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
externalIcon: {
|
||||||
|
true: {
|
||||||
|
_after: {
|
||||||
|
content: 'url(/assets/link-grey.svg)',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
paddingLeft: '.25rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
underline: {
|
||||||
|
false: {
|
||||||
|
textDecoration: 'none',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
important: {
|
||||||
|
fontSize: '0.8rem',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
fontWeight: '700',
|
||||||
|
fontFamily: 'Marianne',
|
||||||
|
textWrap: 'nowrap',
|
||||||
|
},
|
||||||
|
minor: {
|
||||||
|
fontSize: '0.75rem',
|
||||||
|
color: 'rgb(77 77 77)',
|
||||||
|
fontFamily: 'Marianne',
|
||||||
|
textWrap: 'nowrap',
|
||||||
|
lineHeight: '1rem',
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -29,6 +59,17 @@ export type AProps = LinkProps & RecipeVariantProps<typeof link>
|
|||||||
/**
|
/**
|
||||||
* anchor component styled with underline. Used mostly for external links. Use Link for internal links
|
* anchor component styled with underline. Used mostly for external links. Use Link for internal links
|
||||||
*/
|
*/
|
||||||
export const A = ({ size, ...props }: AProps) => {
|
export const A = ({
|
||||||
return <Link {...props} className={link({ size })} />
|
size,
|
||||||
|
externalIcon,
|
||||||
|
underline,
|
||||||
|
footer,
|
||||||
|
...props
|
||||||
|
}: AProps) => {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
{...props}
|
||||||
|
className={link({ size, externalIcon, underline, footer })}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ import { PanelId } from '@/features/rooms/livekit/hooks/useSidePanel'
|
|||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
showHeader: boolean
|
showHeader: boolean
|
||||||
|
showFooter: boolean
|
||||||
activePanelId: PanelId | null
|
activePanelId: PanelId | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export const layoutStore = proxy<State>({
|
export const layoutStore = proxy<State>({
|
||||||
showHeader: false,
|
showHeader: false,
|
||||||
|
showFooter: false,
|
||||||
activePanelId: null,
|
activePanelId: null,
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user