Empty
The box a list shows when it has nothing in it.
src/components/rahti_ui/empty.rs
The box
A picture, a heading, a sentence and a way out.
shadcn's own demo. Six parts and a flexbox — no script, no state and nothing to mount. The two buttons sit side by side because `EmptyContent` was given `flex-row justify-center gap-2`, which is a `class` rather than a prop.
`Learn More` is shadcn's `render={<a href=…/>}` on a link Button, which crosses here as an `<a>` wearing `button_variants(…)` — the same answer this library gives `asChild` everywhere else.
Outlined
One utility away, and the reason it is only one.
The only difference from the box above is `class="border border-dashed"`. That works because the component's own string says `border-dashed` and never says `border` — the border *style* is set and the width is still zero, so the default box draws nothing and this one only has to supply the width.
It is a `class`, not a variant. All three of shadcn's looks on this component are, which is worth knowing before reaching for a `variant` prop that does not exist.
Muted
A filled box, and a narrower sentence.
shadcn's muted demo, again a `class` on the root. The description takes one of its own — `max-w-xs text-pretty` — which narrows it and stops the last line being a single orphan word.
With an avatar
The default media variant, which exists for exactly this.
LR
CN
LR
ERThis is what `variant="default"` is for. The icon variant gives one glyph a tinted rounded square to sit in; the default leaves the box transparent for something that already draws itself — an avatar, or three of them overlapping.
The overlapping stack is `-space-x-2` with a ring the colour of the background, and every avatar is reached through `*:data-[slot=avatar]:…` — which works because this library's Avatar carries that slot, the same way shadcn's does.
With a search
A box with no picture, and a link that styles itself.
No media at all — the header is just a heading and a sentence, and nothing collapses. `EmptyContent` is a column by default, which is why the field and the line under it stack without being told to.
`Contact support` is a plain `<a>` and nothing is said about it: the description's own class list carries `[&>a]:underline` and `[&>a:hover]:text-primary`, so a link inside one styles itself.
`Kbd` is a key drawn the way a keyboard draws it, and the `/` sits in a second addon at the field's trailing edge. A key is `pointer-events-none`, because it is a label rather than a control — one sitting in a field must never eat the click meant to focus it.
Two addons in one group were unwritable until recently: the browser runtime shifted their children by one, so the trailing addon drew the leading one's magnifier and the `/` was lost. The fault was PulsePoint's rather than Rahti's — on a component's first morph the live children still carried its own `<script>` while the rendered body never did, so every sibling after it paired with the one before. An ordinary element was repaired by descent; a nested boundary could not be, because a morph never descends into one.
The port
Eight small differences and one class that stayed behind.
The `cn-font-heading` call is the opposite of the one the Command port made about `cmdk-*`, and the difference is which way the arrow points. shadcn's own class strings *select on* `cmdk-item`, so dropping those would have broken published CSS. Nothing selects on `cn-font-heading` — it is a hook for a heading font this project does not ship, so it is dead weight here.