New Delhi · September 2026
Preceda

08 Feedback

Feedback

Work in progress, known quantities, arriving type, notes to counsel, confirmations, empty desks and error pages. Words carry the meaning; oxblood marks it; nothing spins.

  1. Working line
  2. Progress
  3. Skeleton
  4. Note
  5. Banner
  6. Toast
  7. Empty state
  8. Error page

01

Working line

The turn in progress is one line of chrome type with an oxblood point — what is happening, in counsel’s terms, and how long it has taken. There is no spinner anywhere.

Anatomy

.preceda-working-line
Sans at the small role (12/1.45), ink-tertiary, one line. role="status" so the phrase is announced politely.
__point
A 5px oxblood square. It breathes (opacity only) while live; still under reduced motion.
__text
The phrase. Truncates with an ellipsis; `--wrap` lets it wrap.
__elapsed
Tabular “41 s” after a middot. Hidden from assistive technology so it is not read every second.
--ruled / --waiting / --stalled
On a hairline; hollow point while waiting on counsel; ink-secondary with a grey point when stopped short.

Variants

Working

The default: the point breathes, the time counts.

Paper

Reading authorities on s. 482 BNSS

Lamp

Reading authorities on s. 482 BNSS

Ruled, beneath the last letter

In desktop correspondence the line sits on a hairline and may wrap.

Paper

Reading authorities on 482 BNSS for accused abroad at the time of the alleged offence

Lamp

Reading authorities on 482 BNSS for accused abroad at the time of the alleged offence

Waiting on counsel

Nothing is running; a question waits. The point is hollow and the words say so.

Paper

Waiting for your answer to 2 questions

Lamp

Waiting for your answer to 2 questions

Stalled

The turn stopped short. Pair with a Note that says what is on the desk.

Paper

Stopped at the time limit — the draft so far is on the desk

Lamp

Stopped at the time limit — the draft so far is on the desk

Live, counting

Interactive: `since` makes the line count once a second on the client.

Paper

Idle. Start a turn to see the line count.

Lamp

Idle. Start a turn to see the line count.

State matrix

StatePaperLamp
working

Drafting paragraph 4

Drafting paragraph 4

working, long

Checking Satender Kumar Antil v. CBI, (2022) 10 SCC 51

Checking Satender Kumar Antil v. CBI, (2022) 10 SCC 51

waiting

Waiting for your answer

Waiting for your answer

stalled

Stopped short

Stopped short

reduced motion

Reading the FIR

Reading the FIR

At 390 px

On the phone the working line sits at the foot of the dock, beneath the composer, so a turn never blocks reading. It truncates to one line.

390 px

Reading authorities on 482 BNSS for accused abroad at the time of the alleged offence

Accessibility

  • role="status" (polite): the phrase is announced when it changes, never interrupting.
  • The ticking time is aria-hidden; screen-reader users hear the phrase, not a clock.
  • Colour is never alone: waiting is a hollow point and different words; stalled changes the ink and the words.
  • The breathing point is opacity only and stops under prefers-reduced-motion.

Do

  • Name the work in counsel’s terms: “Reading authorities on s. 482 BNSS”.
  • Use the safe fallback “Working on the matter” when the phase is not a closed, typed value.
  • Keep one working line per turn.

Don’t

  • Add a spinner, a progress ring, or cycling “Thinking…” labels.
  • Render raw tool names, model names, token counts or costs.
  • Put the working line in a card or a bubble.

Usage

HTML
<p class="preceda-working-line preceda-working-line--live" role="status" aria-live="polite">
  <span class="preceda-working-line__point" aria-hidden="true"></span>
  <span class="preceda-working-line__text">Reading authorities on s. 482 BNSS</span>
  <span class="preceda-working-line__elapsed" aria-hidden="true">41 s</span>
</p>
React
import { WorkingLine } from '@luvkapur/preceda-design-system/react';

<WorkingLine label="Reading authorities on s. 482 BNSS" since={turn.startedAt} />
<WorkingLine state="waiting" label="Waiting for your answer to 2 questions" />

02

Progress

When the amount is known, draw it as a printed rule to length and print the figure. Unknown durations use the working line instead.

Anatomy

.preceda-progress
Grid: label and figure on one line, the rule beneath. role="progressbar" with value min/max/now/text.
__track / __fill
A 2px rule in `rule`, filled in binding to `--preceda-progress-value` (0–1).
__value
The printed figure, tabular, ink-tertiary; binding when complete.
--neutral / --inline
Ink-tertiary fill for measures with no call to act; a short inline rule for table cells.

Variants

Labelled

Paper

Authorities verified

Lamp

Authorities verified

Neutral measure

Relevance, treatment share — information, not an obligation.

Paper

Relevance to the proposition

Lamp

Relevance to the proposition

Inline

In a register row or table cell, beside the figure.

Paper

Followed in 41 of 52 citing decisions

Lamp

Followed in 41 of 52 citing decisions

Interactive

Paper

Authorities verified

Lamp

Authorities verified

State matrix

StatePaperLamp
empty
Facts confirmed
Facts confirmed
partial
Facts confirmed
Facts confirmed
complete
Facts confirmed
Facts confirmed

At 390 px

The rule takes the full measure; the label may wrap, the figure never does.

Accessibility

  • role="progressbar" with aria-valuemin/max/now and a spoken aria-valuetext (“6 of 9 verified”).
  • The figure is printed, so length is never the only signal.
  • Label with a visible label; use aria-label only for inline rules beside visible text.

Do

  • Phrase the figure in words counsel uses: “6 of 9 verified”.
  • Use neutral for scores and shares.

Don’t

  • Animate an indeterminate bar — use the working line.
  • Colour the rule by threshold (green/amber/red).

Usage

HTML
<div class="preceda-progress" role="progressbar" aria-labelledby="p" aria-valuemin="0" aria-valuemax="9" aria-valuenow="6" aria-valuetext="6 of 9 verified" style="--preceda-progress-value: 0.667">
  <span class="preceda-progress__label" id="p">Authorities verified</span>
  <span class="preceda-progress__value" aria-hidden="true">6 of 9 verified</span>
  <span class="preceda-progress__track" aria-hidden="true"><span class="preceda-progress__fill"></span></span>
</div>
React
<Progress label="Authorities verified" value={6} max={9} valueText="6 of 9 verified" />
<Progress inline tone="neutral" value={41} max={52} aria-label="Followed" />

03

Skeleton

Hold the shape of the type that has not arrived, on the reading rhythm, so nothing jumps when the words land. Breathe gently; never shimmer.

Anatomy

.preceda-skeleton
role="status" aria-busy="true" with a spoken label (“Loading the draft”). Breathes once every ~2 s.
__bar
A 12px bar in paper-sunken per line of text; `--short / --medium / --long / --title / --label`.
--sheet
A document on the desk: running head over a rule, centred title block, numbered paragraphs.
--register
Rows on hairlines, as in the matters register.

Variants

Text lines

Paper

Lamp

Sheet

The draft, before the first paragraph arrives.

Paper

Lamp

Register

Paper

Lamp

State matrix

StatePaperLamp
loading
still

At 390 px

The sheet skeleton tightens its margins and gutter to the mobile document sheet.

390 px

Accessibility

  • One status region per loading area, named for what is loading; the bars are aria-hidden.
  • Remove the skeleton and aria-busy together when content arrives.
  • Breathing is opacity only and stops under prefers-reduced-motion.

Do

  • Match the skeleton to the layout that will replace it.
  • Show a skeleton only after ~300 ms, so fast loads never flash.

Don’t

  • Use skeletons for work in progress — that is the working line.
  • Add a moving shimmer gradient.

Usage

HTML
<div class="preceda-skeleton" role="status" aria-busy="true" aria-label="Loading the headnote">
  <span class="preceda-skeleton__shapes" aria-hidden="true">
    <span class="preceda-skeleton__bar preceda-skeleton__bar--long"></span>
    <span class="preceda-skeleton__bar"></span>
    <span class="preceda-skeleton__bar preceda-skeleton__bar--short"></span>
  </span>
</div>
React
<Skeleton lines={3} label="Loading the headnote" />
<Skeleton variant="sheet" label="Loading the draft" />

04

Note

The clerk’s note to counsel: a hairline, a small-caps word naming the kind of note, and a plain sentence in ink-secondary. It says what happened, what is on the desk, and what counsel can do next.

Anatomy

.preceda-note
A hairline above; body in the serif at the body role. role="note" by default.
__label
Run-in small caps: “Note”, “Caution”, “Error” — or a precise word (“Limitation”, “Partial draft”).
__title
Optional run-in lead sentence in ink.
__actions
Next acts as a middot-separated line of binding links.
__dismiss
Optional 40px close control.
--caution / --error / --compact
Umber or binding label and hairline; sans at ui size inside forms and dialogs.

Variants

Info — a bounded partial

Paper

Lamp

Caution

Paper

Lamp

Error

Paper

Lamp

Compact, inside a form

Paper

Lamp

Dismissible

Paper

Lamp

State matrix

StatePaperLamp
default
action hover
action focus-visible
action disabled
announced

At 390 px

At 390 px the note keeps the full measure; actions wrap onto a second line. Notes live in the correspondence sheet or under the document, never floating.

390 px

Accessibility

  • The label word differs by tone, so colour never carries the meaning alone.
  • Static notes are role="note"; pass live="polite" for an outcome that just happened, live="assertive" only for an error that stops counsel’s act.
  • Actions are real buttons or links with 40px targets on mobile via their line height and padding in context.

Do

  • Say what is on the desk and what counsel can do next.
  • Quote the bounded-partial sentence from the runtime verbatim.
  • Name the kind precisely: “Limitation”, “Partial draft”, “Verify”.

Don’t

  • Use a red box, an icon standing in for the word, or an emoji.
  • Put a note in a toast — a toast disappears.
  • Apologise or blame: “Oops!”, “Something went wrong on our end :(”.

Usage

HTML
<aside class="preceda-note preceda-note--error" role="note">
  <p class="preceda-note__body">
    <span class="preceda-note__label">Error</span>
    <span class="preceda-note__title">The FIR could not be read.</span>
    The file appears to be a scanned image without a text layer.
  </p>
  <ul class="preceda-note__actions">
    <li><button class="preceda-note__action" type="button">Attach a text PDF</button></li>
  </ul>
</aside>
React
<Note tone="error" title="The FIR could not be read." actions={[<button className="preceda-note__action" onClick={attach}>Attach a text PDF</button>]}>
  The file appears to be a scanned image without a text layer.
</Note>

06

Toast

A short confirmation of something counsel just did — “Copied”, “Download started” — on a raised slip at the foot of the screen. It is announced, it can be dismissed, and it waits while it is being read.

Anatomy

ToastProvider
Owns the stack (max 3) and two live regions (polite, assertive) that stay in the document.
.preceda-toast-region
A manual popover at the viewport foot, so it rises above open dialogs; bottom-right at desk, full width on phones.
.preceda-toast
Raised paper, hairline, sheet shadow; message in ui sans; optional action and dismiss (40px).
--error
A binding hairline and the word “Error”; announced assertively.

Variants

Live demo

Hover or focus the stack to pause it; Esc on a focused toast dismisses it.

Paper

    Lamp

      Confirmation

      Paper

      Link copied

      Lamp

      Link copied

      With an act

      Paper

      Authority removed from the matter

      Lamp

      Authority removed from the matter

      Error

      Paper

      ErrorCould not revoke this link.

      Lamp

      ErrorCould not revoke this link.

      State matrix

      StatePaperLamp
      default

      Download started

      Download started

      dismiss hover

      Authority removed from the matter

      Authority removed from the matter

      action hover

      Authority removed from the matter

      Authority removed from the matter

      action focus-visible

      Authority removed from the matter

      Authority removed from the matter

      error

      ErrorCould not copy — select the link instead.

      ErrorCould not copy — select the link instead.

      At 390 px

      At 390 px the stack spans the width above the safe-area inset, newest nearest the thumb. It sits above the dock but never covers the composer for longer than its duration.

      390 px

      Link copied

      Accessibility

      • Announcements go through polite and assertive live regions that are always rendered; errors are prefixed “Error:”.
      • Auto-dismiss pauses on hover and on focus inside the stack (WCAG 2.2.1); a toast with an act stays at least 8 s.
      • Esc dismisses the focused toast. Dismiss buttons are named.
      • While a package Dialog or Sheet is open the stack renders inside it, so it is not inert.

      Do

      • Confirm an act counsel just took, in two or three words.
      • Offer Undo for a reversible removal.

      Don’t

      • Carry the only copy of an error counsel must act on — use a Note.
      • Toast on page load, or for background agent progress.
      • Use a dark pill or an emoji.

      Usage

      HTML
      <!-- Rendered by ToastProvider; the classes for a product that manages its own stack. -->
      <section class="preceda-toast-region" popover="manual" aria-label="Notifications">
        <ol class="preceda-toast-region__list">
          <li><div class="preceda-toast"><p class="preceda-toast__message">Link copied</p>
            <span class="preceda-toast__actions"><button class="preceda-toast__dismiss" aria-label="Dismiss">…</button></span></div></li>
        </ol>
      </section>
      <div class="preceda-toast-region__announcer" role="status" aria-live="polite">Link copied</div>
      React
      <ToastProvider>{app}</ToastProvider>
      
      const toast = useToast();
      toast.show('Copied');
      toast.show({ message: 'Could not revoke this link.', tone: 'error', action: { label: 'Try again', onAction: retry } });

      07

      Empty state

      Where the work will be, say so honestly and quietly: one sentence, one line of guidance, at most one next act. No icon, no illustration, no welcome card.

      Anatomy

      .preceda-empty
      Serif subheading title in ink, guidance in the body role in ink-secondary.
      __actions
      At most one act, usually a binding link.
      --desk
      The empty sheet on the desk, centred on raised paper.
      --inline
      Inside a tab panel or list, on a hairline, at body size.

      Variants

      The desk

      Paper

      Nothing on the desk yet.

      Instruct the associate in correspondence; the draft will be prepared here.

      Lamp

      Nothing on the desk yet.

      Instruct the associate in correspondence; the draft will be prepared here.

      Inside a tab

      Paper

      No authorities on this matter yet.

      Authorities the associate relies on are listed here with their treatment and verification.

      Lamp

      No authorities on this matter yet.

      Authorities the associate relies on are listed here with their treatment and verification.

      No results

      Paper

      No judgments match “anticipatory bail brother-in-law abroad”.

      Try a case name, a citation such as (2014) 8 SCC 273, or a provision such as s. 482 BNSS.

      Lamp

      No judgments match “anticipatory bail brother-in-law abroad”.

      Try a case name, a citation such as (2014) 8 SCC 273, or a provision such as s. 482 BNSS.

      State matrix

      StatePaperLamp
      desk

      Nothing on the desk yet.

      Nothing on the desk yet.

      inline

      No facts confirmed yet.

      No facts confirmed yet.

      with act, hover

      No matters yet.

      No matters yet.

      At 390 px

      On the phone the desk sheet shrinks its padding and height; the sentence stays on one or two lines.

      390 px

      Nothing on the desk yet.

      Instruct the associate below.

      Accessibility

      • The title is a real heading at the level the page needs (`headingLevel`), or a paragraph inside a panel that already has one.
      • Nothing here is decorative-only, so nothing is hidden from assistive technology.

      Do

      • Say what will appear and where it comes from.
      • Offer the one act that fills the space.

      Don’t

      • Add an icon, illustration or welcome copy.
      • Blame the user: “You haven’t added anything!”

      Usage

      HTML
      <div class="preceda-empty preceda-empty--desk">
        <h2 class="preceda-empty__title">Nothing on the desk yet.</h2>
        <p class="preceda-empty__guidance">Instruct the associate in correspondence; the draft will be prepared here.</p>
      </div>
      React
      <EmptyState variant="desk" guidance="Instruct the associate in correspondence; the draft will be prepared here." />
      <EmptyState variant="inline" headingLevel={3} title="No authorities on this matter yet." />

      08

      Error page

      Not found and something went wrong, set as a notice in the reporter: the status in words, a serif sentence, one paragraph, and the ways back. No giant numerals.

      Anatomy

      .preceda-error-page
      A <main> at the reading measure, vertically centred in 60dvh.
      __head / __code
      Small-caps running head over an ink rule; the status figure in tabular folio numerals.
      __title / __body
      Title role (serif 30); reading-role paragraph in ink-secondary.
      __actions
      Primary way back first: a button to retry, links back.
      __reference
      A reference counsel can quote in a report — an error digest, never an internal record id.

      Variants

      Not found

      Paper

      Not found404

      This page is not in the reporter.

      The address may be mistyped, or the page may have moved. Search the corpus, or return to your matters.

      Lamp

      Not found404

      This page is not in the reporter.

      The address may be mistyped, or the page may have moved. Search the corpus, or return to your matters.

      Something went wrong

      Paper

      Something went wrong500

      The page could not be prepared.

      Try again in a moment. If it happens again, report it and quote the reference below.

      Reference e7f3-21ac

      Lamp

      Something went wrong500

      The page could not be prepared.

      Try again in a moment. If it happens again, report it and quote the reference below.

      Reference e7f3-21ac

      Offline

      Paper

      Offline

      The connection to Preceda was lost.

      The page will not refresh until the connection returns. Anything already on screen is still readable.

      Lamp

      Offline

      The connection to Preceda was lost.

      The page will not refresh until the connection returns. Anything already on screen is still readable.

      Members only

      Paper

      Members only403

      This page is open to members.

      Sign in to continue, or ask the member who shared the link to share it again.

      Lamp

      Members only403

      This page is open to members.

      Sign in to continue, or ask the member who shared the link to share it again.

      State matrix

      StatePaperLamp
      retry hover

      Something went wrong

      The page could not be prepared.

      Try again in a moment. If it happens again, report it and quote the reference below.

      Something went wrong

      The page could not be prepared.

      Try again in a moment. If it happens again, report it and quote the reference below.

      link focus-visible

      Not found

      This page is not in the reporter.

      The address may be mistyped, or the page may have moved. Search the corpus, or return to your matters.

      Not found

      This page is not in the reporter.

      The address may be mistyped, or the page may have moved. Search the corpus, or return to your matters.

      At 390 px

      At 390 px the title drops to the heading role and the page loses its vertical centring, so the ways back stay above the fold.

      390 px

      Not found404

      This page is not in the reporter.

      The address may be mistyped, or the page may have moved. Search the corpus, or return to your matters.

      Accessibility

      • The page is the <main> landmark with one h1; move focus to the h1 after a client-side navigation lands here.
      • The status figure is a word first (“Not found”) and a number second.
      • The reference is plain text so it can be selected and copied.

      Do

      • Offer the two likeliest ways back.
      • Log the digest server-side and show only the digest.

      Don’t

      • Show stack traces, internal ids or provider names.
      • Promise that nothing was lost unless the flow guarantees it.

      Usage

      HTML
      <main class="preceda-error-page">
        <p class="preceda-error-page__head"><span>Not found</span><span class="preceda-error-page__code">404</span></p>
        <h1 class="preceda-error-page__title">This page is not in the reporter.</h1>
        <p class="preceda-error-page__body">The address may be mistyped, or the page may have moved.</p>
        <div class="preceda-error-page__actions"><a class="preceda-link" href="/">‹ Back to search</a></div>
      </main>
      React
      // routes/__root.tsx
      notFoundComponent: () => <ErrorPage as="div" headingLevel={3} kind="not-found" actions={<Link className="preceda-link" to="/">‹ Back to search</Link>} />,
      errorComponent: ({ error }) => <ErrorPage as="div" headingLevel={3} kind="error" reference={digest(error)}
        actions={<><button className="preceda-button" onClick={() => location.reload()}>Try again</button><Link …>‹ Back to search</Link></>} />,