Skip to main content

Style guide

Every element the theme styles, on one page. Use it to check a change against the whole surface rather than the page you happened to be editing.

Headings

Heading one

Heading two

Heading three

Heading four

Heading five
Heading six

Text

Body copy is IBM Plex Sans at 15px with a 1.6 line height. Bold resolves to weight 500, because the type scale has no weight above it — there is no 600 or 700 anywhere in Norn. Italic is a real italic cut, not a synthesised oblique. Inline code is IBM Plex Mono, one step down, on a raised surface with a hairline border.

Links look like this and underline on hover. A link with code inside keeps the link colour.

Press K to search, C to create an issue, J and K to move the cursor.

A blockquote sits behind a two-pixel rule in --line-strong. It carries secondary ink, so it reads as an aside rather than as emphasis.


Lists

  • Unordered items sit on a tight rhythm
  • Nested lists inherit it
    • Second level
    • Second level
  • Back to the first level
  1. Ordered lists are used for sequences
  2. Upgrade steps, install steps, request flows
  3. Anything where the number carries meaning

Admonitions

note

The default. A neutral rule in --ink-400, for a remark that does not change what you would do.

info

Cyan, the same hue as the focus ring. Context worth having.

tip

Green. A better way to do the thing you are already doing.

warning

Amber. Something that will bite if ignored.

danger

Red. Data loss, lockout, or an irreversible action.

Code

internal/service/issues.go
func (s *service) Create(ctx context.Context, in entity.NewIssue) (*entity.Issue, error) {
if err := in.Validate(); err != nil {
return nil, err
}

var created *entity.Issue
err := s.tx.WithTx(ctx, func(ctx context.Context) error {
issue, err := s.issues.Create(ctx, in)
if err != nil {
return err
}
created = issue
return nil
})

return created, err
}

Line highlighting marks the line that matters:

web/src/lib/api/index.ts
import createClient from 'openapi-fetch';
import type {paths} from './dashboard.gen';

export const api = createClient<paths>({baseUrl: '/v1'});

Shell, without a title:

make gen && make wire
go build ./...

Tabs

curl https://norn.example.com/v1/accounts/me \
-H "Authorization: Bearer $NORN_TOKEN"

Tables

Headers are mono, uppercase, and tracked out — the same treatment the application gives a column header. Rows separate on --line-subtle and lift on hover.

TokenValueUsed for
--paper-0#0f1116Page background
--paper-1#14171dCards, sidebar, code blocks
--paper-2#1a1e25Popovers, inline code
--ink-900#e8ebf2Headings and primary fill
--ink-800#d3d8e2Body copy
--ink-500#7e8698Muted copy
--line-subtle#1c2028Row separators
--line-default#262b34Component borders
--line-strong#384050Inputs, raised edges
--ring#35b7d6Focus ring

Details

What is in a collapsed block

Anything a page can hold — prose, code, another table. It is closed by default, so it is the right home for the case that only some readers need.

norn jobs --help

Images

An image picks up a hairline border and the standard five-pixel radius, so a screenshot sits on the page the same way a card does.

The Norn mark