@keboola/tailwind-config 0.3.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -32,6 +32,39 @@ export default {
32
32
  };
33
33
  ```
34
34
 
35
+ ### Class prefix (`tw-`)
36
+
37
+ The default config prefixes every utility with `tw-` (`tw-flex`, `tw-bg-background`, …). `@keboola/design` components ship with those `tw-`-prefixed class names baked into their compiled JS, and those classes only render if a stylesheet the app loads actually **defines** them. How you load that stylesheet decides whether you can drop the prefix:
38
+
39
+ 1. **Build-from-source** (the monorepo / `apps/boilerplate` pattern) — the app imports the source stylesheet `@keboola/design/styles` and runs its **own** Tailwind `@tailwind utilities` pass over design's `dist/` plus its own markup. That pass emits the components' classes _using this config's prefix_, so it only produces `tw-*` when the prefix is `tw-`. **If you flip this setup to `prefix: ''`, design components render UNSTYLED** — your build emits `flex`, never `tw-flex`, so the `tw-flex` baked into the components matches nothing. **Keep `tw-` for build-from-source setups.**
40
+
41
+ 2. **Precompiled CSS** — the app imports `@keboola/design/styles/compiled` (the shipped `dist/styles.css`, which already contains every `tw-*` utility the components use, prebuilt). Design components are then styled by that stylesheet regardless of your app's own Tailwind prefix, so `createKeboolaConfig({ prefix: '' })` is safe **for your own markup**: `tw-flex` (design's) and `flex` (yours) live in the same cascade without colliding.
42
+
43
+ Prefix-less recipe (consume design precompiled, author your own utilities unprefixed):
44
+
45
+ ```css
46
+ @import '@keboola/design/styles/compiled'; /* design components, pre-styled with tw-* */
47
+ @tailwind base;
48
+ @tailwind components;
49
+ @tailwind utilities; /* your own unprefixed utilities */
50
+ ```
51
+
52
+ **Bottom line: prefix-less is safe only when you consume design via `/styles/compiled`, not when you build design's utilities from source.**
53
+
54
+ Opt out of the prefix (or set a custom one) with the `createKeboolaConfig` factory:
55
+
56
+ ```js
57
+ import { createKeboolaConfig } from '@keboola/tailwind-config';
58
+
59
+ /** @type {import('tailwindcss').Config} */
60
+ export default {
61
+ ...createKeboolaConfig({ prefix: '' }), // unprefixed: `flex`, not `tw-flex`
62
+ content: ['./src/**/*.{ts,tsx,mdx}'],
63
+ };
64
+ ```
65
+
66
+ Pass any string to `prefix` for a custom prefix (e.g. `createKeboolaConfig({ prefix: 'kbc-' })`). The default export is `createKeboolaConfig()` (i.e. `prefix: 'tw-'`), so existing `import keboolaConfig from '@keboola/tailwind-config'` consumers are unaffected.
67
+
35
68
  ### Subpath imports
36
69
 
37
70
  If you only need the raw token data:
package/index.js CHANGED
@@ -7,9 +7,26 @@ import containerQueriesPlugin from '@tailwindcss/container-queries';
7
7
  import { typography } from './typography';
8
8
  import { scrollFadePlugin } from './scrollFade';
9
9
 
10
+ /**
11
+ * Build the Keboola Tailwind config, optionally overriding the class prefix.
12
+ *
13
+ * `@keboola/design` and the in-monorepo apps are built with the `tw-` prefix
14
+ * (the default), so the design system's compiled CSS assumes it. External
15
+ * consumers that don't extend design's stylesheet — and want unprefixed
16
+ * utilities (`flex`, not `tw-flex`) — can opt out with `createKeboolaConfig({ prefix: '' })`.
17
+ *
18
+ * @param {{ prefix?: string }} [options]
19
+ * @returns {import('tailwindcss').Config}
20
+ */
21
+ export function createKeboolaConfig({ prefix = 'tw-' } = {}) {
22
+ return {
23
+ ...baseConfig,
24
+ prefix,
25
+ };
26
+ }
27
+
10
28
  /** @type {import('tailwindcss').Config} */
11
- export default {
12
- prefix: 'tw-',
29
+ const baseConfig = {
13
30
  content: ['./src/**/*.{js,jsx,ts,tsx,mdx}', '../../packages/design/src/**/*.{ts,tsx}'],
14
31
  corePlugins: {
15
32
  preflight: false,
@@ -109,6 +126,11 @@ export default {
109
126
  },
110
127
  backgroundImage: {
111
128
  'loader-gradient': 'radial-gradient(circle closest-side,#000 90%,#0000)',
129
+ // Brand gradient — `tw-bg-brand`. Set via `theme.gradient.brand`; the
130
+ // inline fallback equals the stylesheet default (primary→accent), so the
131
+ // utility stays valid even without `@keboola/design/styles`.
132
+ brand:
133
+ 'var(--gradient-brand, linear-gradient(135deg, rgb(var(--color-primary)), rgb(var(--color-accent, var(--color-primary)))))',
112
134
  },
113
135
  ringWidth: {
114
136
  3: '3px',
@@ -117,16 +139,61 @@ export default {
117
139
  outline: '0 0 0 3px rgba(34, 141, 255, 0.25)',
118
140
  table: '0px 6px 6px -4px rgba(100, 135, 153, 0.13)',
119
141
  card: '0px 1px 4px rgba(100, 135, 153, 0.15)',
142
+ // Brand-driven elevation. The inline fallbacks equal the stock Tailwind
143
+ // shadow scale, so `tw-shadow-sm/md/lg` are unchanged until a brand sets
144
+ // `theme.shadows`. `tw-shadow-lift` is a stronger raised shadow.
145
+ sm: 'var(--shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05))',
146
+ md: 'var(--shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))',
147
+ lg: 'var(--shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1))',
148
+ lift: 'var(--shadow-lift, 0 10px 30px -12px rgb(0 0 0 / 0.28), 0 2px 6px rgb(0 0 0 / 0.06))',
149
+ // Raised-surface elevation for Card / Search — dark-aware via the
150
+ // `--shadow-raised` token (flips to a black shadow under `[data-theme=dark]`).
151
+ raised: 'var(--shadow-raised, 0 2px 6px 0 rgb(100 135 153 / 0.13))',
120
152
  },
121
153
  borderRadius: {
122
154
  card: '10px',
123
155
  },
156
+ transitionDuration: {
157
+ brand: 'var(--motion-duration, 200ms)',
158
+ },
159
+ transitionTimingFunction: {
160
+ brand: 'var(--motion-easing, cubic-bezier(0.2, 0.7, 0.2, 1))',
161
+ },
162
+ spacing: {
163
+ // Brand-driven density: `tw-p-inset`, `tw-gap-gutter`, etc.
164
+ gutter: 'var(--space-gutter, 1.5rem)',
165
+ inset: 'var(--space-inset, 1.5rem)',
166
+ },
124
167
  typography: typography,
125
168
  colors,
126
169
  },
127
170
  fontFamily: {
171
+ // Display face for headings — `tw-font-display`. Set via
172
+ // `theme.typography.fontDisplay`; when unset it resolves to `--font-sans`
173
+ // then the Inter stack, so it defaults to the body face rather than a
174
+ // generic `sans-serif`. The fallback chain lives *inside* the `var()` so
175
+ // the declaration stays valid when the vars are undefined — a bare
176
+ // undefined `var()` invalidates the whole `font-family` at
177
+ // computed-value time, and the later families would not rescue it.
178
+ display: [
179
+ 'var(--font-display, var(--font-sans, Inter))',
180
+ 'system-ui',
181
+ '-apple-system',
182
+ 'Segoe UI',
183
+ 'Roboto',
184
+ 'Helvetica Neue',
185
+ 'Arial',
186
+ 'Noto Sans',
187
+ 'Liberation Sans',
188
+ 'sans-serif',
189
+ // Match the canonical sans stack so emoji render consistently.
190
+ 'Apple Color Emoji',
191
+ 'Segoe UI Emoji',
192
+ 'Segoe UI Symbol',
193
+ 'Noto Color Emoji',
194
+ ],
128
195
  mono: [
129
- 'SFMono-Regular',
196
+ 'var(--font-mono, SFMono-Regular)',
130
197
  'Menlo',
131
198
  'Monaco',
132
199
  'Consolas',
@@ -178,3 +245,6 @@ export default {
178
245
  scrollFadePlugin,
179
246
  ],
180
247
  };
248
+
249
+ /** @type {import('tailwindcss').Config} */
250
+ export default createKeboolaConfig();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keboola/tailwind-config",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Shared Tailwind CSS v3 config for the Keboola UI platform — semantic color palette, plugins, and the `tw-` class prefix.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/typography.ts CHANGED
@@ -32,6 +32,7 @@ export const typography = {
32
32
  fontSize: '32px',
33
33
  lineHeight: '40px',
34
34
  fontWeight: '500',
35
+ color: 'rgb(var(--color-foreground))',
35
36
  marginTop: 0,
36
37
  marginBottom: '10px',
37
38
  },
@@ -42,7 +43,7 @@ export const typography = {
42
43
  fontSize: '24px',
43
44
  lineHeight: '32px',
44
45
  fontWeight: '500',
45
- color: colors.neutral[900],
46
+ color: 'rgb(var(--color-foreground))',
46
47
  marginTop: 0,
47
48
  marginBottom: '10px',
48
49
  },
@@ -53,21 +54,25 @@ export const typography = {
53
54
  fontSize: '16px',
54
55
  lineHeight: '24px',
55
56
  fontWeight: '500',
56
- color: colors.neutral[900],
57
+ color: 'rgb(var(--color-foreground))',
57
58
  margin: 0,
58
59
  },
59
60
  h4: {
60
61
  fontSize: '14px',
61
62
  lineHeight: '20px',
62
63
  fontWeight: '500',
63
- color: colors.neutral[900],
64
+ color: 'rgb(var(--color-foreground))',
64
65
  margin: 0,
65
66
  },
66
67
  h5: {
67
68
  fontSize: '12px',
68
69
  lineHeight: '20px',
69
70
  fontWeight: '500',
70
- color: colors.neutral[900],
71
+ color: 'rgb(var(--color-foreground))',
72
+ margin: 0,
73
+ },
74
+ h6: {
75
+ color: 'rgb(var(--color-foreground))',
71
76
  margin: 0,
72
77
  },
73
78
  'h1 small, h2 small, h3 small, h4 small, h5 small, h6 small': {