New Delhi · September 2026
Preceda

15 0.1 primitives

0.1 primitives

The 0.1 classes, kept so existing markup keeps working. Each is superseded by a 0.2 contract (Button, Link, Field, Tabs, Dialog, DocumentSheet, Citation); use those for new work.

  1. Prose
  2. Running head & label
  3. Citation
  4. Rule
  5. Sheet
  6. Button
  7. Link
  8. Field
  9. Tabs
  10. Focus
  11. Dialog shell

01

Prose

Long reading gets the reading role at a 66-character measure. The page, not the chrome, is the product.

Anatomy

.preceda-prose
Newsreader 17/1.55, ink, max 66ch. Apply to the container of paragraphs.

Variants

Reading

Paper

Our endeavour in this judgment is to ensure that police officers do not arrest the accused unnecessarily and Magistrate do not authorise detention casually and mechanically.

Lamp

Our endeavour in this judgment is to ensure that police officers do not arrest the accused unnecessarily and Magistrate do not authorise detention casually and mechanically.

At 390 px

The measure is a maximum; at 390 px prose fills the column with the page gutter.

390 px

Our endeavour in this judgment is to ensure that police officers do not arrest the accused unnecessarily and Magistrate do not authorise detention casually and mechanically.

Accessibility

  • Keep 17px and 1.55 leading for anything read at length.
  • Text resizes with the user’s root font size; the measure is in ch.

Do

  • Use for judgments, letters and the case page.
  • Use the body role (15/1.55) for the desk draft.

Don’t

  • Set long text in Inter.
  • Widen the measure past 66ch to fill a wide screen.

Usage

HTML
<div class="preceda-prose"><p>…</p></div>
React
<div className="preceda-prose">{paragraphs}</div>

02

Running head & label

Short chrome that orients: the forum above a sheet, a field’s name. Never a paragraph.

Anatomy

.preceda-running-head
Inter 12, 600, tracked uppercase, secondary ink. Above a sheet or section.
.preceda-label
The same face for a form label; pair with htmlFor.
.preceda-type-label
The 0.2 serif small-caps label role, as in the approved screenshots.

Variants

0.1 running head

Paper

Draft instrument

Lamp

Draft instrument

0.2 label role

The form the workspace, case and authorities screens use.

Paper

In the Court of Sessions, Saket

Lamp

In the Court of Sessions, Saket

At 390 px

Running heads truncate before they wrap; keep them to one line at 390 px.

Accessibility

  • Uppercase is CSS only; the source text stays in sentence case for screen readers.
  • Secondary ink passes 4.5:1 on every surface.

Do

  • Keep to a few words.
  • Use a real <label> for fields.

Don’t

  • Use tracked caps for sentences or buttons.

Usage

HTML
<p class="preceda-running-head">Draft instrument</p>
<label class="preceda-label" for="objective">Objective</label>
React
<p className="preceda-running-head">Draft instrument</p>

03

Citation

A citation is an exact character sequence. Mono with tabular figures makes it checkable at a glance.

Anatomy

.preceda-citation
JetBrains Mono 13, tabular figures. Inline in serif text.

Variants

Inline

Paper

Arnesh Kumar v. State of Bihar, (2014) 8 SCC 273

Lamp

Arnesh Kumar v. State of Bihar, (2014) 8 SCC 273

Neutral citation

Paper

2014 INSC 463 · Crl. A. No. 1277 of 2014

Lamp

2014 INSC 463 · Crl. A. No. 1277 of 2014

At 390 px

Citations do not break inside a reporter reference; allow the line to wrap before it.

Accessibility

  • Screen readers read the characters as written; do not substitute symbols for words.

Do

  • Pair with a verification status mark.
  • Keep party names in the serif; only the reference is mono.

Don’t

  • Set case names in mono.
  • Link a citation without saying where it goes.

Usage

HTML
<span class="preceda-citation">(2014) 8 SCC 273</span>
React
<span className="preceda-citation">{citation}</span>

04

Rule

A printed rule groups the record. Prefer a rule and whitespace to a box.

Anatomy

.preceda-rule
A 1px <hr> in the rule colour.

Variants

Rule

Paper

Headnote


Judgment

Lamp

Headnote


Judgment

Accessibility

  • An <hr> is a thematic break; use a CSS border for purely visual separation.

Do

  • Use hairline or rule; ink rules only under a running head.

Don’t

  • Nest bordered containers to separate content.

Usage

HTML
<hr class="preceda-rule" />
React
<hr className="preceda-rule" />

05

Sheet

A sheet is a page lying on the desk: raised paper, a rule, the lightest shadow.

Anatomy

.preceda-sheet
Raised surface, rule border, small radius, sheet shadow. Padding is the consumer’s.

Variants

Sheet

Paper

Draft · 10:53

1. The Applicant is the brother-in-law of the complainant.

Lamp

Draft · 10:53

1. The Applicant is the brother-in-law of the complainant.

At 390 px

At 390 px a sheet runs to the gutters; the numbered document sheet (T5) sets its own margins.

Accessibility

  • Use a landmark or article element when the sheet is a document.
  • The shadow is not a boundary; the rule is.

Do

  • Hold one document per sheet.

Don’t

  • Stack sheets inside sheets.
  • Use a sheet as a card for list items.

Usage

HTML
<article class="preceda-sheet">…</article>
React
<article className="preceda-sheet">{children}</article>

06

Button

One clear next act. The primary act is binding-filled; everything else stays quiet.

Anatomy

.preceda-button
Binding fill, action ink, 40px minimum height.
.preceda-button--quiet
Transparent with a binding rule; binding-tint on hover.

Variants

Primary

Paper

Lamp

Quiet

Paper

Lamp

State matrix

StatePaperLamp
default
hover
focus-visible
disabled

At 390 px

In a narrow dialog, stack actions full width with the primary act last (nearest the thumb).

Accessibility

  • Native <button>; 40px minimum target.
  • Focus ring is opaque and passes 3:1.
  • Disabled buttons explain why nearby; prefer an error on submit.

Do

  • Use one primary button per view.
  • Write the act as a verb: “Prepare the matter”.

Don’t

  • Use two primary buttons side by side.
  • Use a link styled as a button for an action.

Usage

HTML
<button class="preceda-button" type="button">Prepare the matter</button>
<button class="preceda-button preceda-button--quiet" type="button">Save draft</button>
React
<button className="preceda-button" type="button" onClick={prepare}>Prepare the matter</button>
// Button and IconButton components arrive in T3.

07

Link

Links go somewhere. Binding ink on a quiet printed underline that darkens on hover.

Anatomy

.preceda-link
Inter 14/600, binding ink, rule-strong underline at 0.25em offset.

Variants

Standalone

State matrix

Accessibility

  • Underlined, so it does not rely on colour.
  • Link text names the destination.

Do

  • Use for navigation and references.

Don’t

  • Use for actions that change state; use a button.

Usage

HTML
<a class="preceda-link" href="/case/…">Read authority</a>
React
<a className="preceda-link" href={href}>Read authority</a>

08

Field

A field is a ruled line with a name above it and its error below it. Nothing decorative.

Anatomy

.preceda-field
Raised surface, rule-strong border, inherits the font.
[aria-invalid="true"]
Border turns to the error colour.
.preceda-field-error
The associated message, Inter 13 in error ink.

State matrix

StatePaperLamp
default
placeholder
focus-visible
error

Court and jurisdiction are required.

Court and jurisdiction are required.

At 390 px

Fields fill the column at 390 px; inputs stay at 16px effective size or larger to avoid zoom.

Accessibility

  • Every field has a <label>; placeholder is a hint, never the label.
  • Link the error with aria-describedby and set aria-invalid.

Do

  • Label above the field with .preceda-label.

Don’t

  • Put the only instruction in the placeholder.

Usage

HTML
<label class="preceda-label" for="court">Court and jurisdiction</label>
<input class="preceda-field" id="court" aria-invalid="true" aria-describedby="court-error" />
<p class="preceda-field-error" id="court-error">Court and jurisdiction are required.</p>
React
<input className="preceda-field" id="court" aria-invalid={Boolean(error)} aria-describedby="court-error" />

09

Tabs

Tabs orient within one surface. The selected tab is underlined in binding; the rest recede.

Anatomy

.preceda-tabs
The ruled tab row (role="tablist").
.preceda-tab
One tab; [aria-selected="true"] draws the binding underline.
<TabList>
React: roving focus with arrows, Home and End. Selection stays with the consumer.

Variants

Desk tabs

Interactive after hydration: click or use the arrow keys.

Paper

Lamp

State matrix

StatePaperLamp
default
hover
focus-visible

At 390 px

At 390 px the row scrolls horizontally; it never wraps to two lines. Swipe arrives with T3 Tabs.

Accessibility

  • WAI-ARIA tab pattern: one tab stop, arrows move, Home/End jump.
  • Each tab controls a panel via aria-controls.

Do

  • Keep to four or five short nouns.

Don’t

  • Use tabs for site navigation.

Usage

HTML
<div class="preceda-tabs" role="tablist" aria-label="Desk">
  <button class="preceda-tab" role="tab" aria-selected="true">Draft</button>
  <button class="preceda-tab" role="tab" aria-selected="false" tabindex="-1">Authorities</button>
</div>
React
import { TabList } from '@luvkapur/preceda-design-system/react';

<TabList aria-label="Desk">
  <button className="preceda-tab" role="tab" aria-selected>Draft</button>
</TabList>

10

Focus

Keyboard focus is always visible and always opaque: a 2px focus ring, offset 2px.

Anatomy

:focus-visible
Shared by button, link, field, tab and dialog.

State matrix

StatePaperLamp
focus-visible

Accessibility

  • The focus colour reaches 3:1 on every adjacent surface in both themes.
  • Never remove outline without an equal replacement.

Do

  • Import focus.css with any per-component CSS file.

Don’t

  • Style focus with a tint or shadow alone.

Usage

HTML
@import '@luvkapur/preceda-design-system/css/focus.css';
React
// Focus is CSS-only; no component is required.

11

Dialog shell

A dialog asks one bounded question, with enough context to answer and a way back to the draft.

Anatomy

.preceda-dialog
Native <dialog>: raised sheet, rule-strong border, dialog shadow, dimmed backdrop.
.preceda-dialog__sheet
Padding container.
.preceda-dialog__title
Serif 30; labels the dialog.
.preceda-dialog__description
Secondary ink; describes the dialog.
<DialogShell>
React: wires aria-labelledby/-describedby. Opening policy stays with the consumer.

Variants

Question

Shown inline here; in product it opens with showModal().

Paper

Which court passed the impugned order?

This completes the jurisdiction paragraph.

Lamp

Which court passed the impugned order?

This completes the jurisdiction paragraph.

At 390 px

At 390 px the dialog is the viewport width less 2rem; actions stack. The bottom Sheet arrives in T4.

Accessibility

  • showModal() gives focus trapping and Escape for free.
  • Title and description are wired automatically by DialogShell.
  • Return focus to the invoking control on close.

Do

  • Ask one question.
  • Offer “Return to draft”.

Don’t

  • Use a dialog for a notification; use a toast (T4).

Usage

HTML
<dialog class="preceda-dialog" aria-labelledby="q">
  <div class="preceda-dialog__sheet">
    <h2 class="preceda-dialog__title" id="q">Which court passed the impugned order?</h2>
    <div class="preceda-dialog__body">…</div>
  </div>
</dialog>
React
import { DialogShell } from '@luvkapur/preceda-design-system/react';

<DialogShell ref={ref} title="Which court passed the impugned order?" description="…">
  {answer}
</DialogShell>