@keboola/tailwind-config 0.2.0 → 0.3.1

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
@@ -15,7 +15,7 @@ branded) typically supplies its own tokens; this package is optional then.
15
15
  ```bash
16
16
  npm install -D @keboola/tailwind-config tailwindcss@^3
17
17
  # or
18
- yarn add -D @keboola/tailwind-config tailwindcss@^3
18
+ pnpm add -D @keboola/tailwind-config tailwindcss@^3
19
19
  ```
20
20
 
21
21
  ## Use
package/colors.ts CHANGED
@@ -1,3 +1,29 @@
1
+ // Keboola brand ramps. Historically these lived under `primary[100..900]` (green)
2
+ // and `secondary[100..900]` (blue); defined once here so the legacy `primary`/
3
+ // `secondary` aliases and the semantic-correct `green`/`blue` palettes can't drift.
4
+ const greenScale = {
5
+ 100: '#e0ffe0',
6
+ 200: '#baf5ba',
7
+ 300: '#93f593',
8
+ 400: '#51e051',
9
+ 500: '#1ec71e',
10
+ 600: '#1bb31b',
11
+ 700: '#189f18',
12
+ 800: '#158b15',
13
+ 900: '#0f630f',
14
+ };
15
+ const blueScale = {
16
+ 100: '#e0f0ff',
17
+ 200: '#c2e0ff',
18
+ 300: '#99ccff',
19
+ 400: '#5cadff',
20
+ 500: '#1f8fff',
21
+ 600: '#0975e0',
22
+ 700: '#075fb8',
23
+ 800: '#064a8f',
24
+ 900: '#043566',
25
+ };
26
+
1
27
  export default {
2
28
  inherit: 'inherit',
3
29
  transparent: 'rgba(255,255,255,0)',
@@ -15,7 +41,10 @@ export default {
15
41
  foreground: 'rgb(var(--color-foreground) / <alpha-value>)',
16
42
 
17
43
  // Raised container chrome (Modal/Card/Sheet). White in light, lifted off background in dark.
18
- surface: 'rgb(var(--color-surface) / <alpha-value>)',
44
+ card: {
45
+ DEFAULT: 'rgb(var(--color-card) / <alpha-value>)',
46
+ foreground: 'rgb(var(--color-card-foreground) / <alpha-value>)',
47
+ },
19
48
 
20
49
  popover: {
21
50
  DEFAULT: 'rgb(var(--color-popover) / <alpha-value>)',
@@ -34,12 +63,32 @@ export default {
34
63
  DEFAULT: 'rgb(var(--color-input) / <alpha-value>)',
35
64
  },
36
65
 
66
+ // Focus ring (brand blue).
67
+ ring: 'rgb(var(--color-ring) / <alpha-value>)',
68
+
69
+ // Focus-ring offset gap (the surface color the ring is inset against).
70
+ 'ring-offset': 'rgb(var(--color-ring-offset) / <alpha-value>)',
71
+
72
+ // Categorical chart palette (brand-derived).
73
+ chart: {
74
+ 1: 'rgb(var(--color-chart-1) / <alpha-value>)',
75
+ 2: 'rgb(var(--color-chart-2) / <alpha-value>)',
76
+ 3: 'rgb(var(--color-chart-3) / <alpha-value>)',
77
+ 4: 'rgb(var(--color-chart-4) / <alpha-value>)',
78
+ 5: 'rgb(var(--color-chart-5) / <alpha-value>)',
79
+ },
80
+
37
81
  destructive: {
38
82
  DEFAULT: 'rgb(var(--color-destructive) / <alpha-value>)',
39
83
  foreground: 'rgb(var(--color-destructive-foreground) / <alpha-value>)',
40
84
  },
41
85
  success: {
42
86
  DEFAULT: 'rgb(var(--color-success) / <alpha-value>)',
87
+ foreground: 'rgb(var(--color-success-foreground) / <alpha-value>)',
88
+ },
89
+ info: {
90
+ DEFAULT: 'rgb(var(--color-info) / <alpha-value>)',
91
+ foreground: 'rgb(var(--color-info-foreground) / <alpha-value>)',
43
92
  },
44
93
 
45
94
  muted: {
@@ -74,28 +123,12 @@ export default {
74
123
  primary: {
75
124
  DEFAULT: 'rgb(var(--color-primary) / <alpha-value>)',
76
125
  foreground: 'rgb(var(--color-primary-foreground) / <alpha-value>)',
77
- 100: '#e0ffe0',
78
- 200: '#baf5ba',
79
- 300: '#93f593',
80
- 400: '#51e051',
81
- 500: '#1ec71e',
82
- 600: '#1bb31b',
83
- 700: '#189f18',
84
- 800: '#158b15',
85
- 900: '#0f630f',
126
+ ...greenScale,
86
127
  },
87
128
  secondary: {
88
- DEFAULT: '#E2E8F0',
89
- foreground: '#1E293B',
90
- 100: '#e0f0ff',
91
- 200: '#c2e0ff',
92
- 300: '#99ccff',
93
- 400: '#5cadff',
94
- 500: '#1f8fff',
95
- 600: '#0975e0',
96
- 700: '#075fb8',
97
- 800: '#064a8f',
98
- 900: '#043566',
129
+ DEFAULT: 'rgb(var(--color-secondary) / <alpha-value>)',
130
+ foreground: 'rgb(var(--color-secondary-foreground) / <alpha-value>)',
131
+ ...blueScale,
99
132
  },
100
133
  error: {
101
134
  100: '#ffe0e6',
@@ -110,6 +143,8 @@ export default {
110
143
  900: '#52000e',
111
144
  },
112
145
  warning: {
146
+ DEFAULT: 'rgb(var(--color-warning) / <alpha-value>)',
147
+ foreground: 'rgb(var(--color-warning-foreground) / <alpha-value>)',
113
148
  100: '#fff3e0',
114
149
  200: '#ffe7c2',
115
150
  300: '#ffd699',
@@ -176,4 +211,15 @@ export default {
176
211
  800: '#8A0F7D',
177
212
  900: '#5C0A54',
178
213
  },
214
+
215
+ // Semantic-correct names for the Keboola brand ramps that historically lived under
216
+ // `primary[100..900]` (green) and `secondary[100..900]` (blue) — fixed tints used
217
+ // directly regardless of brand, unlike `primary.DEFAULT` / `secondary.DEFAULT`
218
+ // (shadcn semantic, CSS-var driven). New code should use these; the `primary`/
219
+ // `secondary` ramps remain as aliases until their callsites are migrated (Step 2).
220
+ //
221
+ // Like the existing custom palettes (`cyan`/`teal`/`yellow`/`pink`/`purple`), these
222
+ // are `100..900` only and override Tailwind's same-named defaults.
223
+ green: { ...greenScale },
224
+ blue: { ...blueScale },
179
225
  };
package/index.js CHANGED
@@ -5,6 +5,7 @@ import { scopedPreflightStyles, isolateInsideOfContainer } from 'tailwindcss-sco
5
5
  import typographyPlugin from '@tailwindcss/typography';
6
6
  import containerQueriesPlugin from '@tailwindcss/container-queries';
7
7
  import { typography } from './typography';
8
+ import { scrollFadePlugin } from './scrollFade';
8
9
 
9
10
  /** @type {import('tailwindcss').Config} */
10
11
  export default {
@@ -174,5 +175,6 @@ export default {
174
175
  },
175
176
  });
176
177
  }),
178
+ scrollFadePlugin,
177
179
  ],
178
180
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@keboola/tailwind-config",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
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",
@@ -14,6 +14,7 @@
14
14
  "index.js",
15
15
  "colors.ts",
16
16
  "typography.ts",
17
+ "scrollFade.ts",
17
18
  "README.md"
18
19
  ],
19
20
  "publishConfig": {
@@ -39,10 +40,6 @@
39
40
  "engines": {
40
41
  "node": ">=20"
41
42
  },
42
- "scripts": {
43
- "knip:check": "yarn --cwd ../.. exec knip --workspace packages/tailwind-config",
44
- "knip:fix": "yarn --cwd ../.. exec knip --workspace packages/tailwind-config --fix-type types,exports,files"
45
- },
46
43
  "peerDependencies": {
47
44
  "tailwindcss": "^3.4.0"
48
45
  },
@@ -51,5 +48,9 @@
51
48
  "@tailwindcss/typography": "^0.5.19",
52
49
  "tailwindcss-animate": "1.0.7",
53
50
  "tailwindcss-scoped-preflight": "3.5.2"
51
+ },
52
+ "scripts": {
53
+ "knip:check": "pnpm --dir ../.. exec knip --workspace packages/tailwind-config",
54
+ "knip:fix": "pnpm --dir ../.. exec knip --workspace packages/tailwind-config --fix-type types,exports,files"
54
55
  }
55
- }
56
+ }
package/scrollFade.ts ADDED
@@ -0,0 +1,53 @@
1
+ import plugin from 'tailwindcss/plugin';
2
+
3
+ // scroll-fade: fades scroll-container edges purely in CSS (mask-image + CSS scroll-driven
4
+ // animations, no JS). Mirrors shadcn/ui. https://ui.shadcn.com/docs/utils/scroll-fade
5
+ // Edge opacity is driven by two registered custom props (0 = faded, 1 = solid). With no
6
+ // overflow the scroll timeline is inactive, both hold their initial value (1), so short
7
+ // content shows no fade. Fade thickness is tunable via `--tw-scroll-fade-size`.
8
+ export const scrollFadePlugin = plugin(function ({ addUtilities, addBase }) {
9
+ addBase({
10
+ '@property --tw-scroll-fade-start': {
11
+ syntax: "'<number>'",
12
+ inherits: 'false',
13
+ 'initial-value': '1',
14
+ },
15
+ '@property --tw-scroll-fade-end': {
16
+ syntax: "'<number>'",
17
+ inherits: 'false',
18
+ 'initial-value': '1',
19
+ },
20
+ '@keyframes tw-scroll-fade-reveal-start': {
21
+ from: { '--tw-scroll-fade-start': '1' },
22
+ to: { '--tw-scroll-fade-start': '0' },
23
+ },
24
+ '@keyframes tw-scroll-fade-reveal-end': {
25
+ from: { '--tw-scroll-fade-end': '0' },
26
+ to: { '--tw-scroll-fade-end': '1' },
27
+ },
28
+ });
29
+
30
+ const scrollFadeMask = (direction: 'bottom' | 'right') =>
31
+ `linear-gradient(to ${direction}, rgb(0 0 0 / var(--tw-scroll-fade-start)) 0, #000 var(--tw-scroll-fade-size), #000 calc(100% - var(--tw-scroll-fade-size)), rgb(0 0 0 / var(--tw-scroll-fade-end)) 100%)`;
32
+
33
+ const scrollFade = (direction: 'bottom' | 'right', axis: 'x' | 'y') => ({
34
+ '--tw-scroll-fade-size': '1.5rem',
35
+ WebkitMaskImage: scrollFadeMask(direction),
36
+ maskImage: scrollFadeMask(direction),
37
+ animation: 'tw-scroll-fade-reveal-start linear both, tw-scroll-fade-reveal-end linear both',
38
+ animationTimeline: `scroll(self ${axis}), scroll(self ${axis})`,
39
+ animationRange: '0 var(--tw-scroll-fade-size), calc(100% - var(--tw-scroll-fade-size)) 100%',
40
+ // Browsers without scroll-driven animations show a static fade on both edges.
41
+ '@supports not (animation-timeline: scroll())': {
42
+ '--tw-scroll-fade-start': '0',
43
+ '--tw-scroll-fade-end': '0',
44
+ },
45
+ });
46
+
47
+ const scrollFadeVertical = scrollFade('bottom', 'y');
48
+ addUtilities({
49
+ '.scroll-fade': scrollFadeVertical,
50
+ '.scroll-fade-y': scrollFadeVertical,
51
+ '.scroll-fade-x': scrollFade('right', 'x'),
52
+ });
53
+ });