Box
The zero-opinion layout primitive — a <div> (or any element via as) wired up to the full LayoutProps surface. Every other primitive composes Box.
Polymorphic via as, so semantics travel with the component. asChild defers rendering to a child component while merging Box's layout class and inline style.
import { Box } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Box padding="6" background="bg.subtle" borderRadius="md">
A boxed surface
</Box>
);
}
LayoutProps
Section titled “LayoutProps”Every spacing, sizing, colour, position, and flex/grid prop exposed by the layout system lives on Box. Each accepts a token value, a raw CSS length, or a responsive map keyed by breakpoint. The same prop surface is composed into Stack, Inline, Flex, Grid, and every Cynosure component that derives from Box.
import { Box } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Box
padding="4"
paddingX="6"
width="100%"
maxWidth="280px"
background="bg.subtle"
borderRadius="md"
borderWidth="1"
borderStyle="solid"
borderColor="border.subtle"
>
Token-driven width, padding, border, and surface — all via props.
</Box>
);
}
Polymorphic via as
Section titled “Polymorphic via as”Render any intrinsic element (or React component) while keeping the LayoutProps surface. The component’s TypeScript type follows as so attribute autocomplete stays accurate — as="a" gives you href, as="button" gives you type, and so on.
import { Box, Stack } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Stack gap="2">
<Box as="article" padding="3" background="bg.subtle" borderRadius="md">
Rendered as <article>
</Box>
<Box as="aside" padding="3" background="bg.subtle" borderRadius="md">
Rendered as <aside>
</Box>
<Box as="section" padding="3" background="bg.subtle" borderRadius="md">
Rendered as <section> — a landmark region
</Box>
</Stack>
);
}
asChild
Section titled “asChild”Pass the layout class + style straight onto a single child — useful when wrapping a third-party component, an <a> from a router, or another Cynosure primitive that you want to extend without an extra wrapper element.
import { Box } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Box asChild padding="3" background="accent.soft" borderRadius="md">
<a href="https://cynosure.arshadshah.com">
Box's layout class flows onto the <a> — no wrapper element added.
</a>
</Box>
);
}
Responsive props
Section titled “Responsive props”Every layout prop accepts a { base, sm, md, lg, xl, 2xl } map. Values cascade upward (a md value applies from the md breakpoint until overridden), so you typically only set the breakpoints that change.
import { Box } from '@arshad-shah/cynosure-react';
export default function Example() {
return (
<Box
padding={{ base: '2', md: '4', lg: '6' }}
background={{ base: 'bg.subtle', md: 'accent.soft' }}
borderRadius={{ base: 'sm', md: 'md', lg: 'lg' }}
maxWidth={{ base: '100%', md: '420px' }}
>
Resize the preview — padding, background, radius, and width all shift at each breakpoint.
</Box>
);
}
Recipes
Section titled “Recipes”- Reach for
Boxwhenever you need a styled wrapper but don’t want to think about flex / grid direction. For row/column flow, preferInlineorStack; for centered single children, preferCenter. - Use
asto keep semantics tight:as="section"for landmark regions,as="article"for self-contained cards,as="aside"for complementary content. - Combine
asChildwithLinkfrom your router to inherit Box’s layout props without adding an extra DOM node.