The as Prop
Used to change the underlying HTML element that a component renders. It provides a straightforward way to change the underlying element while retaining the component’s functionality.
<Heading as="h3">Hello, world!</Heading>TypeScript: the caveat with the
asprop is that the type of the component passed to it must be compatible with the component’s props. We do not infer the underlying component’s props fromas.
as stays a loose ValidComponent rather than a generic that re-types props from the element, and
that is deliberate rather than unfinished: the deep conditional types that would buy you href on
as="a" also wreck editor completions across every component in the library.
import { Box } from "chakra-ui-solid";
export default function BoxWithAsProp() {
return (
<Box as="section" color="fg.muted">
This is a Box rendered as a section
</Box>
);
}The render Prop
Used to compose a component’s functionality onto an element you supply — the React version’s
asChild, which this library does not have.
It is a function that receives the computed props and returns the element, never a JSX element.
A Solid JSX element is an already-constructed node by the time it reaches us and there is no
cloneElement, so accepting one could only mean rendering it with every computed prop dropped.
<Button render={(props) => <MyButton {...props}>Open</MyButton>} />import type { JSX } from "@solidjs/web";
import { Box } from "chakra-ui-solid";
export default function BoxWithRenderProp() {
return (
<Box
px="4"
py="2"
borderRadius="l2"
bg="colorPalette.solid"
color="colorPalette.contrast"
textDecoration="none"
render={(props) => (
<a {...(props as JSX.AnchorHTMLAttributes<HTMLAnchorElement>)} href="https://panda-css.com">
{props.children}
</a>
)}
>
A styled anchor
</Box>
);
}That cast is real, and it is narrow. Every component types its element props against the element
it renders — Box’s are a div’s, Span’s a span’s — and Solid’s Ref<HTMLDivElement> is not
assignable to Ref<HTMLAnchorElement>, so a render target that is a different host element
needs a cast. A target that renders the same element needs none, and neither does a component
typed against the same JSX.HTMLAttributes. A component whose props are a Chakra type needs one
for a different reason, which Best Practices below spells out.
The unstyled Prop
Used to drop a component’s own theme styles while keeping everything else it does. Style props and
the css prop still apply — the opt-out is of the recipe, not of styling.
<Checkmark unstyled css={{ color: "fg.inverted" }} />This is how one component re-dresses another it is built from, rather than a way to render a bare
element: a checkbox built on Checkmark renders <Checkmark unstyled> and hands it its own slot’s
styles, so the mark takes the checkbox’s size and colour instead of the checkmark recipe’s.
Best Practices
as and render both hand your element every prop the component computed for it — the composed
class, the merged ref, the children, and the DOM attributes. To avoid common pitfalls, there are
a few practices to consider:
- Spread the props. A target that picks them off by name loses whichever it did not name — the
class, theref, an attribute — and nothing errors. - Never destructure them. They are a live props proxy whose
classis a getter that recomputes when a style prop changes, sorender={({ class: className }) => …}reads it once and freezes the element at whatever it was on the first render. - Refs need no forwarding. Solid has no
forwardRef:refarrives as an ordinary prop, and the spread applies it whether the target is a host element or another chakra-ui-solid component. Dropping the spread is the only way to lose it.
const MyButton = (props: ComponentProps<"button">) => <button {...props} />;
// with `as` — Button renders MyButton in place of its own element
<Button as={MyButton}>Click me</Button>
// with `render` — the same target, called with the computed props
<Button render={(props) => <MyButton {...props}>Click me</MyButton>} />Type the target against the element’s props, as MyButton does, rather than against the Chakra
component’s. What a target is handed is the DOM props, and a Chakra props type spells five of those
attributes htmlSize, htmlWidth, htmlHeight, htmlTranslate and htmlContent — keeping the
plain names for the style props of the same name — so a target typed BoxProps or ButtonProps
does not accept them without a cast.