Frontend
Layouts
A layout is the frame around a page: the header, footer and shell that stay put while the page changes. Unlike a page, a layout is not an event handler; it lives purely in the view dimension, and it renders the page through a StoneOutlet.
#Defining a layout
Mark a class with @PageLayout({ name }) and render your shell, placing the page where StoneOutlet sits. A layout may implement head, but never handle: it does not process events.
import { PageLayout, IPageLayout, StoneOutlet } from '@stone-js/use-react'
import { ReactNode } from 'react'
@PageLayout({ name: 'default' })
export class BaseLayout implements IPageLayout {
render ({ children }: { children: ReactNode }) {
return (
<div className='app'>
<header>Tasks</header>
<main><StoneOutlet>{children}</StoneOutlet></main>
<footer>© Tasks</footer>
</div>
)
}
}import { definePageLayout, StoneOutlet } from '@stone-js/use-react'
const BaseLayout = () => ({
render: ({ children }) => (
<div className='app'>
<header>Tasks</header>
<main><StoneOutlet>{children}</StoneOutlet></main>
<footer>© Tasks</footer>
</div>
)
})
export const layouts = [definePageLayout(BaseLayout, { name: 'default' }, true)]#Named layouts
The name makes a layout selectable. The one named default wraps any page that does not choose otherwise; register others (admin, auth) and opt in per page.
@Page('/admin', { layout: 'admin' })
export class AdminPage implements IPage<ReactIncomingEvent> {
render () { return <Dashboard /> }
}const AdminPage = () => ({ render: () => <Dashboard /> })
export const pages = [definePage(AdminPage, { path: '/admin', layout: 'admin' }, true)]#Root providers
Some context wraps the whole app, not one layout: a theme, an i18n provider, a data- fetching client. A view provider wraps the entire tree, above every layout and page, and runs on the server render and the client hydration alike, so context is consistent in both.
import { ViewProvider, IViewProvider } from '@stone-js/use-react'
import { ReactNode } from 'react'
@ViewProvider()
export class AppProviders implements IViewProvider {
render ({ children }: { children: ReactNode }) {
return (
<ThemeProvider>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</ThemeProvider>
)
}
}import { defineViewProvider } from '@stone-js/use-react'
const AppProviders = () => ({
render: ({ children }) => (
<ThemeProvider><QueryClientProvider client={queryClient}>{children}</QueryClientProvider></ThemeProvider>
)
})
export const viewProviders = [defineViewProvider(AppProviders, {}, true)]