# Portal layout conventions (Yimaru / Fortune)
Shared shell patterns for list, detail, and create pages.
**Workspace:** `/Users/kirukib/Desktop/Yaltopia Project/Gishen-B2B`
## Components
| Piece | Path | Role |
|-------|------|------|
| `PageShell` | `src/components/layout/page-shell.tsx` | Full-width page header + content; optional `breadcrumb` |
| `DetailPageLayout` | `src/components/layout/detail-layout.tsx` | Detail wrapper; **breadcrumbs on by default** |
| `Breadcrumbs` / `Bc` | `src/components/layout/breadcrumbs.tsx` | Fortune-style trail; locale links via `@/i18n/routing` |
| `StatCard` / `StatCardGrid` | `src/components/layout/stat-card.tsx` | Flat MakerSys metrics (thin border, brand mint icon well) |
| `TablePanel` | `src/components/table/table-panel.tsx` | Flat white panel (`rounded-xl`, thin border, no shadow) wrapping toolbar + table |
| `TableToolbar` | `src/components/table/table-toolbar.tsx` | In-panel search / filter strip (hairline bottom) |
| `DataTable` | `src/components/table/data-table.tsx` | Column-driven table inside `TablePanel` |
| Table primitives | `src/components/ui/table.tsx` | Yimaru / Fortune density: muted uppercase headers, `px-4` cells, mint hover |
## Breadcrumbs API
```tsx
import { Breadcrumbs, Bc } from "@/components/layout/breadcrumbs";
import { PageShell } from "@/components/layout/page-shell";
import { DetailPageLayout } from "@/components/layout/detail-layout";
// Detail — breadcrumbs default true
…
// Create / nested — opt in
…
// Custom trail (tests / one-offs)
```
### Labels
- Static paths and dynamic parents map to `bc.*` keys in `src/messages/en.json` + `am.json`.
- Path map lives in `PATH_LABEL_KEYS` / `DYNAMIC_PARENT_KEYS` inside `breadcrumbs.tsx`.
- To extend: add a path key → `bc` message key, then Amharic/English strings.
## When to use what
| Surface | Stats | Tabs | Breadcrumbs | Width |
|---------|:-----:|:----:|:-----------:|-------|
| List dashboards | ✓ metric strip | — | off | full |
| Detail | metrics + sections | shadcn `Tabs` (line) | on | full |
| Create / import / nested settings | — | optional | on | full-width form card (no `max-w-*` unless interaction needs it) |
## List tables
Use the shared panel pattern so every list matches MakerSys / Yimaru:
```tsx
import { TablePanel } from "@/components/table/table-panel";
import { TableToolbar } from "@/components/table/table-toolbar";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
}
>
```
Conventions:
- **Panel:** `rounded-xl`, `border-border`, white `bg-card`, **no shadow** — do not wrap tables in padded `Card` / `CardContent`.
- **Header row:** muted background, compact uppercase labels (`text-[11px]`, tracking), `px-4`.
- **Body:** comfortable `py-4` rows, mint-tinted hover, last row border removed.
- **Empty / loading:** centered `h-28` empty cell or `TablePanel` `loading` state.
- **Mobile:** horizontal scroll via the table container (`overflow-x-auto`).
- **Detail embeds:** prefer `DetailTableSection` (same panel chrome) with flush table primitives.
## Tabs
Use `@/components/ui/tabs`. Default `TabsList` variant is **line** (Yimaru/Fortune underline). Keep 2–4 sections max.
```tsx
const tTabs = useTranslations("tabs");
{tTabs("profile")}
…
```
Labels live under root `tabs.*` in `en.json` / `am.json` (`profile`, `entitlement`, `dependants`, `clinical`, `rules`, `perks`, `summary`, `errors`, `breakdown`, `contract`, `people`, `spend`, `info`, `basics`). Prefer `useTranslations("tabs")` so missing keys never render as nested `tabs.tabs.*`.
## Related docs
- [i18n.md](i18n.md) — message files
- [INDEX.md](INDEX.md) — feature → route map