Ch. 04 · Components · The Lego bricks every property is built from. Buttons · Cards · Badges · Forms · Rules · Tags · Alerts · Icons
Chapter 04 · Components

Twenty-five components. Every screen in the network is built from them.

A component library that's small on purpose. Twenty-five pieces, every one with a clear job. If a page needs something that isn't here, the right move is almost always to compose it from what is, not to invent a new one. New components require deliberate intent and a written justification.

§ 4.1

Buttons

Five tiers · Three sizes · Hover & disabled

Five visual tiers, ranked by emphasis. Primary is the page's most important action. Secondary is a strong alt. Rust is the alert / urgent CTA ( "Get Pro listing" ). Ghost is the second option in a row. Text is the third. There is no Material-style FAB and no big rounded pill. sharp corners on purpose.

C-01

Primary button

.btn.primary
Recipe

Bluebonnet fill --bluebonnet. Paper text. 2px radius. Inter 600 at 14px. Padding 11px 18px ( regular ), 14px 22px ( lg ), 8px 13px ( sm ). Hover darkens to --bluebonnet-ink.

When to use

The single most important action on a page. Form submit. Newsletter subscribe. "Save," "Continue," "Sign in." Maximum one primary per visible region.

C-02

Secondary, ghost, & text buttons

.btn.secondary · .btn.ghost · .btn.text
Recipe

Secondary: ink fill, paper text. Stronger than ghost, used when bluebonnet would conflict. Ghost: transparent fill, ink text, 1px --rule-2 border; hover flips border to bluebonnet. Text: bluebonnet color, no fill, no border; hover shifts to rust.

When to use

Secondary for "Filter," "Apply," "Export." Ghost for the second option in a row. Text for tertiary actions ( forgot password, skip, dismiss ).

C-03

Rust button & mono CTAs

.btn.rust · .btn.mono
Recipe

Rust: --rust fill, paper text. Same shape as primary but rust. Mono: JetBrains Mono 700, 10.5px, 0.14em tracking, uppercase. Paper-3 fill or transparent with rust border.

When to use

Rust for urgency or alert-flavored CTAs. "Get Pro," "Apply now," "Subscribe." Mono for in-article CTAs ( "View story →," "Read the issue →" ) where the button needs to live next to mono kickers.

C-04

Search input

.search-input · the only pill in the system
Recipe

The only component in the entire system that uses border-radius: 999px. The pill shape signals "search" the same way a magnifying-glass icon does, no second affordance needed. Dark variant for the top bar's primary-band placement.

When to use

Top bar global search, in-page directory search, archive search. Never pill-shape a non-search input.

§ 4.2

Form controls

Inter everywhere · 2px radius · States explicit

Every form field is Inter, 14px, with a 1px ink-3 border on the white card surface. Focus shifts border to bluebonnet and adds a 3px tinted halo. Errors shift to rust. The label sits above the input. never inside as a placeholder pretending to be a label.

C-05

Text input · Select · States

.form-field
Your name* Mateo Reyes As you'd like it to appear on your byline.
Email you@example.com We'll never share your email.
Topics Civic news, business, schools Pick as many as you like.
Focused state Round Rock Focused inputs gain a bluebonnet halo.
Error state notanemail Email looks incomplete.
Success state mateo@wilcoguide.com Email confirmed.
Recipe

Inter 600 11px label, then 14px input on white with 1px --rule-2 border. 2px radius. Focus: --bluebonnet border + 0 0 0 3px bluebonnet tint halo. Error: --rust border + rust helper text. Required asterisk in rust.

When to use

Every text input, email, password, URL, textarea. Same construction for the select; the chevron is an inline SVG, not a system caret.

C-06

Checkbox & toggle

.checkbox-row · .toggle
Subscribe to the daily brief Subscribe to the Friday roundup Send me partner deals Push notifications Weekly digest
Recipe

Checkbox: 18×18 box, 2px radius, rule-2 border. Checked state fills with bluebonnet, paper check glyph. Toggle: 36×20 track, fully rounded, 14px knob. Off = rule-2. On = bluebonnet.

When to use

Checkbox for "and / or" multi-choice. Toggle only for true binary on/off settings ( "Send me emails: yes / no" ). Never use a toggle for a multi-state setting.

§ 4.3

Tags, badges & status indicators

All sharp · All mono · All earned

Tags and badges are tiny mono labels with 2px corners. The point of a tag is to be readable at a glance without competing with the headline. Two-letter rules: ALL CAPS, 0.14em tracking, 9–10 px. Never round the corners off.

C-07

Tag & badge variants

.tag-x · .pro-badge · .live-dot
FEATURED SPONSORED MAY 16 UPDATED VERIFIED EDITORS' PICK DRAFT PRO LIVE
Recipe

JetBrains Mono 700, 9.5px, 0.14em tracking, ALL CAPS. 2px radius. Color tokens determine the meaning: rust = featured/alert, bluebonnet = sponsored, gold = editorial pick, green = verified, ghost = draft / muted.

When to use

Tags label content type or status. Pro badge marks paid business listings ( inline next to the business name ). Live dot marks live events, real-time alerts, breaking-news sticky bar.

§ 4.4

Kickers & eyebrows

The system's voice for "this is a…"

A kicker lives above every headline. It identifies the desk ( "CIVIC DESK" ), the category ( "FRIDAY NIGHT LIGHTS" ), the type ( "FEATURE STORY" ), or the timing ( "BREAKING · 11:42 AM" ). Rust is the default. Variants exist for specific contexts.

C-08

Kicker variants

.kicker · .kicker--ink · .eyebrow
.kicker (default) CIVIC DESK
.kicker--ink FRONT PAGE
.kicker (breaking) BREAKING · 11:42 AM
.cat-tag schools SCHOOLS
.cat-tag business BUSINESS
.cat-tag food FOOD & DRINK
.kicker (named beat) FRIDAY NIGHT LIGHTS
.kicker (gold on dark) SPORTS
.eyebrow (muted sans) ANNOUNCEMENT
Recipe

JetBrains Mono 700, 10.5px, 0.13em tracking, uppercase. Rust default. Bluebonnet for inverted contexts ( e.g. when rust competes ). Gold for dark surfaces only. Category colors for category tags only ( see Color chapter ).

When to use

Above every editorial headline. Always. A page without kickers reads as a generic blog. Named beats ( "FRIDAY NIGHT LIGHTS," "MEMORIAL DESK" ) are part of the editorial voice. proper-noun the recurring ones.

§ 4.5

Cards

Six variants · One construction

All cards share the same construction: white surface, hairline border, 3px corner radius, hover lifts the border to bluebonnet. Variants differ only by content type and decorative flair ( top-stripe for featured, date-block for events ).

C-09

News card

Image, kicker, headline, blurb, meta. The most common card on every property.

C-10

Featured card

Same as news, plus a 3px rust top stripe. Used sparingly. One per visible region.

C-11

List item

Text-only, no image. Date block, kicker, headline, byline.

C-12

Business card

Name, category, address, hours, Pro badge if applicable, action row.

C-13

Event card

Date block + body. Bluebonnet date field with gold month label.

C-14

Job card

Title, company, salary, tags. Premium variant gets a rust top stripe.

C-09 → C-10

News card & featured variant

.news-card · .news-card.featured
PHOTO BY M. REYES
CIVIC DESK

Round Rock council clears site for new fire station off 183A

A unanimous vote ends a 14-month process. The new station opens in 2027 and serves the fast-growing corridor.

By M. Reyes · 1 hr ago READ →
FILE PHOTO
FOOD & DRINK

Five new restaurants opened in Cedar Park this week, ranked

A barbecue spot, a ramen counter, a Filipino bakery, an espresso bar, and a Tex-Mex. We ate at all five so you don't have to.

By K. Doyle · 4 hr ago · 8 min read READ →
Recipe

White surface, 1px --rule border, 3px radius. Image at 16:10 with an optional photo credit chip bottom-left. Body: kicker → Fraunces 600 / opsz 36 headline → Source Serif blurb → mono meta row with bluebonnet "READ →." Hover: border shifts to bluebonnet, image scales 1.04.

When to use

The default for any list of stories. Use the featured variant for the lead story on the home page or the top of a section, max one per visible block. Photo credit chip is required when the photo isn't a stock / file photo.

C-11

List item

.list-item · text-only row
MAY16
SCHOOLS
Leander ISD reopens debate on the four-day school week
By T. Holcomb · 2 hr ago
MAY16
BUSINESS
The plumber on 1431 sold to a regional chain for $4.2M, sources say
By M. Reyes · 4 hr ago
MAY15
TRANSIT
CapMetro adds a third Leander bus, citing 41% ridership growth
By J. Alvarez · Yesterday
MAY15
ARTS
Round Rock Symphony names a new conductor. and the first season looks ambitious
By K. Doyle · Yesterday
Recipe

2-column grid, 80px date column ( month mono rust 700, day 700 ), 1fr content column. Content: cat-tag kicker → Fraunces 600 14.5px headline → mono byline. Items separated by 1px --rule hairlines.

When to use

"More from the desk" sidebars. Archive pages. Search results. Anywhere a list needs to read as text-first ( no images ) and dense.

C-12 → C-14

Business · Event · Job cards

.biz-card · .event-card · .job-card
Round Rock Coffee Co.
COFFEE

122 Main Street, Round Rock TX 78664

OPEN · until 4 pm · 6–4 weekdays

SAT · MAY 18
DOWNTOWN GEORGETOWN
Spring Farmers Market & Live Music on the Square
9 AM – 1 PM · Free admission
Senior Reporter, Civic Desk
WilCo Guide · Round Rock, TX $72,000 – $88,000
PREMIUM FULL-TIME HYBRID
Recipe

Business: name + category tag, address, hours with open/closed signal, Pro badge inline. Event: bluebonnet date block ( gold month, paper day ) atop body. Job: title, company, salary in money-green mono, tags row. Premium variant gets a 3px rust top stripe.

When to use

Anywhere a directory, calendar, or job board lists items. The construction stays the same; the data plugs in.

C-15

Ad slot

.ad-slot · diagonal stripe pattern
SPONSORED · 300×250
SPONSORED · 728×90
Recipe

repeating-linear-gradient at 45° between paper-2 and paper-3, with a 1px --rule-2 border. Mono "SPONSORED" label centered, with the slot's size beside.

When to use

Two purposes: ( 1 ) as a literal ad placeholder during layout, ( 2 ) as a visual signal that an ad will live here. The diagonal-stripe pattern is unique to ad slots. never use it for non-ad content.

§ 4.6

Section rules

Newspaper-style horizontal rules · Four weights

Rules separate sections and bands the way a newspaper does. Four weights. The thicker the rule, the more important the boundary. Never use a wash, gradient, or background tint to separate sections.

C-16

Four rule weights

.section-rule · .widget-rule · .hairline · .double-rule
§ 4.6

Section rule · 2 px ink top border

Major section · Sits above an H2

Widget rule · 1.5 px ink top border

Sub-section · Above an H3
Hairline · 1 px --rule top border for in-card dividers, list separators, footer columns
VOL · III · NO · 142 FRIDAY · MAY 16 · 2026 WILLIAMSON COUNTY · TEXAS
Recipe

Section rule: border-top: 2px solid --ink, mono section number rust 700, H2 Fraunces 600, optional right-aligned meta. Widget rule: 1.5px ink, H3 Fraunces 600 17px. Hairline: 1px --rule for everything else. Double rule: mixed 1px / 3px double pattern, used for vol-no-date rows on print and newsletter.

When to use

Section rule above every major H2 on long pages. Widget rule above each card-grid or list group. Hairline for in-card separators and footer columns. Double rule only at the top of a newsletter or print issue.

§ 4.7

Dark bands

The only dark surfaces in the system

Two dark blocks. The "Today in WilCo" sticky ticker, which rotates every four seconds. And the sports band, which lives below the masthead during the season. Both use bluebonnet as the fill and gold as the on-dark accent.

C-17

"Today in WilCo" sticky ticker

.dark-band · sits at top of every page
Today in WilCo 78° sunny, light wind · Brushy Creek bridge work closes lanes through Friday · HEB hiring at 4 stores Friday · May 16 · 9:42 AM
Recipe

Bluebonnet fill, 3px rust top stripe, mono gold label, Fraunces 500 ticker that rotates through 5 items every 4 seconds with a 350ms cross-fade. Always sticky at the top of the viewport, beneath the primary top bar.

When to use

Every page on every property. The rotation gives the brand a heartbeat. readers expect it. Per-property data ( weather, traffic, local index ) but always this construction.

C-18

Sports band

.sports-band · during season only
SPORTS
LEANDER 42 vs RR 38 · FINAL OT GTOWN 7 vs CP 3 · 7TH INNING HUTTO 2 vs LIBERTY HILL 5 · FINAL
All scores
Recipe

Bluebonnet-ink fill, 3px gold top stripe, Fraunces 700 "SPORTS" gold label, then mono game scores with gold team abbreviations + paper score numbers + mono "FINAL OT / 7TH INNING" mini-status. Right-aligned ghost mono CTA.

When to use

Football season ( Aug–Dec ), baseball ( spring ), playoffs. Hidden in the off-season. The band only appears when there are live or recent local games to report.

§ 4.8

Quotes, stats & alerts

For emphasis, evidence, and signal
C-19

Pull quote

.quote-box
"The math on a $80 million bond doesn't square with the population growth we're actually seeing on the ground." Comm. Bell · The lone "no" vote
Recipe

Paper-2 background, 3px rust left border, no right or bottom borders. Fraunces 400 italic at opsz 96 / SOFT 100, 22px. Attribution in rust mono, the speaker's name in rust.

When to use

One pull quote per article maximum. It exists to break the rhythm of body copy. Quotes from sources go in body paragraphs first; pull-quote treatment is reserved for the line you most want a reader to remember.

C-20

Stat block

.stat
JAIL EXPANSION $80M Total bond. Pays out over 25 years.
PROPERTY IMPACT $34 Per household per year, average.
NEW BEDS 460 Net new capacity once complete.
VOTE 4–1 Tuesday night, after public comment.
Recipe

White card, rust mono label, Fraunces 700 / opsz 144 value at 40px, Source Serif description at 12.5px. Stack horizontally on desktop, vertically on mobile. Always real numbers, never round-number filler.

When to use

Lead-paragraph evidence on civic stories ( bond amounts, vote tallies, capacity numbers ). Sidebar evidence on long-form. Never invent or pad stats.

C-21

Alerts & banners

.alert.success · .error · .info · .warning
Got it. We'll be in touch within 48 hours. ×
! Email is required. Add an email to continue. ×
i Heads up. Live results from the Tuesday vote will update through 11 PM. ×
! One last thing. Verify your email before we activate the Pro listing. ×
Recipe

Each alert is a tinted-paper fill with a matching-hue 1px border. Round icon left, message center, close × right. Inter 13.5px copy. Bold lead sentence + supporting clause.

When to use

Success for form submissions, save confirmations. Error for blocking validation. Info for non-urgent context. Warning for almost-done flows that need an action. Never two alerts on screen at once.

§ 4.9

Navigation

Tabs · Pagination · Breadcrumb · Author row
C-22

Tabs, pagination, breadcrumb

.tabs · .pagination · .breadcrumb
Recipe

Breadcrumb: mono uppercase ink-3, middle-dot separators, ink current. Tabs: mono uppercase ink-3, 2px ink underline rail, rust underline on active. Pagination: 32×32 mono squares, 2px radius, ink fill on active, rule-2 border on others.

When to use

Tabs for switching content type ( all / civic / business ). Pagination for archives, search results, directory. Breadcrumb on any sub-page deeper than two clicks.

C-23

Avatar & author row

.avatar · .author-row
MR Mateo Reyes Civic desk · 4 yrs at WilCo Guide
JA Jess Alvarez Photo desk · Cedar Park
KD K. Doyle
Williamson County Civic news Round Rock
Recipe

Round avatars with Fraunces 700 initials, sized 24 / 32 / 48. Bluebonnet and rust fills are the only two photo-fallback colors. Chips are 2px-radius pills ( exception ) for filter / tag inputs.

When to use

Avatar in bylines, comment threads, internal CMS. Chip for filter selections ( location, category, status ), never for content category tags.

§ 4.10

Newsletter signup

The most-used module on every property

Lives at the bottom of every article, on the homepage above the fold, and as a sticky bottom drawer on mobile. The construction below is the only newsletter signup block in the system. variants change copy only, never the layout.

C-24

Inline newsletter signup

.nl-signup
Recipe

White card with 3px rust top stripe. 2-column grid: copy left ( kicker → headline → blurb ), form right ( label + email + full-width primary button + mono helper ). On mobile, stacks to one column.

When to use

End of every article. Homepage above the fold ( hero-adjacent ). Top of the "Subscribe" page. Sticky mobile bottom drawer for first-time visitors.

§ 4.11

Iconography

Lucide · 16×16 stroked · No fills

All icons are lucide. 16×16 default size, stroke-width: 2, rounded line caps, no fills. The system uses about fifteen icons across every property. If a screen needs one that isn't here, pull it from lucide before inventing one.

C-25

The icon set

15 icons · Lucide-react in production
search
user
message
bell
calendar
map-pin
briefcase
home
plane
target
heart
clock
check-circle
chevron-right
menu
x
Recipe

Pull from lucide.dev. 16×16 default, 20px in nav bars, 24px in big-button contexts. stroke="currentColor" so the icon picks up the text color. Never fill. Never use a different icon library inside the same screen.

When to use

Icons accompany text labels in nav, in form helpers, in empty states. Icon-only buttons require a tooltip. Decorative-only icons get dropped. every icon in the system earns its keep by clarifying an action.

§ 4.12

Do & don't

Component-system hygiene
Do

What keeps the system clean

  • Compose, don't inventIf a page needs a new thing, build it from existing pieces first. Most "new" needs are an old component with different copy.
  • Use 2px and 3px corners2px for tags, badges, buttons, inputs. 3px for cards. Nothing else.
  • Hover = border-color shiftEvery card and ghost button signals interactivity by shifting border from rule-2 to bluebonnet. Never by changing fill.
  • One primary button per regionIf two CTAs are competing, one of them is wrong.
  • Mono for stamped labels, Inter for chromeIf it's stamped, dated, or categorized, mono. If it's tap-able UI, Inter.
  • Kicker above every editorial headlineNo exceptions on news cards, list items, hero blocks. Anonymous content loses the brand.
  • Photo credit on every photoMono uppercase chip bottom-left. "PHOTO BY M. REYES." File photos labeled "FILE PHOTO."
Don't

What breaks the component system

  • Don't round corners offThe brand is allergic to pills. The only pill in the system is the search input. that's it.
  • Don't use shadows for elevationThe brand uses border-color hover, not shadow lift. Glowing or large drop shadows feel SaaS, not editorial.
  • Don't gradient buttonsSolid fills only. Bluebonnet doesn't become teal at the bottom.
  • Don't put icons inside primary buttons by defaultPrimary buttons are usually text-only. An arrow → at the end is fine. Lucide icon left of the label is not.
  • Don't reach for sans for a headlineIf you need big bold sans, you actually need Fraunces 700. the system has no display sans.
  • Don't pile two alerts on screen at onceOne signal at a time. If two competing messages are needed, the design is wrong.
  • Don't theme cards per categoryThe category color lives in the kicker only. never on the card surface, never as a left border, never as a top stripe.
The 25-component rule This chapter ships with 25 components. A new component requires a written 2-sentence justification of why composition wasn't enough, posted in the team Slack. The bar is intentionally high. The smaller this library stays, the more recognizable the brand stays across 25 properties.
What's next

The next chapters compound on this one

After components are locked
  1. Social templates. Instagram feed + carousels, TikTok / Reels covers, LinkedIn, Facebook, stories. The locked grid + locked type cadence built from this chapter, photography doing the variety.
  2. Newsletter template. One master template mapped to the six type tone treatments. Uses cards, kickers, dark bands, and pull-quotes from this chapter.
  3. Photography direction. Mood, palette, rules, examples of what we do and don't shoot.
  4. Sub-brand toolkit. One-pager: how to spin up Cedar Park Scoop, WilCo Families, or a new vertical without breaking the system.