The Eloquent · UI kit

Pragmatic components in ink and paper

Every component, brand component and block for React in one registry, built on Base UI and set in the house style: pure black, white and grey, structured by rules rather than boxes. Each one installs with the shadcn CLI and has a reference page.

Install

Add the registry to components.json:

"registries": {
  "@eloquent": "https://phamdonhatminh.vercel.app/ui/r/{name}.json"
}

Then add the style and any item:

npx shadcn add @eloquent/style

01

Foundations

The tokens every item reads: colour, type, rules and the marker highlight.

Colour

  • paperGround
  • inkText and rules
  • tint-1Highlights, panels
  • tint-2Bands, warnings
  • halftoneDecoration, disabled
  • pressThe one inverse block

Type: read it in serif, use it in sans

A roman lead, an italic tail

Source Serif 4 sets the body: ledes, descriptions and dialog text, at a reading measure.

1,280Barlow Condensed figures

Barlow for labels and controls

Rules, not boxes

Hairline, 1px: between stories, rows and fields

Heavy rule, 3px: opens each section

npx shadcn add @eloquent/style

02

Forms and actions19 items

Buttons, fields and choices, ruled like a newspaper form.

Button

Ink-fill, outline, secondary, ghost, link and destructive (✕ icon) buttons; 44px hit targets.

npx shadcn add @eloquent/buttonReference →

Button Group

Joins related buttons into one segmented control divided by shared 1px ink rules, with a text cell and separator.

npx shadcn add @eloquent/button-groupReference →

Input

Single-line text field as a 1px ink form line; invalid is a 2px rule; 44px high.

Shown on the front page. Keep it under 70 characters.

npx shadcn add @eloquent/inputReference →

Input group

One form line with a control plus text, icons or buttons either side, split by ink hairlines.

https://

Readers can open the edition from this address.

npx shadcn add @eloquent/input-groupReference →

Input OTP

One-time code entry on Base UI OTP Field: square 44px cells sharing 1px ink rules, Barlow Condensed figures.

Enter the 6 digits we sent to your device.

npx shadcn add @eloquent/input-otpReference →

Textarea

Multi-line text field with the 1px ink form line; invalid is a 2px rule.

State the source and the time of the photograph.

npx shadcn add @eloquent/textareaReference →

Label

Form label in the Barlow 600 kicker style.

npx shadcn add @eloquent/labelReference →

Field

Label, control, description and error layout on Base UI Field and Fieldset; errors shown by a 2px ink rule and an ! icon.

Shown on the front page. Keep it under 70 characters.

npx shadcn add @eloquent/fieldReference →

Form

Validated forms on Base UI Form and Field with react-hook-form and zod; errors shown by ink rules, icons and an error summary at the top on submit.

At least 5 characters.

npx shadcn add @eloquent/formReference →

Checkbox

Tick, untick or mixed choice on Base UI Checkbox; checked is an ink fill plus a check glyph.

npx shadcn add @eloquent/checkboxReference →

Radio Group

Pick one option on Base UI RadioGroup and Radio; selected is an ink fill with a paper dot.

Delivery
npx shadcn add @eloquent/radio-groupReference →

Switch

On/off setting on Base UI Switch; on is an ink track with a paper thumb, optional ON/OFF text.

npx shadcn add @eloquent/switchReference →

Slider

Number or range input on Base UI Slider; hairline track, heavy ink range, square thumb.

Drag, or use the arrow keys.

npx shadcn add @eloquent/sliderReference →

Select

Select on Base UI: ink trigger, paper popup with a 1px rule, ink check on the chosen item; no shadow or radius.

npx shadcn add @eloquent/selectReference →

Native select

Native <select> with an ink border, chevron and 44px height; invalid is a 2px ink underline.

npx shadcn add @eloquent/native-selectReference →

Combobox

Filterable single or multiple select on Base UI Combobox; ink rules, tint-1 highlight with an ink rule, no shadow.

The desk that commissioned the story.

npx shadcn add @eloquent/comboboxReference →

Toggle

Two-state button on Base UI Toggle; pressed shown by an ink fill and aria-pressed, never colour alone.

npx shadcn add @eloquent/toggleReference →

Toggle Group

Segmented set of toggles on Base UI ToggleGroup, divided by shared 1px ink rules; pressed segments are ink fills.

npx shadcn add @eloquent/toggle-groupReference →

Kbd

Keyboard key and shortcut chips: Barlow Condensed capitals in a 1px ink rule.

Press CtrlK to search the archive.

npx shadcn add @eloquent/kbdReference →

03

Overlays12 items

Dialogs, menus and notices on paper, with a 1px ink rule and no shadow. Open each one.

Dialog

Dialog on Base UI: paper popup, 1px ink rule and heavy top rule, 85% paper backdrop, focus trapped.

npx shadcn add @eloquent/dialogReference →

Alert Dialog

Alert dialog on Base UI: Dialog's paper and rules, no corner close, Action and Cancel are Buttons, focus trapped.

npx shadcn add @eloquent/alert-dialogReference →

Sheet

Sheet on Base UI Dialog: full-height paper panel from any side, 1px inner ink rule, focus trapped.

npx shadcn add @eloquent/sheetReference →

Drawer

Drawer on Base UI: paper panel from any edge, heavy 3px ink rule as the handle, swipe to dismiss, focus trapped.

npx shadcn add @eloquent/drawerReference →

Popover

Popover on Base UI: ink on paper, 1px ink rule, no shadow, radius or arrow.

npx shadcn add @eloquent/popoverReference →

Hover Card

Hover card on Base UI PreviewCard: link trigger with the marker highlight, popover-style paper and 1px ink rule, opens on hover and focus.

Read the full record in the archive before you republish.

npx shadcn add @eloquent/hover-cardReference →

Tooltip

Tooltip on Base UI: ink block, paper Barlow 12px, no arrow, shadow or radius; opens on focus.

npx shadcn add @eloquent/tooltipReference →

Dropdown Menu

Dropdown menu on Base UI Menu: paper popup, 1px ink rule, ink-fill highlight, hairline separators, checkbox, radio and submenu rows.

npx shadcn add @eloquent/dropdown-menuReference →

Context Menu

Context menu on Base UI ContextMenu: focusable area, opens at the pointer or from Shift+F10, ink-fill highlight, hairline separators.

Right-click here, or focus it and press Shift+F10
npx shadcn add @eloquent/context-menuReference →

Menubar

Menubar on Base UI Menubar and Menu: heavy top rule and bottom hairline, ink-fill trigger when open, Dropdown Menu rows.

npx shadcn add @eloquent/menubarReference →

Command

Command palette on Base UI Autocomplete (inline): type to filter, arrows to choose, Enter to run; CommandDialog for Ctrl+K.

Last command: none

npx shadcn add @eloquent/commandReference →

Sonner

Toaster and toast() on Base UI Toast: paper and 1px ink rule at bottom-right, state by icon, rule or hatched band, never colour.

npx shadcn add @eloquent/sonnerReference →

04

Navigation11 items

Tabs, menus, trails and layout primitives.

Tabs

Tabs on Base UI: 3px ink rule on the selected tab, big ModeSwitcher variant, no hover.

The committee reviewed 14 submissions and recommended 3.

npx shadcn add @eloquent/tabsReference →

Accordion

Accordion on Base UI: hairline items, +/- glyph, opacity-only panel, no hover effect.

Any registered officer of a participating body may submit.

npx shadcn add @eloquent/accordionReference →

Collapsible

Collapsible on Base UI: 44px ink trigger, opacity-only panel, no hover effect.

Two corrections were made to this report.

npx shadcn add @eloquent/collapsibleReference →

Navigation Menu

Navigation menu on Base UI: Barlow caps bar, heavy rule under the current page, flat ruled panel, no hover effect.

npx shadcn add @eloquent/navigation-menuReference →

Breadcrumb

Breadcrumb trail: nav, ordered list, underlined ink links, middle-dot separators, no hover effect.

npx shadcn add @eloquent/breadcrumbReference →

Pagination

Pagination links: Barlow Condensed numerals, ink fill on the current page, 44px targets, no hover effect.

npx shadcn add @eloquent/paginationReference →

Sidebar

Side navigation: hairline edge, heavy-rule active item, collapsible groups, icon rail with tooltips and a sheet on small screens.

The register

Choose a section from the sidebar. Ctrl+B or the toggle collapses it to icons.

Viewing: Notices

npx shadcn add @eloquent/sidebarReference →

Separator

Ink rule on Base UI Separator: hair (1px) or heavy (3px), horizontal or vertical.

Eloquent UI

Components for a newspaper of record.

DocsRegistrySource
npx shadcn add @eloquent/separatorReference →

Resizable

Resizable panels on react-resizable-panels: hairline handle with grip dots, 44px hit area, no hover effect.

Sources

Court filings and committee papers.

Draft

The report as it stands.

npx shadcn add @eloquent/resizableReference →

Scroll Area

Scroll area on Base UI: square ink thumb on a tint-1 track, focusable viewport.

npx shadcn add @eloquent/scroll-areaReference →

Aspect Ratio

Aspect ratio box: CSS aspect-ratio, unstyled, no hover effect.

16:9
Image panel held to 16:9. The caption sits below it.
npx shadcn add @eloquent/aspect-ratioReference →

05

Data and feedback17 items

Tables, states, progress and a greyscale chart; state never relies on colour alone.

Card

Card with no box: heavy 3px top rule, serif content, hairline footer; header, title, description, action, content and footer parts.

Dispatch

The register of record, updated nightly

A short standfirst sets the story in one sentence.

Procurement notices are filed, dated and indexed the same day, so a reader can follow a decision from the first notice to the last.

npx shadcn add @eloquent/cardReference →

Table

Semantic table in Barlow: heavy header rule, hairline rows, tabular right-aligned figures.

Stories filed this week, by desk.
DeskStoriesWords
Politics4251,230
Business3744,105
Culture1923,870
Science1115,402
Total109134,607
npx shadcn add @eloquent/tableReference →

Data table

Table with sortable headers (aria-sort, ink glyphs), a column filter, a columns popover and paging, on TanStack Table and the Eloquent table.

Stories filed this week.
Budget passes second readingPolitics1,240
Port strike enters third dayBusiness980
Museum reopens its east wingCulture760
Telescope finds a quiet starScience1,105
Council rejects the tram planPolitics870
Page 1 of 2
npx shadcn add @eloquent/data-tableReference →

Badge

Square status label in Barlow Condensed capitals: ink fill, tint, outline or 2px destructive outline with a cross.

LiveDraftArchivedRetracted
npx shadcn add @eloquent/badgeReference →

Avatar

Square avatar on Base UI Avatar: hairline frame, greyscale image, initials fallback from props.

JOJane Okafor
npx shadcn add @eloquent/avatarReference →

Alert

Alert panel with a state per variant: tint-1 info, check success, hatched tint-2 warning, 2px ink rule error.

Draft saved
Your changes are kept as a draft until an editor publishes them.
npx shadcn add @eloquent/alertReference →

Progress

Progress bar on Base UI Progress: hairline track, ink fill, value text in Barlow Condensed.

Uploading documents
x
npx shadcn add @eloquent/progressReference →

Meter

Meter on Base UI Meter: same hairline track and ink fill as Progress, for a value in a known range.

Storage used
x
npx shadcn add @eloquent/meterReference →

Skeleton

tint-1 placeholder block that pulses only when motion is allowed.

Loading the front page
npx shadcn add @eloquent/skeletonReference →

Spinner

Ink square outline that turns while loading; labelled status, still under reduced motion.

Fetching the latest edition
npx shadcn add @eloquent/spinnerReference →

Empty

Empty state: ink hairline, tracked kicker, Playfair headline, serif sentence and an optional ink drawing or icon slot.

No filings

Nothing has been filed yet

Notices appear here once the first tender is published. Until then the register is blank.

npx shadcn add @eloquent/emptyReference →

Item

Row for a record: media, title, description and actions, closed by an ink hairline; renders as a link with the render prop.

Notice of tender, lot 4

Filed 3 November. Open for questions until 24 November.

Addendum to the specification

Filed 5 November. Replaces section 2.

npx shadcn add @eloquent/itemReference →

Calendar

Month grid on react-day-picker: hairline weeks, ink-fill selection, heavy-rule today, Barlow Condensed numerals, 44px days.

November 2026
npx shadcn add @eloquent/calendarReference →

Date picker

Date field on Calendar and Popover: a ruled trigger opens a square, flat calendar; Esc returns focus to the trigger.

npx shadcn add @eloquent/date-pickerReference →

Chart

Charts on Recharts in ink: series told apart by pattern, dash and label; one labelled image with a data table alternative; no animation under reduced motion.

A bar chart of stories filed and stories published for four desks. Politics leads on both. The table below gives every value.

Stories filed and published this week, by desk.
Show the data as a table
Stories filed and published, by desk
DeskFiledPublished
Politics4236
Business3731
Culture1918
Science119
npx shadcn add @eloquent/chartReference →

Typography

Brand text elements: two-voice headline, kicker, lede, body, drop cap, pull-quote, figure and meta.

Analysis

Read it in serif, use it in sans

A newspaper of record sets its headlines in one voice and answers in another.

By the Editors · 9 November 2026

Every story opens with a rule. The type does the rest: a headline that carries weight, a lede that explains, and body text that rewards the careful reader.

Structure comes from rules, not boxes.

Style guide

Names and figures are set in capitals so they can be scanned at a glance.

npx shadcn add @eloquent/typographyReference →

06

Brand components15 items

The pieces of The Eloquent itself: kickers, two-voice headlines, figures and story cards.

Kicker

tracked-capitals label with an optional leading ink rule.

Work · Sep 2025 – Present

npx shadcn add @eloquent/kickerReference →

Tech line

middle-dot separated stack line in Barlow.

  • Java
  • Spring Boot
  • PostgreSQL
npx shadcn add @eloquent/tech-lineReference →

Ink figure

greyscale illustration frame (multiply blend) in 9:16, 16:9, 3:4 or 1:1, with required alt text.

Ink drawing: a folded newspaper beside a cup of coffee
Illustration · English edition
npx shadcn add @eloquent/ink-figureReference →

Stat tile

tint-1 figure tile (Barlow Condensed figure, unit, caption) and StatRow, a row of exactly three.

  • 21items

    Brand items in phase 4

  • 60primitives

    Primitives in the registry

  • 2languages

    English and Vietnamese

npx shadcn add @eloquent/stat-tileReference →

Language switch

EN · VI switch; the current locale in ink 700, the other a real link that keeps the hash and ?mode. No flags.

ENVI
npx shadcn add @eloquent/language-switchReference →

Folio line

name · title · city between two ink hairlines, with the language switch.

Pham Do Nhat MinhAgentic Software EngineerHo Chi Minh City

ENVI
npx shadcn add @eloquent/folio-lineReference →

Proof

three lines, Problem. / Built. / Result., with a bold sans lead word and serif text.

  • Problem. Tender documents were drafted by hand, so every bid started from a blank page.
  • Built. A Procurement Docs Platform that assembles, checks and exports the documents from one source.
  • Result. Drafting moved from days to hours, and every document carries a reviewable trail.
npx shadcn add @eloquent/proofReference →

Story card

kicker, headline, lede and stack under a heavy rule, with an optional 96px 9:16 ink thumbnail.

Work · Sep 2025 – Present

Ten agents, one pipeline

A document pipeline in which each agent owns one stage, so that every draft can be traced back to its source.

  • Java
  • Spring Boot
  • PostgreSQL
Ink drawing: a folded newspaper beside a cup of coffee
npx shadcn add @eloquent/story-cardReference →

Cover

kicker, two-voice headline and a 16:9 ink scene, for slide titles and social images.

Case study · 2026

Ten agents, one pipeline

Ink drawing: a folded newspaper beside a cup of coffee
npx shadcn add @eloquent/coverReference →

Language bar

a non-modal bottom bar that offers the other language once, written in that language.

npx shadcn add @eloquent/language-barReference →

Mode switcher

a tint-2 band asking what brings you to the paper, with two large tabs (solid ink when selected) synced to the URL hash; controlled or uncontrolled.

What brings you to the paper?

The CV, recent work and how a project runs from brief to release.

npx shadcn add @eloquent/mode-switcherReference →

CTA band

the press band with a classifieds kicker, a two-voice Playfair headline and an outlined on-press mailto button.

Classifieds

Book a free 20-minute call. No obligation.

Book by email
npx shadcn add @eloquent/cta-bandReference →

Calling card

a 390 × 844 no-scroll screen with four contact buttons, two tiles and a black footer.

The EloquentCalling cardHo Chi Minh City

ENVI
Portrait of Minh Pham in greyscale

Pham Do Nhat Minh

Agentic software engineer. Builds the Procurement Docs Platform.

HiringOpen to the right role
ServicesAgentic software, built to order
npx shadcn add @eloquent/calling-cardReference →

07

Blocks6 items

Whole sections, from the masthead to the A4 print shell.

Article layout

Brand block: front-page link, kicker, headline, standfirst and byline, body column, At a glance aside, pull quote and Keep reading.

The Eloquent · Front page

Field notes · November 2026

Rules, not boxes: a newspaper of record, in code

How a component kit borrows its structure from the front page: hairlines, heavy rules and two voices of type.

By Minh Pham · 9 November 2026 · 6 min read

A newspaper never draws a box around a story. It opens each section with a heavy rule, separates stories with a hairline, and lets the type do the rest. The kit follows the same discipline.

Every headline has two voices: a roman lead and an italic tail. The first tells the reader what the story is; the second tells them why to stay. Both are set in the same face, so the page keeps one tone.

Colour is absent by design. Errors, successes and warnings are told apart by an icon, a rule or a hatched band, never by hue alone, which keeps the page readable in print and in greyscale.

Read it in serif, use it in sans.
Minh Pham, on the type rule
npx shadcn add @eloquent/article-layoutReference →

Classifieds form

Block: the brief form (name, company, email, brief, four-way project size) with an error summary, inline success and error messages and an onSubmit prop; no network call.

Used only to reply to this brief.

A few sentences on the goal, the people who will use it and the timing.

Project size
npx shadcn add @eloquent/classifieds-formReference →

Print A4

Block: an A4 page shell (210 by 297mm, 44 to 52px margins, main column plus a 210 to 228px side column), a named @page rule for print and a page-break helper. Pure layout.

Curriculum vitae

Alex Example

Software engineer, placeholder profile

Profile

Placeholder text. A short paragraph about the person, set in the body face, that runs for three or four lines and says what they build and how they work.

Experience

2023 – present

Lead engineer, Procurement Docs Platform

Placeholder text. Designed the document workflow and the review screens, and kept the release process calm.

2020 – 2023

Senior engineer, Example Studio

Placeholder text. Built internal tools for editors and wrote the first test suite for the publishing system.

2017 – 2020

Engineer, Example Works

Placeholder text. Maintained a set of services and moved the team to a weekly release.

npx shadcn add @eloquent/print-a4Reference →