npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

phosphor-ui

v0.5.4

Published

Phosphor UI — single-channel green-phosphor React component library. Retro/military/cyberpunk CRT aesthetic.

Readme

npm version npm downloads license Storybook TypeScript


Install

npm install phosphor-ui

Peer deps: react ^17 || ^18 || ^19, react-dom ^17 || ^18 || ^19. @mdx-js/react ^2 || ^3 is optional for MDX applications, but the package root does not load it at module initialization.

Setup

Import the full stylesheet once at your app root:

import "phosphor-ui/phosphor.css";

If you need finer control, import tokens.css, global.css, and components.css separately.

CSS import matrix

| Import | Use when | |---|---| | phosphor-ui/phosphor.css | You want the full default theme: fonts, tokens, typography, global defaults, effects, and component styles. | | phosphor-ui/tokens.css | You only need the public --pho-* design tokens. | | phosphor-ui/fonts.css | You want the bundled Bender, JetBrains Mono, and VCR OSD fonts. | | phosphor-ui/typography.css | You want typography utility classes without all globals. | | phosphor-ui/global.css | You want element defaults, cursors, scrollbars, focus helpers, and effect utility classes. | | phosphor-ui/components.css | You are composing React components and need their styles. |

For app code, prefer phosphor.css first. Use granular imports only when your app owns global typography, fonts, cursors, or decorative effects.

Themes

The default theme is green phosphor. Alternate CRT palettes are included in tokens.css and work by setting data-theme on a wrapper or on <html>:

<html data-theme="cyan">

Supported values are phosphor, amber, and cyan.

Tokens

Use the --pho-* tokens for app-level customization. The older raw tokens (--phosphor, --bg, --magenta, etc.) still work, but the semantic names are the stable consumer API.

:root {
  --pho-color-background: #04140a;
  --pho-color-primary: #2cff7a;
  --pho-color-accent: #62ff9a;
  --pho-size-prose: 72ch;
}

.noteShell {
  max-width: var(--pho-size-prose);
  color: var(--pho-color-text);
  border: var(--pho-border-line);
  box-shadow: var(--pho-glow-primary-soft);
}

For TypeScript tooling, token names are exported from the package:

import { PHOSPHOR_TOKEN_GROUPS, phosphorVar } from "phosphor-ui";

const linkColor = phosphorVar("--pho-color-link");

Quick start

import { SiteShell, Post, Callout } from "phosphor-ui";
import "phosphor-ui/phosphor.css";

export default function App() {
  return (
    <SiteShell
      title="field notes"
      tagline="personal wiki / project log"
      nav={[
        { label: "notes", href: "/notes", active: true },
        { label: "projects", href: "/projects" },
      ]}
      footerLinks={[{ label: "rss", href: "/rss.xml" }]}
    >
      <Post
        title="Boot sequence"
        headerProps={{
          eyebrow: "log / systems",
          meta: { date: "2026-05-09", readTime: "3 min", tags: ["wiki"] },
        }}
      >
        <p>Use normal React or MDX content inside the post body.</p>
        <Callout title="signal">
          The shell includes a CRT frame, accessible skip link, header, content
          region, and footer.
        </Callout>
      </Post>
    </SiteShell>
  );
}

Import Model

Use the root package for application code:

import { SiteShell, Post, Button, Callout, TableOfContents } from "phosphor-ui";

The physical folders are organized for maintainers. Consumers should prefer the stable root exports so components can move internally without breaking your site.

Components

| Group | Components | |---|---| | Presets | SiteShell | | Layout | AppShell PageShell SidebarLayout SplitLayout SplitPane Section Panel ContentShell ContentFrame ContentWidth Container Stack Inline Cluster Grid AutoGrid ResponsiveColumns DashboardGrid Row Column | | Chrome | CrtShell Header Footer HeroFrame NerdTree PdaWindow Post | | Content | Prose PostBody Callout CodeBlock Hr Tag Text AsciiBanner TerminalPrompt | | Lists | PostListing PostRow CourseCard LessonRow ModuleAccordion PrereqList Exercise | | Nav | Breadcrumbs Pagination SeriesNav Stepper TableOfContents Link | | Form | Button Input Textarea Checkbox Select DropdownMenu Badge | | Feedback | ProgressBar ReadingRail StatPill Toast Tooltip VideoPlayer |

Recipes

Course cards

<CourseCard
  stamp="COURSE-01"
  thumbSrc="/images/course-frame.png"
  coverMeta="6 modules"
  tag="entry"
  title="Cold-boot operations"
  progress={{ value: 4, total: 6 }}
  cta={{ label: "resume", href: "/courses/cold-boot" }}
/>

For a compact text-only card, remove the cover column:

<CourseCard showCover={false} title="Reference index" cta={{ label: "open", href: "/ref" }} />

Admin editors

<ContentEditor
  kindLabel="POST"
  autoSlug={{ from: "title", to: "slug" }}
  fields={[
    { kind: "text", key: "title", label: "TITLE" },
    { kind: "textarea", key: "body", label: "BODY", rows: 12 },
    { kind: "tags", key: "tags", label: "TAGS" },
  ]}
/>

Personal Site Pattern

For blogs, digital gardens, and second brains, start with SiteShell and add pages with Post:

<SiteShell title="notes" nav={navItems}>
  <Post title="Now page" sidebar={<TableOfContents items={toc} />}>
    <NowPageMdx />
  </Post>
</SiteShell>

Reach for lower-level components when you need custom app structure:

<CrtShell>
  <Header title="lab" />
  <main>
    <NerdTree nodes={nodes} />
    <Prose>{children}</Prose>
  </main>
  <Footer brand="lab" />
</CrtShell>

Layout primitives

Use layout primitives before writing custom page CSS. They cover the common app shapes for blogs, wikis, portfolios, course pages, and admin dashboards.

import {
  AutoGrid,
  ContentFrame,
  Inline,
  PageShell,
  Panel,
  Section,
  SidebarLayout,
  Stack,
  Tag,
} from "phosphor-ui";

export function WikiPage({ nav, toc, children }) {
  return (
    <PageShell
      eyebrow="wiki"
      title="Packet capture checklist"
      description="Reusable runbook for tracing a failing ingestion job."
      actions={<Inline><Tag>runbook</Tag><Tag>ops</Tag></Inline>}
    >
      <SidebarLayout
        left={nav}
        sidebarLabel="content tree"
        right={toc}
        asideLabel="table of contents"
        collapseAt="lg"
      >
        <ContentFrame>
          {children}
        </ContentFrame>
      </SidebarLayout>
    </PageShell>
  );
}

For listing pages, combine Section, AutoGrid, and Panel:

<Section title="Projects" description="Active builds and field notes.">
  <AutoGrid minItemWidth="18rem">
    <Panel title="Terminal CMS" meta="active">
      <p>Admin publishing tools and content workflows.</p>
    </Panel>
    <Panel title="Course Platform" meta="draft">
      <p>Modules, lessons, progress, and media playback.</p>
    </Panel>
  </AutoGrid>
</Section>

For dashboards, use DashboardGrid so cards align consistently:

<DashboardGrid minItemWidth="14rem">
  <Panel title="Drafts" meta="12">Waiting for review.</Panel>
  <Panel title="Published" meta="48" tone="accent">Live entries.</Panel>
</DashboardGrid>

SidebarLayout accepts both the legacy sidebar/aside props and the preferred left/main/right slot names. New code should use left, main or children, and right.

MDX posts

import { PostBody } from "phosphor-ui";
import PostMdx from "./posts/boot.mdx";

<PostBody>
  <PostMdx />
</PostBody>

PostBody wraps content in <Prose>. Use mdxComponents with your MDX provider/compiler to map native MDX tags (h1-h6, pre, blockquote, img, hr, a) to phosphor components. Fenced code blocks render via <CodeBlock> with Shiki syntax highlighting.

Hooks

import { useReadingProgress, useHashRoute } from "phosphor-ui";
  • useReadingProgress<T>(){ ref, pct } — tracks element scroll percentage, pair with <ReadingRail value={pct} />
  • useHashRoute({ routes, fallback })[route, go] — hash-based router with regex/predicate matchers

Animation utilities

Included in global.css:

| Class | Effect | |---|---| | .pho-page-enter | CRT blur + brightness fade-in | | .pho-fade-up | translate + opacity fade | | .pho-stagger > * | auto-staggered children (40–520ms) | | .pho-flicker-in | multi-step CRT flicker | | .pho-blink::after | phosphor block cursor |

All respect prefers-reduced-motion.

Develop

npm install
npm run storybook        # http://localhost:6006
npm run typecheck
npm run build            # rollup → dist/
npm run build-storybook  # static → storybook-static/

Release checks

Before publishing a stable release, run the package validation flow:

npm run validate:package

This runs TypeScript checks, public API export checks, story source audits, Jest, the library build, and a package smoke test against the generated dist/ artifacts. For public API changes, refresh the checked-in declaration snapshot:

npm run build:types:snapshot

Pushes to prod are protected by the tracked pre-push hook in .githooks/. Enable it once per clone:

git config core.hooksPath .githooks

The hook runs the package validation flow, checks that the next prod patch version is not already on npm, and runs npm publish --dry-run before allowing the push that triggers the real GitHub Actions publish.

The supported consumer API is the root import plus the documented CSS subpaths. Deep component imports are internal implementation details.

CI/CD

The GitHub Actions setup uses dev and prod as long-lived branches:

  • dev validates the package and publishes prereleases to npm with the next dist-tag.
  • prod validates the package, publishes the stable npm package with the latest dist-tag, and deploys Storybook to GitHub Pages.

See docs/branching-and-deploy.md for branch setup, required secrets, environments, and release behavior.

License

MIT © sektant1