# Facts

> Information about one thing as a key/value table: what each fact is on the left, its value on the right, one line per fact with a rule under it, and whatever belongs beside the value — a status chip, a mark, a small button — in the fact's block. On a phone the label sits over its value.

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

## Summary        {#summary}

Where a card would otherwise hold lines of `"Label: value"` prose, give each fact its own line. A state reads as a chip
beside its value rather than as a word in a sentence:

```osy title="a server's details as a table" test app=ui-facts
enum ServerState { Running, Stopped }

class Server {
  public string Name;
  public string Engine;
  public int UsedGiB;
  public int SizeGiB;
  public ServerState State;
}

[Route("/server")] [AllowAnonymous]
component ServerPage() {
  Server server = new Server { Name = "db-1", Engine = "Postgres 16", UsedGiB = 63, SizeGiB = 200, State = ServerState.Running };
  render {
    Stack(gap: 3, p: 6) {
      Card(server.Name) {
        slot actions { Badge(server.State.Label, tone: server.State == ServerState.Running ? Tone.Success : Tone.Warning); }
        Facts(label: "About this server") {
          Fact("Engine", value: server.Engine);
          Fact("Storage", value: $"{server.UsedGiB} of {server.SizeGiB} GiB", hint: "As its provider stated it.");
          Fact("State") { Badge(server.State.Label, tone: Tone.Success); }
        }
      }
    }
  }
}
```

## Signature      {#signature}

```osy syntax
Facts(string label) { Fact(…); … }
Fact(string label, string value = "", string hint = "") { /* beside the value: chips, a mark, a button */ }
```

## Description    {#description}

### How do the values line up?   {#alignment}

Every `Fact` is a grid of the same two tracks — the label's, about a third of the width, and the value's — so the values
line up down the table as a header's columns line up over its rows. On a phone it is one column, the label over its
value.

### What goes in the block?   {#block}

What belongs beside the value: a `Badge` for its state, a provider's mark, a link, a small `Button`. The value and the
block sit on one line and wrap together. Leave `value` empty when the block says it all (`Fact("Enrollment") {
Badge("Approved", tone: Tone.Success); }`).

### A figure the app does not have   {#missing}

Say so in words — `value: "not reported"` — rather than leave the value empty: an empty value is a line that promises a
figure and shows nothing.

### How do I read it in a test?   {#test}

Each line is a named group, so a value is read through its label: `Assert.Visible("Postgres 16", within: "Engine")`.
`Facts(label)` names the whole table the same way. It is required: it is the table's only accessible name.

## See also       {#see-also}

- [control — foreign UI controls (charts, grids, maps)](https://osysharp.com/reference/ui/controls/) — `Card`, `Badge` and the rest of the kit
- [SettingsArea — an app's settings: sections, explicit save and discard, undo, who changed what](https://osysharp.com/reference/ui/settings/) — the same aligned layout for the fields a person changes
