Skip to main content

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.

The SDK re-exports a curated set of shadcn/ui 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:
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.
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.
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.
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.
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.
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

RadioGroup

Radio button group for mutually exclusive choices.
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.
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.
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.
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.
import { Separator } from "@skyvexsoftware/stratos-sdk";

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

Tabs

Tabbed content panels.
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>

Feedback

Badge

Inline status label or tag.
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.
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.
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:
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.
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.

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:
<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:
ClassUsage
bg-cardCard and panel backgrounds
bg-mutedSubtle secondary backgrounds
text-muted-foregroundSecondary and supporting text
borderStandard borders
bg-primary / text-primaryAccent colour (configured per-airline)