From 8ef57ccec5debaa0ffa1c0e36005bd478cde60f1 Mon Sep 17 00:00:00 2001 From: Thomas Hallock Date: Sat, 8 Nov 2025 09:34:15 -0600 Subject: [PATCH] feat(abacus-react): add comprehensive Storybook stories for automatic theme detection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new story file demonstrating the automatic theme detection feature: - **AutomaticThemeDetection**: Interactive demo with light/dark toggle showing automatic numeral color adjustment - **UseSystemThemeHook**: Demonstrates the useSystemTheme hook API and how it detects theme changes - **ManualColorOverride**: Shows how custom numeral colors override automatic detection - **NumeralsComparison**: Side-by-side comparison of abacus with/without numerals in both themes - **EducationalAppExample**: Real-world example of a theme-aware math learning app Each story includes: - Interactive theme toggle controls - Visual demonstrations of the feature - Explanatory text and usage notes - Theme-appropriate styling The stories complement the README documentation by providing live, interactive examples that users can experiment with in Storybook. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../AbacusReact.theme-detection.stories.tsx | 628 ++++++++++++++++++ 1 file changed, 628 insertions(+) create mode 100644 packages/abacus-react/src/AbacusReact.theme-detection.stories.tsx diff --git a/packages/abacus-react/src/AbacusReact.theme-detection.stories.tsx b/packages/abacus-react/src/AbacusReact.theme-detection.stories.tsx new file mode 100644 index 00000000..06738622 --- /dev/null +++ b/packages/abacus-react/src/AbacusReact.theme-detection.stories.tsx @@ -0,0 +1,628 @@ +/** + * Automatic Theme Detection + * Features: useSystemTheme hook, automatic numeral color adjustment, manual overrides + */ + +import type { Meta, StoryObj } from "@storybook/react"; +import React, { useState, useEffect } from "react"; +import AbacusReact from "./AbacusReact"; +import { useSystemTheme, ABACUS_THEMES } from "./index"; + +const meta = { + title: "AbacusReact/Theme Detection", + component: AbacusReact, + parameters: { + layout: "centered", + }, + tags: ["autodocs"], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// ============================================================================ +// AUTOMATIC THEME DETECTION +// ============================================================================ + +function AutomaticThemeDemo() { + const [pageTheme, setPageTheme] = useState<"light" | "dark">("light"); + + // Apply theme to document root (simulating parent app's theme system) + useEffect(() => { + document.documentElement.setAttribute("data-theme", pageTheme); + }, [pageTheme]); + + return ( +
+
+

Automatic Theme Detection

+

Numerals automatically adjust for optimal visibility

+ +
+ + {" "} + +
+
+ +
+ +
+ +
+ What's happening: +
    +
  • + Page background changes with theme (dark = black, light = white) +
  • +
  • + Abacus frame adapts (translucent white in dark, solid white in + light) +
  • +
  • + ✨ Numerals stay dark (readable) regardless of page theme +
  • +
+
+
+ ); +} + +export const AutomaticThemeDetection: Story = { + render: () => , +}; + +// ============================================================================ +// useSystemTheme HOOK DEMO +// ============================================================================ + +function SystemThemeHookDemo() { + const systemTheme = useSystemTheme(); // Use the hook directly + const [pageTheme, setPageTheme] = useState<"light" | "dark">("light"); + + // Apply theme to document root + useEffect(() => { + document.documentElement.setAttribute("data-theme", pageTheme); + }, [pageTheme]); + + return ( +
+
+

useSystemTheme Hook

+

Detect and respond to page theme changes

+ +
+ + {" "} + +
+ +
+ + const systemTheme = useSystemTheme(); // "{systemTheme}" + +
+
+ + + +
+ Hook detects: +
    +
  • + data-theme="light" or data-theme="dark"{" "} + attribute on <html> +
  • +
  • + .light or .dark class on{" "} + <html> +
  • +
  • Updates automatically using MutationObserver
  • +
  • SSR-safe with default fallback
  • +
+
+
+ ); +} + +export const UseSystemThemeHook: Story = { + render: () => , +}; + +// ============================================================================ +// MANUAL OVERRIDE +// ============================================================================ + +function ManualOverrideDemo() { + const [pageTheme, setPageTheme] = useState<"light" | "dark">("light"); + + // Apply theme to document root + useEffect(() => { + document.documentElement.setAttribute("data-theme", pageTheme); + }, [pageTheme]); + + return ( +
+
+

Manual Color Override

+

Custom numeral colors override automatic detection

+ +
+ + {" "} + +
+
+ +
+

+ Default (automatic): +

+ +

+ Numerals use automatic color (dark text on light frame) +

+
+ +
+

+ Custom red numerals: +

+ +

+ Custom color overrides automatic detection +

+
+ +
+

+ Custom blue numerals: +

+ +

+ Any color can be used for special effects +

+
+
+ ); +} + +export const ManualColorOverride: Story = { + render: () => , +}; + +// ============================================================================ +// COMPARISON: WITH vs WITHOUT NUMERALS +// ============================================================================ + +function NumeralsComparisonDemo() { + const [pageTheme, setPageTheme] = useState<"light" | "dark">("dark"); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", pageTheme); + }, [pageTheme]); + + return ( +
+
+

Numerals On vs Off

+

Compare visibility with and without numeral labels

+ +
+ + {" "} + +
+
+ +
+
+

+ Without numerals: +

+ +
+ +
+

+ With numerals: +

+ +
+
+ +
+ Note: Numerals remain visible in both light and dark + modes thanks to automatic theme detection. They always use dark color + since the abacus frame is light/translucent. +
+
+ ); +} + +export const NumeralsComparison: Story = { + render: () => , +}; + +// ============================================================================ +// REAL-WORLD EXAMPLE: EDUCATIONAL APP +// ============================================================================ + +function EducationalAppDemo() { + const [pageTheme, setPageTheme] = useState<"light" | "dark">("light"); + const [currentValue, setCurrentValue] = useState(234); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", pageTheme); + }, [pageTheme]); + + return ( +
+ {/* App Header */} +
+

+ Math Learning App +

+ +
+ + {/* Lesson Content */} +
+

Today's Lesson: Place Value

+

Learn to represent numbers on a soroban abacus!

+
+ + {/* Interactive Abacus */} +
+
+ +
+ + +
+ + {/* Info Box */} +
+ ✨ Theme-Aware Design: +
    +
  • Entire app responds to light/dark mode toggle
  • +
  • Abacus frame adapts to page background
  • +
  • Numerals always remain readable
  • +
  • No manual color configuration needed!
  • +
+
+
+ ); +} + +export const EducationalAppExample: Story = { + render: () => , +};