@mastors/core
The design system foundation
@mastors/core is a utility-first SCSS library providing design tokens, utility classes, mixins, functions, and a responsive engine. It is the foundation for every package in the Mastors design system — and can be consumed standalone.
Installation
Add the package via your package manager of choice.
npm
npm install @mastors/core
yarn
yarn add @mastors/core
pnpm
pnpm add @mastors/core
Import & Usage
The main entry point compiles the full library in this order: config → abstracts → variables → tokens → functions → mixins → base → themes → semantic → responsive → helpers → utilities → accessibility.
Full import (outputs all CSS)
@use "@mastors/core";
Selective import (tokens + mixins only, no utility output)
@use "@mastors/core/scss/tokens/color" as ct;
@use "@mastors/core/scss/tokens/spacing" as sp;
@use "@mastors/core/scss/mixins/breakpoint" as *;
.card {
padding: sp.spacing(4);
background: ct.color("primary", 50);
@include bp(md) {
padding: sp.spacing(8);
}
}
Using the vars() function
@use "@mastors/core/scss/functions/vars" as *;
.btn {
background: vars(accent);
color: vars(accent-text);
padding: vars(spacing-2) vars(spacing-4);
border-radius: vars(radius-md);
box-shadow: vars(shadow-sm, none);
}
Design Tokens
Colors
Token6 palettes × 11 shades (50–950) plus white, black, and transparent. Each color is also emitted as a CSS custom property: --mastors-color-{palette}-{shade}.
@use "@mastors/core/scss/tokens/color" as ct;
// Accessor
$blue: ct.color("primary", 500); // → #3b82f6
$green-50: ct.color("success", 50); // → #f0fdf4
$white: ct.color("white"); // → #fff
primary
success
warning
error
info
neutral
Spacing
TokenA complete scale from 0 to 96 (0 → 24rem). Emitted as --mastors-spacing-{key}.
@use "@mastors/core/scss/tokens/spacing" as sp;
.btn { padding: sp.spacing(2) sp.spacing(4); }
// → padding: 0.5rem 1rem;
| Key | Value | px |
|---|---|---|
| 0 | 0px | 0 |
| px | 1px | 1px |
| 0.5 | 0.125rem | 2px |
| 1 | 0.25rem | 4px |
| 2 | 0.5rem | 8px |
| 3 | 0.75rem | 12px |
| 4 | 1rem | 16px |
| 6 | 1.5rem | 24px |
| 8 | 2rem | 32px |
| 12 | 3rem | 48px |
| 16 | 4rem | 64px |
| 24 | 6rem | 96px |
| 32 | 8rem | 128px |
| 64 | 16rem | 256px |
| 96 | 24rem | 384px |
Sizing
TokenWidth/height scale including fractional percentages, viewport units and keyword values. Emitted as --mastors-sizing-{key}.
@use "@mastors/core/scss/tokens/sizing" as sz;
.hero { width: sz.sizing("full"); height: sz.sizing("screen"); }
.card { width: sz.sizing("1/3"); max-width: sz.sizing(64); }
| Key | Value |
|---|---|
| 0 | 0 |
| 1/2 | 50% |
| 1/3 | 33.3333% |
| 2/3 | 66.6667% |
| 1/4 | 25% |
| 3/4 | 75% |
| full | 100% |
| screen | 100vw |
| svw | 100svw |
| dvw | 100dvw |
| auto | auto |
| min | min-content |
| max | max-content |
| fit | fit-content |
Typography
TokenFont sizes (xs–9xl), weights (thin–black), families (sans/serif/mono), line heights, and letter spacing. Emitted as CSS custom properties.
@use "@mastors/core/scss/tokens/typography" as ty;
h1 {
font-size: ty.font-size("4xl"); // 2.25rem
font-weight: ty.font-weight("bold"); // 700
line-height: ty.line-height("tight"); // 1.25
letter-spacing: ty.letter-spacing("tight"); // -0.025em
}
code {
font-family: ty.font-family("mono");
}
Shadows
Token8 elevation steps: xs, sm, md, lg, xl, 2xl, inner, none. Emitted as --mastors-shadow-{key}.
@use "@mastors/core/scss/tokens/shadows" as sh;
.card { box-shadow: sh.shadow("md"); }
.modal { box-shadow: sh.shadow("2xl"); }
.input { box-shadow: sh.shadow("inner"); }
xs
sm
md
lg
xl
2xl
inner
Radii
TokenBorder-radius scale from none (0) to full (9999px). Emitted as --mastors-radius-{key}.
@use "@mastors/core/scss/tokens/radii" as ra;
.btn { border-radius: ra.radius("md"); } // 0.375rem
.badge { border-radius: ra.radius("full"); } // 9999px
.card { border-radius: ra.radius("xl"); } // 0.75rem
Opacity
Token17-step opacity scale 0–100. Emitted as --mastors-opacity-{key}.
@use "@mastors/core/scss/tokens/opacity" as op;
.overlay { opacity: op.opacity(50); } // → 0.5
.disabled { opacity: op.opacity(30); } // → 0.3
Z-Index
TokenNamed stacking layers for predictable layering. Emitted as --mastors-z-{key}.
@use "@mastors/core/scss/tokens/z-index" as zi;
.dropdown { z-index: zi.z("dropdown"); } // 100
.modal { z-index: zi.z("modal"); } // 400
.toast { z-index: zi.z("toast"); } // 500
.tooltip { z-index: zi.z("tooltip"); } // 600
| Key | Value | Use case |
|---|---|---|
| base | 0 | Default document flow |
| raised | 10 | Slightly elevated elements |
| dropdown | 100 | Dropdown menus |
| sticky | 200 | Sticky headers/sidebars |
| overlay | 300 | Overlay backdrops |
| modal | 400 | Modal dialogs |
| toast | 500 | Toast notifications |
| tooltip | 600 | Tooltips |
| max | 9999 | Escape hatch |
Transitions
TokenDuration tokens (75ms–1000ms) and easing curves (linear, in, out, in-out, bounce). Emitted as --mastors-duration-{key} and --mastors-easing-{key}.
@use "@mastors/core/scss/tokens/transitions" as tr;
.btn {
transition: background-color tr.duration("150") tr.easing("in-out");
}
// Values:
// tr.duration("75") → 75ms
// tr.duration("300") → 300ms
// tr.easing("out") → cubic-bezier(0, 0, 0.2, 1)
// tr.easing("bounce") → cubic-bezier(0.34, 1.56, 0.64, 1)
Theming
Light & Dark Themes
ThemeThemes are toggled via .dark / [data-theme="dark"] on any ancestor element (strategy: class, default) or via prefers-color-scheme (strategy: media). Themes redefine semantic custom properties — no class changes needed on individual components.
<!-- Class strategy (default) -->
<html class="dark">
<!-- or -->
<html data-theme="dark">
<!-- Toggle with JS -->
<script>
document.documentElement.classList.toggle('dark');
</script>
// Override dark strategy to media query:
// In your entry scss BEFORE @use "@mastors/core"
// (or via custom theme overrides)
$dark-mode-strategy: "media"; // default: "class"
@use "@mastors/core";
Light theme
Dark theme
Semantic Layer
ThemeRole-based SCSS variables that map to CSS custom properties. Use these in your components instead of raw token references — they update automatically when the theme changes.
@use "@mastors/core/scss/semantic/colors" as sc;
@use "@mastors/core/scss/semantic/spacing" as ss;
@use "@mastors/core/scss/semantic/typography" as st;
.card {
background: sc.$color-surface;
color: sc.$color-text;
border: 1px solid sc.$color-border;
padding: ss.$space-component;
font-family: st.$font-body;
}
// All $color-* variables resolve to var(--mastors-*)
// so they inherit the active theme at runtime.
| Variable | Custom Property | Role |
|---|---|---|
| $color-bg | --mastors-bg | Page background |
| $color-surface | --mastors-surface | Card / panel surface |
| $color-surface-raised | --mastors-surface-raised | Dropdowns, tooltips |
| $color-text | --mastors-text | Primary text |
| $color-text-muted | --mastors-text-muted | Secondary text |
| $color-text-subtle | --mastors-text-subtle | Placeholder / tertiary |
| $color-border | --mastors-border | Default border |
| $color-accent | --mastors-accent | Brand / primary action |
| $color-accent-hover | --mastors-accent-hover | Accent hover state |
| $space-inline | 0.25rem (spacing(1)) | Tight inline gap |
| $space-component | 1rem (spacing(4)) | Component padding |
| $space-section | 4rem (spacing(16)) | Between sections |
Utilities
Spacing Utilities
UtilityMargin, padding, and gap utilities generated from spacing tokens. Supports all directional variants, logical properties, and auto for margins.
<!-- Margin -->
<div class="m-4">margin: 1rem</div>
<div class="mx-auto">margin-inline: auto</div>
<div class="my-8">margin-block: 2rem</div>
<div class="mt-2 mb-6">margin-top + margin-bottom</div>
<div class="ms-4 me-4">margin-inline-start/end (logical)</div>
<!-- Padding -->
<div class="p-6">padding: 1.5rem</div>
<div class="px-4 py-2">padding-x + padding-y</div>
<div class="ps-4 pe-4">padding-inline-start/end</div>
<!-- Gap -->
<div class="flex gap-4">gap: 1rem</div>
<div class="grid gap-x-6 gap-y-3">column + row gap</div>
Plus
auto for margin only.
Display
UtilityResponsiveGenerates display classes including responsive variants (e.g. md:flex, lg:hidden).
<div class="block"></div>
<div class="inline-block"></div>
<div class="inline"></div>
<div class="flex"></div>
<div class="inline-flex"></div>
<div class="grid"></div>
<div class="inline-grid"></div>
<div class="table"></div>
<div class="contents"></div>
<div class="hidden"></div> <!-- display: none -->
<!-- Responsive -->
<div class="hidden md:block">Shows from md up</div>
<div class="flex lg:hidden">Hidden from lg up</div>
Position
UtilityResponsivePositioning classes + inset utilities for top/right/bottom/left values.
<div class="relative">
<div class="absolute top-0 right-0">top-right corner</div>
<div class="absolute inset-0">full overlay</div>
<div class="absolute inset-x-0 bottom-0">bottom bar</div>
</div>
<div class="sticky top-0">Sticky header</div>
<div class="fixed bottom-0 right-0">Floating btn</div>
Inset keys: 0, auto, full (100%), 1/2 (50%)
Sizing
UtilityWidth and height utilities generated from sizing tokens. Includes min-width, max-width, min-height, max-height shortcuts.
<div class="w-full h-screen">Full width, screen height</div>
<div class="w-1/2 h-32">50% width, 8rem height</div>
<div class="w-fit">Width: fit-content</div>
<!-- Min / Max -->
<div class="min-w-0 max-w-prose">Prose width (65ch)</div>
<div class="min-h-screen">Min 100vh height</div>
<div class="min-h-svh">Min 100svh (small viewport)</div>
<div class="min-h-dvh">Min 100dvh (dynamic viewport)</div>
Typography Utilities
UtilityResponsiveText size, weight, family, alignment, leading, tracking, decoration, transform, whitespace, word-break, and more.
<!-- Size -->
<p class="text-xs"> <p class="text-sm"> <p class="text-base">
<p class="text-lg"> <p class="text-xl"> <p class="text-2xl">
<p class="text-3xl"> ... <p class="text-9xl">
<!-- Weight -->
<p class="font-thin"> <p class="font-light"> <p class="font-normal">
<p class="font-medium"> <p class="font-semibold"> <p class="font-bold">
<p class="font-extrabold"> <p class="font-black">
<!-- Family -->
<p class="font-sans"> <p class="font-serif"> <p class="font-mono">
<!-- Align (responsive) -->
<p class="text-left"> <p class="text-center"> <p class="text-right">
<p class="md:text-center">
<!-- Line height -->
<p class="leading-none"> <p class="leading-tight"> <p class="leading-normal">
<p class="leading-relaxed"> <p class="leading-loose">
<!-- Letter spacing -->
<p class="tracking-tight"> <p class="tracking-normal"> <p class="tracking-wide">
<p class="tracking-widest">
<!-- Decoration -->
<p class="underline"> <p class="line-through"> <p class="no-underline">
<p class="decoration-wavy decoration-2">
<!-- Transform -->
<p class="uppercase"> <p class="lowercase"> <p class="capitalize">
<!-- Style -->
<p class="italic"> <p class="not-italic">
<!-- Misc -->
<p class="antialiased"> <p class="text-ellipsis">
<p class="whitespace-nowrap"> <p class="break-words">
<!-- List -->
<ul class="list-disc list-inside"> <ol class="list-decimal">
Size scale →
text-xs — The quick brown fox
text-sm — The quick brown fox
text-base — The quick brown fox
text-xl font-semibold
text-4xl font-bold
decoration-wavy text-blue
TRACKING-WIDEST UPPERCASE
Color Utilities
UtilityText color, background color, and border color classes for both semantic and primitive palettes.
<!-- Semantic text colors -->
<p class="text-default">Default text</p>
<p class="text-muted">Muted text</p>
<p class="text-subtle">Subtle text</p>
<p class="text-accent">Accent text</p>
<p class="text-inverse">Inverse text</p>
<!-- Primitive text colors -->
<p class="text-primary-600">Primary 600</p>
<p class="text-success-500">Success 500</p>
<p class="text-error-500">Error 500</p>
<p class="text-white"> <p class="text-black">
<p class="text-current"> <p class="text-transparent">
<!-- Semantic backgrounds -->
<div class="bg-default"> <div class="bg-subtle">
<div class="bg-surface"> <div class="bg-accent">
<!-- Primitive backgrounds -->
<div class="bg-primary-50"> <div class="bg-neutral-100">
<div class="bg-warning-200"> <div class="bg-white">
<div class="bg-transparent">
Borders
UtilityBorder width, style, color, and radius classes.
<!-- Border width -->
<div class="border">1px solid</div>
<div class="border-0">no border</div>
<div class="border-2">2px solid</div>
<div class="border-4">4px solid</div>
<div class="border-t">top only</div>
<div class="border-b">bottom only</div>
<!-- Border style -->
<div class="border border-dashed">dashed</div>
<div class="border border-dotted">dotted</div>
<!-- Border color -->
<div class="border border-default">semantic border</div>
<div class="border border-strong">strong border</div>
<div class="border border-transparent">transparent</div>
<!-- Border radius -->
<div class="rounded-none"> <div class="rounded-sm">
<div class="rounded"> <div class="rounded-md">
<div class="rounded-lg"> <div class="rounded-xl">
<div class="rounded-2xl"> <div class="rounded-3xl">
<div class="rounded-full">
<!-- Directional radius -->
<div class="rounded-t-lg"> <!-- top corners -->
<div class="rounded-b-xl"> <!-- bottom corners -->
<div class="rounded-l-full"> <!-- left corners -->
Shadow Utilities
Utility<div class="shadow-xs">Extra small shadow</div>
<div class="shadow-sm">Small shadow</div>
<div class="shadow">Default (md) shadow</div>
<div class="shadow-md">Medium shadow</div>
<div class="shadow-lg">Large shadow</div>
<div class="shadow-xl">XL shadow</div>
<div class="shadow-2xl">2XL shadow</div>
<div class="shadow-inner">Inset shadow</div>
<div class="shadow-none">No shadow</div>
Opacity Utilities
Utility<div class="opacity-0"> <!-- 0 -->
<div class="opacity-5"> <!-- 0.05 -->
<div class="opacity-10"> <!-- 0.1 -->
<div class="opacity-25"> <!-- 0.25 -->
<div class="opacity-50"> <!-- 0.5 -->
<div class="opacity-75"> <!-- 0.75 -->
<div class="opacity-90"> <!-- 0.9 -->
<div class="opacity-100"> <!-- 1 -->
Transform
UtilityTranslate, rotate, scale, and transform-origin classes. Use .transform-gpu to promote to a composite layer.
<!-- Translate -->
<div class="translate-x-4"> <!-- translateX(1rem) -->
<div class="translate-y-2"> <!-- translateY(0.5rem) -->
<div class="-translate-y-1"> <!-- translateY(-0.25rem) -->
<div class="translate-x-full"> <!-- translateX(100%) -->
<!-- Rotate -->
<div class="rotate-45"> <!-- 45deg -->
<div class="rotate-90"> <!-- 90deg -->
<div class="rotate-180"> <!-- 180deg -->
<div class="-rotate-45"> <!-- -45deg -->
<!-- Scale -->
<div class="scale-0"> <!-- 0 -->
<div class="scale-50"> <!-- 0.5 -->
<div class="scale-100"> <!-- 1 (normal) -->
<div class="scale-105"> <!-- 1.05 -->
<div class="scale-110"> <!-- 1.1 -->
<div class="scale-150"> <!-- 1.5 -->
<div class="scale-x-75"> <!-- scaleX only -->
<!-- Origin -->
<div class="origin-center"> <div class="origin-top">
<div class="origin-bottom-right">
<!-- GPU acceleration -->
<div class="transform-gpu"> <!-- translateZ(0) -->
<div class="transform-none"> <!-- removes transform -->
Animation & Transitions
UtilityBuilt-in keyframe animations (spin, ping, pulse, bounce, fade-in, fade-out, slide-up, slide-down, scale-in) plus transition property, duration, easing, and delay utilities.
<!-- Animations -->
<div class="animate-spin">Spinner</div>
<div class="animate-ping">Ping dot</div>
<div class="animate-pulse">Pulsing skeleton</div>
<div class="animate-bounce">Bouncing indicator</div>
<div class="animate-fade-in">Fade in on mount</div>
<div class="animate-fade-out">Fade out</div>
<div class="animate-slide-up">Slide up</div>
<div class="animate-slide-down">Slide down</div>
<div class="animate-scale-in">Scale in</div>
<div class="animate-none">No animation</div>
<!-- Transitions -->
<div class="transition">All common properties</div>
<div class="transition-colors">Colors only</div>
<div class="transition-opacity">Opacity only</div>
<div class="transition-transform">Transform only</div>
<div class="transition-shadow">Shadow only</div>
<div class="transition-none">Disable</div>
<!-- Duration -->
<div class="duration-75"> 75ms
<div class="duration-150"> 150ms
<div class="duration-300"> 300ms
<div class="duration-700"> 700ms
<div class="duration-1000"> 1s
<!-- Easing -->
<div class="ease-linear"> <div class="ease-in">
<div class="ease-out"> <div class="ease-in-out">
<div class="ease-bounce">
<!-- Delay -->
<div class="delay-150"> <div class="delay-300"> <div class="delay-700">
<!-- Fill mode / Play state -->
<div class="fill-forwards"> <div class="fill-both">
<div class="animation-paused"> <div class="animation-running">
<!-- Repeat -->
<div class="animate-repeat-infinite"> <div class="animate-repeat-1">
spin
pulse
bounce
Overflow
Utility<div class="overflow-auto"> <!-- scroll when needed -->
<div class="overflow-hidden"> <!-- clip content -->
<div class="overflow-scroll"> <!-- always show scrollbar -->
<div class="overflow-visible"> <!-- default -->
<div class="overflow-clip"> <!-- clip without scrollbar -->
<!-- Axis-specific -->
<div class="overflow-x-auto overflow-y-hidden">Horizontal scroll</div>
Cursor
Utility<div class="cursor-auto"> auto
<div class="cursor-default"> default arrow
<div class="cursor-pointer"> hand pointer
<div class="cursor-wait"> wait spinner
<div class="cursor-text"> I-beam
<div class="cursor-move"> move
<div class="cursor-not-allowed"> blocked
<div class="cursor-grab"> grab hand
<div class="cursor-grabbing"> grabbing hand
<div class="cursor-zoom-in"> zoom in
<div class="cursor-crosshair"> crosshair
<div class="cursor-none"> hidden cursor
Interaction
UtilityUser-select, resize, scroll behavior, scroll snap, touch action, and state-variant pseudo-class utilities (hover:, focus:, disabled:).
<!-- User select -->
<div class="select-none">Cannot select</div>
<div class="select-text">Can select text</div>
<div class="select-all">Select all on click</div>
<!-- Resize -->
<textarea class="resize-none">No resize</textarea>
<textarea class="resize-y">Vertical resize</textarea>
<textarea class="resize">Both directions</textarea>
<!-- Scroll -->
<div class="scroll-smooth">Smooth scrolling</div>
<!-- Scroll snap -->
<div class="snap-x snap-mandatory overflow-x-auto">
<div class="snap-start">Snap item 1</div>
<div class="snap-center">Snap item 2</div>
</div>
<!-- Touch -->
<div class="touch-pan-x">Horizontal pan only</div>
<div class="touch-manipulation">Fast tap, no zoom</div>
<div class="touch-none">Disable touch</div>
<!-- Pointer events -->
<div class="pointer-events-none">Click-through</div>
<div class="pointer-events-auto">Default</div>
<!-- State variants -->
<button class="hover:bg-accent hover:scale-105">Hover effects</button>
<button class="focus:ring focus:ring-2">Focus ring</button>
<button class="disabled:opacity-50 disabled:cursor-not-allowed">Disabled</button>
<a class="hover:underline hover:text-accent">Hover link</a>
Layout
UtilityResponsiveAspect ratio, object-fit, object-position, float, clear, isolation, mix-blend-mode, background blend, appearance, and will-change.
<!-- Aspect ratio -->
<div class="aspect-auto"> <div class="aspect-square">
<div class="aspect-video"> <!-- 16/9 -->
<div class="aspect-4-3"> <div class="aspect-3-2">
<div class="aspect-21-9"> <div class="aspect-9-16">
<div class="aspect-golden"> <!-- 1.618 -->
<!-- Object fit -->
<img class="object-cover"> <img class="object-contain">
<img class="object-fill"> <img class="object-scale-down">
<!-- Object position -->
<img class="object-center"> <img class="object-top">
<img class="object-bottom"> <img class="object-left">
<!-- Float (responsive) -->
<div class="float-left"> <div class="float-right"> <div class="float-none">
<div class="lg:float-right">
<!-- Isolation -->
<div class="isolate">New stacking context</div>
<!-- Mix blend mode -->
<div class="mix-blend-multiply">
<div class="mix-blend-screen">
<div class="mix-blend-overlay">
<!-- Background blend -->
<div class="bg-blend-multiply">
<!-- Appearance -->
<select class="appearance-none">Custom styled select</select>
<!-- Will change -->
<div class="will-change-transform"> <div class="will-change-scroll">
square
16/9
4/3
Z-Index Utilities
Utility<div class="z-base"> z-index: 0</div>
<div class="z-raised"> z-index: 10</div>
<div class="z-dropdown"> z-index: 100</div>
<div class="z-sticky"> z-index: 200</div>
<div class="z-overlay"> z-index: 300</div>
<div class="z-modal"> z-index: 400</div>
<div class="z-toast"> z-index: 500</div>
<div class="z-tooltip"> z-index: 600</div>
<div class="z-max"> z-index: 9999</div>
Helpers
Pre-built helper classes for common patterns: text truncation, line clamping, aspect ratios, clearfix, and visually-hidden content.
Truncate & Line Clamp
<p class="truncate">Single line truncation with ellipsis...</p>
<p class="line-clamp-1">Clamp to 1 line</p>
<p class="line-clamp-2">Clamp to 2 lines</p>
<p class="line-clamp-3">Clamp to 3 lines — max 3 visible</p>
<p class="line-clamp-6">Clamp to 6 lines</p>
<p class="break-words">Break long overflow-wrap words</p>
<p class="break-all">Break at any character</p>
<p class="break-keep">Keep words together (CJK)</p>
This is a very long sentence that should be truncated with an ellipsis at the end when it overflows.
Ratio Helpers
<div class="ratio-square">1:1 ratio</div>
<div class="ratio-video">16:9 ratio</div>
<div class="ratio-portrait">3:4 ratio</div>
<div class="ratio-wide">21:9 ultra-wide</div>
<div class="ratio-golden">Golden ratio (1.618)</div>
Clearfix
<!-- Clears floated children with ::after -->
<div class="clearfix">
<img class="float-left" src="..." />
<p>Text alongside float</p>
</div>
Sass API — Functions
Pure Sass functions — zero CSS output when imported alone. Use via @use "@mastors/core/scss/functions/...".
rem() & em() Unit conversion
@use "@mastors/core/scss/functions/rem" as *;
@use "@mastors/core/scss/functions/em" as *;
.heading { font-size: rem(32px); } // → 2rem
.media { max-width: em(768px, 16px); } // → 48em
Color Functions
@use "@mastors/core/scss/functions/color" as *;
// tint($color, $pct) — mix with white
$light-blue: tint(#3b82f6, 40%);
// shade($color, $pct) — mix with black
$dark-blue: shade(#3b82f6, 30%);
// alpha($color, $alpha) — set alpha
$semi: alpha(#3b82f6, 0.5);
// contrast($bg) — returns black or white for best contrast
$text-color: contrast(#3b82f6); // → white
// palette($name, $shade) — shorthand accessor
$c: palette("primary", 500);
// rgb-color($name, $shade, $opacity) — with optional alpha
$c: rgb-color("primary", 500, 0.6);
// color-ramp($base, $steps, $dir) — tint/shade ramp
$ramp: color-ramp(#3b82f6, 5, "tint");
Math Functions
@use "@mastors/core/scss/functions/math" as *;
// fluid($min, $max, $min-vw, $max-vw) — clamp() expression
font-size: fluid(1rem, 2rem);
// → clamp(1rem, …vw + …, 2rem)
// clamp-value($min, $val, $max)
font-size: clamp-value(0.875rem, 4vw, 2rem);
// strip-unit(16px) → 16
$n: strip-unit(16px);
// round-to(3.14159, 2) → 3.14
$r: round-to(3.14159);
// lerp($a, $b, $t) — linear interpolation
$v: lerp(0, 100px, 0.5); // → 50px
vars() — Token Reference Function
@use "@mastors/core/scss/functions/vars" as *;
// Simple token reference (no fallback)
.card {
background: vars(surface); // var(--mastors-surface)
color: vars(text); // var(--mastors-text)
border: 1px solid vars(border); // var(--mastors-border)
}
// With CSS fallback
.badge {
background: vars(accent-subtle, #eff6ff); // var(--mastors-accent-subtle, #eff6ff)
}
// Path-based accessor (functions/_string.scss)
// vars($category, $keys...)
@use "@mastors/core/scss/functions/string" as sf;
color: sf.vars(color, primary, 500); // var(--mastors-color-primary-500)
gap: sf.vars(spacing, 4); // var(--mastors-spacing-4)
Map Helpers
@use "@mastors/core/scss/functions/map-helpers" as *;
$nested: ("colors": ("blue": #3b82f6));
$blue: map-deep-get($nested, "colors", "blue"); // → #3b82f6
$merged: map-collect($map-a, $map-b, $map-c); // shallow merge
Sass API — Mixins
Breakpoint Mixin Responsive
@use "@mastors/core/scss/mixins/breakpoint" as *;
.sidebar {
display: none;
// Mobile-first: apply at sm and above (min-width: 640px)
@include bp(sm) { display: block; }
@include bp(md) { width: 240px; }
@include bp(lg) { width: 300px; }
@include bp(2xl) { width: 360px; }
}
// Aliases — all three are equivalent
@include respond-to(md) { ... }
@include breakpoint-up(md) { ... }
// Below a breakpoint (max-width)
@include breakpoint-down(lg) { ... }
// Available keys: xs(0) sm(640px) md(768px) lg(1024px) xl(1280px) 2xl(1536px)
Container Mixin
@use "@mastors/core/scss/mixins/container" as *;
.page-wrapper {
@include container;
// → width: 100%; margin-inline: auto; padding-inline: 1rem;
// max-width: 640px @sm, 768px @md, 1024px @lg,
// 1280px @xl, 1400px @2xl
}
Elevation Mixin
@use "@mastors/core/scss/mixins/elevation" as *;
.card { @include elevation("md"); } // box-shadow: md token
.nav { @include elevation("lg"); } // box-shadow: lg token
// Keys: xs sm md lg xl 2xl inner none
Transition Mixin
@use "@mastors/core/scss/mixins/transition" as *;
.btn {
// transition($props, $duration, $easing)
@include transition((background-color, color), "150", "in-out");
// → transition: background-color 150ms cubic-bezier(0.4,0,0.2,1),
// color 150ms cubic-bezier(0.4,0,0.2,1);
}
.modal { @include transition((transform, opacity), "300", "out"); }
Pseudo Mixin
@use "@mastors/core/scss/mixins/pseudo" as *;
.badge::before {
@include pseudo($display: inline-block, $pos: relative, $content: "");
width: 8px;
height: 8px;
border-radius: 50%;
background: currentColor;
}
Theme Mixin
@use "@mastors/core/scss/mixins/theme" as *;
.card {
background: #fff;
@include dark-mode {
background: #1f2937;
color: #f9fafb;
}
@include light-mode {
box-shadow: 0 1px 3px rgb(0 0 0 / 10%);
}
// Named theme (data-theme="ocean")
@include theme("ocean") {
background: #083344;
color: #ecfeff;
}
}
Responsive
Breakpoints
EngineMobile-first breakpoints used by the responsive engine to generate prefixed utility variants. xs is the base (no prefix).
<!-- Pattern: {bp}:{utility} -->
<div class="hidden sm:block"> Shown sm+</div>
<div class="block md:hidden"> Hidden md+</div>
<div class="flex-col lg:flex-row"> Row from lg</div>
<div class="text-sm xl:text-base"> Bigger on xl</div>
| Key | min-width | Breakpoint |
|---|---|---|
| xs | 0px | All screens (no prefix) |
| sm | 640px | Large phones + |
| md | 768px | Tablets + |
| lg | 1024px | Laptops + |
| xl | 1280px | Desktops + |
| 2xl | 1536px | Wide screens + |
responsive: true in their config generate breakpoint variants. Currently enabled: display, position, text-align, float, clear.
Fluid Typography
ResponsiveUses clamp() to scale font sizes smoothly between two viewport widths. No media queries needed.
@use "@mastors/core/scss/responsive/fluid-type" as ft;
// Mixin — apply fluid font-size to the element
.hero-title {
@include ft.apply-fluid-type(2rem, 4rem);
// → font-size: clamp(2rem, …vw + …, 4rem);
}
// Custom viewport range
.headline {
@include ft.apply-fluid-type(1.5rem, 3rem, 480px, 1400px);
}
// Function — use inside any property value
.lead {
font-size: ft.fluid-type(1rem, 1.5rem);
}
// Pre-built fluid heading scale (opt-in)
// Scales h1–h6 + p fluidly across 320px–1280px
@include ft.fluid-scale();
// h1: clamp(2rem, …, 3.75rem)
// h2: clamp(1.5rem, …, 3rem)
// h3: clamp(1.25rem, …, 2.25rem)
// h4: clamp(1.125rem, …, 1.875rem)
// h5: clamp(1rem, …, 1.5rem)
// h6: clamp(0.875rem, …, 1.25rem)
// p: clamp(0.875rem, …, 1.125rem)
Container Queries
ResponsiveCSS container query helpers. Supports inline-size and size containment types.
<!-- Step 1: Create containment context -->
<div class="cq-inline"> <!-- container-type: inline-size -->
<div class="cq-size"> <!-- container-type: size -->
<!-- data attribute shorthand -->
<div data-container> <!-- container-type: inline-size -->
@use "@mastors/core/scss/responsive/container-queries" as cq;
// Inside any component SCSS file:
.card {
// When the container is at least 40rem wide
@include cq.cq(40rem) {
display: grid;
grid-template-columns: 1fr 2fr;
}
// Named container query
@include cq.cq(30rem, "sidebar") {
font-size: 0.875rem;
}
}
Accessibility
Built-in accessibility features: focus rings, reduced motion, screen-reader utilities, and print helpers.
Screen Reader Utilities
<!-- Visually hidden but accessible to screen readers -->
<span class="sr-only">Menu (screen reader label)</span>
<!-- Undo sr-only — make visible again -->
<span class="not-sr-only">Now visible</span>
<!-- Legacy aliases (all equivalent to sr-only) -->
<span class="visually-hidden">Hidden visually</span>
<span class="vh">Shorthand alias</span>
<!-- Shown when focused (skip links pattern) -->
<a class="visually-hidden-focusable" href="#main">
Skip to main content
</a>
Focus Ring
Automatically applied to :focus-visible. Mouse users do not see the ring (:focus:not(:focus-visible) { outline: none }).
/* Auto-applied by accessibility/_focus.scss */
:focus-visible {
outline: 2px solid var(--mastors-color-primary-500, #3b82f6);
outline-offset: 2px;
border-radius: 2px;
}
Reduced Motion
Respects the OS-level "reduce motion" preference. All animations and transitions are disabled to near-zero duration automatically.
/* Auto-applied — no class needed */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Print Utilities
<!-- Hide in print, show on screen -->
<nav class="print:hidden">Navigation</nav>
<!-- Show only in print -->
<div class="screen:hidden">Print-only watermark</div>
<!-- Page break control -->
<section class="print:break-inside-avoid">...</section>
<div class="print:break-before">New page before this</div>
<div class="print:break-after">New page after this</div>
<!-- Print-safe colors -->
<p class="print:text-black print:bg-white">Print-safe</p>
<div class="print:shadow-none print:border-none">Clean print</div>
Base
The base layer applies an opinionated modern CSS reset and emits all token-based CSS custom properties on :root.
Reset Highlights
/* box-sizing: border-box on everything */
*, *::before, *::after { box-sizing: border-box; }
/* Zero margin/padding everywhere */
* { margin: 0; padding: 0; }
/* Smooth scroll + tab-size */
html { text-size-adjust: 100%; tab-size: 4; scroll-behavior: smooth; }
/* Font smoothing */
body { -webkit-font-smoothing: antialiased; }
/* Block images, max 100% */
img, picture, video, canvas, svg { display: block; max-width: 100%; }
/* Form elements inherit font */
input, button, textarea, select { font: inherit; }
/* Break long words in headings/paragraphs */
p, h1, h2, h3, h4, h5, h6 { overflow-wrap: break-word; }
/* Removed list styles */
ol, ul { list-style: none; }
/* Links inherit color and text-decoration */
a { color: inherit; text-decoration: inherit; }
/* Collapsed table borders */
table { border-collapse: collapse; border-spacing: 0; }
/* Cursor on interactive elements */
button, [role="button"] { cursor: pointer; }
:root Custom Properties
Every token map is emitted as CSS custom properties on :root via the generator.
:root {
/* Colors — nested: --mastors-color-primary-50 … -950 */
--mastors-color-primary-500: #3b82f6;
--mastors-color-success-500: #22c55e;
/* … (6 palettes × 11 shades + white + black) … */
/* Spacing */
--mastors-spacing-4: 1rem;
/* Typography */
--mastors-font-size-xl: 1.25rem;
--mastors-font-weight-bold: 700;
/* Radii */
--mastors-radius-md: 0.375rem;
/* Shadows */
--mastors-shadow-md: 0 4px 6px -1px rgb(0 0 0/10%),...;
/* Transitions */
--mastors-duration-300: 300ms;
--mastors-easing-in-out: cubic-bezier(0.4, 0, 0.2, 1);
/* Z-index */
--mastors-z-modal: 400;
/* Opacity */
--mastors-opacity-50: 0.5;
}