Skip to content

Commit 17d8a8f

Browse files
committed
feat: restructure presets with original Tailwind and Josh Comeau values
- Add presets/effective.ts with our Bézier-based shadow config - Add presets/tailwind-original.ts with exact Tailwind CSS v3 values - Add presets/josh-comeau.ts with shadows from his article - Add generate.ts for dynamic CSS generation from presets - Add ShadowComparison component for side-by-side demo - Generate CSS files at build time instead of static copies - Clean up exports and API structure
1 parent b37aa91 commit 17d8a8f

15 files changed

+755
-331
lines changed

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,25 @@
1313
"types": "./dist/factory.d.ts",
1414
"import": "./dist/factory.js"
1515
},
16+
"./presets": {
17+
"types": "./dist/presets/index.d.ts",
18+
"import": "./dist/presets/index.js"
19+
},
20+
"./generate": {
21+
"types": "./dist/generate.d.ts",
22+
"import": "./dist/generate.js"
23+
},
1624
"./shadows.css": "./dist/shadows.css",
1725
"./shadows.module.css": "./dist/shadows.module.css",
26+
"./shadows-effective.css": "./dist/shadows-effective.css",
27+
"./shadows-vars.css": "./dist/shadows-vars.css",
1828
"./tailwind": {
1929
"types": "./dist/tailwind.d.ts",
2030
"import": "./dist/tailwind.js"
2131
}
2232
},
2333
"scripts": {
24-
"build": "rimraf dist && tsc && cp src/*.css dist/",
34+
"build": "rimraf dist && tsc && tsx scripts/build-css.ts",
2535
"check": "tsc --noEmit",
2636
"lint": "eslint src",
2737
"lint:fix": "eslint src --fix",
@@ -92,6 +102,7 @@
92102
"rimraf": "^6.1.2",
93103
"storybook": "^10.1.4",
94104
"tailwindcss": "^4.1.17",
105+
"tsx": "^4.21.0",
95106
"typescript": "^5.9.3",
96107
"typescript-eslint": "^8.48.1",
97108
"vite": "^7.2.6",

pnpm-lock.yaml

Lines changed: 63 additions & 35 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/build-css.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* Build script to generate CSS files from presets.
3+
*
4+
* Run with: npx tsx scripts/build-css.ts
5+
*/
6+
7+
import { writeFileSync, mkdirSync } from "node:fs"
8+
import { join } from "node:path"
9+
import { generateCSS } from "../src/generate"
10+
import { effectivePreset } from "../src/presets"
11+
12+
const DIST_DIR = join(import.meta.dirname, "..", "dist")
13+
14+
// Ensure dist directory exists
15+
mkdirSync(DIST_DIR, { recursive: true })
16+
17+
// Generate default shadows.css (using effective preset)
18+
console.log("Generating shadows.css...")
19+
const shadowsCSS = generateCSS(effectivePreset)
20+
writeFileSync(join(DIST_DIR, "shadows.css"), shadowsCSS)
21+
22+
// Generate shadows.module.css (same content, CSS modules compatible)
23+
console.log("Generating shadows.module.css...")
24+
writeFileSync(join(DIST_DIR, "shadows.module.css"), shadowsCSS)
25+
26+
// Generate named preset file
27+
console.log("Generating shadows-effective.css...")
28+
writeFileSync(join(DIST_DIR, "shadows-effective.css"), shadowsCSS)
29+
30+
// Generate CSS variables version
31+
console.log("Generating shadows-vars.css...")
32+
const varsCSS = generateCSS(effectivePreset, { format: "css-variable" })
33+
writeFileSync(join(DIST_DIR, "shadows-vars.css"), varsCSS)
34+
35+
console.log("Done!")

src/ShadowComparison.css

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
.comparison {
2+
padding: 40px;
3+
font-family:
4+
system-ui,
5+
-apple-system,
6+
sans-serif;
7+
background: #f5f5f5;
8+
min-height: 100vh;
9+
}
10+
11+
.comparison h1 {
12+
margin: 0 0 8px;
13+
font-size: 28px;
14+
font-weight: 600;
15+
}
16+
17+
.comparison .subtitle {
18+
margin: 0 0 32px;
19+
color: #666;
20+
font-size: 16px;
21+
}
22+
23+
.comparison .grid {
24+
display: grid;
25+
grid-template-columns: repeat(3, 1fr);
26+
gap: 40px;
27+
}
28+
29+
.comparison .column {
30+
display: flex;
31+
flex-direction: column;
32+
gap: 24px;
33+
}
34+
35+
.comparison .column h2 {
36+
margin: 0;
37+
font-size: 18px;
38+
font-weight: 600;
39+
color: #333;
40+
}
41+
42+
.comparison .column .description {
43+
margin: -16px 0 0;
44+
font-size: 13px;
45+
color: #888;
46+
}
47+
48+
.comparison .card {
49+
background: white;
50+
border-radius: 12px;
51+
padding: 24px;
52+
display: flex;
53+
align-items: center;
54+
justify-content: center;
55+
min-height: 80px;
56+
transition: transform 0.2s ease;
57+
}
58+
59+
.comparison .card:hover {
60+
transform: translateY(-2px);
61+
}
62+
63+
.comparison .label {
64+
font-size: 14px;
65+
color: #555;
66+
font-weight: 500;
67+
}
68+
69+
.comparison .credits {
70+
margin-top: 48px;
71+
padding-top: 24px;
72+
border-top: 1px solid #ddd;
73+
font-size: 13px;
74+
color: #666;
75+
}
76+
77+
.comparison .credits p {
78+
margin: 0 0 8px;
79+
}
80+
81+
.comparison .credits ul {
82+
margin: 0;
83+
padding-left: 20px;
84+
}
85+
86+
.comparison .credits li {
87+
margin: 4px 0;
88+
}
89+
90+
.comparison .credits a {
91+
color: #0066cc;
92+
text-decoration: none;
93+
}
94+
95+
.comparison .credits a:hover {
96+
text-decoration: underline;
97+
}

src/ShadowComparison.stories.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { Meta, StoryObj } from "@storybook/react-vite"
2+
import { ShadowComparison } from "./ShadowComparison"
3+
4+
const meta = {
5+
title: "Comparison",
6+
component: ShadowComparison,
7+
parameters: {
8+
layout: "fullscreen"
9+
}
10+
} satisfies Meta<typeof ShadowComparison>
11+
12+
export default meta
13+
type Story = StoryObj<typeof meta>
14+
15+
export const AllShadows: Story = {}

src/ShadowComparison.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { boxShadow } from "."
2+
import { tailwindOriginal } from "./presets/tailwind-original"
3+
import { joshComeauShadows } from "./presets/josh-comeau"
4+
5+
import "./ShadowComparison.css"
6+
7+
/**
8+
* Side-by-side comparison of different shadow systems.
9+
*/
10+
export function ShadowComparison() {
11+
return (
12+
<div className="comparison">
13+
<h1>Shadow Comparison</h1>
14+
<p className="subtitle">
15+
Comparing shadow approaches: our multi-layer Bézier curves vs.
16+
established systems.
17+
</p>
18+
19+
<div className="grid">
20+
{/* Effective Shadow */}
21+
<section className="column">
22+
<h2>Effective Shadow</h2>
23+
<p className="description">4 layers with Bézier-curved transitions</p>
24+
{boxShadow.map((shadow, index) => (
25+
<div key={index} className="card" style={{ boxShadow: shadow }}>
26+
<span className="label">Level {index}</span>
27+
</div>
28+
))}
29+
</section>
30+
31+
{/* Tailwind Original */}
32+
<section className="column">
33+
<h2>Tailwind CSS</h2>
34+
<p className="description">Original Tailwind v3 shadows</p>
35+
{tailwindOriginal.levels.map(({ name, boxShadow }) => (
36+
<div key={name} className="card" style={{ boxShadow }}>
37+
<span className="label">{name}</span>
38+
</div>
39+
))}
40+
</section>
41+
42+
{/* Josh Comeau */}
43+
<section className="column">
44+
<h2>Josh Comeau</h2>
45+
<p className="description">Layered shadows from his CSS article</p>
46+
{joshComeauShadows.levels.map(({ name, boxShadow }) => (
47+
<div key={name} className="card" style={{ boxShadow }}>
48+
<span className="label">{name}</span>
49+
</div>
50+
))}
51+
</section>
52+
</div>
53+
54+
<footer className="credits">
55+
<p>
56+
<strong>Sources:</strong>
57+
</p>
58+
<ul>
59+
<li>
60+
<a
61+
href="https://tailwindcss.com/docs/box-shadow"
62+
target="_blank"
63+
rel="noopener"
64+
>
65+
Tailwind CSS Documentation
66+
</a>
67+
</li>
68+
<li>
69+
<a
70+
href="https://www.joshwcomeau.com/css/designing-shadows/"
71+
target="_blank"
72+
rel="noopener"
73+
>
74+
Josh W. Comeau: Designing Beautiful Shadows in CSS
75+
</a>
76+
</li>
77+
</ul>
78+
</footer>
79+
</div>
80+
)
81+
}

0 commit comments

Comments
 (0)