Skip to content

Commit f9a07f2

Browse files
authored
Merge pull request #22 from constructive-io/fix/stack-enter-and-shadow-tokens
fix(ui): restore stack animations and shadow tokens
2 parents e0a0e35 + 1d18e3e commit f9a07f2

10 files changed

Lines changed: 281 additions & 60 deletions

File tree

apps/blocks/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pnpm --filter blocks test
1818
pnpm --filter blocks build:pages
1919
```
2020

21+
The development command builds the local package outputs before Next.js starts,
22+
so it also works from a fresh worktree.
23+
2124
`src/lib/base-primitives.ts`, `src/lib/billing-blocks.ts`, and
2225
`src/lib/feature-packs.ts` are the documentation catalogs. `pnpm gen:check`
2326
regenerates (or checks) generated UI demo source used by the docs app.

apps/blocks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"build:registry": "pnpm --workspace-root build:registry",
99
"check:generated": "pnpm gen:check",
1010
"check:selections": "tsx scripts/check-mutation-selections.ts",
11-
"predev": "pnpm gen:check",
11+
"predev": "pnpm --workspace-root build:packages && pnpm gen:check",
1212
"prebuild": "pnpm gen:check",
1313
"dev": "next dev --turbopack --port 3005",
1414
"build": "next build",

packages/ui/registry.json

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"name": "constructive-theme",
88
"type": "registry:theme",
99
"title": "Constructive Theme",
10-
"description": "Constructive design system theme \u2014 OKLCH colors, z-index layers, shadow utilities, and animations.",
10+
"description": "Constructive design system theme OKLCH colors, z-index layers, shadow utilities, and animations.",
1111
"cssVars": {
1212
"theme": {
1313
"--color-background": "var(--background)",
@@ -102,14 +102,14 @@
102102
"radius": "0.5rem",
103103
"shadow-border": "0 0 0 1px oklch(0 0 0 / 0.06), 0 1px 1px -0.5px rgb(35 35 35 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.04), 0 2px 4px -1px rgb(35 35 35 / 0.03)",
104104
"shadow-border-hover": "0 0 0 1px oklch(0 0 0 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.08), 0 2px 4px -2px rgb(35 35 35 / 0.06), 0 4px 8px -2px rgb(35 35 35 / 0.04), 0 8px 16px -4px rgb(35 35 35 / 0.03)",
105-
"shadow-2xs": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
106-
"shadow-xs": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
107-
"shadow-sm": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
108-
"shadow": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
109-
"shadow-md": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 2px 4px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
110-
"shadow-lg": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 4px 6px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
111-
"shadow-xl": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 8px 10px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
112-
"shadow-2xl": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
105+
"shadow-2xs": "0 1px rgb(0 0 0 / 0.05)",
106+
"shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.05)",
107+
"shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
108+
"shadow": "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)",
109+
"shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)",
110+
"shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)",
111+
"shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)",
112+
"shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.25)",
113113
"z-layer-portal-root": "9999",
114114
"z-layer-floating": "1000",
115115
"z-layer-modal-backdrop": "2000",
@@ -162,14 +162,14 @@
162162
"radius": "0.5rem",
163163
"shadow-border": "0 0 0 1px oklch(1 0 0 / 0.08), 0 1px 1px -0.5px rgb(0 0 0 / 0.25), 0 1px 2px -1px rgb(0 0 0 / 0.15), 0 2px 4px -1px rgb(0 0 0 / 0.10)",
164164
"shadow-border-hover": "0 0 0 1px oklch(1 0 0 / 0.13), 0 1px 2px -1px rgb(0 0 0 / 0.30), 0 2px 4px -2px rgb(0 0 0 / 0.20), 0 4px 8px -2px rgb(0 0 0 / 0.15), 0 8px 16px -4px rgb(0 0 0 / 0.10)",
165-
"shadow-2xs": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
166-
"shadow-xs": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
167-
"shadow-sm": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
168-
"shadow": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
169-
"shadow-md": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 2px 4px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
170-
"shadow-lg": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 4px 6px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
171-
"shadow-xl": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 8px 10px -1px hsl(202.8169 89.1213% 53.1373% / 0)",
172-
"shadow-2xl": "0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)",
165+
"shadow-2xs": "0 1px rgb(0 0 0 / 0.2)",
166+
"shadow-xs": "0 1px 2px 0 rgb(0 0 0 / 0.25)",
167+
"shadow-sm": "0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25)",
168+
"shadow": "0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25)",
169+
"shadow-md": "0 4px 6px -1px rgb(0 0 0 / 0.35), 0 2px 4px -2px rgb(0 0 0 / 0.3)",
170+
"shadow-lg": "0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3)",
171+
"shadow-xl": "0 20px 25px -5px rgb(0 0 0 / 0.45), 0 8px 10px -6px rgb(0 0 0 / 0.35)",
172+
"shadow-2xl": "0 25px 50px -12px rgb(0 0 0 / 0.55)",
173173
"z-layer-portal-root": "9999",
174174
"z-layer-floating": "1000",
175175
"z-layer-modal-backdrop": "2000",

packages/ui/src/components/stack/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export {
4949
export {
5050
DEFAULT_ANIMATION_CONFIG,
5151
createCardVariants,
52+
createEnterTransition,
53+
createExitTransition,
5254
createOffsetTransition,
5355
backdropVariants,
5456
snapBackSpring,

packages/ui/src/components/stack/stack-animations.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,39 @@ export function createOffsetTransition(_config: AnimationConfig = {}): Transitio
6262
};
6363
}
6464

65+
/**
66+
* Enter transition for card slide-in (x: 100% → offset).
67+
* Tween + snappy ease — distinct from offset springs used after settle.
68+
*/
69+
export function createEnterTransition(config: AnimationConfig = {}): Transition {
70+
const { duration, enterEase } = {
71+
...DEFAULT_ANIMATION_CONFIG,
72+
...config,
73+
};
74+
75+
return {
76+
type: 'tween',
77+
duration,
78+
ease: enterEase as [number, number, number, number],
79+
};
80+
}
81+
82+
/**
83+
* Exit transition for card slide-out (offset → x: 100%).
84+
*/
85+
export function createExitTransition(config: AnimationConfig = {}): Transition {
86+
const { duration, exitEase } = {
87+
...DEFAULT_ANIMATION_CONFIG,
88+
...config,
89+
};
90+
91+
return {
92+
type: 'tween',
93+
duration,
94+
ease: exitEase as [number, number, number, number],
95+
};
96+
}
97+
6598
// =============================================================================
6699
// Backdrop Variants
67100
// =============================================================================

packages/ui/src/components/stack/stack-card.tsx

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import { motion, useReducedMotion } from 'motion/react';
66

77
import { cn } from '../../lib/utils';
88

9-
import { createOffsetTransition, peekHoverSpring, peekDragSpring, lastCardExitTransition } from './stack-animations';
9+
import {
10+
createEnterTransition,
11+
createExitTransition,
12+
createOffsetTransition,
13+
peekHoverSpring,
14+
peekDragSpring,
15+
} from './stack-animations';
1016
import { CardReadyProvider, useCardInjectedProps, useStackContext } from './stack-context';
1117
import { StackHeader } from './stack-header';
1218
import type { AnimationConfig, CardSpec, CardStackApi, GestureConfig, PeekGestureConfig } from './stack.types';
@@ -16,6 +22,7 @@ import type { StackGestureBind } from './use-stack-gestures';
1622

1723
/** Default hover expansion in pixels */
1824
const DEFAULT_HOVER_EXPANSION = 48;
25+
const reducedMotionTransition = { duration: 0 } as const;
1926

2027
export type StackCardProps = {
2128
/** The card specification */
@@ -131,8 +138,10 @@ function StackCardInner({
131138
// Card width
132139
const cardWidth = isMobile ? '100%' : normalizeWidth(card.width, config.defaultWidth);
133140

134-
// Animation transition
141+
// Animation transitions: enter/exit tweens, offset spring after settle
135142
const offsetTransition = createOffsetTransition(animation);
143+
const enterTransition = createEnterTransition(animation);
144+
const exitTransition = createExitTransition(animation);
136145

137146
// Close handler
138147
const handleClose = useCallback(() => {
@@ -216,18 +225,27 @@ function StackCardInner({
216225
// Last card fades out as it slides for smoother exit when backdrop is also fading
217226
const exitOpacity = prefersReducedMotion ? 0 : (isLastCard ? 0 : 1);
218227

219-
// Choose transition based on interaction state
220-
let activeTransition = offsetTransition;
221-
if (peekGestures.isDragging || peekDragOffset > 0) {
222-
activeTransition = peekDragSpring;
223-
} else if (isPeekHovered) {
224-
activeTransition = peekHoverSpring;
228+
// Enter uses snappy tween until first settle; then spring for offset/peek.
229+
// Peek/drag always win while interacting.
230+
let activeTransition = prefersReducedMotion
231+
? reducedMotionTransition
232+
: isAnimationComplete
233+
? offsetTransition
234+
: enterTransition;
235+
if (!prefersReducedMotion) {
236+
if (peekGestures.isDragging || peekDragOffset > 0) {
237+
activeTransition = peekDragSpring;
238+
} else if (isPeekHovered) {
239+
activeTransition = peekHoverSpring;
240+
}
225241
}
226242

227-
// Build exit animation object - last card uses tween for smooth fade, others use spring
228-
const exitAnimation = isLastCard && !prefersReducedMotion
229-
? { x: exitX, opacity: exitOpacity, transition: lastCardExitTransition }
230-
: { x: exitX, opacity: exitOpacity };
243+
// Exit always honors the configured tween; reduced motion settles immediately.
244+
const exitAnimation = {
245+
x: exitX,
246+
opacity: exitOpacity,
247+
transition: prefersReducedMotion ? reducedMotionTransition : exitTransition,
248+
};
231249

232250
return (
233251
<motion.div
@@ -236,7 +254,7 @@ function StackCardInner({
236254
data-card-index={index}
237255
data-is-top={isTopCard}
238256
data-offset={baseOffset}
239-
initial={{ x: initialX, opacity: prefersReducedMotion ? 0 : 1 }}
257+
initial={{ x: initialX, opacity: 1 }}
240258
animate={{ x: animateX, opacity: 1 }}
241259
exit={exitAnimation}
242260
transition={activeTransition}

packages/ui/src/components/stack/stack-viewport.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,9 @@ export function CardStackViewport({
268268

269269
const content = (
270270
<div data-slot="stack-viewport" className={cn('pointer-events-none fixed inset-0', className)}>
271-
<AnimatePresence initial={false} mode="popLayout" onExitComplete={handleExitComplete}>
271+
{/* initial must stay true: viewport unmounts when empty, so first open remounts
272+
AnimatePresence with cards already present. initial={false} skips enter. */}
273+
<AnimatePresence mode="popLayout" onExitComplete={handleExitComplete}>
272274
{/* Backdrop - only when cards exist and first card wants it */}
273275
{shouldShowBackdrop && hasCards && renderBackdropNode(resolvedBackdrop.config)}
274276

packages/ui/src/styles/globals.css

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@
5151
--radius: 0.5rem;
5252
--shadow-border: 0 0 0 1px oklch(0 0 0 / 0.06), 0 1px 1px -0.5px rgb(35 35 35 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.04), 0 2px 4px -1px rgb(35 35 35 / 0.03);
5353
--shadow-border-hover: 0 0 0 1px oklch(0 0 0 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.08), 0 2px 4px -2px rgb(35 35 35 / 0.06), 0 4px 8px -2px rgb(35 35 35 / 0.04), 0 8px 16px -4px rgb(35 35 35 / 0.03);
54-
--shadow-2xs: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
55-
--shadow-xs: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
56-
--shadow-sm: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0);
57-
--shadow: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0);
58-
--shadow-md: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 2px 4px -1px hsl(202.8169 89.1213% 53.1373% / 0);
59-
--shadow-lg: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 4px 6px -1px hsl(202.8169 89.1213% 53.1373% / 0);
60-
--shadow-xl: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 8px 10px -1px hsl(202.8169 89.1213% 53.1373% / 0);
61-
--shadow-2xl: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
54+
--shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
55+
--shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
56+
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
57+
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
58+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
59+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
60+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
61+
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
6262
--z-layer-portal-root: 9999;
6363
--z-layer-floating: 1000;
6464
--z-layer-modal-backdrop: 2000;
@@ -112,14 +112,14 @@
112112
--radius: 0.5rem;
113113
--shadow-border: 0 0 0 1px oklch(1 0 0 / 0.08), 0 1px 1px -0.5px rgb(0 0 0 / 0.25), 0 1px 2px -1px rgb(0 0 0 / 0.15), 0 2px 4px -1px rgb(0 0 0 / 0.10);
114114
--shadow-border-hover: 0 0 0 1px oklch(1 0 0 / 0.13), 0 1px 2px -1px rgb(0 0 0 / 0.30), 0 2px 4px -2px rgb(0 0 0 / 0.20), 0 4px 8px -2px rgb(0 0 0 / 0.15), 0 8px 16px -4px rgb(0 0 0 / 0.10);
115-
--shadow-2xs: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
116-
--shadow-xs: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
117-
--shadow-sm: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0);
118-
--shadow: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0);
119-
--shadow-md: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 2px 4px -1px hsl(202.8169 89.1213% 53.1373% / 0);
120-
--shadow-lg: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 4px 6px -1px hsl(202.8169 89.1213% 53.1373% / 0);
121-
--shadow-xl: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0), 0px 8px 10px -1px hsl(202.8169 89.1213% 53.1373% / 0);
122-
--shadow-2xl: 0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0);
115+
--shadow-2xs: 0 1px rgb(0 0 0 / 0.2);
116+
--shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.25);
117+
--shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25);
118+
--shadow: 0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25);
119+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.35), 0 2px 4px -2px rgb(0 0 0 / 0.3);
120+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3);
121+
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.45), 0 8px 10px -6px rgb(0 0 0 / 0.35);
122+
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.55);
123123
}
124124

125125
@theme inline {

packages/ui/src/theme.ts

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,27 @@ const sharedTypographyAndShape = {
2424
radius: '0.5rem',
2525
} as const;
2626

27-
const transparentShadow = '0px 2px 0px 0px hsl(202.8169 89.1213% 53.1373% / 0)';
27+
/** Elevation shadows — were fully transparent (`/ 0`), so shadow-* utilities did nothing. */
28+
const lightElevationShadows = {
29+
'shadow-2xs': '0 1px rgb(0 0 0 / 0.05)',
30+
'shadow-xs': '0 1px 2px 0 rgb(0 0 0 / 0.05)',
31+
'shadow-sm': '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
32+
shadow: '0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1)',
33+
'shadow-md': '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
34+
'shadow-lg': '0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1)',
35+
'shadow-xl': '0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)',
36+
'shadow-2xl': '0 25px 50px -12px rgb(0 0 0 / 0.25)',
37+
} as const;
2838

29-
const sharedShadows = {
30-
'shadow-2xs': transparentShadow,
31-
'shadow-xs': transparentShadow,
32-
'shadow-sm': `${transparentShadow}, 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)`,
33-
shadow: `${transparentShadow}, 0px 1px 2px -1px hsl(202.8169 89.1213% 53.1373% / 0)`,
34-
'shadow-md': `${transparentShadow}, 0px 2px 4px -1px hsl(202.8169 89.1213% 53.1373% / 0)`,
35-
'shadow-lg': `${transparentShadow}, 0px 4px 6px -1px hsl(202.8169 89.1213% 53.1373% / 0)`,
36-
'shadow-xl': `${transparentShadow}, 0px 8px 10px -1px hsl(202.8169 89.1213% 53.1373% / 0)`,
37-
'shadow-2xl': transparentShadow,
39+
const darkElevationShadows = {
40+
'shadow-2xs': '0 1px rgb(0 0 0 / 0.2)',
41+
'shadow-xs': '0 1px 2px 0 rgb(0 0 0 / 0.25)',
42+
'shadow-sm': '0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25)',
43+
shadow: '0 1px 3px 0 rgb(0 0 0 / 0.3), 0 1px 2px -1px rgb(0 0 0 / 0.25)',
44+
'shadow-md': '0 4px 6px -1px rgb(0 0 0 / 0.35), 0 2px 4px -2px rgb(0 0 0 / 0.3)',
45+
'shadow-lg': '0 10px 15px -3px rgb(0 0 0 / 0.4), 0 4px 6px -4px rgb(0 0 0 / 0.3)',
46+
'shadow-xl': '0 20px 25px -5px rgb(0 0 0 / 0.45), 0 8px 10px -6px rgb(0 0 0 / 0.35)',
47+
'shadow-2xl': '0 25px 50px -12px rgb(0 0 0 / 0.55)',
3848
} as const;
3949

4050
export const constructiveTheme = {
@@ -85,7 +95,7 @@ export const constructiveTheme = {
8595
'0 0 0 1px oklch(0 0 0 / 0.06), 0 1px 1px -0.5px rgb(35 35 35 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.04), 0 2px 4px -1px rgb(35 35 35 / 0.03)',
8696
'shadow-border-hover':
8797
'0 0 0 1px oklch(0 0 0 / 0.08), 0 1px 2px -1px rgb(35 35 35 / 0.08), 0 2px 4px -2px rgb(35 35 35 / 0.06), 0 4px 8px -2px rgb(35 35 35 / 0.04), 0 8px 16px -4px rgb(35 35 35 / 0.03)',
88-
...sharedShadows,
98+
...lightElevationShadows,
8999
},
90100
dark: {
91101
background: 'oklch(0.21 0.006 285.885)',
@@ -131,7 +141,7 @@ export const constructiveTheme = {
131141
'0 0 0 1px oklch(1 0 0 / 0.08), 0 1px 1px -0.5px rgb(0 0 0 / 0.25), 0 1px 2px -1px rgb(0 0 0 / 0.15), 0 2px 4px -1px rgb(0 0 0 / 0.10)',
132142
'shadow-border-hover':
133143
'0 0 0 1px oklch(1 0 0 / 0.13), 0 1px 2px -1px rgb(0 0 0 / 0.30), 0 2px 4px -2px rgb(0 0 0 / 0.20), 0 4px 8px -2px rgb(0 0 0 / 0.15), 0 8px 16px -4px rgb(0 0 0 / 0.10)',
134-
...sharedShadows,
144+
...darkElevationShadows,
135145
},
136146
tailwind: {
137147
'--color-background': 'var(--background)',

0 commit comments

Comments
 (0)