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

ceres-ui

v0.1.3

Published

A dark-themed UI component library for blog and content sites, built with React and CSS custom properties.

Downloads

16

Readme

ceres-ui

A React component library intended for blog creation. Ships with light & dark themes, plain CSS with overridable custom properties.

Installation

npm install ceres-ui
# or
pnpm add ceres-ui

Peer Dependencies

React and ReactDOM are required. Everything else is optional depending on which components you use:

| Peer dependency | Required by | Min version | | -------------------------- | ------------------------------------- | ----------- | | react | all | 18.0.0 | | react-dom | all | 18.0.0 | | react-syntax-highlighter | CodeBlock, MarkdownRenderer | 15.0.0 | | react-markdown | MarkdownRenderer | 10.0.0 | | remark-gfm | MarkdownRenderer | 4.0.0 | | remark-math | MarkdownRenderer (math blocks) | 6.0.0 | | rehype-raw | MarkdownRenderer (custom HTML tags) | 7.0.0 | | rehype-katex | MarkdownRenderer (math rendering) | 7.0.0 | | katex | MarkdownRenderer (math rendering) | 0.16.0 | | recharts | Chart | 2.0.0 |

Install only what you need:

# Only using Callout + Badge + DataTable (no extra deps)
pnpm add ceres-ui

# Using CodeBlock
pnpm add ceres-ui react-syntax-highlighter

# Using MarkdownRenderer (full)
pnpm add ceres-ui react-markdown react-syntax-highlighter remark-gfm remark-math rehype-raw rehype-katex katex

# Using Chart
pnpm add ceres-ui recharts

# Full installation (all components)
pnpm add ceres-ui react-markdown react-syntax-highlighter remark-gfm remark-math rehype-raw rehype-katex katex recharts

Quick Start

import { Callout, Badge, CodeBlock } from 'ceres-ui';
import 'ceres-ui/css';

function App() {
  return (
    <html data-theme="dark">
      <body>
        <div className="ceres-root">
          <Callout variant="tip" title="Hello">
            Welcome to ceres-ui.
          </Callout>

          <Badge label="Published" variant="success" />

          <CodeBlock language="typescript">{`const greeting: string = "Hello, world!";`}</CodeBlock>
        </div>
      </body>
    </html>
  );
}

Setup Checklist

  1. Import CSS — add import 'ceres-ui/css' once in your entry point.
  2. Set theme — add data-theme="dark" or data-theme="light" to your <html> element. Dark is the default.
  3. Wrap in .ceres-root — the root class enables themed scrollbars. Apply it to your outermost container.
  4. (Optional) Override fonts — set --ceres-font-heading on :root to use a custom heading font across all components. This applies in both light and dark theme.
/* In your app's global CSS */
:root {
  --ceres-font-heading: 'Inter', system-ui, sans-serif;
}

Theming

ceres-ui ships with two themes built from the Catppuccin palette:

| Theme | Attribute | Palette | | -------------- | -------------------- | ---------------- | | Dark (default) | data-theme="dark" | Catppuccin Mocha | | Light | data-theme="light" | Catppuccin Latte |

Switch themes by changing the data-theme attribute on <html>:

document.documentElement.setAttribute('data-theme', 'light');

Overriding Design Tokens

Every color, font, radius, and shadow is a CSS custom property. Override any of them:

:root {
  /* Custom heading font */
  --ceres-font-heading: 'Playfair Display', serif;

  /* Adjust the primary accent */
  --ceres-blue: #6366f1;
  --ceres-blue-hover: #818cf8;

  /* Change surface colors */
  --ceres-surface: #1a1a2e;
}

Full Token Reference

| Token | Dark (Mocha) | Light (Latte) | | ----------------- | ------------ | ------------- | | --ceres-bg-main | #0a0a0a | #eff1f5 | | --ceres-bg-post | #1a1a1a | #e6e9ef | | --ceres-surface | #1e1e2e | #ccd0da |

| Token | Dark (Mocha) | Light (Latte) | | ----------------------- | ------------ | ------------- | | --ceres-border | #313244 | #bcc0cc | | --ceres-border-subtle | #2a2a2a | #ccd0da | | --ceres-border-hover | #3a3a3a | #acb0be | | --ceres-border-strong | #4a4a4a | #9ca0b0 |

| Token | Dark (Mocha) | Light (Latte) | | -------------------------- | ------------ | ------------- | | --ceres-text-primary | #f5f5f0 | #4c4f69 | | --ceres-text-body | #cdd6f4 | #5c5f77 | | --ceres-text-muted | #a6adc8 | #6c6f85 | | --ceres-text-faint | #6c7086 | #8c8fa1 | | --ceres-text-dim | #585b70 | #9ca0b0 | | --ceres-text-description | #a0a0a0 | #6c6f85 |

| Token | Dark (Mocha) | Light (Latte) | | -------------------- | ------------ | ------------- | | --ceres-blue | #89b4fa | #1e66f5 | | --ceres-blue-hover | #b4befe | #7287fd | | --ceres-green | #a6e3a1 | #40a02b | | --ceres-red | #f38ba8 | #d20f39 | | --ceres-yellow | #f9e2af | #df8e1d | | --ceres-peach | #fab387 | #fe640b | | --ceres-purple | #cba6f7 | #8839ef | | --ceres-teal | #94e2d5 | #179299 | | --ceres-cyan | #89dceb | #04a5e5 | | --ceres-pink | #f5c2e7 | #ea76cb |

| Token | Default | | ---------------------- | ------------------------------------------------------------------ | | --ceres-font-heading | system-ui, -apple-system, sans-serif | | --ceres-font-body | system-ui, -apple-system, sans-serif | | --ceres-font-mono | ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace |

| Token | Value | | --------------------- | ----------------------------- | | --ceres-radius-sm | 4px | | --ceres-radius-md | 8px | | --ceres-radius-lg | 12px | | --ceres-radius-full | 9999px | | --ceres-shadow-sm | 0 1px 2px rgba(0,0,0,0.3) | | --ceres-shadow-md | 0 4px 12px rgba(0,0,0,0.3) | | --ceres-shadow-lg | 0 10px 25px rgba(0,0,0,0.4) |


Components

Callout

Alert boxes with 7 built-in variants.

import { Callout } from 'ceres-ui';

<Callout variant="warning" title="Heads up">
  This API is deprecated and will be removed in v3.
</Callout>

<Callout variant="tip">
  <ul>
    <li>Block-level children get a two-line layout</li>
    <li>Inline children share a line with the title</li>
  </ul>
</Callout>

| Prop | Type | Default | Description | | ----------- | ------------------------------------------------------------------------------ | -------------------- | ------------------------------ | | variant | 'note' \| 'important' \| 'critical' \| 'tip' \| 'warning' \| 'info' \| 'wip' | 'note' | Visual style and default title | | title | string | Derived from variant | Override the title text | | children | ReactNode | required | Callout body | | className | string | — | Additional CSS class |

Default titles: Note, Important, CRITICAL, Tip, Warning, Info, Work in Progress.

Layout behavior: when children contain block-level elements (<ul>, <ol>, <p>, <div>, headings), the title renders on its own line. Otherwise, title and content share a single line.


CodeBlock

Syntax-highlighted code with the Catppuccin Mocha Prism theme.

import { CodeBlock } from 'ceres-ui';

<CodeBlock language="python">
  {`def fibonacci(n: int) -> int:
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)`}
</CodeBlock>;

| Prop | Type | Default | Description | | ----------- | -------- | ------------ | --------------------------------------------------------------- | | language | string | — | Prism language identifier (e.g. typescript, python, bash) | | children | string | required | Code content (leading/trailing whitespace trimmed) | | className | string | — | Additional CSS class |

Requires: react-syntax-highlighter peer dependency.

The font uses --ceres-font-mono and scales responsively via clamp(0.75rem, 2.5vw, 0.875rem).


TableOfContents

Navigation component for page sections. Accepts either structured items or raw children.

import { TableOfContents } from 'ceres-ui';

// Structured items
<TableOfContents
  items={[
    { text: 'Introduction', href: '#introduction' },
    { text: 'Getting Started', href: '#getting-started' },
    { text: 'API Reference', href: '#api-reference' },
  ]}
/>

// Or with raw children
<TableOfContents>
  <li><a href="#intro">Introduction</a></li>
  <li><a href="#setup">Setup</a></li>
</TableOfContents>

| Prop | Type | Default | Description | | ----------- | ----------------------- | ------- | --------------------------------------------------------- | | items | TableOfContentsItem[] | — | Array of { text, href } objects | | children | ReactNode | — | Raw <li> elements (used instead of items if provided) | | className | string | — | Additional CSS class |


PostCard

Clickable card for post previews. Uses a plain <a> tag — no router dependency.

import { PostCard } from 'ceres-ui';

<PostCard
  title="Understanding Moving Averages"
  date="2025-01-15"
  description="A deep dive into SMA, EMA, and MACD crossover strategies."
  tags={['finance', 'technical-analysis']}
  href="/blog/moving-averages"
  onClick={(e) => {
    e.preventDefault();
    router.push('/blog/moving-averages');
  }}
/>;

| Prop | Type | Default | Description | | ------------- | ------------------------- | ------------ | --------------------------------------------------------------------- | | title | string | required | Post title | | date | string | required | ISO date string, formatted as "Month Day, Year" | | description | string | required | Clamped to 2 lines | | tags | string[] | — | Rendered as purple pills | | href | string | required | Link target | | onClick | (e: MouseEvent) => void | — | Click handler (use with e.preventDefault() for client-side routing) | | className | string | — | Additional CSS class |

Router integration: since PostCard renders a plain <a>, integrate with any router by calling e.preventDefault() in onClick and navigating programmatically.


DataTable

Renders tabular data with themed styling and responsive horizontal scroll.

import { DataTable } from 'ceres-ui';

<DataTable
  data={{
    columns: ['Asset', 'Price', 'Change'],
    data: [
      ['Gold', '$2,045.30', '+1.2%'],
      ['Silver', '$23.15', '-0.8%'],
    ],
  }}
/>;

| Prop | Type | Default | Description | | ----------- | ----------- | ------------ | ----------------------------------------- | | data | TableData | required | { columns: string[], data: string[][] } | | className | string | — | Additional CSS class |


Chart

Line charts and histograms powered by Recharts.

import { Chart } from 'ceres-ui';

<Chart
  data={{
    title: 'Gold Price (2024)',
    type: 'line',
    series: [
      { name: 'Price', color: '#89b4fa', data: [1950, 1980, 2010, 2045, 2030] },
      { name: 'SMA 20', color: '#a6e3a1', data: [null, null, 1980, 1995, 2028] },
    ],
    xAxis: { label: 'Date', data: ['Jan', 'Feb', 'Mar', 'Apr', 'May'] },
    yAxis: { label: 'Price', format: 'currency' },
    referenceLines: [{ y: 2000, label: 'Support', color: '#a6e3a1', strokeDasharray: '6 3' }],
  }}
  caption="Gold spot price with 20-day SMA"
  height={400}
/>;

| Prop | Type | Default | Description | | ----------- | ----------- | ------------ | ------------------------------- | | data | ChartData | required | Chart configuration (see below) | | caption | string | — | Caption below the chart | | height | number | 350 | Chart height in pixels | | className | string | — | Additional CSS class |

ChartData shape:

interface ChartData {
  title: string;
  type?: 'line' | 'histogram'; // default: 'line'
  series: ChartSeriesData[]; // { name, color, data: (number | null)[] }
  bins?: number[]; // x-axis bins for histograms
  referenceLines?: ChartReferenceLineData[];
  xAxis: { label: string; data?: (number | string)[] };
  yAxis: { label: string; format?: 'currency' | 'number' | 'percent' };
}

Requires: recharts peer dependency.


Badge

Inline status indicator with three semantic variants.

import { Badge } from 'ceres-ui';

<Badge label="Buy" variant="success" />
<Badge label="Sell" variant="danger" bordered />
<Badge label="Neutral" variant="neutral" size="md" />

| Prop | Type | Default | Description | | ----------- | ------------------------------------ | ------------ | -------------------------------------------- | | label | string | required | Badge text | | variant | 'success' \| 'danger' \| 'neutral' | 'neutral' | Color scheme | | size | 'sm' \| 'md' | 'sm' | Padding and font size | | bordered | boolean | false | Adds a 1px border matching the variant color | | className | string | — | Additional CSS class |


BackToTopButton

Fixed-position scroll-to-top button. Desktop only (hidden below 1024px).

import { BackToTopButton } from 'ceres-ui';

// Automatic: shows after scrolling 400px
<BackToTopButton />

// Manual control
<BackToTopButton visible={showButton} scrollThreshold={600} />

| Prop | Type | Default | Description | | ----------------- | --------- | ------- | -------------------------------------------------------------------------------- | | visible | boolean | — | Override automatic visibility. When omitted, auto-shows based on scroll position | | scrollThreshold | number | 400 | Pixels scrolled before auto-showing | | className | string | — | Additional CSS class |

Clears the URL hash (if any) when scrolling to top.


StarField

Animated starry background overlay. Non-interactive (pointer-events disabled).

import { StarField } from 'ceres-ui';

<StarField starCount={200} />;

| Prop | Type | Default | Description | | ----------- | -------- | ------- | ------------------------------------------- | | starCount | number | 150 | Number of stars. Halved on mobile (< 640px) | | className | string | — | Additional CSS class |

Renders as a fixed full-viewport overlay at z-index: 1. Place your content above it with a higher z-index.


PdfDownloadButton

Opens the browser's print dialog targeting a specific element, enabling save-as-PDF.

import { useRef } from 'react';
import { PdfDownloadButton } from 'ceres-ui';

function Article() {
  const articleRef = useRef<HTMLElement>(null);

  return (
    <>
      <PdfDownloadButton contentRef={articleRef} filename="my-article" />
      <article ref={articleRef}>
        <h1>Article Title</h1>
        <p>Content here...</p>
      </article>
    </>
  );
}

| Prop | Type | Default | Description | | ------------ | -------------------------------- | ------------ | ----------------------------------------------------------------- | | contentRef | RefObject<HTMLElement \| null> | required | Ref to the element whose HTML is printed | | filename | string | required | Used as the print window title (becomes the default PDF filename) | | className | string | — | Additional CSS class |

Copies all page stylesheets into the print window. Applies print-specific rules: A4 page, exact color reproduction, and page-break avoidance inside code blocks, tables, and figures.


MarkdownRenderer

Full-featured markdown renderer that composes all the above components. Supports GFM, math (KaTeX), syntax highlighting, and custom HTML tags.

import { MarkdownRenderer } from 'ceres-ui';

const markdown = `
# Hello World

Some paragraph with **bold** and \`inline code\`.

\`\`\`typescript
const x: number = 42;
\`\`\`

<callout variant="tip" title="Pro tip">
  Use MarkdownRenderer for blog posts.
</callout>

<table-of-contents>
  <li><a href="#hello-world">Hello World</a></li>
</table-of-contents>
`;

<MarkdownRenderer content={markdown} />;

| Prop | Type | Default | Description | | ------------ | --------------------- | ------------ | ----------------------------------------------------- | | content | string | required | Raw markdown string | | components | Partial<Components> | — | Override or extend component mappings for custom tags | | className | string | — | Additional CSS class |

Built-in markdown plugins: remark-gfm, remark-math, rehype-raw, rehype-katex.

Custom HTML tags recognized:

| Tag | Renders | Example | | --------------------- | ----------------- | -------------------------------------------------------- | | <callout> | Callout | <callout variant="warning" title="Oops">Body</callout> | | <table-of-contents> | TableOfContents | <table-of-contents><li>...</li></table-of-contents> |

Extending with custom components:

function MyWidget(props: { src: string }) {
  return <div>Custom: {props.src}</div>;
}

<MarkdownRenderer
  content={markdownWithCustomTags}
  components={{
    'my-widget': MyWidget as any,
  }}
/>;

Exported utilities:

import { generateHeadingId, getTextFromChildren } from 'ceres-ui';

generateHeadingId('Hello World!');
// → 'hello-world'

getTextFromChildren(<span>Hello <strong>World</strong></span>);
// → 'Hello World'

Requires: react-markdown, react-syntax-highlighter, remark-gfm, rehype-raw. Optionally remark-math, rehype-katex, katex for math support.


Exported Types

All types are exported as interfaces for extension:

import type {
  // Component props
  CalloutProps,
  CodeBlockProps,
  TableOfContentsProps,
  TableOfContentsItem,
  PostCardProps,
  DataTableProps,
  ChartProps,
  ChartData,
  ChartSeriesData,
  ChartReferenceLineData,
  BackToTopButtonProps,
  StarFieldProps,
  BadgeProps,
  PdfDownloadButtonProps,
  MarkdownRendererProps,

  // Data models
  Post,
  PostFrontmatter,
  TableData,
  FigureData,

  // Variant types
  CalloutVariant,
  BadgeVariant,
  BadgeSize,
} from 'ceres-ui';

Development

Commands

pnpm dev          # Vite dev server (for development)
pnpm build        # TypeScript check + Vite library build
pnpm typecheck    # tsc -b (type checking only)
pnpm test         # Vitest (single run)
pnpm test:watch   # Vitest (watch mode)

Build Output

dist/
  ceres-ui.es.js     ESM bundle   (~23 KB, ~6 KB gzip)
  ceres-ui.cjs.js    CJS bundle   (~15 KB, ~5 KB gzip)
  ceres-ui.css       Styles       (~17 KB, ~3.5 KB gzip)
  index.d.ts         Declarations (~5 KB)

Heavy dependencies (recharts, react-markdown, react-syntax-highlighter, katex) are not bundled — they're external peer dependencies. The library's own bundle is lightweight.

Testing

51 tests across 10 test files covering all components:

  • Component rendering and prop behavior
  • Variant/size class application
  • CSS class merging via className prop
  • Heading ID generation and text extraction utilities
  • Accessibility attributes

Auto-Versioning

A pre-commit hook (scripts/auto-version.mjs) automatically bumps the minor version on each commit unless the version in package.json was manually changed.

commit with version 0.1.0 (unchanged)  →  auto-bumps to 0.2.0
commit with version 1.0.0 (manually set)  →  keeps 1.0.0

To manually set a version (e.g. for a major release), change the version field in package.json before committing. The hook detects the manual change and skips auto-bumping.

Publishing to npm

Build and publish:

pnpm build
npm publish

Or via GitHub Actions — push a version tag to trigger a release workflow:

git tag v1.0.0
git push origin v1.0.0

CSS Class Reference

All classes use a ceres- prefix with BEM naming to avoid collisions. Every class can be targeted in consumer stylesheets for overrides.

| Component | Root class | Key modifiers | | ----------------- | -------------------- | ------------------------------------------------------------------------------ | | Callout | .ceres-callout | --note, --important, --critical, --tip, --warning, --info, --wip | | CodeBlock | .ceres-code-block | — | | Inline code | .ceres-code-inline | — | | TableOfContents | .ceres-toc | — | | PostCard | .ceres-post-card | — | | DataTable | .ceres-data-table | — | | Chart | .ceres-chart | — | | BackToTopButton | .ceres-back-to-top | — | | StarField | .ceres-star-field | — | | Badge | .ceres-badge | --success, --danger, --neutral, --sm, --md, --bordered | | PdfDownloadButton | .ceres-pdf-button | — | | MarkdownRenderer | .ceres-markdown | — | | Root scroller | .ceres-root | — |