# Looks — a site's whole design, picked per version

> A LOOK is a site's whole design — its frame, its pages, its theme and fonts, its design of every block type — declared in code (normally in a look KIT) and picked per site version at the page desk. Block types and page parts are CONTRACTS (`abstract component`), each look implements them with exactly the contract's parameters, and what staff arrange is stored as the type and its values — so switching a version's look redraws the same content in the new design.

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

## Summary        {#summary}
A store that wants a new design should not need a new app. Write the design as a **look**: the frame around every
page, the front page and the other pages a customer walks through, the theme and fonts, and a design of every block
staff arrange. Install several looks — five shop designs, say — and staff pick one per **version of the site**, at the
page desk: drafted, previewed as a whole site, switched on a date. Orders, stock, customers and everything staff
arranged stay put; only the design changes.

```osy syntax
// a contract — the shape, no design (a contract kit's, or the app's)
[Block("Hero")] public abstract component Hero([Label("Headline")] string title, Picture photo = "");

// a look — one design (a look kit's namespace)
namespace Osysharp.Shop.Looks.Atelier;
look Atelier { Label = "Atelier"; Theme = Gallery; }
component AtelierHero(string title, Picture photo = "") : Hero { render { … } }

// the app — installs looks, names the one it wears until staff choose
app.Look = Atelier;
```

## Signature      {#signature}
```osy syntax
[Block("Label")]                       // optional: a BLOCK TYPE staff place in a region
public abstract component Name(params);   // a contract: parameters, no body

component Design(params) : Name { render { … } }  // a look's design of it — exactly the contract's parameters

look Name { Label = "…"; Hint = "…"; Theme = SomeTheme; }   // in a namespace of its own

app.Look = Name;                       // the look the site wears where a version names none
```

## Description    {#description}

### What is a contract? — `abstract component` {#contract}
An `abstract component` has parameters and no body: it is the SHAPE of something a look draws. With `[Block("…")]` it
is a **block type** — a hero, a quote, a row of products — which staff place in a region and fill in at the desk, exactly
like a block ([Blocks and regions — pages the staff arrange](https://osysharp.com/reference/ui/blocks/)): its parameters are the fields, their types choose the editors, `[Label]`/`[Hint]`/`[Sample]`
name them. Without `[Block]` it is a **part** a page places — the frame around every page, the front page, a listing.

Anywhere a contract is called — a page, a layout, a region's arrangement — the compiler draws the design of the look the
site is wearing, handing on every parameter and every slot.

### What is a design? — `component X(…) : Contract` {#design}
A component that writes `: Hero` is a DESIGN of the contract. It takes exactly the contract's parameters — the same names,
the same types, in the same order — and is refused otherwise, like a class against an interface, naming the difference:

- *"'NightHero' implements Hero, whose 'photo' is a Picture, not a string."*
- *"'NightHero' implements Hero, and leaves out its parameter 'ground'."*
- *"'NightHero' implements Hero, which has no parameter 'moon' — … Something only this look shows is a block of the look's own."*

A design is not a block of its own (the `[Block]` is the contract's, so staff see one "Hero" whichever look draws it),
and a look has one design per contract. A design outside every look is the **default design**: what a look with none of
its own draws, and what an app with no looks draws.

An app may design a PACKAGE's contract in its own source, as a class implements a library's interface — no kit of its
own needed:

```osy syntax
using Osysharp.Site.Looks;

component StoreHero(string title, Markdown words = "", Picture photo = "", Picture second = "", string button = "Shop now",
                    PageLink link = "/", Color ground = Colors.Surface) : Osysharp.Site.Looks.Hero {
  render { Stack(p: 12, bg: ground) { Text(title, fontSize: FontSize.Title); Markdown(words); } }
}
```

The app's design is drawn wherever the contract is placed — by the app's pages, and by the package's own pages and
regions too. It takes the place of the package's design for the same look: an app's design outside every look replaces
the kit's default design, as an app's component shadows a kit's of the same name.

### What is a look? — `look Name { … }` {#look}
A look is everything its NAMESPACE declares: its designs, its regions, its own blocks and the theme it names. So a look
lives in a namespace of its own — a look kit's `namespace Osysharp.Shop.Looks.Atelier;`.

| setting | what it is |
|---|---|
| `Label = "…"` | what staff call it on the desk (its name if left out) |
| `Hint = "…"` | the line under it (the first sentence of its doc comment if left out) |
| `Theme = X` | its theme — served only while the site wears it, under `:root[data-look="atelier"]`, so five looks' palettes live in one app without one taking the others' names ([theme tokens](https://osysharp.com/reference/ui/theming/)); its dark column and its variants (a Christmas palette of this look) come with it |

A **region** the look declares may share its name with another look's: it is ONE arrangement, drawn by each look in its
own design, and what it allows and its default arrangement are the look's. A `[Block]` declared in the look's namespace is
a **look-only block** — drawn only while the site wears that look.

An app with more than one look names the one the site wears until staff choose another — `app.Look = Atelier;` — and is
refused without it. A version's look is `SiteVersion.Look`; the one showing to this browser is `Visitor.Look`, which the
server stamps on the first paint (`data-look` on the page) and `Theme.Look(name)` moves (the PageBuilder kit's `SiteLook()`
does, when a version switches or a member of staff previews another).

```osy title="a florist with two looks of its own" test app=ui-looks
app Florist {
  use Osysharp.Ui;
  use Osysharp.Blocks;
  model "model/**/*.osy";
}

using Osysharp.Blocks;

app.Look = Meadow;

[Principal] public entity Member { [Required, Unique, MaxLength(200)] string Email; }

/// This week's flowers, large, with a line under them.
[Block("Bouquet")]
public abstract component Bouquet([Label("Headline"), MaxLength(80)] string title, [Label("Words under it")] Markdown words = "");

/// The front page, in whichever look the site wears.
public abstract component FrontPage();

[Route("/")]
[AllowAnonymous]
component Front() { render { FrontPage(); } }
```

```osy title="Meadow — pale paper and a green that grows" test app=ui-looks
namespace Florist.Looks.Meadow;

using Osysharp.Blocks;

/// Pale paper and a green that grows.
look Meadow { Label = "Meadow"; Theme = MeadowTheme; }

theme MeadowTheme { Colors { Bg = "#FFFDF5"; Leaf = "#3A7D44"; } }

component MeadowFront() : FrontPage {
  render { Region("front", allow: [Bouquet, Pressed]) { Bouquet(title: "Flowers cut this morning"); Pressed(); } }
}

component MeadowBouquet(string title, Markdown words = "") : Bouquet {
  render { Stack(gap: 2, p: 8, label: "Bouquet") { Text(title, fontSize: FontSize.Title, color: Colors.Leaf); Markdown(words); } }
}

/// A flower pressed between two pages — Meadow's own block.
[Block("Pressed flower")]
component Pressed([Label("Words"), MaxLength(80)] string words = "A daisy from June") {
  render { Text("✿ " + words, p: 4, color: Colors.Leaf); }
}
```

```osy title="Night — near-black paper, the same bouquet" test app=ui-looks
namespace Florist.Looks.Night;

using Osysharp.Blocks;

look Night { Label = "Night"; Theme = NightTheme; }

theme NightTheme { Colors { Bg = "#101014"; Leaf = "#9FD3A8"; } }

component NightFront() : FrontPage {
  render { Box(bg: Colors.Bg, minH: "100vh") { Region("front", allow: [Bouquet]) { Bouquet(title: "Evening bouquets"); } } }
}

component NightBouquet(string title, Markdown words = "") : Bouquet {
  render { Text(title, p: 6, fontSize: FontSize.Title, color: Colors.Leaf); }
}
```

Staff who arranged Meadow's front — their own headline on the bouquet — and switch the version to Night see the same
headline in Night's design. The pressed flower has no design in Night: it stays in the arrangement and is not drawn
while the version wears Night, and comes back with Meadow.

### Switching a version's look — and what will not come along {#switch}
At the desk ([[ui-pages-kit#looks]]) each version names its look. Before a switch, the desk lists everything the new look
has no design for — a look-only block, a type the look does not draw, a region it has no place for — and switches only
when staff say so. Nothing is dropped: the arrangement keeps it, and a later switch back draws it again.

The mechanism is `Osysharp.Blocks`': `SetLook(version, look)` (a look the app has, or "" for the app's), `LookLeavesBehind
(version, look)` (one line per thing that will not come along), `SiteOffers().Looks` and `.DefaultLook`, and
`BlockSpec.EveryLook`/`.Looks` (which looks draw a block).

### How do looks ship as kits? — the three layers {#kits}
A look is normally a KIT, so a store installs designs like any package and a marketplace can offer them. Two contracts:

- **`Osysharp.Site.Looks`** (`kits/site-looks`) — the GENERAL site contract, for any consumer-facing site: `Hero`,
  `PictureWithWords`, `Quote`, `SignUp`, `Banner`, `PhotoGallery`, and around every page `Announcement`, `FooterWords`,
  `FooterLink`, `OpeningHours`, `Address`, `FooterSignUp`.
- **`Osysharp.Shop.Looks`** (inside the shop kit, its types being the shop's data) — the SHOP's: the block types
  `ProductRow` and `CategoryTiles`, and the parts of a store — `ShopFrame` (with the page inside it), `FrontPage`,
  `ShopSection`, `ListingPage`, `ProductGrid`, `ProductPage`, `NotFound`. The shop kit's plain design of each block
  type — the shop's two and every general one — is the default design. The parts have none: a store that names them
  draws them in a look, so a shop look draws all seven (one it skips is drawn by the store's default look's design).

A look kit draws both (`kits/look-atelier` … `kits/look-studio`, the five designs of the Vall fashion store, and
`kits/look-rail` … `kits/look-loud`, the five of the Second Round second-hand shop), and carries its
fonts in its own `osyrin.lock` — a store that installs it ships them. A look kit carries no data and no logic, and needs
no egress and no secret: it reads what a store's page reads, as the visitor.

So there are three layers, and each answers one question: the **site contract** says what any site has, a **category
contract** (the shop's, today) says what that kind of site has on top, and a **look** says how all of it looks — it
draws both contracts below it. Building one from an empty kit — the manifest, the theme, a design of each part, the
fonts, a block of its own, seeing it in a store, and where a café's contract would sit beside the shop's — is
[Building a look — from an empty kit to a design a store can wear](https://osysharp.com/reference/ui/building-a-look/).

### What the compiler refuses {#refusals}
- a design whose parameters are not the contract's — a name, a type, one too many or too few, named;
- `: X` where X is not a contract; two designs of one contract in one look, or two outside every look;
- `[Block]` or `[Route]` on a design; an `abstract component` with a body, or implementing something itself;
- a look outside a namespace of its own, two looks of one name, a look naming a theme nobody declares, two looks
  sharing a theme, a setting other than `Label`/`Hint`/`Theme`;
- an app with several looks and no `app.Look`, and an `app.Look` naming a look the app does not have;
- an app's own design of a package's contract (see [the warning above](#design));
- two regions of one name within one look.

## See also   {#see-also}
- [Building a look — from an empty kit to a design a store can wear](https://osysharp.com/reference/ui/building-a-look/) — building a look kit, step by step.
- [Blocks and regions — pages the staff arrange](https://osysharp.com/reference/ui/blocks/) — blocks, regions, and what a value may be.
- [The PageBuilder kit — the desk staff arrange the site at](https://osysharp.com/reference/ui/pages-kit/) — the desk: versions, the look each wears, the preview.
- [The site's frame — a menu, a strip and a footer staff change](https://osysharp.com/reference/ui/site-frame/) — the frame's menu, strip and footer, which a look's frame declares.
- [[ui-theming#variants]] — a theme's seasonal variants, which a look's theme has too.
