@crowdstrike/tailwind-toucan-base 3.0.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 ADDED
@@ -0,0 +1,78 @@
1
+ # @crowdstrike/tailwind-toucan-base
2
+
3
+ A Tailwind preset that provides the base styles for CrowdStrike's Toucan design system.
4
+
5
+ ## Usage
6
+
7
+ ```bash
8
+ yarn add @crowdstrike/tailwind-toucan-base
9
+ #
10
+ npm install @crowdstrike/tailwind-toucan-base
11
+ #
12
+ pnpm add @crowdstrike/tailwind-toucan-base
13
+ ```
14
+
15
+ ### Tailwind
16
+
17
+ _Note_: This preset is presently only tested with Tailwind v2
18
+
19
+ ```js
20
+ // tailwind.config.js
21
+
22
+ module.exports = {
23
+ presets: [require('@crowdstrike/tailwind-toucan-base')],
24
+ extends: {
25
+ // your customizations here
26
+ }
27
+ };
28
+ ```
29
+
30
+ ### CSS `@import`
31
+
32
+ If your packager supports importing styles directly from an npm package, the Toucan styles are pre-built and can be imported at:
33
+
34
+ ```css
35
+ @import "@crowdstrike/tailwind-toucan-base";
36
+ ```
37
+
38
+ ### CDN Usage
39
+
40
+ Many JS CDNs scrape NPM and automatically serve and cache assets
41
+ deployed to NPM.
42
+
43
+ Here as an example with JSDelivr
44
+ ```
45
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@crowdstrike/tailwind-toucan-base/toucan.css">
46
+ ```
47
+
48
+ ## Previewing the config locally
49
+
50
+ ```bash
51
+ pnpm start
52
+ ```
53
+ which is an alias for:
54
+
55
+ ```bash
56
+ pnpm run build:preview
57
+ npx http-server ./dist
58
+ ```
59
+
60
+ ## Importing colors and shadows from Figma
61
+
62
+ This addon provides the ability to pull our palette information directly from Figma files and store them in
63
+ `themes.json` which is used by the Tailwind configuration to set up our CSS.
64
+
65
+ To import the colors run:
66
+
67
+ ```bash
68
+ LIGHT_ID=fileId DARK_ID=fileId MEZZANINE_ID=fileId \
69
+ FIGMA_TOKEN=some-key pnpm run figma:export-styles
70
+ ```
71
+
72
+ - `FIGMA_TOKEN` here is figma [Personal Access Token](https://www.figma.com/developers/api#access-tokens).
73
+ - `LIGHT_ID`, `DARK_ID`, and `MEZZANINE_ID` are `fileId`s that can be obtained from the URL of the figma project containing the color tokens.
74
+
75
+ ...and commit the changes to `themes.json`.
76
+
77
+ If you see any errors reported then you _may_ need to ensure that the Figma file is set up correctly (and e.g.
78
+ there are corresponding colors across each of the palettes).
package/index.js ADDED
@@ -0,0 +1,390 @@
1
+ 'use strict';
2
+
3
+ const themesData = require('./themes');
4
+
5
+ let colors = themesData.themes['dark'].colors.reduce((acc, { name }) => {
6
+ acc[name.replace('\\.', '.')] = `var(--${name})`;
7
+
8
+ return acc;
9
+ }, {});
10
+
11
+ let boxShadow = themesData.themes['dark'].shadows.reduce((acc, { name }) => {
12
+ acc[name.replace(/^elevation-/, '')] = `var(--${name})`;
13
+
14
+ return acc;
15
+ }, {});
16
+
17
+ const FONT_SIZES = {
18
+ xxs: '.5625rem',
19
+ xs: '.75rem',
20
+ sm: '.875rem',
21
+ md: '1rem',
22
+ lg: '1.25rem',
23
+ xl: '1.5rem',
24
+ '2xl': '2rem',
25
+ '3xl': '2.5rem',
26
+ '4xl': '3rem',
27
+ };
28
+
29
+ module.exports = {
30
+ theme: {
31
+ // Keys placed here will REMOVE the classes included with tailwindcss
32
+ // eg if `padding` was added here we would lose all of tailwinds padding classes.
33
+ // If you want to ADD a custom class then place them in the `extend` object below
34
+ boxShadow: {
35
+ none: 'none',
36
+ 'focusable-outline': 'inset 0 0 0 1px var(--lines-dark), var(--elevation-inner-md)',
37
+ 'focus-outline': 'inset 0 0 0 2px var(--focus)',
38
+ 'error-outline': 'inset 0 0 0 2px var(--critical)',
39
+ 'search-input': 'inset 0 0 0 1px var(--nav-text-secondary)',
40
+ ...boxShadow,
41
+ },
42
+
43
+ colors: {
44
+ current: 'currentColor',
45
+ transparent: 'transparent',
46
+ falcon: 'var(--falcon)',
47
+ ...colors,
48
+ },
49
+
50
+ fontFamily: {
51
+ sans: ['Calibre', 'sans-serif'],
52
+ mono: ['Monaco', 'monospace'],
53
+ },
54
+
55
+ fontSize: (theme) => {
56
+ return {
57
+ xxs: [FONT_SIZES.xxs, theme('lineHeight.4')],
58
+ xs: [FONT_SIZES.xs, theme('lineHeight.5')],
59
+ sm: [FONT_SIZES.sm, theme('lineHeight.6')],
60
+ md: [FONT_SIZES.md, theme('lineHeight.6')],
61
+ lg: [FONT_SIZES.lg, theme('lineHeight.8')],
62
+ xl: [FONT_SIZES.xl, theme('lineHeight.8')],
63
+ '2xl': [FONT_SIZES['2xl'], theme('lineHeight.10')],
64
+ '3xl': [FONT_SIZES['3xl'], theme('lineHeight.12')],
65
+ '4xl': [FONT_SIZES['4xl'], theme('lineHeight.13')],
66
+ };
67
+ },
68
+
69
+ zIndex: {
70
+ '-1': '-1',
71
+ 1: '1',
72
+ 2: '2',
73
+ 3: '3',
74
+ 4: '4',
75
+ 5: '5',
76
+ 6: '6',
77
+ 7: '7',
78
+ 8: '8',
79
+ 9: '9',
80
+ 10: '10',
81
+ 'flash-messages': 'var(--z-index-flash-messages)',
82
+ overlay: 'var(--z-index-overlay)',
83
+ tooltip: 'var(--z-index-tooltip)',
84
+ 'popover-sticky': 'var(--z-index-popover-sticky)',
85
+ popover: 'var(--z-index-popover)',
86
+ 'skip-to-content': 'var(--z-index-skip-to-content)',
87
+ tablist: 'var(--z-index-tablist)',
88
+ tabpanel: 'var(--z-index-tabpanel)',
89
+ 'tabpanel-scrim': 'var(--z-index-tabpanel-scrim)',
90
+ 'template-head': 'var(--z-index-template-head)',
91
+ 'template-main-head-sticky': 'var(--z-index-template-main-head-sticky)',
92
+ 'template-main-head': 'var(--z-index-template-main-head)',
93
+ 'template-main': 'var(--z-index-template-main)',
94
+ 'search-results-navigation': 'var(--z-index-navigation-search)',
95
+ },
96
+
97
+ extend: {
98
+ animation: {
99
+ 'fade-in': 'fade-in .25s linear',
100
+ },
101
+
102
+ cursor: {
103
+ 'col-resize': 'col-resize',
104
+ },
105
+
106
+ flex: {
107
+ 2: '2 2 0%',
108
+ 3: '3 3 0%',
109
+ 4: '4 4 0%',
110
+ },
111
+
112
+ gridTemplateColumns: {
113
+ 'centered-2/3': '2fr 8fr 2fr',
114
+
115
+ 'auto-2': 'auto auto',
116
+
117
+ 'max-content-4': 'repeat(4, minmax(max-content, 1fr))',
118
+ 'max-content-6': 'repeat(6, minmax(max-content, 1fr))',
119
+ },
120
+
121
+ height: {
122
+ 2.5: '0.375rem',
123
+ 7: '1.75rem',
124
+ 9: '2.25rem',
125
+ 11: '2.75rem',
126
+ 'main-content-area': 'calc(100vh - var(--template-head-height))',
127
+ },
128
+
129
+ keyframes: {
130
+ 'fade-in': {
131
+ '0%': { opacity: '0%' },
132
+ '100%': { opacity: '100%' },
133
+ },
134
+ },
135
+
136
+ rotate: {
137
+ '-5': '-5deg',
138
+ },
139
+
140
+ inset: {
141
+ '1/2': '50%',
142
+ },
143
+
144
+ lineHeight: {
145
+ 12: '3rem',
146
+ 13: '3.25rem',
147
+ },
148
+
149
+ maxHeight: {
150
+ listbox: '12em',
151
+ 'under-header': 'calc(100vh - var(--template-head-height))',
152
+ },
153
+
154
+ maxWidth: {
155
+ paragraph: '34rem',
156
+ },
157
+
158
+ minHeight: (theme) => {
159
+ return {
160
+ 3: theme('height.3'),
161
+ 4: theme('height.4'),
162
+ 6: theme('height.6'),
163
+ 16: theme('height.16'),
164
+ };
165
+ },
166
+
167
+ minWidth: (theme) => {
168
+ return {
169
+ 3: theme('width.3'),
170
+ 4: theme('width.4'),
171
+ 6: theme('width.6'),
172
+ 16: theme('width.16'),
173
+ 24: theme('width.24'),
174
+ 48: theme('width.48'),
175
+ phoenix: '1024px',
176
+ popover: '140px',
177
+ toucan: '1380px',
178
+ };
179
+ },
180
+
181
+ padding: {
182
+ 0.25: '0.063rem',
183
+ 'property-tabs-top': 'var(--property-tabs-top)',
184
+ unset: 'unset',
185
+ },
186
+
187
+ spacing: {
188
+ 0.5: '0.125rem',
189
+ },
190
+
191
+ transitionProperty: {
192
+ width: 'width',
193
+ },
194
+
195
+ width: {
196
+ 2.5: '0.375rem',
197
+ 'max-content': 'max-content',
198
+ 7: '1.75rem',
199
+ 15: '3.75rem',
200
+ },
201
+ },
202
+
203
+ screens: {
204
+ print: { raw: 'print' },
205
+
206
+ // Defaults omitted to reduce payload size,
207
+ // sm: md: lg: variants removed to reduce file size by ~700kb
208
+ // https://tailwindcss.com/docs/theme/#screens
209
+ //
210
+ // Now, we add the screens we only need for specific properties
211
+ lg: '1120px',
212
+ '2xl': '1536px',
213
+ },
214
+ },
215
+
216
+ variants: {
217
+ // defaults
218
+ // https://tailwindcss.com/docs/pseudo-class-variants/#default-variants-reference
219
+ // **** NOTE *****
220
+ // Order of variants passed here controls order in source code. You almost certainly
221
+ // want active and disabled at the end so they can override other styles!
222
+ accessibility: ['focus'],
223
+ alignContent: [],
224
+ alignItems: [],
225
+ alignSelf: [],
226
+ animation: [],
227
+ appearance: [],
228
+ backdropBlur: [],
229
+ backdropBrightness: [],
230
+ backdropContrast: [],
231
+ backdropDropShadow: [],
232
+ backdropFilter: [],
233
+ backdropGrayscale: [],
234
+ backdropHueRotate: [],
235
+ backdropInvert: [],
236
+ backdropSaturate: [],
237
+ backdropSepia: [],
238
+ backgroundAttachment: [],
239
+ backgroundBlendMode: [],
240
+ backgroundClip: [],
241
+ backgroundColor: [
242
+ 'even',
243
+ 'group-hover',
244
+ 'hover',
245
+ 'focus',
246
+ 'focus-within',
247
+ 'focus-visible',
248
+ 'active',
249
+ 'disabled',
250
+ ],
251
+ backgroundImage: [],
252
+ backgroundOpacity: ['hover', 'focus'],
253
+ backgroundPosition: [],
254
+ backgroundRepeat: [],
255
+ backgroundSize: [],
256
+ blur: [],
257
+ borderCollapse: [],
258
+ borderColor: ['hover', 'active'],
259
+ borderOpacity: ['hover', 'focus'],
260
+ borderRadius: ['focus', 'first', 'last'],
261
+ borderStyle: [],
262
+ borderWidth: ['first', 'last', 'active'],
263
+ boxDecorationBreak: [],
264
+ boxShadow: [
265
+ 'hover',
266
+ 'group-hover',
267
+ 'focus',
268
+ 'focus-within',
269
+ 'focus-visible',
270
+ 'active',
271
+ 'disabled',
272
+ ],
273
+ boxSizing: [],
274
+ brightness: [],
275
+ clear: [],
276
+ container: [],
277
+ contrast: [],
278
+ cursor: ['disabled'],
279
+ display: ['responsive', 'group-hover'],
280
+ divideColor: [],
281
+ divideOpacity: [],
282
+ divideStyle: [],
283
+ divideWidth: [],
284
+ dropShadow: [],
285
+ fill: [],
286
+ filter: [],
287
+ flex: [],
288
+ flexDirection: [],
289
+ flexGrow: [],
290
+ flexShrink: [],
291
+ flexWrap: [],
292
+ float: [],
293
+ fontFamily: [],
294
+ fontSize: [],
295
+ fontSmoothing: [],
296
+ fontStyle: [],
297
+ fontVariantNumeric: [],
298
+ fontWeight: ['hover', 'focus'],
299
+ gap: [],
300
+ gradientColorStops: ['dark', 'hover', 'focus'],
301
+ grayscale: [],
302
+ gridAutoColumns: [],
303
+ gridAutoFlow: [],
304
+ gridAutoRows: [],
305
+ gridColumn: [],
306
+ gridColumnEnd: [],
307
+ gridColumnStart: [],
308
+ gridRow: [],
309
+ gridRowEnd: [],
310
+ gridRowStart: [],
311
+ gridTemplateColumns: ['responsive'],
312
+ gridTemplateRows: [],
313
+ height: [],
314
+ hueRotate: [],
315
+ inset: ['focus'],
316
+ invert: [],
317
+ isolation: [],
318
+ justifyContent: [],
319
+ justifyItems: [],
320
+ justifySelf: [],
321
+ letterSpacing: [],
322
+ lineHeight: [],
323
+ listStylePosition: [],
324
+ listStyleType: [],
325
+ margin: ['first', 'last'],
326
+ maxHeight: [],
327
+ maxWidth: [],
328
+ minHeight: [],
329
+ minWidth: [],
330
+ mixBlendMode: [],
331
+ objectFit: [],
332
+ objectPosition: [],
333
+ opacity: ['hover', 'focus', 'group-hover', 'group-focus'],
334
+ order: [],
335
+ outline: ['focus'],
336
+ overflow: [],
337
+ overscrollBehavior: [],
338
+ padding: [],
339
+ placeItems: [],
340
+ placeContent: [],
341
+ placeSelf: [],
342
+ placeholderColor: ['focus'],
343
+ placeholderOpacity: ['focus'],
344
+ pointerEvents: ['disabled'],
345
+ position: ['hover'],
346
+ resize: [],
347
+ ringColor: ['dark', 'focus-within', 'focus'],
348
+ ringOffsetColor: ['dark', 'focus-within', 'focus'],
349
+ ringOffsetWidth: ['focus-within', 'focus'],
350
+ ringOpacity: ['dark', 'focus-within', 'focus'],
351
+ ringWidth: ['focus-within', 'focus-visible', 'focus'],
352
+ rotate: ['active'],
353
+ saturate: [],
354
+ scale: ['hover', 'focus', 'active'],
355
+ sepia: [],
356
+ skew: ['hover', 'focus'],
357
+ space: [],
358
+ stroke: [],
359
+ strokeWidth: [],
360
+ tableLayout: [],
361
+ textAlign: [],
362
+ textColor: ['hover', 'focus', 'focus-visible', 'group-hover', 'active', 'disabled'],
363
+ textDecoration: ['hover', 'focus'],
364
+ textOpacity: ['hover', 'focus'],
365
+ textOverflow: [],
366
+ textTransform: [],
367
+ transform: [],
368
+ transformOrigin: [],
369
+ transitionDelay: [],
370
+ transitionDuration: [],
371
+ transitionProperty: ['active'],
372
+ transitionTimingFunction: [],
373
+ translate: ['hover', 'focus'],
374
+ userSelect: [],
375
+ verticalAlign: [],
376
+ visibility: [],
377
+ whitespace: [],
378
+ width: [],
379
+ wordBreak: [],
380
+ zIndex: ['hover', 'active', 'group-hover'],
381
+ },
382
+
383
+ plugins: [
384
+ /**
385
+ * All of our own custom plugins are wrapped up this single
386
+ * configure call -- form fields, variables, etc
387
+ */
388
+ ...require('./plugins').configure({ FONT_SIZES, themesData }),
389
+ ],
390
+ };
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "@crowdstrike/tailwind-toucan-base",
3
+ "version": "3.0.1",
4
+ "private": false,
5
+ "description": "Tailwind preset for CrowdStrike's Toucan design system",
6
+ "repository": "https://github.com/CrowdStrike/tailwind-toucan-base",
7
+ "license": "MIT",
8
+ "author": "CrowdStrike UX Team",
9
+ "main": "index.js",
10
+ "files": [
11
+ "index.js",
12
+ "index.css",
13
+ "toucan.css",
14
+ "plugins/**/*.js"
15
+ ],
16
+ "scripts": {
17
+ "start": "pnpm run build && npx http-server ./dist",
18
+ "build": "npm-run-all clean build:cdn build:alias build:preview",
19
+ "build:preview": "node ./lib/build-preview.mjs",
20
+ "build:cdn": "NODE_ENV=production tailwind build -i ./lib/index.css -o ./index.css -c ./lib/tailwind.config.cdn.js",
21
+ "clean": "rm -f ./toucan.css ./index.css",
22
+ "build:alias": "cp index.css toucan.css",
23
+ "figma:export-styles": "figma-export use-config",
24
+ "test": "pnpm exec vitest --coverage --run",
25
+ "lint:fix": "pnpm run lint:js --fix",
26
+ "lint:js": "eslint ."
27
+ },
28
+ "dependencies": {
29
+ "@figma-export/cli": "3.3.1",
30
+ "tailwindcss": "^2.2.15"
31
+ },
32
+ "devDependencies": {
33
+ "@nullvoxpopuli/eslint-configs": "2.2.16",
34
+ "@semantic-release/changelog": "^5.0.1",
35
+ "@semantic-release/git": "^9.0.1",
36
+ "@types/fs-extra": "^9.0.13",
37
+ "autoprefixer": "^10.3.4",
38
+ "c8": "^7.11.2",
39
+ "common-tags": "^1.8.2",
40
+ "eslint": "^7.32.0",
41
+ "execa": "^6.1.0",
42
+ "fs-extra": "^10.1.0",
43
+ "npm-run-all": "^4.1.5",
44
+ "postcss": "^8.3.6",
45
+ "semantic-release": "^17.4.7",
46
+ "tailwind-config-viewer": "^1.7.0",
47
+ "typescript": "^4.6.4",
48
+ "vitest": "0.12.4"
49
+ },
50
+ "engines": {
51
+ "node": ">=14.15.0"
52
+ },
53
+ "publishConfig": {
54
+ "access": "public"
55
+ },
56
+ "release": {
57
+ "branches": [
58
+ "main",
59
+ "master"
60
+ ],
61
+ "plugins": [
62
+ "@semantic-release/commit-analyzer",
63
+ "@semantic-release/release-notes-generator",
64
+ "@semantic-release/changelog",
65
+ "@semantic-release/npm",
66
+ "@semantic-release/github",
67
+ "@semantic-release/git"
68
+ ]
69
+ },
70
+ "packageManager": "pnpm@7.1.0",
71
+ "volta": {
72
+ "node": "16.15.0",
73
+ "yarn": "1.22.11",
74
+ "npm": "8.9.0"
75
+ }
76
+ }
@@ -0,0 +1,46 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ module.exports = () =>
6
+ plugin((pluginApi) => {
7
+ addFormFieldStyles(pluginApi);
8
+ });
9
+
10
+ function addFormFieldStyles({ addComponents }) {
11
+ let textbox = {
12
+ backgroundColor: 'var(--overlay-1)',
13
+ borderRadius: 'var(--border-radius)',
14
+ boxShadow: 'inset 0 0 0 1px var(--lines-dark), var(--elevation-inner-md)',
15
+ color: 'var(--titles-and-attributes)',
16
+ display: 'block',
17
+ fontFamily: 'inherit',
18
+ fontSize: '1rem',
19
+ lineHeight: '1.5',
20
+ padding: 'var(--space-1) var(--space-2)',
21
+ width: '100%',
22
+
23
+ '&:focus': {
24
+ // TODO: share with definition of boxShadow: shadow-focus-outline
25
+ boxShadow: 'inset 0 0 0 2px var(--focus);',
26
+ outline: 0,
27
+ },
28
+
29
+ '&::placeholder': {
30
+ color: 'var(--disabled)',
31
+ },
32
+ };
33
+
34
+ let textarea = {
35
+ ...textbox,
36
+ minHeight: '150px',
37
+ resize: 'vertical',
38
+ };
39
+
40
+ let formFields = {
41
+ '.textbox': textbox,
42
+ '.textarea': textarea,
43
+ };
44
+
45
+ addComponents(formFields);
46
+ }
@@ -0,0 +1,12 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ configure: ({ FONT_SIZES, themesData }) => [
5
+ require('./interaction')(),
6
+ require('./form-fields')(),
7
+ require('./line-clamp'),
8
+ require('./typography')(FONT_SIZES),
9
+ require('./theme-plugin')(themesData),
10
+ require('./variables'),
11
+ ],
12
+ };
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ module.exports = () =>
6
+ plugin((pluginApi) => {
7
+ addFocusStyles(pluginApi);
8
+ addInteractiveStyles(pluginApi);
9
+ });
10
+
11
+ function addFocusStyles({ addComponents }) {
12
+ addComponents({
13
+ '.focusable': {
14
+ '@apply ring-ground-floor': {},
15
+ '@apply ring-inset': {},
16
+ '@apply ring-offset-2': {},
17
+ '@apply ring-offset-focus': {},
18
+ },
19
+
20
+ '.focusable:focus': {
21
+ '@apply outline-none': {},
22
+ },
23
+
24
+ '.focusable:focus-visible': {
25
+ '@apply ring-2': {},
26
+ },
27
+
28
+ '.focusable-destructive': {
29
+ '@apply ring-offset-destructive-pressed': {},
30
+ },
31
+
32
+ '.focusable-outer': {
33
+ '@apply ring-offset-ground-floor': {},
34
+ '@apply ring-offset-1': {},
35
+ '@apply ring-focus': {},
36
+ },
37
+
38
+ '.focusable-outer:focus': {
39
+ '@apply outline-none': {},
40
+ },
41
+
42
+ '.focusable-outer:focus-visible': {
43
+ '@apply ring-2': {},
44
+ },
45
+ });
46
+ }
47
+
48
+ function addInteractiveStyles({ addComponents }) {
49
+ addComponents({
50
+ '.interactive-normal': {
51
+ '@apply bg-normal-idle': {},
52
+ '@apply shadow-base': {},
53
+ '@apply text-text-and-icons': {},
54
+ },
55
+
56
+ '.interactive-normal:not(.interactive-disabled):hover': {
57
+ '@apply bg-normal-hover': {},
58
+ '@apply shadow-md': {},
59
+ },
60
+
61
+ '.interactive-normal:not(.interactive-disabled):focus-visible': {
62
+ '@apply bg-normal-hover': {},
63
+ },
64
+
65
+ '.interactive-normal:not(.interactive-disabled):active': {
66
+ '@apply bg-normal-pressed': {},
67
+ '@apply shadow-inner-md': {},
68
+ },
69
+
70
+ '.interactive-primary': {
71
+ '@apply bg-primary-idle': {},
72
+ '@apply shadow-base': {},
73
+ '@apply text-ground-floor': {},
74
+ },
75
+
76
+ '.interactive-primary:not(.interactive-disabled):focus-visible': {
77
+ '@apply bg-primary-hover': {},
78
+ },
79
+
80
+ '.interactive-primary:not(.interactive-disabled):hover': {
81
+ '@apply bg-primary-hover': {},
82
+ '@apply shadow-md': {},
83
+ },
84
+
85
+ '.interactive-primary:not(.interactive-disabled):active': {
86
+ '@apply bg-primary-pressed': {},
87
+ '@apply shadow-inner-md': {},
88
+ },
89
+
90
+ '.interactive-destructive': {
91
+ '@apply bg-destructive-idle': {},
92
+ '@apply shadow-base': {},
93
+ '@apply text-destructive-pressed': {},
94
+ },
95
+
96
+ '.interactive-destructive:not(.interactive-disabled):focus-visible': {
97
+ '@apply bg-destructive-hover': {},
98
+ '@apply text-ground-floor': {},
99
+ },
100
+
101
+ '.interactive-destructive:not(.interactive-disabled):hover': {
102
+ '@apply shadow-md': {},
103
+ '@apply bg-destructive-hover': {},
104
+ '@apply text-ground-floor': {},
105
+ },
106
+
107
+ '.interactive-destructive:not(.interactive-disabled):active': {
108
+ '@apply bg-destructive-pressed': {},
109
+ '@apply text-ground-floor': {},
110
+ '@apply shadow-inner-md': {},
111
+ },
112
+
113
+ '.interactive-link': {
114
+ '@apply bg-transparent': {},
115
+ '@apply text-primary-idle': {},
116
+ },
117
+
118
+ '.interactive-link:not(.interactive-disabled):hover': {
119
+ '@apply bg-opacity-0': {},
120
+ '@apply text-primary-hover': {},
121
+ },
122
+
123
+ '.interactive-link:not(.interactive-disabled):active': {
124
+ '@apply text-primary-pressed': {},
125
+ },
126
+
127
+ '.interactive-quiet': {
128
+ '@apply bg-transparent': {},
129
+ '@apply text-text-and-icons': {},
130
+ },
131
+
132
+ '.interactive-quiet:not(.interactive-disabled):focus-visible': {
133
+ '@apply bg-normal-hover': {},
134
+ },
135
+
136
+ '.interactive-quiet:not(.interactive-disabled):hover': {
137
+ '@apply bg-normal-hover': {},
138
+ '@apply shadow-md': {},
139
+ },
140
+
141
+ '.interactive-quiet:not(.interactive-disabled):active': {
142
+ '@apply bg-normal-pressed': {},
143
+ '@apply shadow-inner-md': {},
144
+ },
145
+
146
+ '.interactive-disabled': {
147
+ '@apply bg-overlay-1': {},
148
+ '@apply cursor-default': {},
149
+ '@apply shadow-none': {},
150
+ '@apply text-disabled': {},
151
+ },
152
+
153
+ '.interactive-quiet.interactive-disabled': {
154
+ '@apply bg-transparent': {},
155
+ },
156
+ });
157
+ }
@@ -0,0 +1,44 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ const addLineClampUtilities = ({ addUtilities }) => {
6
+ let clampUtility = {};
7
+
8
+ for (let c = 1; c <= 10; c++) {
9
+ clampUtility[`.clamp-${c}`] = {
10
+ display: '-webkit-box',
11
+ '-webkit-line-clamp': `${c}`,
12
+ '-webkit-box-orient': 'vertical',
13
+ overflow: 'hidden',
14
+ };
15
+ }
16
+
17
+ return addUtilities(clampUtility);
18
+ };
19
+
20
+ /*
21
+ Clamp
22
+
23
+ this adds overflow hidden and ellipsis for multiple lines of text
24
+ The following utility is added for creating truncated line:
25
+
26
+ clamp-<lineNumber>
27
+
28
+ This currently support up to 10 lines.
29
+
30
+ Examples
31
+
32
+ <div>
33
+ <span class="clamp-7">
34
+ Green juice tumeric coloring book, before they sold out sartorial post-ironic edison bulb. Beard fashion axe +1 hell of, bushwick ugh kogi pickled williamsburg chartreuse. Kale chips normcore cornhole, art party before they sold out PBR&B kogi roof party listicle taxidermy asymmetrical actually hot chicken. Etsy XOXO freegan trust fund bicycle rights, cronut meditation chillwave ramps meggings letterpress.
35
+ Pork belly yr pickled twee shaman biodiesel hammock tattooed etsy keffiyeh literally semiotics forage tote bag. Kinfolk chicharrones wolf shaman butcher knausgaard. Ethical seitan beard hella asymmetrical. Prism trust fund lomo, next level sriracha iceland snackwave sustainable chillwave locavore gluten-free drinking vinegar raclette yr. Edison bulb celiac brunch flexitarian. Beard yuccie venmo keytar chillwave tbh trust fund locavore.
36
+ </span>
37
+ </div>
38
+
39
+ This will truncate the paragraph after 7 lines and show an ellipsis
40
+
41
+ */
42
+ module.exports = plugin(function (pluginApi) {
43
+ addLineClampUtilities(pluginApi);
44
+ });
@@ -0,0 +1,42 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ module.exports = function (themesData) {
6
+ const addThemeColorBaseClasses = ({ addBase }) => {
7
+ let generatedCss = Object.entries(themesData.themes).reduce((css, [, themeData]) => {
8
+ css[themeData.cssSelector] = themeData.colors.reduce((acc, { name, value }) => {
9
+ acc[`--${name}`] = value;
10
+
11
+ return acc;
12
+ }, {});
13
+
14
+ return css;
15
+ }, {});
16
+
17
+ addBase(generatedCss);
18
+ };
19
+
20
+ const addThemeShadowBaseClasses = ({ addBase }) => {
21
+ let generatedCss = Object.entries(themesData.themes).reduce((css, [, themeData]) => {
22
+ css[themeData.cssSelector] = themeData.shadows.reduce((acc, { name, effects }) => {
23
+ acc[`--${name}`] = effects.join(', ');
24
+
25
+ return acc;
26
+ }, {});
27
+
28
+ return css;
29
+ }, {});
30
+
31
+ addBase(generatedCss);
32
+ };
33
+
34
+ /*
35
+ This plugin will add base classes for each theme which specify all of the color
36
+ values for that theme.
37
+ */
38
+ return plugin(function (pluginApi) {
39
+ addThemeColorBaseClasses(pluginApi);
40
+ addThemeShadowBaseClasses(pluginApi);
41
+ });
42
+ };
@@ -0,0 +1,140 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ module.exports = (fontSizes) =>
6
+ plugin((pluginApi) => {
7
+ addTextStyles(pluginApi, fontSizes);
8
+ });
9
+
10
+ function addTextStyles({ addComponents, theme }, fontSize) {
11
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/text-rendering
12
+ let geometricPrecision = { textRendering: 'geometricPrecision' };
13
+ let underline = { textDecoration: 'underline' };
14
+
15
+ let text = {
16
+ '.geometric-precision-text': {
17
+ ...geometricPrecision,
18
+ },
19
+ };
20
+
21
+ /**
22
+ * NOTE:
23
+ * We cannot use theme('fontSize.XY') for everything because it contains both
24
+ * fontSize and lineHeight when used in this type of object, every usage
25
+ * provides *two* fontSizes (one desired, one is supposed to be the lineHeight,
26
+ * but is interpreted as a fontSize here).
27
+ */
28
+ let textStyles = {
29
+ '.type-4xl': {
30
+ fontSize: fontSize['4xl'],
31
+ lineHeight: theme('lineHeight.13'),
32
+ fontWeight: theme('fontWeight.medium'),
33
+ letterSpacing: theme('letterSpacing.tight'),
34
+ },
35
+ '.type-3xl': {
36
+ fontSize: fontSize['3xl'],
37
+ lineHeight: theme('lineHeight.12'),
38
+ fontWeight: theme('fontWeight.medium'),
39
+ letterSpacing: theme('letterSpacing.tight'),
40
+ },
41
+ '.type-2xl': {
42
+ fontSize: fontSize['2xl'],
43
+ lineHeight: theme('lineHeight.10'),
44
+ fontWeight: theme('fontWeight.medium'),
45
+ },
46
+ '.type-xl': {
47
+ fontSize: fontSize.xl,
48
+ lineHeight: theme('lineHeight.8'),
49
+ fontWeight: theme('fontWeight.medium'),
50
+ ...geometricPrecision,
51
+ },
52
+ '.type-lg': {
53
+ fontSize: fontSize.lg,
54
+ lineHeight: theme('lineHeight.8'),
55
+ },
56
+ '.type-lg-medium': {
57
+ fontSize: fontSize.lg,
58
+ lineHeight: theme('lineHeight.8'),
59
+ fontWeight: theme('fontWeight.medium'),
60
+ },
61
+ '.type-lg-tight-medium': {
62
+ fontSize: fontSize.lg,
63
+ lineHeight: theme('lineHeight.6'),
64
+ fontWeight: theme('fontWeight.medium'),
65
+ ...geometricPrecision,
66
+ },
67
+ '.type-md': {
68
+ fontSize: fontSize.md,
69
+ lineHeight: theme('lineHeight.6'),
70
+ },
71
+ // deprecated? md-medium?
72
+ '.type-md-medium': {
73
+ fontSize: fontSize.md,
74
+ lineHeight: theme('lineHeight.6'),
75
+ fontWeight: theme('fontWeight.medium'),
76
+ },
77
+ '.type-md-underline': {
78
+ fontSize: fontSize.md,
79
+ lineHeight: theme('lineHeight.6'),
80
+ ...underline,
81
+ },
82
+ '.type-md-tight': {
83
+ fontSize: fontSize.md,
84
+ lineHeight: theme('lineHeight.5'),
85
+ },
86
+ '.type-md-tight-medium': {
87
+ fontSize: fontSize.md,
88
+ lineHeight: theme('lineHeight.5'),
89
+ fontWeight: theme('fontWeight.medium'),
90
+ ...geometricPrecision,
91
+ },
92
+ '.type-md-tight-underline': {
93
+ fontSize: fontSize.md,
94
+ lineHeight: theme('lineHeight.5'),
95
+ ...underline,
96
+ },
97
+ '.type-sm-mono': {
98
+ fontSize: fontSize.sm,
99
+ lineHeight: theme('lineHeight.6'),
100
+ fontFamily: theme('fontFamily.mono'),
101
+ },
102
+ '.type-sm-mono-tight': {
103
+ fontSize: fontSize.sm,
104
+ fontFamily: theme('fontFamily.mono'),
105
+ lineHeight: theme('lineHeight.5'),
106
+ },
107
+ '.type-sm-mono-underline': {
108
+ fontSize: fontSize.sm,
109
+ lineHeight: theme('lineHeight.6'),
110
+ fontFamily: theme('fontFamily.mono'),
111
+ ...underline,
112
+ },
113
+ '.type-xs': {
114
+ fontSize: fontSize.xs,
115
+ lineHeight: theme('lineHeight.5'),
116
+ },
117
+ '.type-xs-tight': {
118
+ fontSize: fontSize.xs,
119
+ lineHeight: theme('lineHeight.4'),
120
+ },
121
+ '.type-xs-tight-underline': {
122
+ fontSize: fontSize.xs,
123
+ lineHeight: theme('lineHeight.4'),
124
+ ...underline,
125
+ },
126
+ '.type-xs-mono': {
127
+ fontSize: fontSize.xs,
128
+ lineHeight: theme('lineHeight.6'),
129
+ fontFamily: theme('fontFamily.mono'),
130
+ },
131
+ '.type-xxs-mono': {
132
+ fontSize: fontSize.xxs,
133
+ lineHeight: theme('lineHeight.4'),
134
+ fontFamily: theme('fontFamily.mono'),
135
+ },
136
+ };
137
+
138
+ addComponents(textStyles);
139
+ addComponents(text);
140
+ }
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ const plugin = require('tailwindcss/plugin');
4
+
5
+ const FALCON_VARIBALES = {
6
+ '--side-nav-width-collapsed': '122px',
7
+ '--side-nav-width-expanded': '247px',
8
+
9
+ '--tab-list-height': '40px',
10
+ '--tab-height': '40px',
11
+ '--tab-border-radius': '8px',
12
+
13
+ '--process-offset-top': '40px',
14
+
15
+ '--default-animation-duration': '125ms',
16
+ '--default-animation-timing-function': 'ease-out',
17
+
18
+ '--default-animation-settings':
19
+ 'var(--default-animation-duration) var(--default-animation-timing-function)',
20
+ };
21
+
22
+ module.exports = plugin(function ({ addComponents, theme }) {
23
+ let roots = {};
24
+
25
+ // See: https://tailwindcss.com/docs/margin/#app
26
+ // for values
27
+ let space = theme(`space`);
28
+
29
+ if (!space) {
30
+ throw new Error('TailwindCSS 1.9.6 or greater is required');
31
+ }
32
+
33
+ for (let [specifier, amount] of Object.entries(space)) {
34
+ let varName = `--space-${specifier}`;
35
+
36
+ roots[varName] = amount;
37
+ }
38
+
39
+ addComponents({
40
+ ':root': {
41
+ ...roots,
42
+ ...FALCON_VARIBALES,
43
+ },
44
+ });
45
+ });