All components panel settings
Page
Page scaffolds with header, title, description, and body in panel and settings variants.
Dashboard
Overview of your workspace.
12345678910111213141516171819import { Page } from "#components/ui/base-ui/page.tsx";
export function Example() { return ( // variant resolves once on Root; every part inherits it via context — // composition per part via render <Page.Root variant="panel"> <Page.Header> <Page.HeaderContent> <Page.Heading> <Page.Title>Dashboard</Page.Title> <Page.Description>Overview of your workspace.</Page.Description> </Page.Heading> </Page.HeaderContent> </Page.Header> <Page.Body>…</Page.Body> </Page.Root> );}Variants
Dashboard
Overview of your workspace.
Dashboard
Overview of your workspace.
Install
1npx stylexblocks add pageSource
components/ui/base-ui/page.tsx
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179import * as stylex from "@stylexjs/stylex";import { createSlotRecipeContext } from "#lib/base-ui/create-slot-recipe-context.tsx";import { defineSlotRecipe } from "#lib/recipe-props.ts";import { fontSizes } from '@stylexblocks/ui/tokens/font-sizes.stylex.ts'import { fontWeights } from '@stylexblocks/ui/tokens/font-weights.stylex.ts'import { lineHeights } from '@stylexblocks/ui/tokens/line-heights.stylex.ts'import { semanticColors } from '@stylexblocks/ui/semantic-tokens/colors.stylex.ts'import { sizes } from '@stylexblocks/ui/tokens/sizes.stylex.ts'import { spacing } from '@stylexblocks/ui/tokens/spacing.stylex.ts'
const pageRoot = stylex.create({ base: { display: 'flex', flexDirection: 'column', flex: 1, minHeight: 0, },})
const pageRootVariants = stylex.create({ panel: { '--page-bg-color': semanticColors.bg, backgroundColor: 'var(--page-bg-color)', zIndex: 1, }, settings: { overflowY: 'auto', paddingInline: spacing._4, },})
const pageHeader = stylex.create({ base: { display: 'flex', flexDirection: 'column', flexShrink: 0, },})
const pageHeaderVariants = stylex.create({ panel: { '--page-header-row-height': '40px', '--page-header-padding-x': spacing._4, borderBottomWidth: '1px', }, settings: {},})
const pageHeaderContent = stylex.create({ base: { display: 'flex', flex: 1, alignItems: 'center', gap: spacing._2, minWidth: 0, },})
const pageHeaderContentVariants = stylex.create({ panel: { minHeight: 'var(--page-header-row-height)', paddingInline: 'var(--page-header-padding-x)', }, settings: { minHeight: sizes._24, },})
const pageHeading = stylex.create({ base: { flex: 1, minWidth: 0, },})
const pageHeadingVariants = stylex.create({ settings: {},})
const pageHeaderFooter = stylex.create({ base: { display: 'flex', flexDirection: 'column', width: sizes.full, },})
const pageTitle = stylex.create({ base: { fontWeight: fontWeights.medium, },})
const pageTitleVariants = stylex.create({ panel: { marginInlineEnd: spacing._4, fontSize: fontSizes.sm, lineHeight: lineHeights.sm, }, settings: { fontSize: fontSizes._2xl, lineHeight: lineHeights._2xl, },})
const pageDescription = stylex.create({ base: { color: semanticColors.fgMuted, },})
const pageDescriptionVariants = stylex.create({ panel: { fontSize: fontSizes.xs, lineHeight: lineHeights.xs, }, settings: { fontSize: fontSizes.md, lineHeight: lineHeights.md, },})
const pageBody = stylex.create({ base: { flex: 1, overflowY: 'auto', padding: spacing._4, },})
const pageBodyVariants = stylex.create({ settings: { overflow: 'visible', padding: 0, },})
export type PageVariant = keyof typeof pageRootVariants
// defineSlotRecipe validates the shape at compile time: default values must// exist in the axis maps, and slot keys must be `styles` or a declared axis.// The heading and body variant maps are sparse (only `settings` restyles// them) — the mechanical resolver skips axis values a slot doesn't style.const pageSlotRecipe = defineSlotRecipe({ slots: { root: { styles: pageRoot, variants: pageRootVariants }, header: { styles: pageHeader, variants: pageHeaderVariants }, headerContent: { styles: pageHeaderContent, variants: pageHeaderContentVariants, }, heading: { styles: pageHeading, variants: pageHeadingVariants }, headerFooter: { styles: pageHeaderFooter }, title: { styles: pageTitle, variants: pageTitleVariants }, description: { styles: pageDescription, variants: pageDescriptionVariants }, body: { styles: pageBody, variants: pageBodyVariants }, }, defaultVariants: { variant: "panel" },});
/** * Page — recipe and component colocated in one file. `<Page.Root variant>` * resolves the recipe once and every part inherits it through context; each * part composes via `render`. */const { withProvider, withContext } = createSlotRecipeContext(pageSlotRecipe);
export const Page = { // slot names resolve mechanically from the recipe maps above Root: withProvider("main", "root", "PageRoot"), Header: withContext("header", "header", "PageHeader"), HeaderContent: withContext("div", "headerContent", "PageHeaderContent"), Heading: withContext("div", "heading", "PageHeading"), HeaderFooter: withContext("div", "headerFooter", "PageHeaderFooter"), Title: withContext("h1", "title", "PageTitle"), Description: withContext("p", "description", "PageDescription"), Body: withContext("div", "body", "PageBody"),};