Skip to main content

Components Reference

Complete catalog of UI components available in the Vertical Template.

Component Categories

UI Primitives (Shadcn/ui)

Base components built on Radix UI with Tailwind CSS styling.

ComponentDescriptionProps
ButtonConfigurable buttonvariant, size, disabled
InputText input fieldtype, placeholder, disabled
LabelForm labelhtmlFor
CheckboxCheckbox with indeterminatechecked, onCheckedChange
SelectDropdown selectvalue, onValueChange
SwitchToggle switchchecked, onCheckedChange
TextareaMulti-line text inputplaceholder, rows
BadgeStatus and label badgesvariant
AlertAlert box with variantsvariant
CardCard containerCardHeader, CardContent, CardFooter
DialogModal dialogopen, onOpenChange
DropdownMenuDropdown menuTrigger, Content, Item
RadioGroupRadio button groupvalue, onValueChange
TableData tableTableHeader, TableBody, TableRow
TooltipTooltip on hovercontent
SkeletonLoading placeholderclassName

Button Variants

import { Button } from '@/components/ui/button';

// Variants
<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

// Sizes
<Button size="default">Default</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button size="icon"><Icon /></Button>

Card Usage

import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';

<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description</CardDescription>
</CardHeader>
<CardContent>
<p>Card content goes here.</p>
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>

Layout Components

Top navigation bar with branding and user controls.

{
component: 'Header',
priority: 1,
props: {
logo: '/logo.svg',
title: 'My Application',
showUserMenu: true,
showNotifications: true,
navItems: [
{ label: 'Dashboard', href: '/dashboard' },
{ label: 'Settings', href: '/settings' },
],
},
storeBindings: [
{ prop: 'userName', storePath: 'user.name' },
{ prop: 'isAuthenticated', storePath: 'user.isAuthenticated' },
],
}

Props:

  • logo: string - Path to logo image
  • title: string - Application title
  • showUserMenu: boolean - Show user dropdown
  • showNotifications: boolean - Show notification bell
  • navItems: NavItem[] - Navigation links

ThreePanelLayout

Desktop layout with three column panes.

import { ThreePanelLayout } from '@enterpriseaigroup/client';

<ThreePanelLayout
leftPane={<Sidebar />}
middlePane={<MainContent />}
rightPane={<ContextPanel />}
/>

Collapsible left sidebar navigation.

{
component: 'Sidebar',
priority: 1,
props: {
collapsible: true,
defaultOpen: true,
},
storeBindings: [
{ prop: 'isOpen', storePath: 'ui.sidebarOpen' },
],
}

Workflow Components

StageProgress

Progress indicator showing workflow stages.

{
component: 'StageProgress',
priority: 1,
props: {
steps: ['Start', 'Details', 'Review', 'Complete'],
},
storeBindings: [
{ prop: 'currentStep', storePath: 'workflow.currentStep' },
{ prop: 'completedSteps', storePath: 'workflow.completedSteps' },
],
}

WelcomeCard

Welcome message for new users.

{
component: 'WelcomeCard',
priority: 1,
props: {
title: 'Welcome!',
message: 'Get started by signing in.',
ctaText: 'Sign In',
ctaHref: '/api/auth/signin',
},
showWhen: (state) => !state.user?.isAuthenticated,
}

Property Components

PropertyInfoCard

Property details with interactive map.

{
component: 'PropertyInfoCard',
priority: 1,
props: {
mapConfig: {
accessToken: 'mapbox-token',
interactive: true,
},
},
storeBindings: [
{ prop: 'address', storePath: 'property.selectedAddress' },
{ prop: 'propertyId', storePath: 'property.propertyId' },
],
showWhen: (state) => state.property?.selectedAddress !== null,
}

AddressLookup

Address autocomplete with Mapbox.

{
component: 'AddressLookup',
priority: 1,
props: {
placeholder: 'Search for an address...',
minCharacters: 3,
},
storeBindings: [
{ prop: 'value', storePath: 'property.searchQuery' },
],
}

Chat Components

Chatbot

Full chat interface with SSE streaming.

{
component: 'Chatbot',
priority: 1,
props: {
title: 'AI Assistant',
placeholder: 'Ask me anything...',
streamingEnabled: true,
},
storeBindings: [
{ prop: 'messages', storePath: 'chat.messages' },
{ prop: 'isLoading', storePath: 'chat.isLoading' },
],
showWhen: (state) => state.features?.chat === true,
}

FloatingChatbot

Mobile floating chat button.

{
component: 'FloatingChatbot',
priority: 1,
props: {
position: 'bottom-right',
},
}

Form Components

Input with Label

import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';

<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="Enter your email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</div>

Select

import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';

<Select value={status} onValueChange={setStatus}>
<SelectTrigger>
<SelectValue placeholder="Select status" />
</SelectTrigger>
<SelectContent>
<SelectItem value="draft">Draft</SelectItem>
<SelectItem value="active">Active</SelectItem>
<SelectItem value="completed">Completed</SelectItem>
</SelectContent>
</Select>

Using Components

Direct Import

import { Button, Card, Input } from '@/components/ui';
import { PropertyInfoCard } from '@enterpriseaigroup/client';

function MyPage() {
return (
<Card>
<PropertyInfoCard address="123 Main St" />
<Button>Submit</Button>
</Card>
);
}
// In tenant config
{
component: 'PropertyInfoCard',
priority: 1,
storeBindings: [
{ prop: 'address', storePath: 'property.selectedAddress' },
],
}

The SlotRenderer:

  1. Resolves component from ComponentRegistry
  2. Applies storeBindings
  3. Evaluates showWhen
  4. Renders with merged props

Component Registry

Register custom components:

// packages/client/src/config/ComponentRegistry.ts
import { MyCustomComponent } from '@/components/MyCustomComponent';

registry.set('MyCustomComponent', MyCustomComponent);

Check if component is registered:

import { ComponentRegistry } from '@enterpriseaigroup/client';

if (ComponentRegistry.has('MyComponent')) {
// Component is available
}

Styling

All components use:

  • Tailwind CSS for utility classes
  • CSS Variables for theming
  • class-variance-authority (CVA) for variants

Import styles:

import '@enterpriseaigroup/client/styles.css';

Customize with cn() utility:

import { cn } from '@/lib/utils';

<Button className={cn('custom-class', isActive && 'active')}>
Click me
</Button>