Component Library

The set of Astro and Vue components that ship with ShockStack — what they do, when to reach for them, and how to build your own.

Component library

ShockStack ships two tiers of components:

  • Astro content components (src/components/content/) — zero-JS presentational primitives. Safe to drop into MDX.
  • Vue UI components (src/components/ui/) — interactive islands built on reka-ui primitives.

Everything reads from design tokens, so components look correct in every theme without per-component work.

Content components (Astro)

Import from src/components/content/ in .astro or .mdx files.

<Alert>

Status callout — info, success, warning, error. Dismissible variant loads a small inline script.

<Alert variant="warning" title="Heads up" dismissible>
  Rotate this secret before deploying.
</Alert>

Props: variant (info | success | warning | error), title?, dismissible?.

<Badge>

Inline label. Supports the full accent palette and three visual modes.

<Badge color="cyan" variant="subtle" size="sm">beta</Badge>

Props: color (accent name or neutral), variant (solid | subtle | outline), size (sm | md).

<Avatar>

Profile image with initials fallback and optional gradient background.

<Avatar name="Ada Lovelace" size="md" gradient="purple-pink" />

Props: src?, alt?, name? (used for initials), size (xsxl), gradient?.

<Kbd>

Keyboard shortcut indicator. Automatically renders ⌘ on macOS and Ctrl elsewhere.

<Kbd keys={["Mod", "K"]} />

Props: keys: string[], size? (sm | md).

<ProgressBar>

Linear progress or indeterminate loader.

<ProgressBar value={62} label="Uploading" showValue />
<ProgressBar indeterminate label="Processing…" />

<Skeleton>

Shimmer placeholder for loading states. Respects prefers-reduced-motion.

<Skeleton shape="text" lines={3} />
<Skeleton shape="circle" width="3rem" height="3rem" />

<TerminalTabs>

Multi-OS command blocks (Linux / macOS / Windows). Selection persists across the page.

<TerminalTabs
  title="Install"
  variants={{
    linux: { lines: [{ kind: "command", text: "pnpm install" }] },
    mac: { lines: [{ kind: "command", text: "pnpm install" }] },
    windows: { lines: [{ kind: "command", text: "pnpm install" }] },
  }}
/>

Marketing primitives

Used on landing pages; also available to you:

  • <FeatureCardGradient> — gradient-bordered feature card with icon slot.
  • <StatsCard> — numeric stat with gradient label.
  • <TestimonialCard>, <PricingCard>, <UseCaseCard> — specific page patterns.

Vue UI components (interactive)

Import from src/components/ui/. These are the islands — add client:load / client:idle when dropping them into .astro.

ComponentBuilt onUse for
AccordionPanel.vuereka-ui AccordionGrouped collapsible sections
TooltipHover.vuereka-ui TooltipHover hints
ConfirmDialog.vuereka-ui AlertDialogConfirm before destructive actions
DestructiveDialog.vuereka-ui AlertDialogTyped-confirmation (“delete my data”)
SheetPanel.vuereka-ui DialogSide sheets / slide-overs
OperationQueue.vueToast-style queue for async ops
ThemeToggle.vueThe theme picker in the header
PagesMenu.vue, UserMenu.vue, MobileNav.vuereka-ui Menu / DialogHeader navigation
AuthForm.vueSign-in / sign-up form, wired to Better Auth

Variant pattern

Components use class:list with a shared base class plus modifier classes. No cva runtime — the pattern is purposefully simple and Tailwind-friendly.

---
interface Props {
  variant?: "primary" | "secondary";
  size?: "sm" | "md" | "lg";
}
const { variant = "primary", size = "md" } = Astro.props;
---

<button class:list={["btn", `btn-${variant}`, `btn-${size}`]}>
  <slot />
</button>

<style>
  .btn {
    border-radius: var(--radius-lg);
    transition: background-color 0.15s ease;
  }
  .btn-primary {
    background-color: var(--color-accent-purple);
    color: var(--color-bg-primary);
  }
  .btn-sm {
    padding: 0.35rem 0.85rem;
    font-size: 0.875rem;
  }
</style>

Adding your own component

  1. Choose a tier. Static & no state → Astro in content/. Interactive & stateful → Vue in ui/.
  2. Consume tokens. Reference CSS custom properties (var(--color-bg-secondary)) or semantic Tailwind utilities (bg-bg-secondary). Never hex.
  3. Follow the variant pattern above; avoid a runtime class-variance library.
  4. Scaffold with the CLI: pnpm ss add component MyThing creates a skeleton in frontend/src/components/ with a props interface.

See also

  • Design tokens — the values your component will consume.
  • Theming — verify your component works across themes.
  • Frontend guide — when to choose an island vs. a static component.