# 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