Svelte components that are up before you are.

Forms, dialogs, menus and tables with keyboard handling and dark mode already done. Restyle the lot with three CSS variables, or let the generator pick something for you.

Big, juicy components. Size isn't everything, but 63 of them certainly help.

~/new-project
$ bun add @joshicodes/cock
+ @joshicodes/[email protected]
63 components, 2 dependencies, no surprises
$ bun run dev
  Local   http://localhost:5173
cock-a-doodle-done in 412 ms
Button Terminal Modal Odometer Tabs CommandPalette Toast PinInput Field Heatmap Drawer Scramble Accordion TagInput Table Typewriter Tooltip Sparkline Switch confetti()

Install

Published to GitHub Packages, so your package manager needs to know where the scope lives and needs a token to get in. After that it installs in seconds. No performance anxiety.

  1. 1. Tell bun where the scope lives, and how to get in

    .npmrc
    @joshicodes:registry=https://npm.pkg.github.com
    //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
  2. 2. Add the package

    terminal
    bun add @joshicodes/cock
  3. 3. Import the tokens after Tailwind

    app.css
    @import 'tailwindcss';
    @import '@joshicodes/cock/theme.css';
  4. 4. Use it. Responsibly.

    +page.svelte
    import { Button, Card, toast } from '@joshicodes/cock';

GITHUB_TOKEN is a personal access token with the read:packages scope. Always use protection: keep it in an environment variable, never in the repository.

Theme

Three colours are set by hand. Surfaces, borders and secondary text are mixed from them with color-mix, so changing the background is enough to re-skin everything. It looks good in anything.

Surfaces

Background

--ck-bg

Surface

--ck-surface

Muted

--ck-muted

Border

--ck-border

Foreground

Foreground

--ck-fg

Muted

--ck-fg-muted

Subtle

--ck-fg-subtle

Border strong

--ck-border-strong

Accent & status

Accent

--ck-accent

Success

--ck-success

Warning

--ck-warning

Danger

--ck-danger

Type scale

Display The quick brown fox
Heading The quick brown fox
Subheading The quick brown fox
Body The quick brown fox
Small The quick brown fox
Mono The quick brown fox

Radius & elevation

rounded-sm

rounded-md

rounded-lg

rounded-xl

rounded-2xl

rounded-full

shadow-xs

shadow-sm

shadow-md

shadow-lg

Primitives

The small stuff. Every component takes a class prop that is merged with tailwind-merge, so a one-off override does not need a new variant. Small, but they get the job done.

Button variants

Six ways to get pushed.

Sizes, icons and state

As a link

Badge

Label things. It helps everyone know where they stand.

Draft Featured Active Pending Overdue New v0.1.0 Hard-coded

Avatar

With or without a picture. No pressure.

LW TF MV JK
IB OP PR

Inline marks

Press ⌘ K to open the palette, or Esc if it all gets a bit much.

Install with bun add @joshicodes/cock and import from '@joshicodes/cock'. Say it with confidence.

CopyButton

Copies a value and confirms it in place.

ThemeToggle

Switches light and dark through the theme state and remembers the choice. Some prefer it with the lights off.

Loading

For when it takes a while to get going.

Separator

Sometimes you just need a little space.

or
Drafts Published Archived

Layout

Cards come in parts: header, content and footer. Skip them and set the padding prop when you only need a box. Comes in four positions.

Card

Weekly digest

Goes out every Monday at 8:00.

Scheduled

1,284 subscribers. Last week's issue was opened by 61 percent of them, which is better than most meetings manage.

Feedback on the name

Collected from fourteen standups.

  • "Can we not?" — everyone, at first
  • "It's growing on me." — most of them, later
  • "Bigger than I expected." — the one who read the docs

Card variants

Flat by default. Elevated adds depth, raised lifts when you hover it, flat fills instead of outlining.

Default

A border, nothing else.

Elevated

Sits a little higher than the rest.

Raised

Hover it. It rises to the occasion.

Flat

Filled, no outline.

Empty state

No messages yet

Don't worry, it happens to everyone. Messages will show up here once they arrive.

Forms

Every control works with bind:value or bind:checked. Field connects the label, help text and error message to the control, including the aria attributes. They handle input really well.

Field

Pass the generated id straight through to the control.

Decides the currency at checkout.

Input

Textarea

Checkbox, radio, switch

Checkbox

Radio

Switch

Slider

Morning crow volume 65%

PinInput

One box per character. Paste and one-time-code autofill land in the right boxes.

TagInput

Enter or a comma adds a tag, Backspace in an empty field removes the last one.

design svelte long walks

Inside a form

Field, Input, Textarea, Checkbox and Button in a plain <form>. Nothing is intercepted.

Plain text, no attachments.

Feedback

Alerts sit in the page and stay until something changes. Toasts are for results that arrive after the user has moved on. Nobody likes to be left hanging.

Alert

Progress

Getting it up 42%

Indeterminate

ProgressRing

The round version, for compact spots and dashboards.

72% 92% 38%

Toast

Tooltip

Overlays

Each one renders into <body> and positions itself against its trigger, which is why a scrolling table or an overflow-hidden card never cuts them off. Escape closes, focus goes back where it came from. They always end up on top.

Modal

Drawer

Dropdown menu

Arrow keys move between items, Escape closes.

CommandPalette

Fuzzy search over a list of commands. The shortcut works anywhere on this page.

Popover

A positioned panel. Put whatever you want in it.

Data

Table only styles plain thead and tbody markup. Sorting and selection are left out on purpose: every project wants them slightly differently. Big numbers, no exaggeration.

Stat

Eggs this week

142

+12 vs last week

Average weight

63 g

+2 g above average

Lost to foxes

1

+1 this month

Water left

82%

0%

Sparkline

A trend without a chart library. Stretches to fill its container.

Eggs per day

21

Fox sightings

3 this week

Coop temperature

18 °C

Heatmap

One cell per day, shaded with the accent. With fit it fills the width. Hover a cell for its value.

Table

tone='accent' carries the theme into the header and rows. Click a row to select it.

NameBreedStatusEggs this weekLast seenActions
H Henrietta
Orpington Laying6Just now
G Gertrude
Sussex Broody110 min ago
M Mabel
Leghorn Laying71 h ago
D Doris
Silkie Molting0Under the shed

Dense and striped

Egg log, Coop 2. Sizes vary.
DayNestWeight
MondayBox 161 g
MondayBox 364 g
TuesdayFlower bed58 g
TuesdayBox 271 g

Effects

Small animated pieces for landing pages and empty states. All of them settle on the final text when the visitor prefers reduced motion, and screen readers get the full text instead of the animation. They all know when to stop.

Terminal

Types commands, prints output. Waits until it is on screen before it starts.

~/farm
$ bun run count-flock
Coop 1  ......  6 hens
Coop 2  ......  6 hens
Rooster ......  on the roof again
12 of 12 accounted for

Typewriter

Types, pauses, deletes and moves on. One string types once; an array cycles.

Wake up to fresh eggs, a finished UI, a very loud bird, morning glory

All twelve hens accounted for. Nothing else to do.

Caret

The blinking bar on its own, for prompts and fake inputs. Stands up straight, never gets tired.

~/farm $ bun run dev
bar block underline

Scramble

Settles from random glyphs into the text. Plays when it scrolls into view, on hover, or whenever the text changes.

Asleep Hover this line. It likes the attention.

CountUp

Counts to its value once it is on screen, and from the old value to the new one after that.

Eggs since March

12,840

Mornings he was on time

99.95%

Odometer

Each digit rolls to its new value, like a mechanical counter.

People who giggled at the package name

1,284

Marquee

Scrolls its content in a loop and pauses on hover. Fills the width however short the content is. It just keeps going.

SvelteKit Tailwind 4 Runes OKLCH color-mix TypeScript Vite Bun GitHub Packages
SvelteKit Tailwind 4 Runes OKLCH color-mix TypeScript Vite Bun GitHub Packages

Highlight

A marker stroke that draws itself once the text is on screen.

Size isn't everything. It's what you do with it that counts.

confetti()

A function, not a component. Bursts from an element or a point and cleans up after itself.

Reveal

Fades content in as it scrolls into view. Anything already visible on load is left alone.

Step 1

Foreplay

Step 2

Build

Step 3

Ship

cock. Yes, it stands for core component kit. We checked twice.

Source on GitHub