# Looks for business apps — start from a finished design and make it yours

> Osysharp.Ui.Looks ships seven finished looks for any app built on the UI kit — Ledger, Relay, Civic, Studio, Signal, Folio and Tempo — each a whole design: palette in light and dark, the faces it ships, density, corners, elevation and the colours of the app's chrome. A look is a BASE: derive from the closest (`theme Brand : Looks.Ledger { … }`), override what makes it your brand's, and check it still reads with `Assert.Contrast`.

<!-- id: ui-looks-kit · area: ui · stability: stable · html: https://osysharp.com/reference/ui/looks-kit/ -->

## Summary        {#summary}

An app on the UI kit already works and reads well. What it does not have yet is a **point of view**: every app on the
kit's own floor looks like every other one. `Osysharp.Ui.Looks` is seven finished points of view to start from — each a
complete design for a business app, built and photographed over the same specimen of tables, forms, records, boards,
inboxes, dashboards, settings, dialogs and empty states, light and dark, wide and on a phone.

| look | for | what it is |
|---|---|---|
| **Ledger** | finance, billing, accounting, procurement | white paper and hairline rules, headings at an ordinary weight, every figure in a mono that lines up, a Prussian-navy accent |
| **Relay** | support desks, operations, dispatch, developer tools | the densest look; graphite that is as good dark as light, a mono for every time and id, signal orange |
| **Civic** | healthcare, public services, anything anyone may have to use | large type in Atkinson Hyperlegible, controls you cannot miss, square corners, bold headings, a black focus ring |
| **Studio** | CRM, agencies, recruiting, project tools | Figtree, ink-black actions, soft grey chrome, round corners and pill tags, colour kept for people and states |
| **Signal** | analytics, reporting, dashboards, growth tools | an ink rail beside a light page, figures set tall in a condensed face, cards without an outline, ultraviolet |
| **Folio** | content sites: guides, articles, a programme, an organisation's pages | white paper and ink, words in Source Serif 4 at 18px, headings in a heavy Epilogue, solid ink rules instead of grey boxes, a deep teal |
| **Tempo** | booking: classes, appointments, rooms, courts, tables | every time in Azeret Mono down a column, Albert Sans for the words, free slots as square tickets, a magenta for the time you chose |

**A look is a base, not a final pick.** The app derives a theme from the closest one and overrides what makes it its
own — every token it does not override comes from the look:

```osy title="Studio, made a recruiting firm's own: its plum accent and squarer tags" run app=ui-looks-kit
app Hiring {
  use Osysharp.Ui;
  use Osysharp.Ui.Looks@0;
  model "model/**/*.osy";
}

using Osysharp.Ui.Looks;

theme Brand : Looks.Studio {
  Colors {
    Primary   = Modes.Of(light: Palette.From("#6B2D5C"), dark: Palette.From("#E7B8D9"));
    OnPrimary = Modes.Of(light: "#FFFFFF", dark: "#2A0F23");
  }
  Radius { Tag = "6px"; }
}

[Route("/")] [AllowAnonymous]
component Home() {
  render {
    Stack(gap: 4, p: 6) {
      PageHead("Candidates", subtitle: "12 in the pipeline");
      Card("Shortlist") { Badge("Interviewing", tone: Tone.Primary); }
    }
  }
}
```

## Description    {#description}

### Which look is closest? — `osy kit looks`   {#choose}

`osy kit looks` lists every look in scope — each one's purpose, the faces it sets, its accent in light and dark, its
density and its corners — and the two lines that put one on:

```console
$ osy kit looks
Looks — 7 finished designs for an app on the UI kit. A look is a BASE: pick the closest, derive from it, …
  Looks.Ledger — white paper, hairline rules, figures in a mono that lines up, a Prussian-navy accent. …
    faces Wix Madefor Text · Wix Madefor Display · DM Mono  figures in DM Mono  accent #1F4E89 / #86B6F2  density step 0.235rem  corners 4px
  …
```

Pick by what the app is FOR, not by colour: the colour is the first thing you will change, and the density, the type
and the way the page is built are what the look really decides.

### Which looks are made for my kind of app? — `osy kit looks <category>`   {#categories}

Every look names the categories of app it is a starting point for, and `osy kit looks <category>` lists only those.
The categories are a closed set: `shop`, `booking`, `internal-tool`, `content-site` and `dashboard`. A word a builder
would type for one ("dashboards", "admin", "blog", "appointments") lands on it, and any other word is refused with the
five names.

```console
$ osy kit looks booking
Looks for booking — an app people book a time in: classes, appointments, rooms, courts, tables.
  Looks.Civic — plain and certain: large type in Atkinson Hyperlegible, controls you cannot miss, square corners, …
  Looks.Studio — the record desk: Figtree, ink-black actions, soft grey chrome, round corners and pill tags, …
  Looks.Tempo — the timetable on the wall: times set in Azeret Mono down a column, the words in Albert Sans, …
Put one on: derive the app's theme from it: `theme Brand : Looks.X { … }`
```

| category | its looks | how it is put on |
|---|---|---|
| `shop` | the shop's look kits (`Osysharp.Shop.Looks.*`: Atelier, Drop, Rail, …) | `use Osysharp.Shop.Looks.<Name>@0;`, then staff pick it per version of the site ([Looks — a site's whole design, picked per version](https://osysharp.com/reference/ui/looks/)) |
| `booking` | Tempo, Civic, Studio | derive the theme |
| `internal-tool` | Ledger, Relay, Civic, Studio | derive the theme |
| `content-site` | Folio | derive the theme |
| `dashboard` | Signal, Relay, Ledger | derive the theme |

Two builds of the same kind of app that start from the same look arrive at the same page, so **choose by the brief,
not by the order printed**, and make the look the brand's own before the first screen ([[ui-design#concept]]). A look
names its categories in its own doc comment, on a line of its own: `/// Categories: booking, internal-tool.`

### Can I try one without editing anything? — `--theme Looks.X`   {#try}

Every verb that compiles takes a look's name: the app compiles wearing it, and nothing in the project changes.

```console
$ osy compile --theme Looks.Relay              # the browsable app, in Relay
$ osy test --pixels --theme Looks.Civic        # every UI test photographed in Civic
```

So the honest way to choose is to look: photograph your own pages in two or three looks and keep the one that fits.

### How do I make it my own? — derive, then override   {#derive}

`theme Brand : Looks.Ledger { … }` is a theme that starts as everything Ledger declares. What you write inside it
replaces Ledger's value for that token — light and dark together, so an override written as one value is that value in
both modes. Change, in this order, only what makes the brand:

1. **The accent** — `Primary` and `OnPrimary` (a `Palette.From` seed for each mode), and `Focus` if your accent is too
   light to ring a control on white.
2. **The display face** — `Font { Display = "…"; }` with a face you ship (`osy font add`), for page titles and figures'
   headings; keep the look's text face unless the brand has its own.
3. **Corners** — `Radius { Sm; Md; Lg; Tag; }` if the brand is rounder or squarer than the look.

Leave the rest. A look's surfaces, ink steps, chrome and status colours were chosen together and contrast-checked
together, and they keep working only as a set.

### What does a look set? — the contract   {#contract}

Every look declares the same tokens, so you can derive from any of them and override the same names:

| group | tokens |
|---|---|
| `Colors` — the page | `Bg` `OnBg` `Surface` `OnSurface` `Elevated` `Sunken` `Muted` `Border` `CardLine` `TextSecondary` `TextMuted` `BorderDanger` `Scrim` |
| `Colors` — action and state | `Primary` `OnPrimary` `Focus` `Success` `Danger` `Warning` `Waiting` |
| `Colors` — the chrome (rail and bars) | `Chrome` `OnChrome` `ChromeMuted` `ChromeFaint` `ChromeHover` `ChromeSunken` `ChromeElevated` `ChromeLine` `ChromeCurrent` `OnChromeCurrent` `ChromeFocus` |
| `Font` | `Sans` (text) · `Display` (titles) · `Mono` · `Figure` (statistics and number columns) |
| `FontSize` · `FontWeight` | `Caption` `Label` `Body` `Subhead` `Heading` `Title` · `Regular` `Medium` `Semibold` `Bold` `Headings` |
| `Radius` · `Shadow` | `Sm` `Md` `Lg` `Tag` · `Raised` `Floating` `Deep` |
| `Space` · `Length` | `Step` (the density) · `ControlSm` `ControlMd` `ControlLg` `Touch` `TouchDense` |

Each look also colours the chart kit (`Series1`, `Series2`, `ChartSurface`, …) to match.

### Does it still read after my changes? — `Assert.Contrast`   {#check}

A look ships with every words-on-ground pair checked at WCAG AA in light and dark. After you override its accent, run
the same checks against your own theme — they read the RESOLVED tokens, so they need no browser:

```osy title="the pairs an accent change can break, in both modes" run app=ui-looks-kit
[Test]
void the_brand_still_reads() {
  Assert.Contrast("Colors.OnPrimary", "Colors.Primary");
  Assert.Contrast("Colors.Primary.Text", "Colors.Surface");
  Assert.Contrast("Colors.OnPrimary", "Colors.Primary", mode: "dark");
  Assert.Contrast("Colors.Focus", "Colors.Surface", 3, mode: "dark");
}
```

The package's own specimen carries the whole list — every pair the kit paints — in `tests/contrast.test.osy`; copy it
into your app's tests.

### Which arrangement goes with which look?   {#shells}

A look colours whatever the app is built as; it does not build it. But each look was drawn for a way of working, and
names the ARRANGEMENT it pairs with by default — `osy kit looks` prints it on its "arranged as" line:

| look | arrangement | navigation | how a change is kept |
|---|---|---|---|
| Ledger | the document desk — a record as tabs that go deeper, the chosen item as paper | `TabbedShell` (top) | `SaveBar` |
| Relay | the workbench — a dense table, the opened row docked right, a live log below | `WorkbenchShell` (split) | `SaveActions` |
| Civic | the flow — one plain question at a time, a check of every answer | `FocusedShell` (none) | "Save and continue" |
| Studio | the record desk — a list with the record beside it, an assistant a press away | `SidebarShell` | `AutoSave` |
| Signal | the command centre — a workspace of cards a person arranges | `RailShell` (marks) | `SaveActions` |

Any app may take any arrangement in any look — they are ordinary kit components. [Arrangements — five ways to build a whole app, and which look wears each](https://osysharp.com/reference/ui/arrangements/) shows all five
with a compiled example each.

## See also       {#see-also}
- [theme tokens](https://osysharp.com/reference/ui/theming/) — tokens, groups, light and dark, and deriving a theme (`#derive`)
- [compiling with a different theme](https://osysharp.com/reference/ui/theme-override/) — `--theme <file or look>`: dress an app in a theme it does not declare
- [Theme assertions — does the app really look the way the theme says?](https://osysharp.com/reference/testing/theme/) — `Assert.Token`, `Assert.Font` and `Assert.Contrast`
- [Designing an app that looks designed — direction, type, colour, composition and motion](https://osysharp.com/reference/ui/design/) — the design method a look is the first step of
- [Arrangements — five ways to build a whole app, and which look wears each](https://osysharp.com/reference/ui/arrangements/) — the five arrangements, and which look pairs with each
- [App shells](https://osysharp.com/reference/ui/shell/) — the shells a look colours
