chore: initial commit
I just realized i was using this without commiting it, so this is a very big commit
This commit is contained in:
35
src/colors/generateColors.ts
Normal file
35
src/colors/generateColors.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import type { Recursive, Token } from '@pandacss/types'
|
||||
import * as radixColors from '@radix-ui/colors'
|
||||
import { type RequireDarkForeground, requireDarkForeground } from '@/types.js'
|
||||
|
||||
const generateColors = () => {
|
||||
const colors: Recursive<Token<string>> = {}
|
||||
for (const [key, value] of Object.entries(radixColors)) {
|
||||
const colorName = /([a-z]*)/.exec(key)?.[1] as keyof typeof radixColors
|
||||
// if (colorName === 'default' || !colorName) continue
|
||||
const newColor: Recursive<Token<string>> = {}
|
||||
const isAlpha = key.endsWith('A')
|
||||
const isP3 = key.includes('P3')
|
||||
const isDark = key.includes('Dark')
|
||||
const newColorName = `${colorName}${isDark ? 'Dark' : ''}${isP3 ? 'P3' : ''}${isAlpha ? 'Alpha' : ''}`
|
||||
|
||||
newColor.foreground = {
|
||||
value: requireDarkForeground.includes(colorName as RequireDarkForeground) ? '#000' : '#fff'
|
||||
}
|
||||
|
||||
for (const [subKey, subValue] of Object.entries(value)) {
|
||||
const colorNumber = /.*?([0-9]{1,2})$/.exec(subKey)?.[1]
|
||||
newColor[`${colorNumber}`] = { value: subValue }
|
||||
if (colorNumber === '9') {
|
||||
newColor.DEFAULT = { value: subValue }
|
||||
}
|
||||
}
|
||||
|
||||
colors[newColorName] = newColor
|
||||
}
|
||||
return colors
|
||||
}
|
||||
|
||||
export default generateColors
|
||||
|
||||
export type GeneratedColorsReturn = ReturnType<typeof generateColors>
|
||||
29
src/colors/generateNeutralColor.ts
Normal file
29
src/colors/generateNeutralColor.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Recursive, Token } from '@pandacss/types'
|
||||
import type { ColorVariation, NeutralColor } from '@/types.js'
|
||||
|
||||
const generateNeutralColor = (color: NeutralColor, colorVariation: ColorVariation) => {
|
||||
const colorName = `${color}${colorVariation.dark ? 'Dark' : ''}${colorVariation.p3 ? 'P3' : ''}${colorVariation.alpha ? 'Alpha' : ''}`
|
||||
|
||||
const neutralColor: Recursive<Token<string>> = {
|
||||
DEFAULT: { value: `{colors.${colorName}.DEFAULT}` },
|
||||
foreground: { value: `{colors.${colorName}.foreground}` },
|
||||
'1': { value: `{colors.${colorName}.1}` },
|
||||
'2': { value: `{colors.${colorName}.2}` },
|
||||
'3': { value: `{colors.${colorName}.3}` },
|
||||
'4': { value: `{colors.${colorName}.4}` },
|
||||
'5': { value: `{colors.${colorName}.5}` },
|
||||
'6': { value: `{colors.${colorName}.6}` },
|
||||
'7': { value: `{colors.${colorName}.7}` },
|
||||
'8': { value: `{colors.${colorName}.8}` },
|
||||
'9': { value: `{colors.${colorName}.9}` },
|
||||
'10': { value: `{colors.${colorName}.10}` },
|
||||
'11': { value: `{colors.${colorName}.11}` },
|
||||
'12': { value: `{colors.${colorName}.12}` }
|
||||
}
|
||||
|
||||
return neutralColor
|
||||
}
|
||||
|
||||
export default generateNeutralColor
|
||||
|
||||
export type GenerateNeutralColorReturn = typeof generateNeutralColor
|
||||
37
src/colors/generateSemanticColors.ts
Normal file
37
src/colors/generateSemanticColors.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import type { Recursive, Token } from '@pandacss/types'
|
||||
import type { BrandColor, ColorVariation } from '@/types.js'
|
||||
|
||||
interface SemanticColors {
|
||||
[key: string]: BrandColor
|
||||
}
|
||||
|
||||
const generateSemanticColors = (
|
||||
semanticColors: SemanticColors,
|
||||
variation: ColorVariation
|
||||
): Recursive<Token<string>> => {
|
||||
const colors: Recursive<Token<string>> = {}
|
||||
for (const [key, value] of Object.entries(semanticColors)) {
|
||||
const colorName = `${value}${variation.dark ? 'Dark' : ''}${
|
||||
variation.p3 ? 'P3' : ''
|
||||
}${variation.alpha ? 'Alpha' : ''}`
|
||||
colors[key] = {
|
||||
DEFAULT: { value: `{colors.${colorName}.DEFAULT}` },
|
||||
foreground: { value: `{colors.${colorName}.foreground}` },
|
||||
'1': { value: `{colors.${colorName}.1}` },
|
||||
'2': { value: `{colors.${colorName}.2}` },
|
||||
'3': { value: `{colors.${colorName}.3}` },
|
||||
'4': { value: `{colors.${colorName}.4}` },
|
||||
'5': { value: `{colors.${colorName}.5}` },
|
||||
'6': { value: `{colors.${colorName}.6}` },
|
||||
'7': { value: `{colors.${colorName}.7}` },
|
||||
'8': { value: `{colors.${colorName}.8}` },
|
||||
'9': { value: `{colors.${colorName}.9}` },
|
||||
'10': { value: `{colors.${colorName}.10}` },
|
||||
'11': { value: `{colors.${colorName}.11}` },
|
||||
'12': { value: `{colors.${colorName}.12}` }
|
||||
}
|
||||
}
|
||||
return colors
|
||||
}
|
||||
|
||||
export default generateSemanticColors
|
||||
51
src/index.ts
Normal file
51
src/index.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { definePreset } from '@pandacss/dev'
|
||||
import generateColors from '@/colors/generateColors.js'
|
||||
import generateNeutralColor from '@/colors/generateNeutralColor.js'
|
||||
import buttonRecipe from '@/recipes/button.js'
|
||||
import { detailsRecipe } from '@/recipes/details.js'
|
||||
import inputRecipe from '@/recipes/input.js'
|
||||
import type { BrandColor, ColorVariation, NeutralColor } from '@/types.js'
|
||||
import generateSemanticColors from './colors/generateSemanticColors.js'
|
||||
|
||||
export type themeConfig = {
|
||||
neutral?: NeutralColor
|
||||
semanticColors?: Record<string, BrandColor>
|
||||
colorVariation?: ColorVariation
|
||||
}
|
||||
|
||||
const defaultConfig: Required<themeConfig> = {
|
||||
neutral: 'slate',
|
||||
colorVariation: { dark: false, p3: false, alpha: false },
|
||||
semanticColors: { primary: 'teal' }
|
||||
}
|
||||
|
||||
const srJuggernautPandaPreset = (config?: themeConfig) => {
|
||||
const mergedConfig = { ...defaultConfig, ...config }
|
||||
const colors = generateColors()
|
||||
const neutral = generateNeutralColor(mergedConfig.neutral, mergedConfig.colorVariation)
|
||||
const semanticColors = generateSemanticColors(mergedConfig.semanticColors, mergedConfig.colorVariation)
|
||||
return definePreset({
|
||||
name: 'srjuggernaut-panda-preset',
|
||||
theme: {
|
||||
recipes: {
|
||||
button: buttonRecipe({ semanticColors: Object.keys(semanticColors) }),
|
||||
details: detailsRecipe({ semanticColors: Object.keys(semanticColors) }),
|
||||
input: inputRecipe
|
||||
},
|
||||
tokens: {
|
||||
colors
|
||||
},
|
||||
semanticTokens: {
|
||||
colors: {
|
||||
neutral: neutral,
|
||||
...semanticColors
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export default srJuggernautPandaPreset
|
||||
export { buttonVariants } from '@/recipes/button.js'
|
||||
|
||||
export { BrandColor, ColorVariation, NeutralColor } from '@/types.js'
|
||||
143
src/recipes/button.ts
Normal file
143
src/recipes/button.ts
Normal file
@@ -0,0 +1,143 @@
|
||||
import { defineRecipe } from '@pandacss/dev'
|
||||
|
||||
export const buttonVariants = ['solid', 'outline', 'ghost'] as const
|
||||
|
||||
interface ButtonRecipeArg {
|
||||
semanticColors: string[]
|
||||
}
|
||||
|
||||
const buttonRecipe = ({ semanticColors }: ButtonRecipeArg) => {
|
||||
const colorVariants = ['neutral', ...semanticColors]
|
||||
|
||||
return defineRecipe({
|
||||
className: 'button',
|
||||
base: {
|
||||
display: 'inline-flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
gap: '0.5em',
|
||||
width: 'fit-content',
|
||||
borderRadius: '4px',
|
||||
paddingBlock: '0.25em',
|
||||
paddingInline: '0.5em',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 200ms ease-in-out'
|
||||
},
|
||||
variants: {
|
||||
color: {
|
||||
...Object.fromEntries(colorVariants.map((color) => [color, {}]))
|
||||
},
|
||||
size: {
|
||||
small: {
|
||||
fontSize: '0.875em'
|
||||
},
|
||||
medium: {
|
||||
fontSize: '1em'
|
||||
},
|
||||
large: {
|
||||
fontSize: '1.125em'
|
||||
}
|
||||
},
|
||||
variant: {
|
||||
...Object.fromEntries(buttonVariants.map((variant) => [variant, {}]))
|
||||
}
|
||||
},
|
||||
compoundVariants: colorVariants.flatMap((color) =>
|
||||
buttonVariants.map((variant) => {
|
||||
switch (variant) {
|
||||
case 'outline':
|
||||
return {
|
||||
color,
|
||||
variant,
|
||||
css: {
|
||||
border: '1px solid',
|
||||
borderColor: `${color}.9`,
|
||||
backgroundColor: 'transparent',
|
||||
color: `${color}.9`,
|
||||
_hover: {
|
||||
backgroundColor: `${color}.10`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_active: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_disabled: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`,
|
||||
color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`,
|
||||
borderColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`,
|
||||
cursor: 'not-allowed',
|
||||
pointerEvents: 'none',
|
||||
_hover: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`,
|
||||
color: `${color}.4/50`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
case 'ghost':
|
||||
return {
|
||||
color,
|
||||
variant,
|
||||
css: {
|
||||
border: 'none',
|
||||
backgroundColor: 'transparent',
|
||||
color: `${color}.9`,
|
||||
_hover: {
|
||||
backgroundColor: `${color}.10`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_active: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_disabled: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`,
|
||||
color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`,
|
||||
cursor: 'not-allowed',
|
||||
pointerEvents: 'none',
|
||||
_hover: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 10%, transparent)`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default:
|
||||
return {
|
||||
color,
|
||||
variant,
|
||||
css: {
|
||||
border: 'none',
|
||||
backgroundColor: `${color}.9`,
|
||||
color: `${color}.foreground`,
|
||||
_hover: {
|
||||
backgroundColor: `${color}.10`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_active: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`,
|
||||
color: `${color}.foreground`
|
||||
},
|
||||
_disabled: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 40%, transparent)`,
|
||||
color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`,
|
||||
cursor: 'not-allowed',
|
||||
pointerEvents: 'none',
|
||||
_hover: {
|
||||
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 40%, transparent)`,
|
||||
color: `color-mix(in srgb, {colors.${color}.foreground} 40%, transparent)`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
),
|
||||
defaultVariants: {
|
||||
color: 'neutral',
|
||||
size: 'medium',
|
||||
variant: 'solid'
|
||||
}
|
||||
})
|
||||
}
|
||||
export default buttonRecipe
|
||||
59
src/recipes/details.ts
Normal file
59
src/recipes/details.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import { defineSlotRecipe } from '@pandacss/dev'
|
||||
|
||||
export interface DetailsRecipeArg {
|
||||
semanticColors: string[]
|
||||
}
|
||||
|
||||
export const detailsRecipe = ({ semanticColors }: DetailsRecipeArg) => {
|
||||
const colorVariants = ['neutral', ...semanticColors]
|
||||
const recipe = defineSlotRecipe({
|
||||
className: 'details',
|
||||
slots: ['summary', 'details'],
|
||||
base: {
|
||||
details: {
|
||||
display: 'block',
|
||||
overflow: 'hidden',
|
||||
borderRadius: '0.25em',
|
||||
transition: 'all 300ms ease-in-out'
|
||||
},
|
||||
summary: {
|
||||
display: 'block',
|
||||
overflow: 'hidden',
|
||||
borderRadius: '0.25em',
|
||||
padding: '0.25em',
|
||||
cursor: 'pointer',
|
||||
transition: 'all 300ms ease-in-out'
|
||||
}
|
||||
},
|
||||
variants: {
|
||||
color: {
|
||||
...Object.fromEntries(
|
||||
colorVariants.map((color) => [
|
||||
color as keyof typeof colorVariants,
|
||||
{
|
||||
summary: {
|
||||
backgroundColor: `{colors.${color}.3}`,
|
||||
color: `{colors.${color}.12}`,
|
||||
_hover: {
|
||||
backgroundColor: `{colors.${color}.4}`
|
||||
},
|
||||
'[open] &': {
|
||||
backgroundColor: `{colors.${color}.4}`
|
||||
}
|
||||
},
|
||||
details: {
|
||||
backgroundColor: `{colors.${color}.2}`,
|
||||
color: `{colors.${color}.12}`
|
||||
}
|
||||
}
|
||||
])
|
||||
)
|
||||
}
|
||||
},
|
||||
defaultVariants: {
|
||||
color: 'neutral'
|
||||
}
|
||||
})
|
||||
|
||||
return recipe
|
||||
}
|
||||
36
src/recipes/input.ts
Normal file
36
src/recipes/input.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
import { defineRecipe } from '@pandacss/dev'
|
||||
|
||||
export const inputRecipe = defineRecipe({
|
||||
className: 'input',
|
||||
base: {
|
||||
display: 'inline-flex',
|
||||
borderRadius: '4px',
|
||||
cursor: 'pointer',
|
||||
paddingBlock: '0.25em',
|
||||
paddingInline: '0.5em',
|
||||
border: '1px solid',
|
||||
borderColor: 'neutral.7',
|
||||
backgroundColor: 'neutral.3',
|
||||
color: 'neutral.12',
|
||||
outline: 'none',
|
||||
transition: 'all 200ms ease-in-out',
|
||||
_hover: {
|
||||
backgroundColor: 'neutral.4'
|
||||
},
|
||||
_disabled: {
|
||||
backgroundColor: 'neutral.3/50',
|
||||
color: 'neutral.11/50',
|
||||
borderColor: 'neutral.6/50',
|
||||
cursor: 'not-allowed',
|
||||
_hover: {
|
||||
backgroundColor: 'neutral.6/50',
|
||||
color: 'neutral.11/50'
|
||||
}
|
||||
},
|
||||
_active: {
|
||||
backgroundColor: 'neutral.8'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export default inputRecipe
|
||||
43
src/types.ts
Normal file
43
src/types.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
export const brandColor = [
|
||||
'bronze',
|
||||
'gold',
|
||||
'brown',
|
||||
'orange',
|
||||
'tomato',
|
||||
'red',
|
||||
'ruby',
|
||||
'crimson',
|
||||
'pink',
|
||||
'plum',
|
||||
'purple',
|
||||
'violet',
|
||||
'iris',
|
||||
'indigo',
|
||||
'blue',
|
||||
'cyan',
|
||||
'teal',
|
||||
'jade',
|
||||
'green',
|
||||
'grass',
|
||||
'sky',
|
||||
'mint',
|
||||
'lime',
|
||||
'yellow',
|
||||
'amber'
|
||||
] as const
|
||||
|
||||
export type BrandColor = (typeof brandColor)[number]
|
||||
|
||||
export const neutralColor = ['gray', 'mauve', 'slate', 'sage', 'olive', 'sand'] as const
|
||||
|
||||
export type NeutralColor = (typeof neutralColor)[number]
|
||||
|
||||
export type ColorVariation = {
|
||||
dark?: boolean
|
||||
p3?: boolean
|
||||
alpha?: boolean
|
||||
}
|
||||
|
||||
export const requireDarkForeground = ['sky', 'mint', 'lime', 'yellow', 'amber'] as const
|
||||
|
||||
export type RequireDarkForeground = (typeof requireDarkForeground)[number]
|
||||
Reference in New Issue
Block a user