This mini project builds a small set of themeable components – button, card, and alert – using tokens, CSS custom properties, and a light/dark switch. It pulls together folder structure, maps, and theming from earlier tutorials.
What you are building
- Folder layout:
abstracts/,base/,components/,themes/,main.scss. - Token maps for colour and spacing.
- CSS variables emitted for light and dark themes.
- Three components styled only with
var(--color-*)and spacing tokens. - Optional
data-themetoggle (HTML + a few lines of JS).
Starter structure
scss/
abstracts/
_variables.scss
_mixins.scss
_functions.scss
base/
_reset.scss
_typography.scss
components/
_button.scss
_card.scss
_alert.scss
themes/
_light.scss
_dark.scss
main.scss
css/
main.css
index.html
Theme partial example
// themes/_light.scss
$theme-light: (
'bg': #ffffff,
'text': #1a1a1a,
'brand': #2563eb,
'danger': #dc2626,
'success': #16a34a,
);
:root,
[data-theme='light'] {
@each $key, $value in $theme-light {
--color-#{$key}: #{$value};
}
color-scheme: light;
}
Button component
// components/_button.scss
.button {
display: inline-flex;
align-items: center;
padding: var(--space-sm, 0.75rem) var(--space-md, 1rem);
border: 1px solid transparent;
border-radius: 0.375rem;
font: inherit;
cursor: pointer;
}
.button--primary {
background: var(--color-brand);
color: var(--color-bg);
}
.button--ghost {
background: transparent;
color: var(--color-brand);
border-color: var(--color-brand);
}
HTML smoke test
Add buttons, a card, an alert, and a theme toggle to index.html. Use classes button, button--primary, button--ghost, card, card__title, card__body, alert alert--danger, and id="theme-toggle" on the toggle button.
Wire the toggle to flip data-theme on <html>. Compile with watch mode and check both themes in the browser.
Acceptance checks
- No raw hex in component partials – only in theme/token files.
- Light and dark both readable (contrast sanity check).
- Compiled CSS one file; source map works in DevTools.
- Lint passes with your Stylelint config.
Stretch goals
- Add a second brand theme class.
- Generate spacing utilities from a map with
@each. - Document tokens in a short README.

