Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[examples] Fix vite example & add dark mode support #340

Merged
merged 5 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading