From ffbdae7ac93415d7c3f1c2cfd87212d678e8a930 Mon Sep 17 00:00:00 2001 From: Madison Date: Wed, 2 Jul 2025 12:05:53 -0500 Subject: [PATCH] light mode and accessibility feat --- docs/src/components/mdx/sdk-components.tsx | 132 ++++++++++++++++++++- 1 file changed, 128 insertions(+), 4 deletions(-) diff --git a/docs/src/components/mdx/sdk-components.tsx b/docs/src/components/mdx/sdk-components.tsx index 8a1e9e698..999d1acf4 100644 --- a/docs/src/components/mdx/sdk-components.tsx +++ b/docs/src/components/mdx/sdk-components.tsx @@ -1,5 +1,6 @@ 'use client'; +import { Palette } from 'lucide-react'; import React, { useEffect, useRef, useState } from 'react'; import { codeToHtml } from "shiki"; import './clickable-code-styles.css'; @@ -22,8 +23,64 @@ function ClickableCodeblock({ }) { const [highlightedCode, setHighlightedCode] = useState(""); const [linePositions, setLinePositions] = useState>([]); + const [selectedLightTheme, setSelectedLightTheme] = useState('github-light-default'); + const [selectedDarkTheme, setSelectedDarkTheme] = useState('github-dark'); + const [isThemeSwitcherOpen, setIsThemeSwitcherOpen] = useState(false); const codeRef = useRef(null); + // Available themes + const lightThemes = [ + { value: 'github-light-default', label: 'GitHub Light' }, + { value: 'light-plus', label: 'VS Code Light' }, + { value: 'min-light', label: 'Minimal Light' }, + { value: 'slack-ochin', label: 'Slack Light' }, + ]; + + const darkThemes = [ + { value: 'github-dark', label: 'GitHub Dark' }, + { value: 'github-dark-dimmed', label: 'GitHub Dimmed' }, + { value: 'dark-plus', label: 'VS Code Dark' }, + { value: 'dracula', label: 'Dracula' }, + ]; + + // Load saved theme preferences on mount + useEffect(() => { + const savedLightTheme = localStorage.getItem('stack-docs-light-theme'); + const savedDarkTheme = localStorage.getItem('stack-docs-dark-theme'); + + if (savedLightTheme) { + setSelectedLightTheme(savedLightTheme); + } + if (savedDarkTheme) { + setSelectedDarkTheme(savedDarkTheme); + } + }, []); + + // Close theme switcher when clicking outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (isThemeSwitcherOpen && !(event.target as Element).closest('.theme-switcher-container')) { + setIsThemeSwitcherOpen(false); + } + }; + + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + }, [isThemeSwitcherOpen]); + + // Save theme preferences when they change + const handleThemeChange = (isDark: boolean, theme: string) => { + if (isDark) { + setSelectedDarkTheme(theme); + localStorage.setItem('stack-docs-dark-theme', theme); + } else { + setSelectedLightTheme(theme); + localStorage.setItem('stack-docs-light-theme', theme); + } + }; + // Measure actual line positions after code is rendered useEffect(() => { if (codeRef.current && highlightedCode) { @@ -102,12 +159,15 @@ function ClickableCodeblock({ const updateHighlightedCode = async () => { try { // Detect if we're in dark mode by checking CSS custom properties or document class - const isDarkMode = document.documentElement.classList.contains('dark') || + const isDarkMode = document.documentElement.classList.contains('dark') || getComputedStyle(document.documentElement).getPropertyValue('--fd-background').includes('0 0% 3.9%'); - + + // Use selected themes instead of hardcoded ones + const themeToUse = isDarkMode ? selectedDarkTheme : selectedLightTheme; + const html = await codeToHtml(code, { lang: language, - theme: isDarkMode ? 'github-dark' : 'github-light-default', + theme: themeToUse, transformers: [{ pre(node) { // Remove background styles from pre element @@ -156,7 +216,7 @@ function ClickableCodeblock({ return () => { observer.disconnect(); }; - }, [code, language]); + }, [code, language, selectedLightTheme, selectedDarkTheme]); return (
@@ -168,6 +228,70 @@ function ClickableCodeblock({ lineHeight: '1.5', }} > + {/* Theme Switcher */} +
+
+ + + {isThemeSwitcherOpen && ( +
+
+ {/* Title */} +
+ Code Theme +
+ + {/* Current mode indicator */} +
+
+
+ + {document.documentElement.classList.contains('dark') ? 'Dark Mode' : 'Light Mode'} + +
+
+ {(document.documentElement.classList.contains('dark') ? darkThemes : lightThemes).map((theme) => { + const isDark = document.documentElement.classList.contains('dark'); + const isSelected = isDark ? selectedDarkTheme === theme.value : selectedLightTheme === theme.value; + return ( + + ); + })} +
+
+
+
+ )} +
+