Skip to content

Commit

Permalink
[examples] Fix vite example & add dark mode support (#340)
Browse files Browse the repository at this point in the history
  • Loading branch information
mnajdova authored Dec 5, 2024
1 parent 4666708 commit 339f253
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 131 deletions.
1 change: 1 addition & 0 deletions examples/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
{
Expand Down
3 changes: 2 additions & 1 deletion examples/pigment-css-vite-ts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
290 changes: 166 additions & 124 deletions examples/pigment-css-vite-ts/src/App.tsx
Original file line number Diff line number Diff line change
@@ -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)' },
Expand Down Expand Up @@ -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 (
<main
className={css({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100lvh',
padding: '20px',
color: 'hsl(var(--palette-foreground))',
backgroundColor: 'hsl(var(--palette-background))',
fontFamily:
"system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
})}
>
<h1
className={`my-custom-class ${css(({ theme }) => ({
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&nbsp;CSS
<span
className={css(({ theme }) => ({
position: 'absolute',
inset: '0',
background: 'white',
mixBlendMode: 'color-burn',
overflow: 'hidden',
pointerEvents: 'none',
...theme.applyStyles('dark', {
mixBlendMode: 'darken',
filter: 'brightness(2)',
}),
}))}
>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
</span>
</h1>
<div
className={css({
fontFamily: 'system-ui, sans-serif',
letterSpacing: '2px',
opacity: 0.6,
lineHeight: 2,
textAlign: 'center',
textWrap: 'balance',
})}
>
CSS-in-JS library with static extraction
</div>
<div sx={{ position: 'absolute', top: 10, right: 10 }}>
<IconButton sx={{ fontSize: 20, px: 1.5 }} onClick={toggleColorScheme}>
{colorScheme === 'light' ? '🌙' : '🔆'}
</IconButton>
</div>
);
}

function Home() {
const { colorScheme } = useColorScheme();

return (
<main className={colorScheme}>
<div
className={css({
display: 'flex',
flexWrap: 'wrap',
gap: '1rem',
marginTop: '2rem',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100lvh',
padding: '20px',
color: 'hsl(var(--palette-foreground))',
backgroundColor: 'hsl(var(--palette-background))',
fontFamily:
"system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'",
})}
>
<Link
href="https://github.com/mui/pigment-css/blob/master/README.md"
target="_blank"
rel="noopener noreferrer"
<ColorSchemeToggleButton />
<h1
className={`my-custom-class ${css(({ theme }) => ({
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
</Link>
<Link
outlined
href="https://github.com/orgs/mui/projects/27/views/3"
target="_blank"
rel="noopener noreferrer"
Pigment&nbsp;CSS
<span
className={css(({ theme }) => ({
position: 'absolute',
inset: '0',
background: 'white',
mixBlendMode: 'color-burn',
overflow: 'hidden',
pointerEvents: 'none',
...theme.applyStyles('dark', {
mixBlendMode: 'darken',
filter: 'brightness(2)',
}),
}))}
>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
<Bubble
className={css`
${generateBubbleVars()}
`}
/>
</span>
</h1>
<div
className={css({
fontFamily: 'system-ui, sans-serif',
letterSpacing: '2px',
opacity: 0.6,
lineHeight: 2,
textAlign: 'center',
textWrap: 'balance',
})}
>
Roadmap
</Link>
CSS-in-JS library with static extraction
</div>
<div
className={css({
display: 'flex',
flexWrap: 'wrap',
gap: '1rem',
marginTop: '2rem',
})}
>
<Link
href="https://github.com/mui/pigment-css/blob/master/README.md"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</Link>
<Link
outlined
href="https://github.com/orgs/mui/projects/27/views/3"
target="_blank"
rel="noopener noreferrer"
>
Roadmap
</Link>
</div>
</div>
</main>
);
}

const defaultColorScheme = localStorage.getItem('colorScheme') ?? 'light';

export default function App() {
return (
<ColorSchemeProvider colorScheme={defaultColorScheme}>
<Home />
</ColorSchemeProvider>
);
}
11 changes: 11 additions & 0 deletions examples/pigment-css-vite-ts/src/augment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,14 @@ declare module '@pigment-css/react/theme' {
}>;
}
}

declare global {
namespace React {
interface HTMLAttributes {
sx?: SxProps<Theme>;
}
interface SVGProps {
sx?: SxProps<Theme>;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react';

const ColorSchemeContext = React.createContext<{
colorScheme: string;
setColorScheme: React.Dispatch<React.SetStateAction<string>>;
}>({
colorScheme: 'light',
setColorScheme: () => '',
});

export function ColorSchemeProvider({
colorScheme: initialColorScheme,
children,
}: React.PropsWithChildren<{ colorScheme: string }>) {
const [colorScheme, setColorScheme] = React.useState<string>(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 <ColorSchemeContext.Provider value={contextValue}>{children}</ColorSchemeContext.Provider>;
}

export const useColorScheme = () => {
return React.useContext(ColorSchemeContext);
};
Loading

0 comments on commit 339f253

Please sign in to comment.