diff --git a/examples/.eslintrc.js b/examples/.eslintrc.js index a5dcccaf..51584473 100644 --- a/examples/.eslintrc.js +++ b/examples/.eslintrc.js @@ -12,6 +12,7 @@ module.exports = { // create-vite generates .jsx 'react/jsx-filename-extension': 'off', 'react/react-in-jsx-scope': 'off', + 'react/no-unknown-property': ['error', { ignore: ['sx'] }], }, overrides: [ { diff --git a/examples/pigment-css-vite-ts/package.json b/examples/pigment-css-vite-ts/package.json index b5a49e55..683fa579 100644 --- a/examples/pigment-css-vite-ts/package.json +++ b/examples/pigment-css-vite-ts/package.json @@ -12,7 +12,8 @@ "@pigment-css/react": "latest", "prop-types": "latest", "react": "latest", - "react-dom": "latest" + "react-dom": "latest", + "react-is": "latest" }, "devDependencies": { "@eslint/js": "latest", diff --git a/examples/pigment-css-vite-ts/src/App.tsx b/examples/pigment-css-vite-ts/src/App.tsx index 6d506d7d..fb90708f 100644 --- a/examples/pigment-css-vite-ts/src/App.tsx +++ b/examples/pigment-css-vite-ts/src/App.tsx @@ -1,4 +1,5 @@ import { styled, css, keyframes } from '@pigment-css/react'; +import { ColorSchemeProvider, useColorScheme } from './components/ColorSchemeProvider'; const scale = keyframes({ to: { scale: 'var(--s2)' }, @@ -58,139 +59,180 @@ function generateBubbleVars() { `; } -export default function Home() { +const IconButton = styled('button')({ + background: 'transparent', + border: 'none', + cursor: 'pointer', + padding: '0', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', +}); + +function ColorSchemeToggleButton() { + const { colorScheme, setColorScheme } = useColorScheme(); + + const toggleColorScheme = () => { + setColorScheme(colorScheme === 'dark' ? 'light' : 'dark'); + }; + return ( -
-

({ - fontFamily: 'system-ui, sans-serif', - fontSize: '4rem', - fontWeight: 500, - textAlign: 'center', - position: 'relative', - display: 'flex', - alignItems: 'center', - color: '#888', - marginBottom: '1rem', - ...theme.applyStyles('dark', { color: '#fff' }), - }))}`} - > - Pigment CSS - ({ - position: 'absolute', - inset: '0', - background: 'white', - mixBlendMode: 'color-burn', - overflow: 'hidden', - pointerEvents: 'none', - ...theme.applyStyles('dark', { - mixBlendMode: 'darken', - filter: 'brightness(2)', - }), - }))} - > - - - - - - - - - - - -

-
- CSS-in-JS library with static extraction -
+
+ + {colorScheme === 'light' ? '🌙' : '🔆'} + +
+ ); +} + +function Home() { + const { colorScheme } = useColorScheme(); + + return ( +
- +

({ + fontFamily: 'system-ui, sans-serif', + fontSize: '4rem', + fontWeight: 500, + textAlign: 'center', + position: 'relative', + display: 'flex', + alignItems: 'center', + color: '#888', + marginBottom: '1rem', + ...theme.applyStyles('dark', { color: '#fff' }), + }))}`} > - Documentation - - ({ + position: 'absolute', + inset: '0', + background: 'white', + mixBlendMode: 'color-burn', + overflow: 'hidden', + pointerEvents: 'none', + ...theme.applyStyles('dark', { + mixBlendMode: 'darken', + filter: 'brightness(2)', + }), + }))} + > + + + + + + + + + + + +

+
- Roadmap - + CSS-in-JS library with static extraction +
+
+ + Documentation + + + Roadmap + +
); } + +const defaultColorScheme = localStorage.getItem('colorScheme') ?? 'light'; + +export default function App() { + return ( + + + + ); +} diff --git a/examples/pigment-css-vite-ts/src/augment.d.ts b/examples/pigment-css-vite-ts/src/augment.d.ts index d10b46e0..aed8e0c6 100644 --- a/examples/pigment-css-vite-ts/src/augment.d.ts +++ b/examples/pigment-css-vite-ts/src/augment.d.ts @@ -17,3 +17,14 @@ declare module '@pigment-css/react/theme' { }>; } } + +declare global { + namespace React { + interface HTMLAttributes { + sx?: SxProps; + } + interface SVGProps { + sx?: SxProps; + } + } +} diff --git a/examples/pigment-css-vite-ts/src/components/ColorSchemeProvider.tsx b/examples/pigment-css-vite-ts/src/components/ColorSchemeProvider.tsx new file mode 100644 index 00000000..d4c81bef --- /dev/null +++ b/examples/pigment-css-vite-ts/src/components/ColorSchemeProvider.tsx @@ -0,0 +1,51 @@ +import * as React from 'react'; + +const ColorSchemeContext = React.createContext<{ + colorScheme: string; + setColorScheme: React.Dispatch>; +}>({ + colorScheme: 'light', + setColorScheme: () => '', +}); + +export function ColorSchemeProvider({ + colorScheme: initialColorScheme, + children, +}: React.PropsWithChildren<{ colorScheme: string }>) { + const [colorScheme, setColorScheme] = React.useState(initialColorScheme); + + const contextValue = React.useMemo( + () => ({ colorScheme, setColorScheme }), + [colorScheme, setColorScheme], + ); + + // Set the colorScheme in localStorage + React.useEffect(() => { + localStorage.setItem('colorScheme', colorScheme); + }, [colorScheme]); + + // Handle when localStorage has changed + React.useEffect(() => { + const handleStorage = (event: StorageEvent) => { + const value = event.newValue; + if ( + typeof event.key === 'string' && + event.key === 'colorScheme' && + typeof value === 'string' + ) { + setColorScheme(value); + } + }; + // For syncing color-scheme changes between iframes + window.addEventListener('storage', handleStorage); + return () => { + window.removeEventListener('storage', handleStorage); + }; + }, [setColorScheme]); + + return {children}; +} + +export const useColorScheme = () => { + return React.useContext(ColorSchemeContext); +}; diff --git a/examples/pigment-css-vite-ts/src/globals.css b/examples/pigment-css-vite-ts/src/globals.css index a1e5313f..3dd82369 100644 --- a/examples/pigment-css-vite-ts/src/globals.css +++ b/examples/pigment-css-vite-ts/src/globals.css @@ -8,9 +8,3 @@ a { color: inherit; text-decoration: none; } - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} diff --git a/examples/pigment-css-vite-ts/vite.config.ts b/examples/pigment-css-vite-ts/vite.config.ts index a4e005fa..d336e83b 100644 --- a/examples/pigment-css-vite-ts/vite.config.ts +++ b/examples/pigment-css-vite-ts/vite.config.ts @@ -22,6 +22,9 @@ const theme = extendTheme({ }, }, }, + getSelector: (colorScheme: string) => { + return `.${colorScheme}`; + }, }); // https://vite.dev/config/