Krizaka UI
Krizaka UI
Foundations

Frames, layouts and templates

Which frame, layout or template to start from, on the web, on a phone and in a Mac window, and at which size class.

A screen of a Krizaka product starts from one frame and a few layouts, chosen by the room it is given, not by the device it runs on. A tablet in split view is a compact room; a phone in landscape can be a regular one. Every layout below measures the width it receives and decides from that — so a rotation, a split view or a resized window just works.

Size classes

ClassWidth of the roomTypical roomsColumns by default
Compactunder 600 pta phone in portrait, a split-view sliver1
Regular600 to 839 pta large phone in landscape, a small tablet2
Expanded840 pt and morea tablet, a Mac window3 or more

On the phone, Grid and Columns read the width of their own container (sizeClassOf(width)); useSizeClass() reads the window's. A cell is never narrower than minItemWidth, and that minimum grows with the system's text scale: at 200 % text a card that held two per row on a phone stacks into one, so no number is cut. They use no physical edge, so right-to-left needs nothing.

Which one to start from

You buildOn the webOn a phoneIn a Mac window
The signed-in app of a productAppFrame — rail (a tab bar on a phone), top bar, account menuScreen + TabBarDesktopWindow
A console with grouped sections and shortcutsAppShell—AppShell with desktop
A list and the item open from itSplitViewListDetail — one pane, or both when the room holds themDesktopWindow (list · content · inspector)
A dashboardDashboardLayoutthe dashboard template: stat strip in a Grid, then a listDesktopWindow
A form in stepsStepper above a formFormFlowa Dialog with Stepper
SettingsSettingsLayoutthe settings home template (SettingsGroup, SettingsRow)a DesktopWindow pane
Nothing to show, a failure, no networkEmptyState, ErrorPageStateScreen, OfflineBannerEmptyState
A first launchProductPageOnboarding—

The signed-in frame (web)

One frame for every product, so a person who uses two of them finds the same things in the same places:

  • The account menu is fixed: identity, Profile, Settings, Billing (only for a product that sells), Administration (only for an admin), then Language and Theme, then Sign out. Settings is one entry that lands on the settings home.
  • A place is on the rail or under the avatar, never both. A section with the id of an account link leaves the rail.
  • Preferences live in the menu, not in the header: a phone's header has no room for them.
  • The public bar is flat: How it works · Pricing · Docs · Download, four links at most (publicBarLinks), and the words are the shared vocabulary (navWords: Docs, Terms / Conditions d'utilisation, Settings / Réglages).

A phone's screens

Every phone template sits on Screen: the header keeps clear of the status bar, the footer of the home indicator, the content rises with the keyboard (keyboard) and refreshes on a pull (onRefresh). The templates are listed by what they are for on the templates page.

A Mac window

DesktopWindow is the window of a Tauri app: a sidebar, the content and an inspector, resizable (drag a divider, or focus it and use the arrows) and collapsible (⌘B, ⌘I). The toolbar is the drag region and clears the traffic lights (--kz-titlebar-inset, --kz-traffic-lights-inset); the density is the desktop's and the focus ring the macOS halo. Write the window's commands once with useDesktopCommands: the page answers the keys and the native menu bar gets the same ones through setNativeMenu of @krizaka/app-desktop.

const { menus, handlers } = useDesktopCommands([
  { id: "view.sidebar", menu: "View", label: "Hide sidebar", shortcut: "mod+b", run: toggleSidebar },
]);
useEffect(() => { void setNativeMenu(bridge, { labels, menus }, handlers); }, [menus, handlers]);

On this page