Also: Documentation home · DSL · CLI · Extensions
Crepuscularity supports reusable components via include statements.
One .crepus file = one component. Use $: default to declare optional props:
# components/card.crepus
$: default subtitle = ""
div rounded-lg border border-zinc-700 p-4
div font-bold
{title}
if {subtitle}
div text-sm text-zinc-400
{subtitle}
slot
div text-zinc-500 italic
"No content provided"
Or in JSX syntax:
// components/card.crepus
let-default subtitle = ""
<div class="rounded-lg border border-zinc-700 p-4">
<div class="font-bold">{title}</div>
<if condition={subtitle}>
<div class="text-sm text-zinc-400">{subtitle}</div>
</if>
<slot>
<div class="text-zinc-500 italic">No content provided</div>
</slot>
</div>Include from another template:
include components/card.crepus title="Dashboard" subtitle="Overview"
div p-4
"Card body content"
Or using fragment syntax for multi-component files:
include ui.crepus#Card title="Settings"
div
"Settings content"
In JSX syntax:
<include src="components/card.crepus" title="Dashboard" subtitle="Overview">
<div class="p-4">Card body content</div>
</include>
<include src="ui.crepus#Card" title="Settings">
<div>Settings content</div>
</include>Group related components in a single file with TOML frontmatter:
+++
[Card]
description = "A bordered card"
[Card.defaults]
title = "Untitled"
[Button]
description = "A clickable button"
[Button.defaults]
label = "Click"
variant = "primary"
+++
--- Card
div rounded-lg border border-zinc-700 p-4
div font-bold
{title}
slot
--- Button
$: default variant = "primary"
button px-4 py-2 rounded cursor-pointer
{label}
Include with #Name fragment:
include ui.crepus#Card title="Settings"
div
"Settings content"
include ui.crepus#Button label="Save" variant="primary"
The slot keyword renders content passed by the parent:
# Layout component
div flex flex-col min-h-screen
header bg-zinc-900 p-4
"Header"
main flex-1
slot
footer bg-zinc-900 p-4
"Footer"
Usage:
include layout.crepus
div p-8
"Main content goes here"
Slot can have fallback children if nothing is passed:
slot
div text-gray-500
"Default content"
Each component gets its own context with:
- Props passed via
prop=valuesyntax - Defaults from
$: defaultor TOML[Component.defaults] - The slot content (accessible via
slotkeyword)
Props always override defaults:
# In component:
$: default color = "blue"
# In parent:
include component.crepus color="red" # color is "red"
include component.crepus # color is "blue"
Crepuscularity ships a small set of reusable UI components in examples/ui-library/. They are intentionally generic so they can be used across projects; see the examples/ui-library/examples/ demos for sample usage.
| Component | File | Props | Use case |
|---|---|---|---|
Grid |
ui-library.crepus |
columns, gap, aspectRatio |
Photo galleries, dashboards |
Panel |
ui-library.crepus |
title, collapsible, defaultExpanded |
Grouped settings, collapsible sections |
Wizard |
ui-library.crepus |
steps, currentStep, showProgress, allowSkip |
Pairing flows, onboarding |
List |
ui-library.crepus |
items (label, detail), selectable |
File lists, logs, settings |
Card |
ui-library.crepus |
title, subtitle, slot |
Dashboards, detail panels |
Badge |
ui-library.crepus |
label, color |
Status indicators |
Button |
ui-library.crepus |
label, variant |
Actions, forms |
Alert |
ui-library.crepus |
message, kind |
Feedback banners |
Tabs |
ui-library.crepus |
tabs, active |
Navigation, settings |
EmptyState |
ui-library.crepus |
message, action |
Empty lists, pages |
Avatar |
ui-library.crepus |
src, label, size |
User avatars, icons |
TransferProgress |
transfer-progress.crepus |
label, fileName, value, max, speed, eta |
Upload/download progress |
include ui-library/ui-library.crepus#Grid columns=4 gap=4
for photo in {photos}
div aspect-square rounded-lg overflow-hidden
img src={photo.thumb} object-cover w-full h-full
Components are documented by their TOML frontmatter and can be rendered with crepus render or any supported target.
The include statement and multi-component files are runtime-only features. The compile-time view! macro does not support includes.
For compile-time composition, use Rust functions or the GPUI component model directly.