c-deck
v1.1.1
Published
A reusable, React-based presentation system
Maintainers
Readme
c-deck
A reusable, high-performance React presentation system. Author decks using clean JSON configuration or compose custom presentations manually via JSX components with responsive grid layouts, animations, and dark-themed developer aesthetics.
🚀 Installation
Install the package via npm:
npm install c-deckPeer Dependencies
Ensure you have react and react-dom installed:
npm install react react-dom🛠️ Usage Patterns
Pattern A: JSON-Driven Presenter (Recommended)
Render entire slide decks from a single structured JSON object.
import React from 'react';
import { JsonSlideDeck } from 'c-deck';
const presentationData = {
brand: "Abudhahir FinOps",
meterLabel: "CREDIT COST OVERVIEW",
slides: [
{
type: "TitleSlide",
tagText: "PILOT SUMMARY · 2026",
chipText: "FINOPS",
title: "Optimizing AI Credits",
subtitle: "Reducing seat costs under the new token-based billing model.",
creditBold: "One Shared Pool",
creditMuted: "govern the pool, not the seats",
hintContent: "<kbd>→</kbd> Next slide · <kbd>O</kbd> Overview Grid · <kbd>F</kbd> Fullscreen"
},
{
type: "Slide",
content: [
{ "type": "Eyebrow", "num": "01", "text": "Cost Drivers" },
{ "type": "Headline", "html": "Analyze consumption <span class='hl'>by agent activity</span>" },
{ "type": "Lead", "html": "A high-level summary of seat draws." },
{
"type": "CardGrid",
"cols": 2,
"content": [
{ "type": "SlideCard", "variant": "good", "title": "Chat", "content": "Lowest multiplier. Highly transactional." },
{ "type": "SlideCard", "variant": "bad", "title": "Background Agents", "content": "Highest multiplier. High token usage." }
]
}
]
}
]
};
export default function MyPresentation() {
return <JsonSlideDeck data={presentationData} />;
}Pattern B: JSX Manual Primitives
Compose slides manually for custom layouts, interactivity, or custom animations.
import React, { useState, useCallback, useEffect } from 'react';
import { SlideStyles, TitleSlide, Slide, Eyebrow, Headline, Hl, CardGrid, SlideCard } from 'c-deck';
export default function MyPresentationJSX() {
const [cur, setCur] = useState(0);
const TOTAL = 2;
const go = useCallback((i) => setCur(Math.max(0, Math.min(TOTAL - 1, i))), []);
const next = useCallback(() => go(cur + 1), [cur, go]);
const prev = useCallback(() => go(cur - 1), [cur, go]);
useEffect(() => {
const handler = (e) => {
if (['ArrowRight', ' ', 'PageDown'].includes(e.key)) { next(); e.preventDefault(); }
if (['ArrowLeft', 'PageUp'].includes(e.key)) { prev(); e.preventDefault(); }
};
document.addEventListener('keydown', handler);
return () => document.removeEventListener('keydown', handler);
}, [next, prev]);
return (
<div className="slide-deck" style={{ position: 'fixed', inset: 0 }}>
{/* Inject global typography resets, styling, animations & colors once */}
<SlideStyles />
<TitleSlide
active={cur === 0}
title="Manual Deck"
subtitle="Made with JSX Primitives"
/>
<Slide active={cur === 1}>
<Eyebrow num="01" text="Structure" />
<Headline>Fully customized <Hl>nested React cards</Hl></Headline>
<CardGrid cols={2}>
<SlideCard title="Component A">Description here</SlideCard>
<SlideCard title="Component B">Description here</SlideCard>
</CardGrid>
</Slide>
</div>
);
}⌨️ Controls & Keybindings
Presenters using the JsonSlideDeck enjoy out-of-the-box support for:
Right Arrow/Space/PageDown: Next slideLeft Arrow/PageUp: Previous slideHome/End: Jump to first / last slideOkey: Open Overview Thumbnail Grid (visual slide index to jump directly)Fkey: Toggle browser Fullscreen modeMouse Click: Click/tap right 62% for next, left 38% for previous.Touch Swipes: Swipe left for next, swipe right for previous.
🎨 Design System & Highlights
The library is themed around high-end dark FinOps layouts:
hlclass /<Hl>: Amber highlighting (#F5B43C)coolclass /<Cool>: Teal highlighting (#46D4B3)vioclass /<Vio>: Violet highlighting (#9B8CFF)coralaccent: Coral alerts (#FF6F5E)
Primitives Included
See every primitive rendered live, each paired with its JSON snippet: Kitchen Sink →
<TitleSlide>- Hero layout<Slide>- Layout shell with fade-up transitions<Eyebrow>- Running section tag<Headline>- Display header<Lead>- Context text<CardGrid>&<SlideCard>- Gridded card layouts<DataTable>- Beautiful styled tables<NoteBlock>- Callout blocks<StatRow>&<Stat>- Dashboard data points<PoolReservoir>- Reservoir volume graphic<Spectrum>- Spectrum gradient comparison scale<LadderChart>- Stacked bar pricing ladders<Stages>&<StageCard>- Roller playbooks<SplitColumns>&<SplitCol>- Dual track side-by-side lists<NestedLayers>&<Layer>- Layered system blocks<Code>&<Mono>- Code elements<MermaidDiagram>- Mermaid diagrams, rendered if the host loadsmermaid(see Kitchen Sink for the install note)<Timeline>&<TimelineItem>- Status-colored roadmap timeline, horizontal or vertical
📘 Tutorials
Step-by-step guides for installing c-deck from npm into a brand-new project: docs/tutorials/ (Vite + React · Astro · Docusaurus).
🧪 Running the Demos
Three self-contained demo apps live in the demo/ directory, each showing how to integrate c-deck into a different framework with every component covered.
| Demo | Framework | Key concept |
|------|-----------|-------------|
| demo/vite-react/ | Vite + React | Standard import — Pattern A (JSON) + Pattern B (JSX) |
| demo/astro/ | Astro 4 | client:only="react" to skip SSR |
| demo/docusaurus/ | Docusaurus 3 | BrowserOnly + embedded={true} |
Each demo is independent. Pick one and run:
# Vite + React or Astro:
cd demo/vite-react # or: demo/astro
npm install
npm run dev
# Docusaurus:
cd demo/docusaurus
npm install
npm startThe demos point
c-deckat the library source via a bundler alias, so you don't need to runnpm run buildfirst.
See demo/README.md for the full comparison and framework-specific notes, and each demo's HOW-TO.md for a step-by-step setup walkthrough.
✅ Testing
Unit tests (Vitest + React Testing Library) cover every exported component in
SlideTemplates.jsx and JsonSlideDeck.jsx's navigation, keyboard, touch, and
overview behavior, including the DOMPurify sanitization paths.
npm install
npm test # run once
npm run test:watchEnd-to-end tests (Playwright) drive demo/vite-react in a real browser to
verify navigation, the overview grid, and the progress meter:
npm install
cd demo/vite-react && npm install && cd ../..
npx playwright install chromium # first run only
npm run test:e2e🎭 Theming
Customize the palette and fonts without touching component code. Works with both JsonSlideDeck (via data.theme) and the manual JSX primitives (via a theme prop on <SlideStyles>).
// Named preset
const presentationData = { theme: 'light', slides: [/* ... */] };
// Preset + overrides
const presentationData = {
theme: { preset: 'light', overrides: { amber: '#FF8800' } },
slides: [/* ... */],
};
// Overrides only (based on the default dark-finops preset)
const presentationData = {
theme: { overrides: { teal: '#00C2A8' } },
slides: [/* ... */],
};// Manual JSX usage
<SlideStyles theme="light" />Built-in presets: dark-finops (default) and light.
Overridable tokens: ink, ink2, ink3, paper, amber, amberDeep, teal, coral, violet, text, muted, line, line2, disp (display font), body (body font), mono (monospace font).
Known limitation: a few decorative chrome elements (the ambient background glow, the pool-reservoir stripe overlay, and the nav-button backdrop tint) use fixed semi-transparent white overlays rather than theme tokens. They're tuned to read reasonably under both built-in presets but aren't fully theme-aware yet.
Themes are resolved once when the deck mounts; there's no built-in runtime theme switcher.
📄 License
MIT
