Cards & Grids

Pixel UI Kit

A pixel-art UI trio — a stepped-border card, a pixel button that sinks on press, and a block-by-block progress bar, all drawn with box-shadow and CSS.

One component, three sub-components: PixelUiKit is the container that owns the size and accent colour (written to --wb-pixel-accent), with PixelUiKit.Card, PixelUiKit.Button and PixelUiKit.Progress attached as static properties. No pixel border uses an image — stacked box-shadow layers push one cell out on each side and leave the corners empty, giving a stepped, notched corner. Cards jump one cell on hover, buttons hard-cut down when pressed, and the progress bar lights up cell by cell. Typography is left to your site; the component only uses font-mono.

Bring this into your project

Run this command in your project folder. The CLI adds the source and dependencies; then follow the usage example below.

npx webberui@latest add pixel-ui-kit.en

New project or installation trouble? Start here →

Playground

Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.

20
4
Active edited usageDefault props
<PixelUiKit/>

The complete example includes the preview layout and data. Install the component first, then paste this file into your project.

Installation

npx webberui@latest add https://webberui.com/r/pixel-ui-kit.en.json

Or, once registries are configured in components.json, install it as @webberui/pixel-ui-kit.

Usage

import { PixelUiKit } from "@/components/ui/pixel-ui-kit";

const [days, setDays] = React.useState(3);

<PixelUiKit size="md" accent="#22c55e">
  <PixelUiKit.Card title="Level 1">
    <p>Daily check-in {days}/5</p>
    <PixelUiKit.Progress value={(days / 5) * 100} label="Check-in progress" striped />
    <PixelUiKit.Button variant="secondary" onClick={() => setDays((d) => Math.min(5, d + 1))}>
      +1
    </PixelUiKit.Button>
    <PixelUiKit.Button variant="primary" disabled={days < 5}>
      Claim reward
    </PixelUiKit.Button>
  </PixelUiKit.Card>
</PixelUiKit>

Props

PixelUiKit

PropTypeDefaultDescription
size"sm" | "md""md"Kit size: affects font size, padding and progress bar height
accentstring"#22c55e"Accent colour, written to --wb-pixel-accent; used by primary buttons and the progress fill
childrenReactNode—Children (Card / Button / Progress or any content)
classNamestring—Passed through to the outermost container

PixelUiKit.Card

FieldTypeDefaultDescription
titleReactNode—Title bar text; the title bar is hidden when omitted
iconReactNode—Optional icon at the left of the title bar, gets image-rendering: pixelated
childrenReactNode—Card content
classNamestring—Passed through to the card root

PixelUiKit.Button

FieldTypeDefaultDescription
variant"primary" | "secondary" | "danger""primary"Appearance: primary (accent), secondary (neutral), danger (red)
childrenReactNode—Button content
onClick(event: MouseEvent) => void—Click handler
disabledbooleanfalseDisables the button
type"button" | "submit" | "reset""button"Native button type
classNamestring—Passed through to the button element

PixelUiKit.Progress

FieldTypeDefaultDescription
valuenumber—Controlled progress value (0–100); falls back to defaultValue when omitted
defaultValuenumber0Initial progress value for uncontrolled mode (0–100)
segmentsnumber20Number of segments
stripedbooleanfalseShow looping stripes on filled segments
labelstring"Progress"Progress bar name, used as aria-label and shown above the bar (the Chinese registry defaults to "進度" (Progress))
classNamestring—Passed through to the progress root

CSS variables

FieldTypeDefaultDescription
--wb-pixel-sizelength4pxEdge length of one pixel cell; override on any ancestor
--wb-pixel-accentcolor#22c55eAccent colour (written by the accent prop)
--wb-pixel-steptime40msDelay between cells lighting up in the progress bar
--wb-pixel-presstime60msDuration of the button sink and the card jump

How it works

  • Stepped border: four box-shadow layers each push one --wb-pixel-size cell out from a side, leaving the corners empty — the notched outline familiar from pixel games. Cards add a dark drop shadow offset two cells to the bottom right.
  • On hover the card moves up one cell with steps(2) — it jumps instead of sliding — and returns while pressed.
  • Buttons have a two-cell bottom edge; on press they hard-cut with steps(1): the whole button sinks two cells and the edge drops to zero, so the top edge stays put and it reads as a key being pushed in.
  • The progress bar splits 0–100 into segments cells; each lights up or dims via a 0s transition plus an increasing delay of --wb-pixel-step. With striped, filled cells show stripes looping with steps(4).
  • Line, surface and shadow colours are CSS variables set on the container for light and dark, so the sub-components follow the theme.

Accessibility

  • PixelUiKit.Button is a real <button> with type="button" by default; keyboard focus shows a 2px dashed pixel outline
  • When a card has a title, it is linked to the card via aria-labelledby
  • PixelUiKit.Progress is role="progressbar" with aria-label, aria-valuenow, aria-valuemin, aria-valuemax and aria-valuetext; a text percentage is shown besides colour
  • When the system "reduce motion" setting is on, cards do not jump on hover, the progress bar fills straight to its target and the stripes do not animate