Skip to content

Commit 67e0e2a

Browse files
committed
refactor: ship uncompiled CSS, fix #16 duplicate Tailwind stylesheets
- Remove CSS compilation from tsdown (drop tailwindPlugin, stableCssNamePlugin) - Add copy-styles.mjs to ship raw CSS files to dist with @repo/shadcn path rewrite - Embed @source "../*.mjs" in root.css for zero-config consumer class scanning - Pre-expand grid CSS @apply directives into self-contained raw CSS - Split grid and nprogress CSS into separate optional exports - Update storybook and docs to use package imports instead of source paths - Update installation docs with simplified setup instructions - Bump to 0.2.0-alpha.8
1 parent d48e335 commit 67e0e2a

12 files changed

Lines changed: 1003 additions & 985 deletions

File tree

apps/docs/app/globals.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
@import 'tailwindcss';
22
@import '@datum-cloud/datum-ui/styles';
3+
@import '@datum-cloud/datum-ui/grid';
4+
@import '@datum-cloud/datum-ui/nprogress';
35
@import 'fumadocs-ui/style.css';

apps/docs/content/docs/components/features/grid.mdx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ The Grid system provides a 24-column layout using `Row` and `Col` components. Ro
1313

1414
No additional dependencies required — this component uses only React and Tailwind CSS.
1515

16+
## Setup
17+
18+
Import the grid CSS in your app's stylesheet:
19+
20+
```css title="app.css"
21+
@import '@datum-cloud/datum-ui/grid';
22+
```
23+
1624
## Usage
1725

1826
<ComponentPreview name="Basic Grid">

apps/docs/content/docs/components/features/nprogress.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ nprogress
2222
Import the NProgress CSS in your root stylesheet:
2323

2424
```css
25-
@import '@datum-cloud/datum-ui/nprogress.css';
25+
@import '@datum-cloud/datum-ui/nprogress';
2626
```
2727

2828
Then configure NProgress once at app startup:

apps/docs/content/docs/installation.mdx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ description: Install and configure datum-ui in your project.
1111

1212
## Peer Dependencies
1313

14-
datum-ui requires React 19, Tailwind CSS v4, and lucide-react:
14+
datum-ui requires React 19, Tailwind CSS v4 (v4.0.7 or later, v4.2.1+ recommended), and lucide-react:
1515

1616
```package-install
1717
react react-dom tailwindcss lucide-react
@@ -24,12 +24,16 @@ Each component may have additional peer dependencies — check the component's d
2424
Add the datum-ui styles import to your CSS file, after Tailwind:
2525

2626
```css
27-
/* app.css */
27+
/* Required */
2828
@import 'tailwindcss';
2929
@import '@datum-cloud/datum-ui/styles';
30+
31+
/* Optional — import only if you use these components */
32+
@import '@datum-cloud/datum-ui/grid';
33+
@import '@datum-cloud/datum-ui/nprogress';
3034
```
3135

32-
This loads all design tokens, theme variables, fonts, and component styles. datum-ui's tokens are registered with Tailwind via `@theme inline`, so utilities like `bg-primary` and `text-foreground` work automatically in your code.
36+
This loads all design tokens, theme variables, fonts, and component styles. The styles import automatically configures Tailwind to scan datum-ui's components for class usage, so utilities like `bg-primary` and `text-foreground` work out of the box.
3337

3438
## Theme Provider
3539

apps/storybook/stories/features/grid.stories.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ export const Default: Story = {
4343
}
4444

4545
export const ResponsiveGrid: Story = {
46-
render: () => (
46+
args: {
47+
gutter: 32,
48+
},
49+
50+
render: (args: Record<string, unknown>) => (
4751
<div className="flex flex-col gap-4">
48-
<Row type="flex" gutter={16}>
52+
<Row type="flex" gutter={args.gutter as number}>
4953
<Col xs={24} sm={12} md={8} lg={6}>
5054
<div style={{ ...colStyle, background: '#3b82f6' }}>xs=24 sm=12 md=8 lg=6</div>
5155
</Col>
@@ -60,7 +64,7 @@ export const ResponsiveGrid: Story = {
6064
</Col>
6165
</Row>
6266

63-
<Row type="flex" gutter={16}>
67+
<Row type="flex" gutter={args.gutter as number}>
6468
<Col span={6}>
6569
<div style={{ ...colStyle, background: '#14b8a6' }}>Col 6</div>
6670
</Col>
Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
/**
22
* Storybook CSS entry point.
33
*
4-
* Tailwind is owned by the storybook app. datum-ui styles are imported
5-
* from source for hot-reloaded styles during development.
6-
*
7-
* The @source directives tell Tailwind CSS v4 where to scan for utility classes.
8-
* Without these, Tailwind would only scan apps/storybook/ and miss all the
9-
* utility classes used inside datum-ui and shadcn component source files,
10-
* resulting in missing styles (no colors, spacing, fonts, etc.).
4+
* Uses package imports to dogfood the real consumer experience.
5+
* Run `pnpm --filter @datum-cloud/datum-ui build` before starting storybook.
116
*/
127
@import 'tailwindcss';
138
@import 'tw-animate-css';
149
@import 'tailwind-scrollbar-hide/v4';
15-
@import '../../../packages/datum-ui/src/styles/root.css';
10+
@import '@datum-cloud/datum-ui/styles';
11+
@import '@datum-cloud/datum-ui/grid';
12+
@import '@datum-cloud/datum-ui/nprogress';
1613

17-
@source "../../../packages/datum-ui/src";
18-
@source "../../../packages/shadcn";
1914
@source "./";

packages/datum-ui/package.json

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@datum-cloud/datum-ui",
33
"type": "module",
4-
"version": "0.2.0-alpha.7",
4+
"version": "0.2.0-alpha.8",
55
"license": "MIT",
66
"repository": {
77
"url": "https://github.com/datum-cloud/datum-ui"
@@ -15,8 +15,8 @@
1515
"default": "./dist/index.mjs"
1616
},
1717
"./styles": {
18-
"style": "./dist/styles.css",
19-
"default": "./dist/styles.css"
18+
"style": "./dist/styles/root.css",
19+
"default": "./dist/styles/root.css"
2020
},
2121
"./theme": {
2222
"types": "./dist/components/themes/index.d.ts",
@@ -184,6 +184,7 @@
184184
},
185185
"./grid": {
186186
"types": "./dist/components/features/grid/index.d.ts",
187+
"style": "./dist/grid/style.css",
187188
"default": "./dist/grid/index.mjs"
188189
},
189190
"./input-number": {
@@ -208,6 +209,7 @@
208209
},
209210
"./nprogress": {
210211
"types": "./dist/components/features/nprogress/index.d.ts",
212+
"style": "./dist/nprogress/nprogress.css",
211213
"default": "./dist/nprogress/index.mjs"
212214
},
213215
"./page-title": {
@@ -244,7 +246,7 @@
244246
"dist"
245247
],
246248
"scripts": {
247-
"build": "tsdown --config-loader native && tsc -p tsconfig.build.json && node scripts/fix-dts-imports.mjs && cp -r src/styles/fonts dist/fonts",
249+
"build": "tsdown --config-loader native && tsc -p tsconfig.build.json && node scripts/fix-dts-imports.mjs && node scripts/copy-styles.mjs",
248250
"dev": "tsdown --config-loader native --watch",
249251
"lint": "eslint .",
250252
"typecheck": "tsc --noEmit",
@@ -410,14 +412,12 @@
410412
}
411413
},
412414
"dependencies": {
413-
"@repo/shadcn": "workspace:*",
414415
"class-variance-authority": "^0.7",
415416
"clsx": "^2.1.1",
416417
"lucide-react": "^0.556",
417418
"tailwind-merge": "^3.5.0"
418419
},
419420
"devDependencies": {
420-
"@bosh-code/tsdown-plugin-tailwindcss": "^1.0.1",
421421
"@conform-to/react": "^1.17.1",
422422
"@conform-to/zod": "^1.17.1",
423423
"@radix-ui/react-dialog": "^1.1.15",
@@ -427,8 +427,6 @@
427427
"@radix-ui/react-tooltip": "^1.2.8",
428428
"@repo/config": "workspace:*",
429429
"@stepperize/react": "^6.1.0",
430-
"@tailwindcss/node": "^4.2.1",
431-
"@tailwindcss/oxide": "^4.2.1",
432430
"@tanstack/react-virtual": "^3.13.19",
433431
"@testing-library/jest-dom": "^6",
434432
"@testing-library/react": "^16",
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import process from 'node:process'
4+
5+
const PKG_ROOT = path.resolve(import.meta.dirname, '..')
6+
const SRC_STYLES = path.join(PKG_ROOT, 'src', 'styles')
7+
const DIST_STYLES = path.join(PKG_ROOT, 'dist', 'styles')
8+
const SHADCN_STYLES = path.resolve(PKG_ROOT, '..', 'shadcn', 'styles')
9+
10+
// 1. Copy src/styles/ assets to dist/styles/
11+
fs.mkdirSync(DIST_STYLES, { recursive: true })
12+
13+
fs.copyFileSync(
14+
path.join(SRC_STYLES, 'root.css'),
15+
path.join(DIST_STYLES, 'root.css'),
16+
)
17+
18+
fs.copyFileSync(
19+
path.join(SRC_STYLES, 'fonts.css'),
20+
path.join(DIST_STYLES, 'fonts.css'),
21+
)
22+
23+
fs.cpSync(
24+
path.join(SRC_STYLES, 'fonts'),
25+
path.join(DIST_STYLES, 'fonts'),
26+
{ recursive: true },
27+
)
28+
29+
fs.cpSync(
30+
path.join(SRC_STYLES, 'tokens'),
31+
path.join(DIST_STYLES, 'tokens'),
32+
{ recursive: true },
33+
)
34+
35+
fs.cpSync(
36+
path.join(SRC_STYLES, 'themes'),
37+
path.join(DIST_STYLES, 'themes'),
38+
{ recursive: true },
39+
)
40+
41+
// 2. Copy shadcn CSS to dist/styles/shadcn/
42+
const DIST_SHADCN = path.join(DIST_STYLES, 'shadcn')
43+
fs.mkdirSync(DIST_SHADCN, { recursive: true })
44+
45+
fs.copyFileSync(
46+
path.join(SHADCN_STYLES, 'shadcn.css'),
47+
path.join(DIST_SHADCN, 'shadcn.css'),
48+
)
49+
50+
fs.copyFileSync(
51+
path.join(SHADCN_STYLES, 'animations.css'),
52+
path.join(DIST_SHADCN, 'animations.css'),
53+
)
54+
55+
// 3. Rewrite import path in dist/styles/root.css
56+
const rootCssPath = path.join(DIST_STYLES, 'root.css')
57+
const rootCss = fs.readFileSync(rootCssPath, 'utf-8')
58+
const rewritten = rootCss.replace(
59+
'@import \'@repo/shadcn/styles/shadcn.css\'',
60+
'@import \'./shadcn/shadcn.css\'',
61+
)
62+
fs.writeFileSync(rootCssPath, rewritten, 'utf-8')
63+
64+
// Validate no @repo/ references remain
65+
if (rewritten.includes('@repo/')) {
66+
console.error('ERROR: Unrewritten @repo/ imports remain in dist/styles/root.css')
67+
process.exit(1)
68+
}
69+
70+
// 4. Copy component CSS to separate export locations
71+
const componentCopies = [
72+
{
73+
src: path.join(PKG_ROOT, 'src', 'components', 'features', 'grid', 'style.css'),
74+
dest: path.join(PKG_ROOT, 'dist', 'grid', 'style.css'),
75+
},
76+
{
77+
src: path.join(PKG_ROOT, 'src', 'components', 'features', 'nprogress', 'nprogress.css'),
78+
dest: path.join(PKG_ROOT, 'dist', 'nprogress', 'nprogress.css'),
79+
},
80+
]
81+
82+
for (const { src, dest } of componentCopies) {
83+
fs.mkdirSync(path.dirname(dest), { recursive: true })
84+
fs.copyFileSync(src, dest)
85+
}
86+
87+
console.log('Styles copied to dist/')

0 commit comments

Comments
 (0)