Getting Started
Learn how to use primitives and components in your Blazor application
Primitives vs Components
Primitives
Headless, unstyled components that provide behavior, accessibility, and state management.
Components
Pre-styled wrappers around primitives with shadcn/ui design and Tailwind classes.
Usage Examples
Using a Component (Quick Start)
Import and use styled components directly with beautiful defaults:
@using BlazorUI.Components.Dialog
<Dialog>
<DialogTrigger>Open Dialog</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Dialog Title</DialogTitle>
<DialogDescription>Description text</DialogDescription>
</DialogHeader>
<p>Dialog content goes here</p>
</DialogContent>
</Dialog>Using a Primitive (Custom Styling)
Use primitives when you want full control over styling:
@using BlazorUI.Primitives.Dialog
<DialogPrimitive>
<DialogTrigger class="my-custom-button-class">
Open Dialog
</DialogTrigger>
<DialogPortal>
<DialogOverlay class="my-overlay-styles" />
<DialogContent class="my-custom-dialog-styles">
<DialogTitle class="my-title-styles">
Custom Styled Dialog
</DialogTitle>
<p class="my-content-styles">Fully custom!</p>
</DialogContent>
</DialogPortal>
</DialogPrimitive>Composition Patterns
Components are built using composition - combine sub-components to create complex UIs.
Required Pattern
Most primitives require a specific component hierarchy:
<!-- Root component manages state -->
<DialogPrimitive>
<!-- Trigger opens the dialog -->
<DialogTrigger>...</DialogTrigger>
<!-- Portal renders outside DOM hierarchy -->
<DialogPortal>
<!-- Overlay for click-outside behavior -->
<DialogOverlay />
<!-- Content with focus management -->
<DialogContent>...</DialogContent>
</DialogPortal>
</DialogPrimitive>Controlled State
Control component state from parent using @bind-:
<DialogPrimitive @bind-Open="isDialogOpen">
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<p>Controlled by parent component</p>
<button @onclick="() => isDialogOpen = false">
Close
</button>
</DialogContent>
</DialogPrimitive>
@code {
private bool isDialogOpen = false;
}Uncontrolled State
Let the component manage its own state:
<DialogPrimitive>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<p>Component manages its own open/close state</p>
<DialogClose>Close</DialogClose>
</DialogContent>
</DialogPrimitive>Common Patterns
Cascading Context
Root components use CascadingValue to
share state with child components. Child components automatically receive context - no prop drilling needed.
Portal Rendering
Components like Dialog and Popover use Portal
to render outside their parent DOM to avoid z-index issues and enable proper overlays.
Event Callbacks
Components expose events like OpenChanged
that you can hook into for custom logic when state changes.