feat: add alert recipe and fade keyframes, update font sizes and global styles

This commit is contained in:
2025-09-26 14:08:48 -06:00
parent 0d8ccf5fdb
commit 50502ea63e
4 changed files with 236 additions and 23 deletions

View File

@@ -6,9 +6,11 @@ import detailsRecipe from '@/recipes/details.js'
import inputRecipe from '@/recipes/input.js'
import { type BrandColor, type Color, type ColorVariation, color, type NeutralColor } from '@/types.js'
import generateSemanticColors from './colors/generateSemanticColors.js'
import fadeKeyframes from './keyframes/fade.js'
import pulseKeyframes from './keyframes/pulse.js'
import shimmerKeyframes from './keyframes/shimmer.js'
import skeletonPattern from './patterns/skeleton.js'
import alertRecipe from './recipes/alert.js'
import chipRecipe from './recipes/chip.js'
import iconButtonRecipe from './recipes/iconButton.js'
import markRecipe from './recipes/mark.js'
@@ -40,6 +42,7 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
},
theme: {
recipes: {
alert: alertRecipe({ semanticColorNames: semanticColorKeysArray }),
button: buttonRecipe({ semanticColorNames: semanticColorKeysArray }),
chip: chipRecipe({ semanticColorNames: semanticColorKeysArray }),
details: detailsRecipe({ semanticColorNames: semanticColorKeysArray }),
@@ -84,24 +87,24 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
sm: { value: '0.875em' },
base: { value: '1em' },
lg: { value: '1.125em' },
xl: { value: '1.5em' },
h1: { value: '3em' },
h2: { value: '2.5em' },
h3: { value: '2.25em' },
h4: { value: '2em' },
h5: { value: '1.75em' },
xl: { value: '1.375em' },
h6: { value: '1.5em' },
h5: { value: '1.625em' },
h4: { value: '1.75em' },
h3: { value: '1.875em' },
h2: { value: '2em' },
h1: { value: '2.25em' },
rxs: { value: '0.75rem' },
rsm: { value: '0.875rem' },
rbase: { value: '1rem' },
rlg: { value: '1.25rem' },
rxl: { value: '1.5rem' },
rh1: { value: '3rem' },
rh2: { value: '2.5rem' },
rh3: { value: '2.25rem' },
rh4: { value: '2rem' },
rh5: { value: '1.75rem' },
rh6: { value: '1.5rem' }
rxl: { value: '1.375rem' },
rh6: { value: '1.5rem' },
rh5: { value: '1.625rem' },
rh4: { value: '1.75rem' },
rh3: { value: '1.875rem' },
rh2: { value: '2rem' },
rh1: { value: '2.25rem' }
},
fontWeights: {
thin: { value: '100' },
@@ -173,7 +176,8 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
animationStyles: {},
keyframes: {
...shimmerKeyframes,
...pulseKeyframes
...pulseKeyframes,
...fadeKeyframes
},
semanticTokens: {
colors: {
@@ -181,6 +185,70 @@ const srJuggernautPandaPreset = (config?: ThemeConfig) => {
...semanticColors
}
}
},
globalCss: {
'*, *:before, *:after': {
boxSizing: 'border-box',
margin: 0,
padding: 0
},
body: {
backgroundColor: 'neutral.1',
color: 'neutral.12'
},
'img, picture, video, canvas, svg ': {
display: 'block',
maxWidth: '100%'
},
'input, button, textarea, select': {
font: 'inherit'
},
button: {
cursor: 'pointer'
},
'h1, h2, h3, h4, h5, h6': {
fontWeight: 'bold',
lineHeight: 'tight'
},
h1: {
fontSize: 'h1'
},
h2: {
fontSize: 'h2'
},
h3: {
fontSize: 'h3'
},
h4: {
fontSize: 'h4'
},
h5: {
fontSize: 'h5'
},
h6: {
fontSize: 'h6'
},
p: {
fontSize: 'base',
lineHeight: 'normal',
textWrap: 'pretty'
},
small: {
fontSize: 'xs'
},
a: {
color: 'inherit',
textDecoration: 'none',
fontWeight: 'semibold',
_hover: {
color: 'primary.9'
}
},
'@media (prefers-reduced-motion: no-preference)': {
html: {
interpolateSize: 'allow-keywords'
}
}
}
})
}

10
src/keyframes/fade.ts Normal file
View File

@@ -0,0 +1,10 @@
import { defineKeyframes } from '@pandacss/dev'
const fadeKeyframes = defineKeyframes({
fade: {
'0%': { opacity: '0' },
'100%': { opacity: '1' }
}
})
export default fadeKeyframes

106
src/recipes/alert.ts Normal file
View File

@@ -0,0 +1,106 @@
import { defineSlotRecipe, type SystemStyleObject } from '@pandacss/dev'
export const alertSlots = ['root', 'title', 'description', 'closeButton', 'actionsContainer'] as const
interface AlertRecipeArg {
semanticColorNames: string[]
}
const alertRecipe = ({ semanticColorNames }: AlertRecipeArg) => {
const colors = ['neutral', ...semanticColorNames]
return defineSlotRecipe({
className: 'alert',
slots: alertSlots,
base: {
root: {
position: 'relative',
display: 'flex',
flexDirection: 'column',
gap: 'xs',
padding: 'sm',
borderRadius: 'md',
backgroundColor: 'var(--alert-background-color)',
color: 'var(--alert-color)'
},
title: {
color: 'var(--alert-color)',
fontWeight: 'semibold',
lineHeight: 'tight',
'&[aria-level="1"]': {
fontSize: 'h1'
},
'&[aria-level="2"]': {
fontSize: 'h2'
},
'&[aria-level="3"]': {
fontSize: 'h3'
},
'&[aria-level="4"]': {
fontSize: 'h4'
},
'&[aria-level="5"]': {
fontSize: 'h5'
},
'&[aria-level="6"]': {
fontSize: 'h6'
}
},
description: {
color: 'var(--alert-color)'
},
closeButton: {
all: 'unset',
position: 'absolute',
top: 'sm',
right: 'sm',
cursor: 'pointer',
color: 'var(--alert-color)'
},
actionsContainer: {
display: 'flex',
gap: 'xs',
justifyContent: 'flex-end'
}
},
variants: {
color: {
...Object.fromEntries(
colors.map((color) => [
color,
{
...Object.fromEntries(
alertSlots.map((slot) => {
switch (slot) {
case 'root':
return [
slot,
{
'--alert-background-color': `{colors.${color}.3}`,
'--alert-color': `{colors.${color}.12}`
} as SystemStyleObject
]
case 'title':
return [slot, {} as SystemStyleObject]
case 'closeButton':
return [slot, {} as SystemStyleObject]
case 'description':
return [slot, {} as SystemStyleObject]
case 'actionsContainer':
return [slot, {} as SystemStyleObject]
default:
return [slot, {} as SystemStyleObject]
}
})
)
}
])
)
}
},
defaultVariants: {
color: 'neutral'
}
})
}
export default alertRecipe

View File

@@ -20,7 +20,17 @@ const markRecipe = ({ semanticColorNames }: MarkRecipeArg) => {
},
variants: {
color: {
...Object.fromEntries(colors.map((color) => [color, {}]))
...Object.fromEntries(
colors.map((color) => [
color,
{
'&::selection': {
backgroundColor: `{colors.${color}.2}`,
color: `{colors.${color}.9}`
}
}
])
)
},
variant: {
...Object.fromEntries(markVariants.map((variant) => [variant, {}]))
@@ -34,15 +44,34 @@ const markRecipe = ({ semanticColorNames }: MarkRecipeArg) => {
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',
position: 'relative',
marginBlock: '0',
marginInline: '-0.4ch',
paddingBlock: '0.2ch',
paddingInline: '0.6ch',
borderTopLeftRadius: '0.5em 40%',
borderTopRightRadius: '0.3em 15%',
borderBottomLeftRadius: '0.45em 80%',
borderBottomRightRadius: '0.75em 60%',
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}`
color: `{colors.${color}.foreground}`,
_before: {
content: '""',
position: 'absolute',
inset: '0',
width: '100%',
height: '80%',
top: '50%',
left: '50%',
boxDecorationBreak: 'clone',
WebkitBoxDecorationBreak: 'clone',
borderRadius: 'inherit',
background: 'inherit',
backgroundImage: `linear-gradient(to right,color-mix(in srgb, {colors.${color}.9} 15%,transparent) 0%,color-mix(in srgb, {colors.${color}.9} 65%, transparent) 12%, color-mix(in srgb, {colors.${color}.9} 20%, transparent 80%))`,
transform: 'translate(-50%, -50%) skewX(-15deg)',
zIndex: '-1'
}
} as SystemStyleObject
}
case 'bold':
@@ -70,7 +99,7 @@ const markRecipe = ({ semanticColorNames }: MarkRecipeArg) => {
})
),
defaultVariants: {
color: 'neutral',
color: 'primary',
variant: 'highlight'
}
})