feat: add new components and improve styling utilities
- Add chip, mark, and iconButton recipes with semantic color support - Introduce skeleton pattern and shimmer gradient for loading states - Enhance button and details recipes with refined transition properties - Update border radius tokens to include 'full' and negative spacing values - Refactor details recipe export and semantic color key handling - Bump package version to 0.0.6
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"version": "0.0.5",
|
"version": "0.0.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "ts-patch install -s && bun .husky/install.ts",
|
"prepare": "ts-patch install -s && bun .husky/install.ts",
|
||||||
"prepublishOnly": "bun run build",
|
"prepublishOnly": "bun run build",
|
||||||
|
|||||||
59
src/index.ts
59
src/index.ts
@@ -2,10 +2,16 @@ import { definePreset } from '@pandacss/dev'
|
|||||||
import generateColors from '@/colors/generateColors.js'
|
import generateColors from '@/colors/generateColors.js'
|
||||||
import generateNeutralColor from '@/colors/generateNeutralColor.js'
|
import generateNeutralColor from '@/colors/generateNeutralColor.js'
|
||||||
import buttonRecipe from '@/recipes/button.js'
|
import buttonRecipe from '@/recipes/button.js'
|
||||||
import { detailsRecipe } from '@/recipes/details.js'
|
import detailsRecipe from '@/recipes/details.js'
|
||||||
import inputRecipe from '@/recipes/input.js'
|
import inputRecipe from '@/recipes/input.js'
|
||||||
import { type BrandColor, type Color, type ColorVariation, color, type NeutralColor } from '@/types.js'
|
import { type BrandColor, type Color, type ColorVariation, color, type NeutralColor } from '@/types.js'
|
||||||
import generateSemanticColors from './colors/generateSemanticColors.js'
|
import generateSemanticColors from './colors/generateSemanticColors.js'
|
||||||
|
import pulseKeyframes from './keyframes/pulse.js'
|
||||||
|
import shimmerKeyframes from './keyframes/shimmer.js'
|
||||||
|
import skeletonPattern from './patterns/skeleton.js'
|
||||||
|
import chipRecipe from './recipes/chip.js'
|
||||||
|
import iconButtonRecipe from './recipes/iconButton.js'
|
||||||
|
import markRecipe from './recipes/mark.js'
|
||||||
|
|
||||||
export type ThemeConfig = {
|
export type ThemeConfig = {
|
||||||
neutral?: NeutralColor
|
neutral?: NeutralColor
|
||||||
@@ -26,13 +32,20 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
|
|||||||
const colors = generateColors(config?.includeColors)
|
const colors = generateColors(config?.includeColors)
|
||||||
const neutral = generateNeutralColor(mergedConfig.neutral, mergedConfig.colorVariation)
|
const neutral = generateNeutralColor(mergedConfig.neutral, mergedConfig.colorVariation)
|
||||||
const semanticColors = generateSemanticColors(mergedConfig.semanticColors, mergedConfig.colorVariation)
|
const semanticColors = generateSemanticColors(mergedConfig.semanticColors, mergedConfig.colorVariation)
|
||||||
|
const semanticColorKeysArray = Object.keys(semanticColors)
|
||||||
return definePreset({
|
return definePreset({
|
||||||
name: 'srjuggernaut-panda-preset',
|
name: 'srjuggernaut-panda-preset',
|
||||||
|
patterns: {
|
||||||
|
skeleton: skeletonPattern
|
||||||
|
},
|
||||||
theme: {
|
theme: {
|
||||||
recipes: {
|
recipes: {
|
||||||
button: buttonRecipe({ semanticColors: Object.keys(semanticColors) }),
|
button: buttonRecipe({ semanticColorNames: semanticColorKeysArray }),
|
||||||
details: detailsRecipe({ semanticColors: Object.keys(semanticColors) }),
|
chip: chipRecipe({ semanticColorNames: semanticColorKeysArray }),
|
||||||
input: inputRecipe
|
details: detailsRecipe({ semanticColorNames: semanticColorKeysArray }),
|
||||||
|
mark: markRecipe({ semanticColorNames: semanticColorKeysArray }),
|
||||||
|
input: inputRecipe({ semanticColorNames: semanticColorKeysArray }),
|
||||||
|
iconButton: iconButtonRecipe({ semanticColorNames: semanticColorKeysArray })
|
||||||
},
|
},
|
||||||
tokens: {
|
tokens: {
|
||||||
animations: {},
|
animations: {},
|
||||||
@@ -102,15 +115,16 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
|
|||||||
black: { value: '900' }
|
black: { value: '900' }
|
||||||
},
|
},
|
||||||
gradients: {
|
gradients: {
|
||||||
skeleton: {
|
shimmer: {
|
||||||
value: {
|
value: {
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
placement: 'to right',
|
placement: 'to right',
|
||||||
stops: [
|
stops: [
|
||||||
'color-mix(in srgb, {colors.neutral.12} 0%, transparent 100%) 0%',
|
'color-mix(in srgb, {colors.neutral.12} 0%, transparent) 0%',
|
||||||
'color-mix(in srgb, {colors.neutral.12} 10%, transparent 100%) 20%',
|
'color-mix(in srgb, {colors.neutral.12} 0%, transparent) 15%',
|
||||||
'color-mix(in srgb, {colors.neutral.12} 30%, transparent 100%) 30%',
|
'color-mix(in srgb, {colors.neutral.12} 10%, transparent) 20%',
|
||||||
'color-mix(in srgb, {colors.neutral.12} 0%, transparent 100%) 40%'
|
'color-mix(in srgb, {colors.neutral.12} 20%, transparent) 25%',
|
||||||
|
'color-mix(in srgb, {colors.neutral.12} 0%, transparent) 30%'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,7 +145,8 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
|
|||||||
md: { value: '0.375rem' },
|
md: { value: '0.375rem' },
|
||||||
lg: { value: '0.5rem' },
|
lg: { value: '0.5rem' },
|
||||||
xl: { value: '0.75rem' },
|
xl: { value: '0.75rem' },
|
||||||
xxl: { value: '1rem' }
|
xxl: { value: '1rem' },
|
||||||
|
full: { value: '9999px' }
|
||||||
},
|
},
|
||||||
shadows: {},
|
shadows: {},
|
||||||
opacity: {},
|
opacity: {},
|
||||||
@@ -144,19 +159,21 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
|
|||||||
lg: { value: '1.5rem' },
|
lg: { value: '1.5rem' },
|
||||||
xl: { value: '2rem' },
|
xl: { value: '2rem' },
|
||||||
xxl: { value: '3rem' },
|
xxl: { value: '3rem' },
|
||||||
xxxl: { value: '4rem' }
|
xxxl: { value: '4rem' },
|
||||||
|
'-xs': { value: '-0.25rem' },
|
||||||
|
'-sm': { value: '-0.5rem' },
|
||||||
|
'-md': { value: '-1rem' },
|
||||||
|
'-lg': { value: '-1.5rem' },
|
||||||
|
'-xl': { value: '-2rem' },
|
||||||
|
'-xxl': { value: '-3rem' },
|
||||||
|
'-xxxl': { value: '-4rem' }
|
||||||
},
|
},
|
||||||
zIndex: {}
|
zIndex: {}
|
||||||
},
|
},
|
||||||
|
animationStyles: {},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
shimmerRight: {
|
...shimmerKeyframes,
|
||||||
'0%': { transform: 'translateX(-100%)' },
|
...pulseKeyframes
|
||||||
'100%': { transform: 'translateX(150%)' }
|
|
||||||
},
|
|
||||||
shimmerLeft: {
|
|
||||||
'0%': { transform: 'translateX(100%)' },
|
|
||||||
'100%': { transform: 'translateX(-150%)' }
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
semanticTokens: {
|
semanticTokens: {
|
||||||
colors: {
|
colors: {
|
||||||
@@ -169,6 +186,10 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default srJuggernautPandaPreset
|
export default srJuggernautPandaPreset
|
||||||
|
|
||||||
export { buttonVariants } from '@/recipes/button.js'
|
export { buttonVariants } from '@/recipes/button.js'
|
||||||
|
export { chipVariants } from '@/recipes/chip.js'
|
||||||
|
export { iconButtonShapes, iconButtonVariants } from '@/recipes/iconButton.js'
|
||||||
|
export { markVariants } from '@/recipes/mark.js'
|
||||||
|
|
||||||
export { BrandColor, ColorVariation, NeutralColor } from '@/types.js'
|
export { BrandColor, ColorVariation, NeutralColor } from '@/types.js'
|
||||||
|
|||||||
11
src/keyframes/pulse.ts
Normal file
11
src/keyframes/pulse.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { defineKeyframes } from '@pandacss/dev'
|
||||||
|
|
||||||
|
const pulseKeyframes = defineKeyframes({
|
||||||
|
pulse: {
|
||||||
|
'0%': { opacity: '0.8' },
|
||||||
|
'50%': { opacity: '0.2' },
|
||||||
|
'100%': { opacity: '0.8' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default pulseKeyframes
|
||||||
10
src/keyframes/shimmer.ts
Normal file
10
src/keyframes/shimmer.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import { defineKeyframes } from '@pandacss/dev'
|
||||||
|
|
||||||
|
const shimmerKeyframes = defineKeyframes({
|
||||||
|
shimmer: {
|
||||||
|
'0%': { transform: 'translateX(-100%)' },
|
||||||
|
'100%': { transform: 'translateX(150%)' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default shimmerKeyframes
|
||||||
43
src/patterns/skeleton.ts
Normal file
43
src/patterns/skeleton.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { definePattern } from '@pandacss/dev'
|
||||||
|
import type { SystemStyleObject } from '@pandacss/types'
|
||||||
|
|
||||||
|
const skeletonPattern = definePattern({
|
||||||
|
properties: {
|
||||||
|
variant: { type: 'enum', value: ['shimmerLeft', 'shimmerRight', 'pulse'] },
|
||||||
|
duration: { type: 'number' }
|
||||||
|
} as const,
|
||||||
|
defaultValues: {
|
||||||
|
variant: 'pulse',
|
||||||
|
duration: 2
|
||||||
|
},
|
||||||
|
transform(props) {
|
||||||
|
const { variant, ...allOther } = props as SystemStyleObject & {
|
||||||
|
variant: 'shimmerLeft' | 'shimmerRight' | 'pulse'
|
||||||
|
duration: number
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...allOther,
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
_before: {
|
||||||
|
content: '""',
|
||||||
|
display: 'block',
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
background: variant === 'pulse' ? '{colors.neutral.3}' : undefined,
|
||||||
|
backgroundImage: variant === 'shimmerRight' || variant === 'shimmerLeft' ? '{gradients.shimmer}' : undefined,
|
||||||
|
animationDirection: variant === 'shimmerLeft' ? 'reverse' : 'normal',
|
||||||
|
animationName: variant === 'pulse' ? 'pulse' : 'shimmer',
|
||||||
|
animationDuration: `${props.duration}s`,
|
||||||
|
animationIterationCount: 'infinite',
|
||||||
|
animationTimingFunction: 'easeInOut'
|
||||||
|
}
|
||||||
|
} as SystemStyleObject
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export default skeletonPattern
|
||||||
@@ -3,11 +3,11 @@ import { defineRecipe } from '@pandacss/dev'
|
|||||||
export const buttonVariants = ['solid', 'outline', 'ghost'] as const
|
export const buttonVariants = ['solid', 'outline', 'ghost'] as const
|
||||||
|
|
||||||
interface ButtonRecipeArg {
|
interface ButtonRecipeArg {
|
||||||
semanticColors: string[]
|
semanticColorNames: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonRecipe = ({ semanticColors }: ButtonRecipeArg) => {
|
const buttonRecipe = ({ semanticColorNames }: ButtonRecipeArg) => {
|
||||||
const colorVariants = ['neutral', ...semanticColors]
|
const colorVariants = ['neutral', ...semanticColorNames]
|
||||||
|
|
||||||
return defineRecipe({
|
return defineRecipe({
|
||||||
className: 'button',
|
className: 'button',
|
||||||
@@ -15,13 +15,15 @@ const buttonRecipe = ({ semanticColors }: ButtonRecipeArg) => {
|
|||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
gap: '0.5em',
|
gap: 'xs',
|
||||||
width: 'fit-content',
|
width: 'fit-content',
|
||||||
borderRadius: '4px',
|
borderRadius: 'sm',
|
||||||
paddingBlock: '0.25em',
|
paddingBlock: 'xs',
|
||||||
paddingInline: '0.5em',
|
paddingInline: 'sm',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
transition: 'all 200ms ease-in-out'
|
transition: 'all',
|
||||||
|
transitionDuration: 'normal',
|
||||||
|
transitionTimingFunction: 'easeOut'
|
||||||
},
|
},
|
||||||
variants: {
|
variants: {
|
||||||
color: {
|
color: {
|
||||||
@@ -29,13 +31,19 @@ const buttonRecipe = ({ semanticColors }: ButtonRecipeArg) => {
|
|||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
small: {
|
small: {
|
||||||
fontSize: '0.875em'
|
paddingBlock: 'calc({spacing.xs} * 0.5)',
|
||||||
|
paddingInline: 'calc({spacing.xs} * 1)',
|
||||||
|
fontSize: 'sm'
|
||||||
},
|
},
|
||||||
medium: {
|
medium: {
|
||||||
fontSize: '1em'
|
paddingBlock: 'calc({spacing.xs} * 0.75)',
|
||||||
|
paddingInline: 'calc({spacing.xs} * 1.25)',
|
||||||
|
fontSize: 'base'
|
||||||
},
|
},
|
||||||
large: {
|
large: {
|
||||||
fontSize: '1.125em'
|
paddingBlock: 'calc({spacing.xs} * 1)',
|
||||||
|
paddingInline: 'calc({spacing.xs} * 1.5)',
|
||||||
|
fontSize: 'lg'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
variant: {
|
variant: {
|
||||||
|
|||||||
97
src/recipes/chip.ts
Normal file
97
src/recipes/chip.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
import { defineRecipe } from '@pandacss/dev'
|
||||||
|
|
||||||
|
export const chipVariants = ['solid', 'outline', 'ghost'] as const
|
||||||
|
|
||||||
|
interface ChipRecipeArg {
|
||||||
|
semanticColorNames: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const chipRecipe = ({ semanticColorNames }: ChipRecipeArg) => {
|
||||||
|
const colors = ['neutral', ...semanticColorNames]
|
||||||
|
return defineRecipe({
|
||||||
|
className: 'chip',
|
||||||
|
base: {
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
gap: 'xs',
|
||||||
|
lineHeight: '1',
|
||||||
|
borderRadius: 'sm',
|
||||||
|
fontWeight: 'semibold',
|
||||||
|
lineHeightStep: 'none',
|
||||||
|
userSelect: 'none'
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
color: {
|
||||||
|
...Object.fromEntries(colors.map((color) => [color, {}]))
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
...Object.fromEntries(chipVariants.map((variant) => [variant, {}]))
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
small: {
|
||||||
|
paddingBlock: 'calc({spacing.sm} * 0.5)',
|
||||||
|
paddingInline: 'calc({spacing.sm} * 0.75)',
|
||||||
|
fontSize: 'xs'
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
paddingBlock: 'calc({spacing.sm} * 0.75)',
|
||||||
|
paddingInline: 'calc({spacing.sm})',
|
||||||
|
fontSize: 'sm'
|
||||||
|
},
|
||||||
|
large: {
|
||||||
|
paddingBlock: 'calc({spacing.sm})',
|
||||||
|
paddingInline: 'calc({spacing.sm} * 1.25)',
|
||||||
|
fontSize: 'base'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compoundVariants: colors.flatMap((color) => {
|
||||||
|
return chipVariants.map((variant) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'solid':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
backgroundColor: `{colors.${color}.9}`,
|
||||||
|
color: `{colors.${color}.foreground}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'outline':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
border: '1px solid',
|
||||||
|
borderColor: `{colors.${color}.6}`,
|
||||||
|
color: `{colors.${color}.9}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'ghost':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
backgroundColor: `{colors.${color}.2}`,
|
||||||
|
color: `{colors.${color}.9}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
defaultVariants: {
|
||||||
|
color: 'neutral',
|
||||||
|
size: 'medium',
|
||||||
|
variant: 'solid'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default chipRecipe
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { defineSlotRecipe } from '@pandacss/dev'
|
import { defineSlotRecipe } from '@pandacss/dev'
|
||||||
|
|
||||||
export interface DetailsRecipeArg {
|
export interface DetailsRecipeArg {
|
||||||
semanticColors: string[]
|
semanticColorNames: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export const detailsRecipe = ({ semanticColors }: DetailsRecipeArg) => {
|
const detailsRecipe = ({ semanticColorNames }: DetailsRecipeArg) => {
|
||||||
const colorVariants = ['neutral', ...semanticColors]
|
const colorVariants = ['neutral', ...semanticColorNames]
|
||||||
const recipe = defineSlotRecipe({
|
const recipe = defineSlotRecipe({
|
||||||
className: 'details',
|
className: 'details',
|
||||||
slots: ['summary', 'details'],
|
slots: ['summary', 'details'],
|
||||||
@@ -13,16 +13,20 @@ export const detailsRecipe = ({ semanticColors }: DetailsRecipeArg) => {
|
|||||||
details: {
|
details: {
|
||||||
display: 'block',
|
display: 'block',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderRadius: '0.25em',
|
borderRadius: 'sm',
|
||||||
transition: 'all 300ms ease-in-out'
|
transition: 'all',
|
||||||
|
transitionTimingFunction: 'easeOut',
|
||||||
|
transitionDuration: 'normal'
|
||||||
},
|
},
|
||||||
summary: {
|
summary: {
|
||||||
display: 'block',
|
display: 'block',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
borderRadius: '0.25em',
|
borderRadius: 'sm',
|
||||||
padding: '0.25em',
|
padding: 'xs',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
transition: 'all 300ms ease-in-out'
|
transition: 'all',
|
||||||
|
transitionTimingFunction: 'easeOut',
|
||||||
|
transitionDuration: 'normal'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
variants: {
|
variants: {
|
||||||
@@ -57,3 +61,5 @@ export const detailsRecipe = ({ semanticColors }: DetailsRecipeArg) => {
|
|||||||
|
|
||||||
return recipe
|
return recipe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default detailsRecipe
|
||||||
|
|||||||
176
src/recipes/iconButton.ts
Normal file
176
src/recipes/iconButton.ts
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
import { defineRecipe, type SystemStyleObject } from '@pandacss/dev'
|
||||||
|
|
||||||
|
export const iconButtonVariants = ['solid', 'outline', 'ghost'] as const
|
||||||
|
export const iconButtonShapes = ['circle', 'square'] as const
|
||||||
|
|
||||||
|
interface IconButtonRecipeArg {
|
||||||
|
semanticColorNames: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const iconButtonRecipe = ({ semanticColorNames }: IconButtonRecipeArg) => {
|
||||||
|
const colors = ['neutral', ...semanticColorNames]
|
||||||
|
return defineRecipe({
|
||||||
|
className: 'iconButton',
|
||||||
|
base: {
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
width: 'calc(max-content)',
|
||||||
|
height: 'auto',
|
||||||
|
aspectRatio: '1/1',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transitionProperty: 'color, background-color, border-color',
|
||||||
|
transitionDuration: 'normal',
|
||||||
|
transitionTimingFunction: 'easeOut',
|
||||||
|
_disabled: {
|
||||||
|
cursor: 'not-allowed'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
shape: {
|
||||||
|
...Object.fromEntries(
|
||||||
|
iconButtonShapes.map((shape) => {
|
||||||
|
switch (shape) {
|
||||||
|
case 'circle':
|
||||||
|
return [
|
||||||
|
shape,
|
||||||
|
{
|
||||||
|
borderRadius: 'full'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
case 'square':
|
||||||
|
return [
|
||||||
|
shape,
|
||||||
|
{
|
||||||
|
borderRadius: 'none'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
default:
|
||||||
|
return [shape, {}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
},
|
||||||
|
color: {
|
||||||
|
...Object.fromEntries(colors.map((color) => [color, {}]))
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
...Object.fromEntries(iconButtonVariants.map((variant) => [variant, {}]))
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
small: {
|
||||||
|
padding: 'calc({spacing.xs} * 0.75) '
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
padding: 'xs'
|
||||||
|
},
|
||||||
|
large: {
|
||||||
|
padding: 'calc({spacing.xs} * 1.25)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compoundVariants: colors.flatMap((color) =>
|
||||||
|
iconButtonVariants.map((variant) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'solid':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: `${color}.9`,
|
||||||
|
color: `${color}.foreground`,
|
||||||
|
_hover: {
|
||||||
|
backgroundColor: `${color}.10`
|
||||||
|
},
|
||||||
|
_active: {
|
||||||
|
backgroundColor: `color-mix(in srgb, {colors.${color}.9} 80%, {colors.${color}.1})`
|
||||||
|
},
|
||||||
|
_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)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} as SystemStyleObject
|
||||||
|
}
|
||||||
|
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: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
defaultVariants: {
|
||||||
|
shape: 'circle',
|
||||||
|
color: 'neutral',
|
||||||
|
variant: 'solid',
|
||||||
|
size: 'medium'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default iconButtonRecipe
|
||||||
@@ -1,36 +1,69 @@
|
|||||||
import { defineRecipe } from '@pandacss/dev'
|
import { defineRecipe } from '@pandacss/dev'
|
||||||
|
|
||||||
export const inputRecipe = defineRecipe({
|
export interface InputRecipeArg {
|
||||||
className: 'input',
|
semanticColorNames: string[]
|
||||||
base: {
|
}
|
||||||
display: 'inline-flex',
|
|
||||||
borderRadius: '4px',
|
export const inputRecipe = ({ semanticColorNames }: InputRecipeArg) => {
|
||||||
cursor: 'pointer',
|
const colorVariants = ['neutral', ...semanticColorNames]
|
||||||
paddingBlock: '0.25em',
|
|
||||||
paddingInline: '0.5em',
|
return defineRecipe({
|
||||||
border: '1px solid',
|
className: 'input',
|
||||||
borderColor: 'neutral.7',
|
base: {
|
||||||
backgroundColor: 'neutral.3',
|
display: 'inline-flex',
|
||||||
color: 'neutral.12',
|
borderRadius: 'sm',
|
||||||
outline: 'none',
|
paddingBlock: 'xs',
|
||||||
transition: 'all 200ms ease-in-out',
|
paddingInline: 'sm',
|
||||||
_hover: {
|
border: '1px solid',
|
||||||
backgroundColor: 'neutral.4'
|
outline: 'none',
|
||||||
},
|
transitionProperty: 'color, background-color, border-color',
|
||||||
_disabled: {
|
transitionDuration: 'normal',
|
||||||
backgroundColor: 'neutral.3/50',
|
transitionTimingFunction: 'easeOut',
|
||||||
color: 'neutral.11/50',
|
cursor: 'text',
|
||||||
borderColor: 'neutral.6/50',
|
_disabled: {
|
||||||
cursor: 'not-allowed',
|
cursor: 'not-allowed'
|
||||||
_hover: {
|
|
||||||
backgroundColor: 'neutral.6/50',
|
|
||||||
color: 'neutral.11/50'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_active: {
|
variants: {
|
||||||
backgroundColor: 'neutral.8'
|
color: {
|
||||||
|
...Object.fromEntries(
|
||||||
|
colorVariants.map((color) => [
|
||||||
|
color,
|
||||||
|
{
|
||||||
|
borderColor: `${color}.6`,
|
||||||
|
backgroundColor: `${color}.2`,
|
||||||
|
color: `${color}.12`,
|
||||||
|
_hover: {
|
||||||
|
backgroundColor: `${color}.3`
|
||||||
|
},
|
||||||
|
_focus: {
|
||||||
|
backgroundColor: `${color}.3`,
|
||||||
|
borderColor: `${color}.7`
|
||||||
|
},
|
||||||
|
_disabled: {
|
||||||
|
backgroundColor: `color-mix(in srgb, {colors.${color}.2} 30%, transparent)`,
|
||||||
|
color: `color-mix(in srgb, {colors.${color}.11} 30%, transparent)`,
|
||||||
|
borderColor: `color-mix(in srgb, {colors.${color}.6} 30%, transparent)`,
|
||||||
|
_hover: {
|
||||||
|
backgroundColor: `color-mix(in srgb, {colors.${color}.2} 30%, transparent)`,
|
||||||
|
borderColor: `color-mix(in srgb, {colors.${color}.6} 30%, transparent)`,
|
||||||
|
color: `color-mix(in srgb, {colors.${color}.11} 30%, transparent)`
|
||||||
|
},
|
||||||
|
_focus: {
|
||||||
|
backgroundColor: `color-mix(in srgb, {colors.${color}.2} 30%, transparent)`,
|
||||||
|
borderColor: `color-mix(in srgb, {colors.${color}.6} 30%, transparent)`,
|
||||||
|
color: `color-mix(in srgb, {colors.${color}.11} 30%, transparent)`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
])
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
color: 'neutral'
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
}
|
||||||
|
|
||||||
export default inputRecipe
|
export default inputRecipe
|
||||||
|
|||||||
80
src/recipes/mark.ts
Normal file
80
src/recipes/mark.ts
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import { defineRecipe, type SystemStyleObject } from '@pandacss/dev'
|
||||||
|
|
||||||
|
const markVariants = ['highlight', 'bold', 'underline'] as const
|
||||||
|
|
||||||
|
interface MarkRecipeArg {
|
||||||
|
semanticColorNames: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const markRecipe = ({ semanticColorNames }: MarkRecipeArg) => {
|
||||||
|
const colors = ['neutral', ...semanticColorNames] as const
|
||||||
|
return defineRecipe({
|
||||||
|
className: 'mark',
|
||||||
|
base: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
display: 'inline-block',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
color: 'inherit',
|
||||||
|
gap: 'xs'
|
||||||
|
},
|
||||||
|
variants: {
|
||||||
|
color: {
|
||||||
|
...Object.fromEntries(colors.map((color) => [color, {}]))
|
||||||
|
},
|
||||||
|
variant: {
|
||||||
|
...Object.fromEntries(markVariants.map((variant) => [variant, {}]))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
compoundVariants: markVariants.flatMap((variant) =>
|
||||||
|
colors.map((color) => {
|
||||||
|
switch (variant) {
|
||||||
|
case 'highlight':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
margin: '0 -0.4em',
|
||||||
|
padding: '0.1em 0.4em 0.1em 0.4em',
|
||||||
|
borderRadius: '0.8em 0.3em',
|
||||||
|
boxDecorationBreak: 'clone',
|
||||||
|
WebkitBoxDecorationBreak: 'clone',
|
||||||
|
backgroundClip: 'padding-box',
|
||||||
|
fontWeight: 'semibold',
|
||||||
|
backgroundImage: `linear-gradient(to right, color-mix(in srgb, {colors.${color}.9} 10%,transparent) 0%, color-mix(in srgb, {colors.${color}.9} 73%, transparent) 12%, color-mix(in srgb, {colors.${color}.9} 25%, transparent) 100%)`,
|
||||||
|
color: `{colors.${color}.foreground}`
|
||||||
|
} as SystemStyleObject
|
||||||
|
}
|
||||||
|
case 'bold':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: `{colors.${color}.9}`
|
||||||
|
} as SystemStyleObject
|
||||||
|
}
|
||||||
|
case 'underline':
|
||||||
|
return {
|
||||||
|
color,
|
||||||
|
variant,
|
||||||
|
css: {
|
||||||
|
textDecorationLine: 'underline',
|
||||||
|
textDecorationThickness: '2px',
|
||||||
|
textDecorationColor: `{colors.${color}.9}`
|
||||||
|
} as SystemStyleObject
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return { color, variant, css: {} }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
|
defaultVariants: {
|
||||||
|
color: 'neutral',
|
||||||
|
variant: 'highlight'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export default markRecipe
|
||||||
|
export { markVariants }
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
// Environment setup & latest features
|
// Environment setup & latest features
|
||||||
"lib": ["esnext"],
|
"lib": ["esnext"],
|
||||||
"target": "ES6",
|
"target": "es2024",
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleDetection": "auto",
|
"moduleDetection": "auto",
|
||||||
"allowJs": false,
|
"allowJs": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user