Frontend pages and layout
All UI visuals and interactions also follow the design spec (tokens, component semantics, three states, copy, anti-patterns).
ToolShell
Section titled “ToolShell”Wrap every tool page in @/components/tool/ToolShell; it provides a page header
(title / description / action buttons) and a full-width content area:
<template> <ToolShell title="My tool" description="Description"> <template #actions> <Button>Action</Button> </template>
<!-- content fills the width --> </ToolShell></template>- Props:
title,description - Slots:
actions, default
Wrap every module in Panel
Section titled “Wrap every module in Panel”Every functional module on a page (settings / input / output / result / list) must be wrapped in
@/components/tool/Panel (frame + header-bar title + top-right actions + body). Never expose a module
on the page, and never nest a card inside a Panel — previews, tables and the like carry no frame of
their own; the frame belongs to the Panel.
<Panel title="Input"> <template #actions> <Button size="sm" variant="ghost"><Trash2 class="size-3.5" />Clear</Button> </template> <!-- body defaults to space-y-3 p-4; override with body-class for full-bleed --></Panel>- Header title
text-xs font-medium text-muted-foreground; action buttonssize="sm", iconssize-3.5. - Error bars use
rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive.
Lay out with the native grid
Section titled “Lay out with the native grid”Centered columns and splits use the native Tailwind grid directly (grid grid-cols-12 +
col-start-* / col-span-*). Do not invent a custom grid, and do not use an mx-auto max-w-*
centered container.
<ToolShell title="My tool" description="Description"> <div class="grid w-full grid-cols-12 gap-4"> <div class="col-span-12 lg:col-start-3 lg:col-span-8"> <!-- centered 8 columns; full width below lg --> </div> </div></ToolShell>Common steps:
| Situation | Classes |
|---|---|
| Full-width table | none (full width by default) |
| Wide content | col-span-10 |
| Mixed | col-span-8 |
| Forms / settings | md:col-start-4 md:col-span-6 |
Empty / loading / error states
Section titled “Empty / loading / error states”Use EmptyState / LoadingState / ErrorState from @/components/native; the standard usage is in
the “page template” tool (hello-world/frontend/views/TemplateTool.vue). Do not invent your own
three-state styles; keep them consistent across the app.