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
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,17 +72,18 @@ pnpm dlx shadcn@latest add radiumcoders/23rd.dev/gooey-color-picker

## Components

| Component | Install | Description |
| ------------------------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------- |
| [ASCII Fluid](https://23rd.dev/docs/components/ascii-fluid) | `@23rd/ascii-fluid` | Mouse-trail WebGL fluid quantized to a clean ASCII brightness ramp |
| [ASCII Logo](https://23rd.dev/docs/components/ascii-logo) | `@23rd/ascii-logo` | Interactive ASCII wordmark — hover shove, then click to scatter, drop, and gather |
| [Gooey Color Picker](https://23rd.dev/docs/components/gooey-color-picker) | `@23rd/gooey-color-picker` | Floating swatch → hue wheel, alpha, hex — joined by an SVG gooey filter |
| [Logo Burst](https://23rd.dev/docs/components/logo-burst) | `@23rd/logo-burst` | Hair-line tentacles explode from the center, then breathe — light and dark |
| [Radiant Lines](https://23rd.dev/docs/components/radiant-lines) | `@23rd/radiant-lines` | Hyperspace starfield background; warp speed driven by scroll |
| [Shader Fire](https://23rd.dev/docs/components/shader-fire) | `@23rd/shader-fire` | Sparse 2D fire wash — tongues rise from the bottom behind a landing hero |
| [Shader Gradient](https://23rd.dev/docs/components/shader-gradient) | `@23rd/shader-gradient` | Quiet WebGL wash behind landing heroes, empty states, and marketing sections |
| [Stretchy Footer](https://23rd.dev/docs/components/stretchy-footer) | `@23rd/stretchy-footer` | Dia-style rubber overscroll; aurora stretches past the bottom, then snaps back |
| [Tangle Footer](https://23rd.dev/docs/components/tangle-footer) | `@23rd/tangle-footer` | Nested SVG text ribbons as a footer |
| Component | Install | Description |
| ------------------------------------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
| [ASCII Fluid](https://23rd.dev/docs/components/ascii-fluid) | `@23rd/ascii-fluid` | Mouse-trail WebGL fluid quantized to a clean ASCII brightness ramp |
| [ASCII Logo](https://23rd.dev/docs/components/ascii-logo) | `@23rd/ascii-logo` | Interactive ASCII wordmark — hover shove, then click to scatter, drop, and gather |
| [Gooey Color Picker](https://23rd.dev/docs/components/gooey-color-picker) | `@23rd/gooey-color-picker` | Floating swatch → hue wheel, alpha, hex — joined by an SVG gooey filter |
| [Logo Burst](https://23rd.dev/docs/components/logo-burst) | `@23rd/logo-burst` | Hair-line tentacles explode from the center, then breathe — light and dark |
| [Phosphor Score](https://23rd.dev/docs/components/phosphor-score) | `@23rd/phosphor-score` | Vertical CRT sheet music — notes fall, bloom at the playhead, then exit in a flare |
| [Radiant Lines](https://23rd.dev/docs/components/radiant-lines) | `@23rd/radiant-lines` | Hyperspace starfield background; warp speed driven by scroll |
| [Shader Fire](https://23rd.dev/docs/components/shader-fire) | `@23rd/shader-fire` | Sparse 2D fire wash — tongues rise from the bottom behind a landing hero |
| [Shader Gradient](https://23rd.dev/docs/components/shader-gradient) | `@23rd/shader-gradient` | Quiet WebGL wash behind landing heroes, empty states, and marketing sections |
| [Stretchy Footer](https://23rd.dev/docs/components/stretchy-footer) | `@23rd/stretchy-footer` | Dia-style rubber overscroll; aurora stretches past the bottom, then snaps back |
| [Tangle Footer](https://23rd.dev/docs/components/tangle-footer) | `@23rd/tangle-footer` | Nested SVG text ribbons as a footer |

```tsx
import { GooeyColorPicker } from "@/components/ui/gooey-color-picker"
Expand Down
1 change: 1 addition & 0 deletions content/docs/components/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"pages": [
"---Background---",
"logo-burst",
"phosphor-score",
"radiant-lines",
"ascii-fluid",
"---Shaders---",
Expand Down
86 changes: 86 additions & 0 deletions content/docs/components/phosphor-score.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Phosphor Score
description: Vertical CRT sheet music — notes slide down the staves, bloom at the playhead, then exit in a flare.
---

import { PhosphorScoreDemo } from "@/registry/phosphor-score/phosphor-score-demo"

A falling score, not a piano roll. Two vertical staves, beamed runs, dynamics, and a scan line: notes dim on the way down, bloom in the phosphor color as they play, then flare out. Default `theme="auto"` follows the site — phosphor on black, forest ink on the page background. `glow` is 0–100 (default `50`) and stays a tight halo on the note. Press `d` to toggle.

<PhosphorScoreDemo />

## Installation

<CliCommand item="phosphor-score" />

Or install straight from the public GitHub source registry:

<CliCommand item="phosphor-score" github />

## Usage

Give the parent a size. The canvas fills the parent.

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

import { PhosphorScore } from "@/components/ui/phosphor-score"

export function HeroScore() {
return (
<div className="relative h-svh w-full bg-background">
<PhosphorScore />
</div>
)
}
```
</FrameworkReact>
<FrameworkSvelte>
```svelte
<script>
import PhosphorScore from "$lib/components/ui/phosphor-score.svelte"
</script>

<div class="relative h-svh w-full bg-background">
<PhosphorScore />
</div>
```
</FrameworkSvelte>
</FrameworkCode>

Lock a theme or push the bloom. Omit `color` to follow light / dark.

<FrameworkCode>
<FrameworkReact>
```tsx
<PhosphorScore theme="light" glow={50} />
<PhosphorScore theme="dark" color="#4DFF6A" glow={50} />
```
</FrameworkReact>
<FrameworkSvelte>
```svelte
<PhosphorScore theme="light" glow={50} />
<PhosphorScore theme="dark" color="#4DFF6A" glow={50} />
```
</FrameworkSvelte>
</FrameworkCode>

`prefers-reduced-motion: reduce` freezes the scroll and the camera drift, and keeps a still frame of the score.

## Props

| Prop | Type | Default |
| ----------- | ----------------------------- | --------------------------------------- |
| `color` | `string` | theme phosphor / forest ink |
| `glow` | `number` | `50` — 0–100, halo size at the playhead |
| `speed` | `number` | `1.35` — beats per second |
| `density` | `number` | `1` — how packed the notation is |
| `sway` | `boolean` | `true` — slow camera drift |
| `seed` | `number` | `23` |
| `theme` | `"light" \| "dark" \| "auto"` | `"auto"` |
| `className` | `string` | React only |
| `class` | `string` | Svelte only |

Omit `color` and `theme="auto"` picks phosphor green on dark, forest ink on light. The canvas is transparent in light mode so the parent background shows through.
18 changes: 9 additions & 9 deletions content/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Or pull straight from the public GitHub source registry:

<CliCommand item="shader-gradient" github />

Swap `shader-gradient` for any item name — `shader-fire`, `live-orb`, `ascii-logo`, `logo-burst`, `radiant-lines`, `dithered-404`, `tangle-footer`, and so on. Svelte installs as `@23rd/<name>-svelte` and lands in `src/lib/components/ui/` so `$lib` imports resolve.
Swap `shader-gradient` for any item name — `shader-fire`, `live-orb`, `ascii-logo`, `logo-burst`, `phosphor-score`, `radiant-lines`, `dithered-404`, `tangle-footer`, and so on. Svelte installs as `@23rd/<name>-svelte` and lands in `src/lib/components/ui/` so `$lib` imports resolve.

## Use a background or shader

Expand Down Expand Up @@ -54,11 +54,11 @@ Shaders such as [Shader Gradient](/docs/components/shader-gradient) and [Shader

## Browse

| Category | Components |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Background | [Logo Burst](/docs/components/logo-burst), [Radiant Lines](/docs/components/radiant-lines), [ASCII Fluid](/docs/components/ascii-fluid) |
| Shaders | [Shader Gradient](/docs/components/shader-gradient), [Shader Fire](/docs/components/shader-fire) |
| Footers | [Tangle Footer](/docs/components/tangle-footer), [Stretchy Footer](/docs/components/stretchy-footer) |
| Characters | [Live Orb](/docs/components/live-orb), [ASCII Logo](/docs/components/ascii-logo) |
| Pages | [Dithered 404](/docs/components/dithered-404) |
| Components | [Gooey Color Picker](/docs/components/gooey-color-picker) |
| Category | Components |
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Background | [Logo Burst](/docs/components/logo-burst), [Phosphor Score](/docs/components/phosphor-score), [Radiant Lines](/docs/components/radiant-lines), [ASCII Fluid](/docs/components/ascii-fluid) |
| Shaders | [Shader Gradient](/docs/components/shader-gradient), [Shader Fire](/docs/components/shader-fire) |
| Footers | [Tangle Footer](/docs/components/tangle-footer), [Stretchy Footer](/docs/components/stretchy-footer) |
| Characters | [Live Orb](/docs/components/live-orb), [ASCII Logo](/docs/components/ascii-logo) |
| Pages | [Dithered 404](/docs/components/dithered-404) |
| Components | [Gooey Color Picker](/docs/components/gooey-color-picker) |
1 change: 1 addition & 0 deletions content/docs/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ Most component kits hand you every option. 23rd picks a direction: spacing, radi
- [Shader Gradient](/docs/components/shader-gradient) — quiet wash behind a landing hero
- [Shader Fire](/docs/components/shader-fire) — sparse fire tongues under a landing hero
- [Logo Burst](/docs/components/logo-burst) — hair-line tentacles explode from the center, then breathe
- [Phosphor Score](/docs/components/phosphor-score) — vertical CRT sheet music that falls and flares
- [Radiant Lines](/docs/components/radiant-lines) — hyperspace starfield background
- [Dithered 404](/docs/components/dithered-404) — Bayer-pixel 404 that burns under a fireball cursor
15 changes: 15 additions & 0 deletions public/r/phosphor-score-svelte.json

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions public/r/phosphor-score.json

Large diffs are not rendered by default.

26 changes: 26 additions & 0 deletions public/r/registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,32 @@
],
"type": "registry:ui"
},
{
"name": "phosphor-score",
"title": "Phosphor Score",
"description": "Vertical sheet music on a CRT phosphor — notes fall, bloom at the playhead, then exit in a flare.",
"files": [
{
"path": "registry/phosphor-score/phosphor-score.tsx",
"type": "registry:ui",
"target": "components/ui/phosphor-score.tsx"
}
],
"type": "registry:ui"
},
{
"name": "phosphor-score-svelte",
"title": "Phosphor Score",
"description": "Vertical sheet music on a CRT phosphor — notes fall, bloom at the playhead, then exit in a flare.",
"files": [
{
"path": "registry/phosphor-score/phosphor-score.svelte",
"type": "registry:file",
"target": "src/lib/components/ui/phosphor-score.svelte"
}
],
"type": "registry:ui"
},
{
"name": "radiant-lines",
"title": "Radiant Lines",
Expand Down
1 change: 1 addition & 0 deletions registry.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"registry/gooey-color-picker/registry.json",
"registry/live-orb/registry.json",
"registry/logo-burst/registry.json",
"registry/phosphor-score/registry.json",
"registry/radiant-lines/registry.json",
"registry/shader-fire/registry.json",
"registry/shader-gradient/registry.json",
Expand Down
128 changes: 128 additions & 0 deletions registry/phosphor-score/phosphor-score-demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
"use client"

import { useLayoutEffect, useMemo } from "react"

import {
ComponentControls,
ControlColor,
ControlSlider,
ControlSwitch,
} from "@/components/component-controls"
import { ComponentPreview } from "@/components/component-preview"
import { useHydratedTheme } from "@/hooks/use-hydrated-theme"
import { usePreviewProps } from "@/hooks/use-preview-props"
import {
DARK_COLOR,
DEFAULT_DENSITY,
DEFAULT_GLOW,
DEFAULT_SPEED,
LIGHT_COLOR,
PhosphorScore,
} from "@/registry/phosphor-score/phosphor-score"

function norm(hex: string) {
return hex.trim().toUpperCase()
}

function isStockColor(color: string) {
return norm(color) === norm(LIGHT_COLOR) || norm(color) === norm(DARK_COLOR)
}

export function PhosphorScoreDemo() {
const theme = useHydratedTheme()
const stock = theme === "dark" ? DARK_COLOR : LIGHT_COLOR

const defaults = useMemo(
() => ({
color: stock,
glow: DEFAULT_GLOW,
speed: DEFAULT_SPEED,
density: DEFAULT_DENSITY,
sway: true,
}),
[stock]
)

const { props, updateProp, resetProps, hasChanges, setProps } =
usePreviewProps(defaults)

useLayoutEffect(() => {
setProps((prev) => {
if (!isStockColor(prev.color)) return prev
if (norm(prev.color) === norm(stock)) return prev
return { ...prev, color: stock }
})
}, [setProps, stock])

const useAutoColor = isStockColor(props.color)

return (
<>
<ComponentPreview
title="Phosphor Score"
stageClassName="min-h-0 overflow-hidden bg-background p-0"
>
<div className="relative h-[56svh] w-full bg-background">
<PhosphorScore
color={useAutoColor ? undefined : props.color}
glow={props.glow}
speed={props.speed}
density={props.density}
sway={props.sway}
theme="auto"
/>
</div>
</ComponentPreview>

<ComponentControls
hasChanges={hasChanges}
onReset={resetProps}
component="PhosphorScore"
snippetProps={{
color: useAutoColor ? undefined : props.color,
glow: props.glow === DEFAULT_GLOW ? undefined : props.glow,
speed: props.speed === DEFAULT_SPEED ? undefined : props.speed,
density:
props.density === DEFAULT_DENSITY ? undefined : props.density,
sway: props.sway ? undefined : false,
}}
>
<ControlColor
label="Phosphor"
value={props.color}
onChange={(v) => updateProp("color", v)}
/>
<ControlSlider
label="Glow"
value={props.glow}
min={0}
max={100}
step={1}
onChange={(v) => updateProp("glow", v)}
/>
<ControlSlider
label="Speed"
value={props.speed}
min={0.3}
max={3}
step={0.05}
onChange={(v) => updateProp("speed", v)}
/>
<ControlSlider
label="Density"
value={props.density}
min={0.4}
max={1.8}
step={0.05}
onChange={(v) => updateProp("density", v)}
/>
<ControlSwitch
label="Sway"
description="Slow camera drift around the plane"
checked={props.sway}
onChange={(v) => updateProp("sway", v)}
/>
</ComponentControls>
</>
)
}
Loading
Loading