Skip to content
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
6 changes: 6 additions & 0 deletions .changeset/energy-colour-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@surf-kit/theme': minor
'@surf-kit/tokens': minor
---

Add energy colour mode with dedicated token set and build pipeline
6 changes: 6 additions & 0 deletions packages/theme/src/ThemeContext.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client'

import { createContext } from 'react'
import type { ThemeContextValue } from './types'

export const ThemeContext = createContext<ThemeContextValue | null>(null)
4 changes: 1 addition & 3 deletions packages/theme/src/ThemeProvider.native.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client'

import React, {
createContext,
useCallback,
useEffect,
useMemo,
Expand All @@ -14,14 +13,13 @@ import type {
Theme,
ThemeContextValue,
} from './types'
import { ThemeContext } from './ThemeContext'

const DEFAULT_THEME: Theme = {
name: 'default',
cssVars: {},
}

export const ThemeContext = createContext<ThemeContextValue | null>(null)

function getSystemPreference(): ColorMode {
return (Appearance.getColorScheme() as ColorMode) ?? 'light'
}
Expand Down
4 changes: 1 addition & 3 deletions packages/theme/src/ThemeProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'use client'

import React, {
createContext,
useCallback,
useEffect,
useMemo,
Expand All @@ -14,14 +13,13 @@ import type {
Theme,
ThemeContextValue,
} from './types'
import { ThemeContext } from './ThemeContext'

const DEFAULT_THEME: Theme = {
name: 'default',
cssVars: {},
}

export const ThemeContext = createContext<ThemeContextValue | null>(null)

function getSystemPreference(): ColorMode {
if (typeof window === 'undefined') return 'light'
return window.matchMedia('(prefers-color-scheme: dark)').matches
Expand Down
3 changes: 2 additions & 1 deletion packages/theme/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export { ThemeProvider, ThemeContext } from './ThemeProvider'
export { ThemeProvider } from './ThemeProvider'
export { ThemeContext } from './ThemeContext'
export { useTheme } from './useTheme'
export { useColorMode } from './useColorMode'
export { createTheme } from './createTheme'
Expand Down
2 changes: 1 addition & 1 deletion packages/theme/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/** Resolved color mode applied to the DOM */
export type ColorMode = 'light' | 'dark' | 'brand'
export type ColorMode = 'light' | 'dark' | 'brand' | 'energy'

/** User-facing color mode preference (includes 'system') */
export type ColorModePreference = ColorMode | 'system'
Expand Down
2 changes: 1 addition & 1 deletion packages/theme/src/useTheme.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client'

import { useContext } from 'react'
import { ThemeContext } from './ThemeProvider'
import { ThemeContext } from './ThemeContext'
import type { ThemeContextValue } from './types'

/**
Expand Down
5 changes: 5 additions & 0 deletions packages/tokens/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"./css/light": "./dist/css/variables-light.css",
"./css/dark": "./dist/css/variables-dark.css",
"./css/brand": "./dist/css/variables-brand.css",
"./css/energy": "./dist/css/variables-energy.css",
"./ts": {
"types": "./dist/ts/tokens.d.ts",
"default": "./dist/ts/tokens.js"
Expand All @@ -43,6 +44,10 @@
"types": "./dist/native/tokens-brand.ts",
"default": "./dist/native/tokens-brand.ts"
},
"./native/energy": {
"types": "./dist/native/tokens-energy.ts",
"default": "./dist/native/tokens-energy.ts"
},
".": "./dist/ts/tokens.js"
},
"repository": {
Expand Down
54 changes: 54 additions & 0 deletions packages/tokens/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,21 @@ StyleDictionary.registerFormat({
},
});

// Register custom format that wraps output in [data-color-mode="energy"] { ... }
StyleDictionary.registerFormat({
name: "css/variables-energy",
format: ({ dictionary, options }) => {
const selector = '[data-color-mode="energy"]';
const vars = formattedVariables({
format: "css",
dictionary,
outputReferences: options?.outputReferences ?? false,
usesDtcg: true,
});
return `@layer surf.tokens {\n ${selector} {\n${vars}\n }\n}\n`;
},
});

// Register format for resolved JS objects (React Native fallback)
StyleDictionary.registerFormat({
name: 'js/nested-object',
Expand Down Expand Up @@ -248,6 +263,45 @@ async function build() {
await brandSD.buildAllPlatforms();
console.log("Brand build complete.");

// ── Energy build ────────────────────────────────────────────
const energySD = new StyleDictionary({
include: [...primitives, componentTokens],
source: [
resolve(root, "src/semantic/energy.json"),
],
platforms: {
css: {
transformGroup: "css",
prefix: "surf",
buildPath: resolve(root, "dist/css") + "/",
files: [
{
destination: "variables-energy.css",
format: "css/variables-energy",
options: {
outputReferences: false,
},
},
],
},
'react-native': {
transformGroup: 'js',
prefix: 'surf',
buildPath: resolve(root, 'dist/native') + '/',
files: [
{
destination: 'tokens-energy.ts',
format: 'js/nested-object',
},
],
},
},
});

await energySD.hasInitialized;
await energySD.buildAllPlatforms();
console.log("Energy build complete.");

console.log("All token builds complete.");
}

Expand Down
38 changes: 38 additions & 0 deletions packages/tokens/src/semantic/energy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"color": {
"bg": {
"canvas": { "$value": "#ffffff" },
"surface": { "$value": "#ffffff" },
"surface-raised": { "$value": "#ffffff" },
"surface-sunken": { "$value": "{color.charcoal.50}" }
},
"text": {
"primary": { "$value": "{color.charcoal.900}" },
"secondary": { "$value": "{color.charcoal.500}" },
"muted": { "$value": "{color.charcoal.300}" },
"inverse": { "$value": "#ffffff" }
},
"accent": {
"primary": { "$value": "{color.watermelon.500}" },
"primary-hover": { "$value": "#d00f4a" },
"primary-active": { "$value": "{color.watermelon.700}" },
"primary-subtle": { "$value": "rgba(232,23,93,0.12)" },
"primary-subtlest": { "$value": "rgba(232,23,93,0.08)" }
},
"border": {
"default": { "$value": "{color.charcoal.100}" },
"strong": { "$value": "{color.charcoal.300}" },
"interactive": { "$value": "{color.watermelon.500}" }
},
"status": {
"success": { "$value": "#16a34a" },
"success-subtle": { "$value": "rgba(22,163,74,0.12)" },
"warning": { "$value": "#d97706" },
"warning-subtle": { "$value": "rgba(217,119,6,0.12)" },
"error": { "$value": "#b91c1c" },
"error-subtle": { "$value": "rgba(185,28,28,0.12)" },
"info": { "$value": "#0284c7" },
"info-subtle": { "$value": "rgba(2,132,199,0.12)" }
}
}
}
Loading