Standalone Components
Use BTST's UI components independently of any plugin — auto-form, markdown editor, kanban, form builder, UI builder, and more.
BTST ships a set of UI components that can be used without setting up any plugin. Each is available as its own import path from @btst/stack, so you only bundle what you use.
| Import path | CSS export | What you get |
|---|---|---|
@btst/stack/components/auto-form | — | AutoForm, AutoFormSubmit |
@btst/stack/components/stepped-auto-form | — | SteppedAutoForm |
@btst/stack/components/form-builder | — | FormBuilder and schema helpers |
@btst/stack/components/markdown | @btst/stack/components/markdown/css | MarkdownContent, MarkdownEditor |
@btst/stack/components/multi-select | — | MultipleSelector |
@btst/stack/components/search-select | — | SearchSelect |
@btst/stack/components/empty | — | Empty, EmptyHeader, EmptyTitle, … |
AutoForm
Generate forms automatically from Zod schemas. Learn more →
import { AutoForm, AutoFormSubmit } from "@btst/stack/components/auto-form"
import type { FieldConfig, Dependency } from "@btst/stack/components/auto-form"<AutoForm
formSchema={z.object({
name: z.string().min(1),
email: z.string().email(),
})}
onSubmit={(values) => console.log(values)}
>
<AutoFormSubmit>Submit</AutoFormSubmit>
</AutoForm>Stepped AutoForm
Multi-step wizard variant. Learn more →
import { SteppedAutoForm } from "@btst/stack/components/stepped-auto-form"
import type { SteppedAutoFormProps, StepperComponentProps } from "@btst/stack/components/stepped-auto-form"FormBuilder
A JSON-schema-driven form editor — lets users visually create form definitions that can be stored and later rendered. Learn more →
import {
FormBuilder,
defaultComponents,
objectFieldDefinition,
arrayFieldDefinition,
defineComponent,
baseMetaSchema,
baseMetaSchemaWithPlaceholder,
} from "@btst/stack/components/form-builder"
import type {
FormBuilderComponentDefinition,
FormBuilderField,
JSONSchema,
JSONSchemaProperty,
} from "@btst/stack/components/form-builder"<FormBuilder
schema={currentSchema}
onChange={(schema) => setSchema(schema)}
components={defaultComponents}
/>The full Form Builder plugin (@btst/stack/plugins/form-builder) layers data persistence, API routes, and submissions on top of this component. Use the standalone import when you want to manage your own storage.
Markdown
MarkdownContent
Renders Markdown/MDX to HTML with syntax highlighting:
import { MarkdownContent } from "@btst/stack/components/markdown"
import type { MarkdownContentProps } from "@btst/stack/components/markdown"<MarkdownContent content="# Hello\n\nSome **bold** text." />Import the stylesheet in your root CSS (or layout):
@import "@btst/stack/components/markdown/css";MarkdownEditor
A rich Markdown editor powered by Milkdown/Crepe with optional image upload:
import { MarkdownEditor } from "@btst/stack/components/markdown"
import type { MarkdownEditorProps } from "@btst/stack/components/markdown"<MarkdownEditor
value={content}
onChange={(markdown) => setContent(markdown)}
placeholder="Write something..."
uploadImage={async (file) => {
const url = await uploadToStorage(file)
return url
}}
/>MarkdownEditor Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | "" | Current Markdown content |
onChange | (markdown: string) => void | — | Called on every change |
className | string | — | Additional CSS classes |
placeholder | string | "Write something..." | Placeholder when empty |
uploadImage | (file: File) => Promise<string> | — | Enables image upload; must return the public URL |
The stylesheet also covers the Markdown editor. Import once from @btst/stack/components/markdown/css.
MultipleSelector
A multi-select combobox with search, async options, and tag-style values:
import { MultipleSelector } from "@btst/stack/components/multi-select"
import type { Option, MultipleSelectorRef } from "@btst/stack/components/multi-select"const options: Option[] = [
{ value: "react", label: "React" },
{ value: "vue", label: "Vue" },
{ value: "svelte", label: "Svelte" },
]
<MultipleSelector
options={options}
value={selected}
onChange={setSelected}
placeholder="Select frameworks..."
/>SearchSelect
A searchable single-value select powered by Radix + cmdk:
import { SearchSelect } from "@btst/stack/components/search-select"<SearchSelect
options={[
{ value: "us", label: "United States" },
{ value: "gb", label: "United Kingdom" },
]}
value={country}
onValueChange={setCountry}
placeholder="Select a country..."
/>Empty
Composable empty-state UI components:
import {
Empty,
EmptyHeader,
EmptyTitle,
EmptyDescription,
EmptyContent,
EmptyMedia,
} from "@btst/stack/components/empty"<Empty>
<EmptyMedia>
<InboxIcon className="size-12 text-muted-foreground" />
</EmptyMedia>
<EmptyHeader>
<EmptyTitle>No results</EmptyTitle>
<EmptyDescription>Try adjusting your search or filters.</EmptyDescription>
</EmptyHeader>
<EmptyContent>
<Button>Clear filters</Button>
</EmptyContent>
</Empty>