> ## Documentation Index
> Fetch the complete documentation index at: https://docs.skyvexsoftware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Components

> Pre-built UI components from the Stratos SDK.

The SDK re-exports a curated set of [shadcn/ui](https://ui.shadcn.com) components that are already themed to match the Stratos shell. Use these instead of installing your own UI library to stay visually consistent across plugins.

## Import

All components are available from a single import:

```tsx theme={null}
import {
  Button,
  Card,
  CardHeader,
  CardTitle,
  CardContent,
  Badge,
  Input,
  Label,
  // ... etc
} from "@skyvexsoftware/stratos-sdk";
```

## Component Reference

### Dialogs

#### AlertDialog

Accessible alert dialog for confirmations and destructive actions.

```tsx theme={null}
import {
  AlertDialog,
  AlertDialogTrigger,
  AlertDialogContent,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogAction,
  AlertDialogCancel,
} from "@skyvexsoftware/stratos-sdk";

<AlertDialog>
  <AlertDialogTrigger asChild>
    <Button variant="destructive">Delete</Button>
  </AlertDialogTrigger>
  <AlertDialogContent>
    <AlertDialogHeader>
      <AlertDialogTitle>Are you sure?</AlertDialogTitle>
      <AlertDialogDescription>
        This action cannot be undone.
      </AlertDialogDescription>
    </AlertDialogHeader>
    <AlertDialogFooter>
      <AlertDialogCancel>Cancel</AlertDialogCancel>
      <AlertDialogAction>Delete</AlertDialogAction>
    </AlertDialogFooter>
  </AlertDialogContent>
</AlertDialog>
```

**Sub-components:** `AlertDialog`, `AlertDialogPortal`, `AlertDialogOverlay`, `AlertDialogTrigger`, `AlertDialogContent`, `AlertDialogHeader`, `AlertDialogFooter`, `AlertDialogTitle`, `AlertDialogDescription`, `AlertDialogAction`, `AlertDialogCancel`

#### Dialog

General-purpose modal dialog.

```tsx theme={null}
import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  DialogClose,
} from "@skyvexsoftware/stratos-sdk";

<Dialog>
  <DialogTrigger asChild>
    <Button>Open</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit Fleet Entry</DialogTitle>
      <DialogDescription>
        Make changes to the aircraft record.
      </DialogDescription>
    </DialogHeader>
    {/* form content */}
    <DialogFooter>
      <DialogClose asChild>
        <Button variant="outline">Cancel</Button>
      </DialogClose>
      <Button>Save</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
```

**Sub-components:** `Dialog`, `DialogClose`, `DialogContent`, `DialogDescription`, `DialogFooter`, `DialogHeader`, `DialogOverlay`, `DialogPortal`, `DialogTitle`, `DialogTrigger`

***

### Forms

#### Input

Single-line text input.

```tsx theme={null}
import { Input, Label } from "@skyvexsoftware/stratos-sdk";

<div className="flex flex-col gap-1.5">
  <Label htmlFor="callsign">Callsign</Label>
  <Input id="callsign" placeholder="BAW123" />
</div>
```

#### Textarea

Multi-line text input.

```tsx theme={null}
import { Textarea, Label } from "@skyvexsoftware/stratos-sdk";

<div className="flex flex-col gap-1.5">
  <Label htmlFor="remarks">Remarks</Label>
  <Textarea id="remarks" placeholder="Enter flight remarks..." rows={4} />
</div>
```

#### Select

Dropdown select menu.

```tsx theme={null}
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
  SelectGroup,
  SelectLabel,
} from "@skyvexsoftware/stratos-sdk";

<Select onValueChange={(value) => setUnit(value)}>
  <SelectTrigger className="w-[180px]">
    <SelectValue placeholder="Select units" />
  </SelectTrigger>
  <SelectContent>
    <SelectGroup>
      <SelectLabel>Unit System</SelectLabel>
      <SelectItem value="imperial">Imperial</SelectItem>
      <SelectItem value="metric">Metric</SelectItem>
    </SelectGroup>
  </SelectContent>
</Select>
```

**Sub-components:** `Select`, `SelectContent`, `SelectGroup`, `SelectItem`, `SelectLabel`, `SelectScrollDownButton`, `SelectScrollUpButton`, `SelectSeparator`, `SelectTrigger`, `SelectValue`

#### Combobox

Searchable single-select. Prefer this over `Select` when there are many options — the list filters as you type and scrolls natively.

```tsx theme={null}
import { Combobox } from "@skyvexsoftware/stratos-sdk";

<Combobox
  value={aircraftId}
  onValueChange={setAircraftId}
  options={[
    { value: "1", label: "Boeing 737-800 — VH-VXA" },
    { value: "2", label: "Airbus A320 — VH-XYZ" },
  ]}
  placeholder="Select aircraft"
  searchPlaceholder="Search aircraft…"
  emptyText="No aircraft found"
/>
```

**Props:** `options` (`{ value, label }[]`), `value`, `onValueChange`, `placeholder`, `searchPlaceholder`, `emptyText`, `loading`, `loadingText`, `disabled`, `triggerClassName`, `contentClassName`, `align`, `onOpenChange`. Pass `loading` while options are being fetched to avoid a flickering empty state.

#### RadioGroup

Radio button group for mutually exclusive choices.

```tsx theme={null}
import { RadioGroup, RadioGroupItem, Label } from "@skyvexsoftware/stratos-sdk";

<RadioGroup defaultValue="imperial" onValueChange={setUnit}>
  <div className="flex items-center gap-2">
    <RadioGroupItem value="imperial" id="imperial" />
    <Label htmlFor="imperial">Imperial</Label>
  </div>
  <div className="flex items-center gap-2">
    <RadioGroupItem value="metric" id="metric" />
    <Label htmlFor="metric">Metric</Label>
  </div>
</RadioGroup>
```

#### Slider

Range slider for numeric values.

```tsx theme={null}
import { Slider, Label } from "@skyvexsoftware/stratos-sdk";

<div className="flex flex-col gap-2">
  <Label>Refresh interval: {interval}s</Label>
  <Slider
    min={5}
    max={120}
    step={5}
    value={[interval]}
    onValueChange={([v]) => setInterval(v)}
  />
</div>
```

#### Switch

Toggle switch for boolean settings.

```tsx theme={null}
import { Switch, Label } from "@skyvexsoftware/stratos-sdk";

<div className="flex items-center gap-2">
  <Switch
    id="show-map"
    checked={showMap}
    onCheckedChange={setShowMap}
  />
  <Label htmlFor="show-map">Show map</Label>
</div>
```

***

### Layout

#### Card

Elevated container for grouping related content.

```tsx theme={null}
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
  CardAction,
} from "@skyvexsoftware/stratos-sdk";

<Card>
  <CardHeader>
    <CardTitle>Fleet Status</CardTitle>
    <CardDescription>Aircraft currently available</CardDescription>
  </CardHeader>
  <CardContent>
    <p className="text-2xl font-bold">24</p>
  </CardContent>
  <CardFooter className="text-muted-foreground text-sm">
    Last updated 2 minutes ago
  </CardFooter>
</Card>
```

#### Separator

Horizontal or vertical visual divider.

```tsx theme={null}
import { Separator } from "@skyvexsoftware/stratos-sdk";

<div>
  <p>Section one</p>
  <Separator className="my-4" />
  <p>Section two</p>
</div>
```

#### Tabs

Tabbed content panels.

```tsx theme={null}
import {
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
} from "@skyvexsoftware/stratos-sdk";

<Tabs defaultValue="overview">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="roster">Roster</TabsTrigger>
    <TabsTrigger value="flights">Flights</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">
    <OverviewPanel />
  </TabsContent>
  <TabsContent value="roster">
    <RosterPanel />
  </TabsContent>
  <TabsContent value="flights">
    <FlightsPanel />
  </TabsContent>
</Tabs>
```

#### Popover

Floating panel anchored to a trigger. Use it for lightweight overlays (filters, pickers, info panels); for modal flows use `Dialog`. It's the primitive behind `Combobox`.

```tsx theme={null}
import {
  Popover,
  PopoverTrigger,
  PopoverContent,
  Button,
} from "@skyvexsoftware/stratos-sdk";

<Popover>
  <PopoverTrigger asChild>
    <Button variant="outline">Filters</Button>
  </PopoverTrigger>
  <PopoverContent align="start">
    <p className="text-sm">Panel content</p>
  </PopoverContent>
</Popover>
```

**Sub-components:** `Popover`, `PopoverTrigger`, `PopoverAnchor`, `PopoverContent`

***

### Feedback

#### Badge

Inline status label or tag.

```tsx theme={null}
import { Badge, badgeVariants } from "@skyvexsoftware/stratos-sdk";

<Badge>Active</Badge>
<Badge variant="outline">Pending</Badge>
<Badge variant="destructive">Error</Badge>

// Use the variant helper for non-Badge elements
<span className={badgeVariants({ variant: "secondary" })}>Tag</span>
```

#### Button

Primary interactive element.

```tsx theme={null}
import { Button, buttonVariants } from "@skyvexsoftware/stratos-sdk";

<Button>Primary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
<Button size="sm">Small</Button>
<Button disabled>Disabled</Button>

// Use the variant helper for link elements
<a href="/page" className={buttonVariants({ variant: "outline" })}>
  Go to page
</a>
```

#### Tooltip

Non-interactive contextual hint.

```tsx theme={null}
import {
  Tooltip,
  TooltipTrigger,
  TooltipContent,
  TooltipProvider,
} from "@skyvexsoftware/stratos-sdk";

// Wrap your root (or the relevant section) in TooltipProvider
<TooltipProvider>
  <Tooltip>
    <TooltipTrigger asChild>
      <Button size="icon" variant="ghost">
        <InfoIcon size={16} />
      </Button>
    </TooltipTrigger>
    <TooltipContent>
      <p>This value updates every 30 seconds</p>
    </TooltipContent>
  </Tooltip>
</TooltipProvider>
```

***

## Icons

Import icons directly from `lucide-react` — they're tree-shaken, so only the icons you use land in your bundle:

```tsx theme={null}
import { Plane, Map, Settings, History } from "lucide-react";
```

The shell provides a single React instance to all plugins via the SDK's Vite shim, so `lucide-react`'s own React imports resolve to the same instance — no two-React crashes, no bundle duplication.

<Note>
  Earlier SDK versions exposed `STRATOS_ICONS` (a re-export of lucide's full `icons` object) for dynamic name→component lookup. That export is still available but **deprecated**. For static imports, use `lucide-react` directly. For genuinely dynamic lookup (e.g. icon names from a remote config), `import { icons } from "lucide-react"` gets you the same registry at the cost of bundling the full set (\~60 KB gzipped) into your plugin — prefer a curated static map when you can.
</Note>

***

## Styling Notes

All components use the shell's Tailwind theme tokens automatically. Dark mode is handled for you — use semantic class names like `bg-card`, `text-muted-foreground`, and `border` rather than hardcoded colours:

```tsx theme={null}
<div className="bg-card rounded-lg border p-6">
  <h2 className="text-lg font-semibold">My Section</h2>
  <p className="text-muted-foreground mt-2 text-sm">Description</p>
</div>
```

Key theme tokens:

| Class                         | Usage                                  |
| ----------------------------- | -------------------------------------- |
| `bg-card`                     | Card and panel backgrounds             |
| `bg-muted`                    | Subtle secondary backgrounds           |
| `text-muted-foreground`       | Secondary and supporting text          |
| `border`                      | Standard borders                       |
| `bg-primary` / `text-primary` | Accent colour (configured per-airline) |
