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
38 changes: 38 additions & 0 deletions .changeset/color-palette-handling.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
'@pandacss/types': minor
'@pandacss/token-dictionary': minor
'@pandacss/core': minor
'@pandacss/config': minor
'@pandacss/generator': minor
---

Add support for controlling the color palette generation via `theme.colorPalette` property.

```ts
// Disable color palette generation completely
export default defineConfig({
theme: {
colorPalette: {
enabled: false,
},
},
})

// Include only specific colors
export default defineConfig({
theme: {
colorPalette: {
include: ['gray', 'blue', 'red'],
},
},
})

// Exclude specific colors
export default defineConfig({
theme: {
colorPalette: {
exclude: ['yellow', 'orange'],
},
},
})
```
1 change: 1 addition & 0 deletions packages/core/src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export class Context {
themes: themeVariants,
prefix: this.prefix.tokens,
hash: this.hash.tokens,
colorPalette: theme.colorPalette,
})
}

Expand Down
167 changes: 167 additions & 0 deletions packages/token-dictionary/__tests__/color-palette.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { addVirtualPalette } from '../src/middleware'
import { transforms } from '../src/transform'
import { TokenDictionary } from '../src/dictionary'

const createDictionary = (options: any = {}) => {
const dictionary = new TokenDictionary(options)
return dictionary
.registerTokens()
.registerTransform(...transforms)
.registerMiddleware(addVirtualPalette)
.build()
}

const dasherize = (token: string) =>
token
.toString()
Expand Down Expand Up @@ -1634,3 +1643,161 @@ test('should generate virtual palette with DEFAULT value', () => {
}
`)
})

test('should disable color palette when enabled is false', () => {
const dictionary = createDictionary({
tokens: {
colors: {
red: {
500: { value: '#red500' },
700: { value: '#red700' },
},
blue: {
500: { value: '#blue500' },
700: { value: '#blue700' },
},
},
},
colorPalette: {
enabled: false,
},
})

const getVar = dictionary.view.get
expect(getVar('colors.colorPalette.500')).toBeUndefined()
expect(getVar('colors.colorPalette.700')).toBeUndefined()

expect(Array.from(dictionary.view.colorPalettes.keys())).toHaveLength(0)
})

test('should include only specified colors in color palette', () => {
const dictionary = createDictionary({
tokens: {
colors: {
red: {
500: { value: '#red500' },
700: { value: '#red700' },
},
blue: {
500: { value: '#blue500' },
700: { value: '#blue700' },
},
green: {
500: { value: '#green500' },
700: { value: '#green700' },
},
},
},
colorPalette: {
include: ['red', 'blue'],
},
})

const getVar = dictionary.view.get
expect(getVar('colors.colorPalette.500')).toBe('var(--colors-color-palette-500)')
expect(getVar('colors.colorPalette.700')).toBe('var(--colors-color-palette-700)')

expect(Array.from(dictionary.view.colorPalettes.keys())).toMatchInlineSnapshot(`
[
"red",
"blue",
]
`)
})

test('should exclude specified colors from color palette', () => {
const dictionary = createDictionary({
tokens: {
colors: {
red: {
500: { value: '#red500' },
700: { value: '#red700' },
},
blue: {
500: { value: '#blue500' },
700: { value: '#blue700' },
},
green: {
500: { value: '#green500' },
700: { value: '#green700' },
},
},
},
colorPalette: {
exclude: ['red'],
},
})

const getVar = dictionary.view.get
expect(getVar('colors.colorPalette.500')).toBe('var(--colors-color-palette-500)')
expect(getVar('colors.colorPalette.700')).toBe('var(--colors-color-palette-700)')

expect(Array.from(dictionary.view.colorPalettes.keys())).toMatchInlineSnapshot(`
[
"blue",
"green",
]
`)
})

test('should handle semantic tokens with colorPalette configuration', () => {
const dictionary = createDictionary({
semanticTokens: {
colors: {
primary: {
value: '{colors.blue.500}',
},
secondary: {
value: '{colors.red.500}',
},
accent: {
value: '{colors.green.500}',
},
},
},
tokens: {
colors: {
blue: {
500: { value: '#blue500' },
},
red: {
500: { value: '#red500' },
},
green: {
500: { value: '#green500' },
},
},
},
colorPalette: {
include: ['primary'],
},
})

expect(Array.from(dictionary.view.colorPalettes.keys())).toMatchInlineSnapshot(`
[
"primary",
]
`)
})

test('should enable color palette by default when no configuration is provided', () => {
const dictionary = createDictionary({
tokens: {
colors: {
red: {
500: { value: '#red500' },
},
},
},
// No colorPalette config provided - should default to enabled: true
})

const getVar = dictionary.view.get
expect(getVar('colors.colorPalette.500')).toBe('var(--colors-color-palette-500)')

expect(Array.from(dictionary.view.colorPalettes.keys())).toMatchInlineSnapshot(`
[
"red",
]
`)
})
4 changes: 4 additions & 0 deletions packages/token-dictionary/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
"@pandacss/logger": "workspace:^",
"@pandacss/shared": "workspace:*",
"@pandacss/types": "workspace:*",
"picomatch": "^4.0.0",
"ts-pattern": "5.8.0"
},
"devDependencies": {
"@types/picomatch": "4.0.2"
}
}
14 changes: 13 additions & 1 deletion packages/token-dictionary/src/dictionary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,14 @@ import {
type CssVar,
type CssVarOptions,
} from '@pandacss/shared'
import type { Recursive, SemanticTokens, ThemeVariantsMap, TokenCategory, Tokens } from '@pandacss/types'
import type {
Recursive,
SemanticTokens,
ThemeVariantsMap,
TokenCategory,
Tokens,
ColorPaletteOptions,
} from '@pandacss/types'
import { isMatching, match } from 'ts-pattern'
import { isCompositeTokenValue } from './is-composite'
import { middlewares } from './middleware'
Expand All @@ -37,6 +44,7 @@ export interface TokenDictionaryOptions {
themes?: ThemeVariantsMap | undefined
prefix?: string
hash?: boolean
colorPalette?: ColorPaletteOptions
}

export interface TokenMiddleware {
Expand Down Expand Up @@ -81,6 +89,10 @@ export class TokenDictionary {
return this.options.hash
}

get colorPalette() {
return this.options.colorPalette
}

getByName = (path: string) => {
return this.byName.get(path)
}
Expand Down
6 changes: 6 additions & 0 deletions packages/token-dictionary/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@ export const addPixelUnit: TokenMiddleware = {
export const addVirtualPalette: TokenMiddleware = {
enforce: 'post',
transform(dictionary: TokenDictionary) {
const colorPaletteConfig = dictionary.colorPalette
const enabled = colorPaletteConfig?.enabled ?? true

// If disabled, skip generating color palettes
if (!enabled) return

const tokens = dictionary.filter({ extensions: { category: 'colors' } })

const keys = new Map<string, string[]>()
Expand Down
Loading