Import System
Sassy supports splitting a theme across multiple files using the config.import array. Imported files contribute palette definitions, variables, colours, token colours, and semantic token colours to the final theme.
Syntax
Section titled “Syntax”config: name: "My Theme" type: dark import: - ./shared/variables.yaml - ./shared/colors.yaml - ./shared/tokenColors.yamlPaths are relative to the importing file.
Merge Behaviour
Section titled “Merge Behaviour”| Content Type | Merge Behaviour |
|---|---|
palette | Deep merge; later values override earlier ones |
vars | Deep merge; later values override earlier ones |
colors | Deep merge; later values override earlier ones |
semanticTokenColors | Deep merge; later values override earlier ones |
config | Deep merge; later values override earlier ones |
tokenColors | Append-only concatenation (order preserved) |
Merge Order
Section titled “Merge Order”- Imports are processed in array order, left to right.
- Each successive import is deep-merged (or appended for
tokenColors) onto the accumulated result. - The main file’s own
palette,vars,colors,semanticTokenColors, andtokenColorsare applied last, giving the main file final override authority.
import[0] → import[1] → ... → import[n] → main fileThis same order determines source location resolution: when a key is defined in multiple files, tools like resolve report the location from the last file in the chain that defines it — the effective definition. For example, if an import defines palette.pink and the main file overrides it, the reported location points to the main file.
tokenColors Ordering
Section titled “tokenColors Ordering”VS Code evaluates tokenColors rules using first-match semantics. The order of rules matters:
- Imported
tokenColorsappear first in the output. - The main file’s
tokenColorsare appended after all imports.
This means imports provide the base/specific rules while the main file can add fallback rules that only apply if no import already matched.
Dynamic Import Paths
Section titled “Dynamic Import Paths”Variable substitution is supported in import paths. Variables from config are available:
config: name: "Midnight Ocean" type: dark import: - ./import/tokenColors-$(type).yamlHere $(type) resolves to dark, producing the path ./import/tokenColors-dark.yaml.
Séance Operator
Section titled “Séance Operator”When redefining a palette key that already exists from a prior import, the séance operator (^) substitutes the accumulated prior value of that key inline.
| Form | Syntax |
|---|---|
| Bare | ^ |
| Parenthesised | ^() |
| Braced | ^{} |
All three forms are equivalent. Use whichever reads cleanly in context.
Given an imported palette that defines black: oklch(.145 0 0), a later file can derive from it:
palette: black: darken(^, 5)The ^ is replaced with the accumulated prior value of black before evaluation. The operator is resolved at compile time before the palette is evaluated. The prior value is captured as a synthetic palette token, which means the full derivation chain is visible in resolve output.
Chaining: If multiple import layers each redefine the same key with ^, each step captures the accumulated value to that point in the import sequence. Each layer sees the result of the previous one.
Constraints:
- Only valid in
palettedefinitions. - Only fires on leaf (string) values — not on object nodes.
- Silently passes through if no prior value exists for the key.
Dependency Tracking
Section titled “Dependency Tracking”In watch mode (--watch), Sassy automatically tracks all imported files. When any imported file changes, the theme is recompiled. No additional configuration is needed.
Example Multi-File Structure
Section titled “Example Multi-File Structure”my-theme/├── theme.yaml # Main entry: config + theme overrides├── shared/│ ├── palette.yaml # Colour palette definitions│ ├── variables.yaml # Semantic variables│ ├── colors.yaml # VS Code colour mappings│ ├── tokenColors.yaml # Syntax highlighting rules│ └── semanticTokenColors.yaml # Semantic token stylingtheme.yaml
config: name: "My Theme" type: dark import: - ./shared/palette.yaml - ./shared/variables.yaml - ./shared/colors.yaml - ./shared/tokenColors.yaml - ./shared/semanticTokenColors.yaml
theme: colors: # Override specific colours from imports statusBar.background: $$blueshared/palette.yaml
palette: blue: "#61afef" cyan: "#56b6c2"shared/variables.yaml
vars: accent: $$cyan std: bg: "#282c34" fg: "#abb2bf"shared/colors.yaml
theme: colors: editor.background: $(std.bg) editor.foreground: $(std.fg)shared/tokenColors.yaml
theme: tokenColors: - name: Keywords scope: keyword settings: foreground: $$cyanshared/semanticTokenColors.yaml
theme: semanticTokenColors: variable.declaration: foreground: $(std.fg) fontStyle: italic function.declaration: foreground: $(accent) fontStyle: bold "string:escape": $$cyan
