This library is in alpha version, lots of functionality is expected to be added or changed. To ease testing and make sure people building solutions with that (probably shouldn't do it but you know). The only way to "install" the library is to copy src/lib/boomer.ts
to your project.
You first need to install unplugin-parcel-macros and @parcel/macros as devDepencies. You can follow the instructions on how to setup your bundler configuration. You can also use parcel and leverage macros and not worry about anything.
Whenever you import a function from boomer.ts
, you need to use import { css } from '@/src/lib/boomer.ts' with { type: 'macro' }
. If you don't, the library will thrown at runtime.
This repo is a nextjs example. You can fork this repo and get started or inspire yourself from the setup for your own project. More examples will be available later, as well as ready made configuration to use in your projects.
First, run the development server:
pnpm dev
Open http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx
. The page auto-updates as you edit the file.
WIP Documentation below
BoomerCSS is a zero-runtime CSS-in-TS styling solution that generates CSS at build time using Parcel macros. It provides a type-safe way to author CSS with themes, variants, and responsive designs.
The theme system is configured using createConfig
which sets up your design tokens and media queries:
export const { queries, theme } = createConfig({
queries: {
desktop: 'media (min-width: 1024px)',
tablet: 'media (min-width: 768px)',
mobile: 'media (max-width: 767px)',
dark: 'media (prefers-color-scheme: dark)',
light: 'media (prefers-color-scheme: light)',
highContrast: 'media (forced-colors: active)',
},
theme: {
base: {
colors: {
colorScheme: 'light dark',
primary: '#000',
secondary: '#fff',
background: '#f0f0f0',
},
},
dark: {
colors: {
colorScheme: 'dark',
primary: '#fff',
secondary: '#000',
background: '#101010',
},
}
},
})
This generates CSS custom properties and media query utilities at build time.
Create components using the styled
function:
interface ICounterProps {
count: number;
onIncrement: () => Promise<void>;
}
const Button = styled('button', {
base: {
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem'
}
}, { name: 'button' })
export function Counter({ count, onIncrement }: ICounterProps): JSX.Element {
return (
<Button
type="button"
onClick={onIncrement}
>
Add 1 to {count}?
</Button>
)
}
BoomerCSS uses CSS layers for predictable style application, they are defined in this order (last layer wins):
tokenBase
- Theme tokens base valuestokenMedia
- Media query-based token overridesreset
- Global reset stylesbase
- Component base stylesvariants
- Variant stylescompoundVariants
- Complex variant combinations
The styling system works through Parcel macros that:
- Generate unique class names based on style content
- Create CSS files at build time
- Insert the CSS into your application
- Provide type-safe props for variants
Creates theme tokens and media query configurations:
createConfig({
queries: Record<string, string>,
theme: {
base: ThemeTokens,
[mediaQuery: string]: Partial<ThemeTokens>
}
})
Creates styled components with variants:
const buttonCSS = css({
base: {
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem'
},
variants: {
type: {
primary: {
backgroundColor: v('colors.primaryBackground'),
},
secondary: {
backgroundColor: v('colors.secondaryBackground'),
}
}
}
}, { name: 'button' })
Creates styled components with variants:
const Button = styled('button', {
base: {
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem'
},
variants: {
type: {
primary: {
backgroundColor: v('colors.primaryBackground'),
},
secondary: {
backgroundColor: v('colors.secondaryBackground'),
}
}
}
}, { name: 'button' })
Applies global styles:
globalCSS({
selector: CSSRules
})
BoomerCSS provides TypeScript types for:
- Theme tokens and values
- Component variants
- CSS properties
- Media queries
- HTML element props
- Zero runtime JavaScript for styles
- CSS is generated at build time
- Styles are loaded via standard CSS files
- No style calculation or injection at runtime
- Optimal browser caching of CSS
- Always import with macro directive:
import { styled, css, q, v } from '../libs/boomer' with { type: 'macro' }
- As much as possible, use the css function to define styles, this offers better reusability to different html tags and better portability across different ui frameworks:
const boxCSS = css({
base: {
color: v('colors.primary'),
backgroundColor: v('colors.background')
}
}, { name: 'box' })
// then use the css function in the component
function Box({ children }: { children: React.ReactNode }): JSX.Element {
return <div className={boxCSS()}>{children}</div>
}
- Use theme tokens via the v function for consistent styling:
const boxCSS = css({
base: {
color: v('colors.primary'),
backgroundColor: v('colors.background')
}
})
- use media queries via the q function to define responsive styles
const buttonCSS = css({
base: {
fontSize: '2rem',
fontWeight: 'bold',
marginBottom: '1rem',
query: {
[q('tablet/media (min-width: 768px) and (max-width: 1023px)')]: {
fontSize: '1rem',
}
}
}
}, { name: 'button' })
- Use variants rather than redeclaring similar styles.
const boxCSS = css({
base: {
color: v('colors.primary'),
backgroundColor: v('colors.background')
},
variants: {
size: {
large: {
padding: v('size.paddingL'),
},
small: {
padding: v('size.paddingS'),
}
},
}
}, { name: 'box' })
// then use the css function in the component
function Box({ children }: { children: React.ReactNode }): JSX.Element {
return <div className={boxCSS({ size: 'big' })}>{children}</div>
}
- Use semantic tokens and variant names, this will make your styles more readable and maintainable in the long run
BoomerCSS generates standard CSS using:
- CSS Custom Properties
- CSS Layers
- Standard media queries
- No runtime requirements
This ensures broad browser compatibility while maintaining modern CSS features, regardless of the ui framework you are using or if this library is updated.