Krizaka UI
Krizaka UI
Fondations

Navigation de la famille

Une seule barre pour chaque site et produit Krizaka : ce qui est commun, ce qui est propre à chaque produit, le sélecteur de langue, le contrôle.

A visitor who has seen one Krizaka bar knows them all. The bar is custom where the product needs it, and always recognisably Krizaka: the structure, the components and the behaviours are shared; the brand and the section names belong to the product. Nothing is hand-made — every bar is NavBar, and the language is always the LanguageSwitch.

What is shared

The rule
StructureLeft: the product's mark and name. Centre: the sections. Right: GitHub · theme · language · Sign in · the one primary action.
Left, in orderMark and name · Product ▾ · Platforms ▾ (only when there is more than one platform) · Docs · Pricing when it exists. Four entries at most.
NeverA lone entry that belongs to a group (« Mobile », « Mac », « Demo » on their own), a dead link, a version chip in the bar, a family switcher on a product site.
ComponentsNavBar.Root / Brand / Items / Menu / MenuLink / Link / Actions / Mobile, ThemeToggle, Button (variant="primary" for the primary action).
Three or fewerA section of three links or fewer stands in the bar as plain links (the current one marked) — no hidden list for three entries. NavBar.Menu does it itself (inlineUpTo, 3 by default); above three it is a dropdown. On a phone the panel groups them as usual.
Menu panel28 rem wide (40 rem in two columns), never wider than the page between its gutters, aligned under its trigger and kept inside the page. Icon tile · title · a description of two lines at most.
Hover and focusA quiet light under the item (surface-3), no blue glow; a 2 px focus ring on every control; the current page marked with aria-current="page".
PhoneA disclosure under the bar with the same groups in the same order, then the preferences (theme, language), then the primary action.
KeyboardMenus open on Enter, Space or ↓, ↑ ↓ walk them, Esc closes and returns the focus.

The language switch

One control everywhere: a globe and the code of the language you are in (FR), opening a short list of the languages, each named in its own language — Français, English. Each item is a link with hreflang to the same page in that language (query and hash kept). It replaces the pill that named the other language (« English » on a French page), which said what you were not in and looked different on every site.

import { languagesFor } from "@krizaka/ui/language-switch";
import { NavBar } from "@krizaka/ui/nav-bar";

<NavBar.Language label={t("chrome.languageLabel")} current={locale} languages={languagesFor(pathname)} linkAs={Link} />

Inside NavBar.Mobile the same component renders as a row, in NavBar.MobilePreferences next to the theme. An app's account menu offers the same items (languagesFor) for consistency.

What is the product's own

Per product
BrandThe accent colour of the primary action and the active states comes from the product's tokens (.brand-<product>), never a hard-coded colour.
MarkThe product's animated mark (OrazakaLogo, YomizakaLogo…) beside its name.
SectionsThe names and the links of Product ▾ suit the app: Studios and Packs for Orazaka, How it works and Verify for Yomizaka. Same groups, its own words.
ChipsA status chip (DEV, « In development ») when the site is not released — in the bar's badge, not as a link.
ActionsUsing the app is the primary action (ProductBarActions: « Sign in » while sign-up is closed, « Try » once open). Contact is a link in the footer, not a bar button.

Signed-in apps

The same principle, other components: AppShell with RailNav (a rail on a desktop, a bottom bar on a phone), AppHeader for the name of the screen, and AccountMenu for the person — theme and language in the account menu, the language through the same languagesFor items. A section bar inside an app is NavBar with floating={false}.

The check

A product's repository fails its lint when its bar drifts: a navigation component not imported from @krizaka/ui/nav-bar, or a hand-made language pill (a link whose text is the other language's name). The rule is an ast-grep rule with a ratchet baseline (no-hand-made-nav), so the count of offenders only goes down.

Sur cette page