Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .cursor/skills/23rd/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: 23rd
description: >
Install, choose, and compose 23rd shadcn/ui registry components for React and
Svelte 5. Use when the user wants a UI component, background, shader, WebGL
wash, liquid metal or chrome, hero atmosphere, footer, 404, color picker, typewriter text, ASCII effect,
wash, liquid metal or chrome, hero atmosphere, footer, 404, color picker, typewriter text, keyboard shortcut recorder, ASCII effect,
starfield, orb, or page-tilt from the 23rd registry (@23rd, 23rd.dev, radiumcoders/23rd.dev),
or when adding a new component to this registry. Covers install commands,
import paths, props, theming, and when not to use each item.
Expand Down Expand Up @@ -76,6 +76,7 @@ npm dependencies the registry declares:
| --- | --- | --- |
| `gooey-color-picker` | `motion` | none |
| `ring-tower` | `three` | `three` |
| `mech-keyboard` | `three` | `three` |
| every other item | none | none |

Published index: `https://23rd.dev/r/registry.json`. Docs: `https://23rd.dev/docs`.
Expand All @@ -93,6 +94,7 @@ flowchart TD
pick -->|Scroll makes the page lean| folio[folio]
pick -->|Character or wordmark| mark{Which}
pick -->|Type text out letter by letter| tw[typewriter]
pick -->|Show or record a keyboard shortcut| mk[mech-keyboard]
atmo -->|Quiet wash| sg[shader-gradient]
atmo -->|Cel-shaded fire from the bottom| saf[shader-anime-fire]
atmo -->|Sky or rain, optional glass| ss[shader-sky]
Expand Down Expand Up @@ -127,6 +129,7 @@ Disambiguation that agents get wrong:
| Rings, bands, or a tower of screenshots that spins | `ring-tower` | `shader-metal` (no images) |
| A face / orb / mascot | `live-orb` | `logo-burst` |
| Typing effect, typewriter, text that types itself | `typewriter` | `ascii-logo` (a wordmark, not prose) |
| Keyboard, keycaps, record a shortcut, onboarding hotkey step | `mech-keyboard` | `typewriter` (types prose, not chords) |

There is one variant enum in the whole registry: `LiveOrb` `variant` is `"white" | "black" | "webgl" | "custom"`. Nothing else has `variant`.

Expand Down Expand Up @@ -196,6 +199,7 @@ Categories match `content/docs/components/meta.json`.
| `folio` | Sections | Page leans on scroll, then springs flat | React + Svelte |
| `gooey-color-picker` | Components | Swatch opens into hue, alpha, and hex under an SVG goo filter | React + Svelte |
| `typewriter` | Components | A real typewriter in SVG: keys press, typebars strike, the carriage steps | React + Svelte |
| `mech-keyboard` | Components | Isometric 75% keyboard illustration; presses with yours and records shortcuts | React + Svelte |

## Minimal installs that must be right

Expand Down
31 changes: 31 additions & 0 deletions .cursor/skills/23rd/apis.md
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,37 @@ Also exported: `DEFAULT_COLOR`, `DEFAULT_TEXT`, `DEFAULT_SPEED`, `DEFAULT_COLUMN

Vanilla `TypewriterInstance`: `{ setOptions, restart, destroy }`. Not returned to app code by the React component; remount with a `key` to type again. No `ticks` or `theme` props; `color` is the only color prop and it paints the enamel.

## mech-keyboard

```ts
type MechKeyboardProps = {
x?: number // 0 px
y?: number // 0 px, +y is down
scale?: number // 1, times the fitted size
monochrome?: boolean // false: white and grey caps, ink only
interactive?: boolean // true: window keys and clicks press keys
recorder?: boolean // true: illustrated keycaps spelling out the chord
placeholder?: string // "Press a shortcut"
highlight?: string[] // KeyboardEvent.code values to pulse
platform?: "auto" | "mac" | "pc" // "auto": bottom-row legends and labels
sound?: boolean // false: synthesized switch sounds
intro?: boolean // true: rise into place with a wave across the keys
onKey?: (code: string, pressed: boolean) => void
onShortcut?: (shortcut: MechKeyboardShortcut) => void
className?: string
}

type MechKeyboardShortcut = {
codes: string[] // modifiers first
keys: string[] // one legend per key
label: string // "⌘⇧K" on Mac, "Ctrl+Shift+K" elsewhere
}
```

Also exported: `DEFAULT_PLACEHOLDER`, `buildLayout(platform)`, `formatShortcut(codes, platform)`, types `MechKeyboardKey`, `MechKeyboardPlatform`.

Vanilla `createMechKeyboard(root, stage, options)` returns `{ setOptions, replay, destroy }`. Not returned to app code by the React component; remount with a `key` to replay the intro.

## Events that are not props

| Name | Constant | Who listens |
Expand Down
25 changes: 25 additions & 0 deletions .cursor/skills/23rd/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,31 @@ Controlled when `value` is not `undefined`. Otherwise uncontrolled, seeded from

Pitfalls: the panel overflows the trigger. Do not put it in `overflow-hidden`. React also exports `parseColor`. No `className` on Svelte; use `class`.

## mech-keyboard

Component. A 75% mechanical keyboard drawn as an isometric illustration with three.js on a transparent canvas: a milled case, a volume knob, and 82 keycaps fading from dusty blue to off-white, shaded in three flat tone bands and outlined in ink, with ink legends. The visitor's keyboard presses the matching keys (window-wide, ignoring typing in inputs), clicks press them too (modifiers latch), and the recorder above draws the chord as small illustrated keycaps, then "Shortcut saved" on release.

Best fit: a "create a shortcut" step in onboarding, a keyboard-shortcuts page, or a hero that reacts to typing.

Not this: typed prose (`typewriter`), a text input, or a background behind other copy.

Deps: `three` (+ `@types/three`). Props: `x` / `y` (0, px), `scale` (1), `monochrome` (false), `interactive` (true), `recorder` (true), `placeholder` (`"Press a shortcut"`), `highlight` (codes to pulse), `platform` (`"auto"`), `sound` (false), `intro` (true), `onKey(code, pressed)`, `onShortcut(shortcut)`.

```tsx
"use client"
import { MechKeyboard } from "@/components/ui/mech-keyboard"

export function ShortcutStep() {
return (
<div className="h-[28rem] w-full overflow-hidden rounded-xl border bg-background">
<MechKeyboard onShortcut={(s) => console.log(s.label)} />
</div>
)
}
```

Pitfalls: give the parent a height; the keyboard fits itself inside it. The pose is fixed isometric: there are no rotation, `fov`, `z`, `fade`, `variant`, `colorway`, or `theme` props. Codes are `KeyboardEvent.code` (`"MetaLeft"`, `"KeyK"`), not `key`. `onShortcut` fires on release of the whole chord with `{ codes, keys, label }`; `label` is `"⌘⇧K"` on Mac and `"Ctrl+Shift+K"` elsewhere. While the keyboard has focus it calls `preventDefault` on every key but Tab, so it can record browser shortcuts. Needs WebGL; without it only the recorder renders. The knob turns under the wheel and with volume keys; clicking it records `AudioVolumeMute`.

## typewriter

Component. A real typewriter drawn in SVG. Every key is wired to its own typebar: a letter presses its key, swings that bar up out of the basket to strike the ribbon, lands on the sheet, and the carriage steps one character left. Capitals hold shift. At the margin the return lever kicks, the platen turns the paper up a line, and the carriage slides home. With `loop`, the sheet is pulled out and a fresh one rolls in.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ npx skills add radiumcoders/23rd.dev --skill 23rd -g
| [Shader Metal](https://23rd.dev/docs/components/shader-metal) | `@23rd/shader-metal` | Liquid chrome, gold, or copper ribbons; the key light follows the pointer |
| [Stretchy Footer](https://23rd.dev/docs/components/stretchy-footer) | `@23rd/stretchy-footer` | Dia-style rubber overscroll; aurora stretches past the bottom, then snaps back |
| [Typewriter](https://23rd.dev/docs/components/typewriter) | `@23rd/typewriter` | A playable typewriter in SVG; keys press, typebars strike, the carriage steps |
| [Mech Keyboard](https://23rd.dev/docs/components/mech-keyboard) | `@23rd/mech-keyboard` | An isometric keyboard illustration that presses with yours and records shortcuts |

```tsx
import { GooeyColorPicker } from "@/components/ui/gooey-color-picker"
Expand Down
6 changes: 6 additions & 0 deletions components/demos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ export const LogoBurstDemo = lazyDemo(() =>
import("@/registry/logo-burst/logo-burst-demo").then((m) => m.LogoBurstDemo)
)

export const MechKeyboardDemo = lazyDemo(() =>
import("@/registry/mech-keyboard/mech-keyboard-demo").then(
(m) => m.MechKeyboardDemo
)
)

export const PhosphorScoreDemo = lazyDemo(() =>
import("@/registry/phosphor-score/phosphor-score-demo").then(
(m) => m.PhosphorScoreDemo
Expand Down
100 changes: 100 additions & 0 deletions content/docs/components/mech-keyboard.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
title: Mech Keyboard
description: A 75% keyboard drawn as an isometric illustration that presses along with yours and records shortcuts.
---

import { MechKeyboardDemo } from "@/components/demos"

Press a few keys. It is a three.js scene drawn as an isometric illustration: a milled case around a recessed plate, a volume knob, and 82 keycaps fading from dusty blue at the back to off-white at the front, shaded in three flat tone bands and outlined in ink. Legends are printed in the same ink. Your keyboard drives the keys, and the recorder above spells out the chord, ready for a "create a shortcut" step in onboarding.

<MechKeyboardDemo />

## Installation

<CliCommand item="mech-keyboard" />

Or from the public GitHub registry:

<CliCommand item="mech-keyboard" github />

## Usage

Give the parent a size; the keyboard fits itself inside it.

<FrameworkCode>
<FrameworkReact>
```tsx
"use client"

import { MechKeyboard } from "@/components/ui/mech-keyboard"

export function ShortcutStep() {
return (
<div className="h-[28rem] w-full overflow-hidden rounded-xl border bg-background">
<MechKeyboard
onShortcut={(shortcut) => console.log(shortcut.label)}
/>
</div>
)
}
```
</FrameworkReact>
<FrameworkSvelte>
```svelte
<script>
import MechKeyboard from "$lib/components/ui/mech-keyboard.svelte"
</script>

<div class="h-[28rem] w-full overflow-hidden rounded-xl border bg-background">
<MechKeyboard
onShortcut={(shortcut) => console.log(shortcut.label)}
/>
</div>
```
</FrameworkSvelte>
</FrameworkCode>

`onShortcut` fires when every key of a chord is released. It gets `codes` (`KeyboardEvent.code`s, modifiers first), `keys` (one legend per key), and `label` (`"⌘⇧K"` on Mac, `"Ctrl+Shift+K"` elsewhere).

Keys listen on the window, but typing in an input, textarea, or contenteditable elsewhere on the page is ignored. While the keyboard itself has focus, the browser's own handling of those keys is prevented (except Tab), so it can record combos like `⌘S`. Clicking a modifier latches it; clicking another key then fires the chord.

Needs WebGL; without it the canvas stays empty and the recorder still works. The pose is fixed at true isometric. Move it, drop the color, or pulse the keys you want pressed:

<FrameworkCode>
<FrameworkReact>
```tsx
<MechKeyboard x={-40} y={20} scale={0.9} />
<MechKeyboard monochrome />
<MechKeyboard highlight={["MetaLeft", "KeyK"]} recorder={false} />
```
</FrameworkReact>
<FrameworkSvelte>
```svelte
<MechKeyboard x={-40} y={20} scale={0.9} />
<MechKeyboard monochrome />
<MechKeyboard highlight={["MetaLeft", "KeyK"]} recorder={false} />
```
</FrameworkSvelte>
</FrameworkCode>

`monochrome` swaps the blue caps for white and grey, leaving a pure ink drawing. The recorder draws each key of the chord as a small keycap in the same style; held keys sink into their skirts. The knob turns under the mouse wheel and with the volume keys, and clicking it records Mute.

## Props

| Prop | Type | Default |
| ------------- | ------------------------------------- | -------------------------- |
| `x` | `number` | `0`, px |
| `y` | `number` | `0`, px |
| `scale` | `number` | `1`, times the fitted size |
| `monochrome` | `boolean` | `false` |
| `interactive` | `boolean` | `true` |
| `recorder` | `boolean` | `true` |
| `placeholder` | `string` | `"Press a shortcut"` |
| `highlight` | `string[]` | none, codes to pulse |
| `platform` | `"auto" \| "mac" \| "pc"` | `"auto"`, bottom-row legends |
| `sound` | `boolean` | `false` |
| `intro` | `boolean` | `true` |
| `onKey` | `(code: string, pressed: boolean) => void` | none |
| `onShortcut` | `(shortcut: MechKeyboardShortcut) => void` | none |
| `className` | `string` | React only |
| `class` | `string` | Svelte only |
1 change: 1 addition & 0 deletions content/docs/components/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"folio",
"---Components---",
"gooey-color-picker",
"mech-keyboard",
"---Experiments---",
"phosphor-score",
"typewriter"
Expand Down
Binary file added public/og/docs/components/mech-keyboard/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions public/r/mech-keyboard-svelte.json

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions public/r/mech-keyboard.json

Large diffs are not rendered by default.

38 changes: 38 additions & 0 deletions public/r/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,44 @@
],
"type": "registry:ui"
},
{
"name": "mech-keyboard",
"title": "Mech Keyboard",
"description": "A 75% mechanical keyboard drawn as an isometric illustration in three.js, with ink outlines and a volume knob. Keys press along with your real keyboard, and a recorder spells out the shortcut for onboarding flows.",
"dependencies": [
"three"
],
"devDependencies": [
"@types/three"
],
"files": [
{
"path": "registry/mech-keyboard/mech-keyboard.tsx",
"type": "registry:ui",
"target": "components/ui/mech-keyboard.tsx"
}
],
"type": "registry:ui"
},
{
"name": "mech-keyboard-svelte",
"title": "Mech Keyboard",
"description": "A 75% mechanical keyboard drawn as an isometric illustration in three.js, with ink outlines and a volume knob. Keys press along with your real keyboard, and a recorder spells out the shortcut for onboarding flows.",
"dependencies": [
"three"
],
"devDependencies": [
"@types/three"
],
"files": [
{
"path": "registry/mech-keyboard/mech-keyboard.svelte",
"type": "registry:file",
"target": "src/lib/components/ui/mech-keyboard.svelte"
}
],
"type": "registry:ui"
},
{
"name": "phosphor-score",
"title": "Phosphor Score",
Expand Down
1 change: 1 addition & 0 deletions registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"registry/iso-lattice/registry.json",
"registry/live-orb/registry.json",
"registry/logo-burst/registry.json",
"registry/mech-keyboard/registry.json",
"registry/phosphor-score/registry.json",
"registry/radiant-lines/registry.json",
"registry/ring-tower/registry.json",
Expand Down
Loading
Loading