swatchkit 1.0.1 → 1.1.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/build.js +31 -2
- package/package.json +2 -2
- package/src/blueprints/colors.json +11 -0
- package/src/blueprints/compositions/cluster.css +20 -0
- package/src/blueprints/compositions/flow.css +10 -0
- package/src/blueprints/compositions/grid.css +36 -0
- package/src/blueprints/compositions/index.css +12 -0
- package/src/blueprints/compositions/prose.css +89 -0
- package/src/blueprints/compositions/repel.css +23 -0
- package/src/blueprints/compositions/sidebar.css +44 -0
- package/src/blueprints/compositions/switcher.css +32 -0
- package/src/blueprints/compositions/wrapper.css +14 -0
- package/src/blueprints/fonts.json +24 -0
- package/src/blueprints/global/elements.css +609 -0
- package/src/blueprints/global/index.css +13 -0
- package/src/blueprints/global/reset.css +91 -0
- package/src/blueprints/global/variables.css +58 -0
- package/src/blueprints/main.css +27 -0
- package/src/blueprints/spacing.json +19 -0
- package/src/blueprints/swatchkit-ui.css +79 -0
- package/src/blueprints/text-leading.json +13 -0
- package/src/blueprints/text-sizes.json +21 -0
- package/src/blueprints/text-weights.json +11 -0
- package/src/blueprints/utilities/index.css +9 -0
- package/src/blueprints/utilities/region.css +12 -0
- package/src/blueprints/utilities/visually-hidden.css +18 -0
- package/src/blueprints/viewports.json +10 -0
- package/src/generators/index.js +401 -0
- package/src/preview-layout.html +14 -0
- package/src/templates/compositions/cluster/description.html +7 -0
- package/src/templates/compositions/cluster/index.html +7 -0
- package/src/templates/compositions/flow/description.html +8 -0
- package/src/templates/compositions/flow/index.html +6 -0
- package/src/templates/compositions/grid/description.html +12 -0
- package/src/templates/compositions/grid/index.html +7 -0
- package/src/templates/compositions/prose/description.html +8 -0
- package/src/templates/compositions/prose/index.html +6 -0
- package/src/templates/compositions/repel/description.html +9 -0
- package/src/templates/compositions/repel/index.html +4 -0
- package/src/templates/compositions/sidebar/description.html +13 -0
- package/src/templates/compositions/sidebar/index.html +4 -0
- package/src/templates/compositions/switcher/description.html +8 -0
- package/src/templates/compositions/switcher/index.html +29 -0
- package/src/templates/compositions/wrapper/description.html +8 -0
- package/src/templates/compositions/wrapper/index.html +5 -0
- package/src/templates/prose.html +366 -0
- package/src/templates/script.js +44 -0
- package/src/templates/utilities/region/description.html +8 -0
- package/src/templates/utilities/region/index.html +5 -0
- package/src/templates/utilities/visually-hidden/description.html +7 -0
- package/src/templates/utilities/visually-hidden/index.html +7 -0
- package/src/tokens.js +428 -0
- package/src/utils/clamp-generator.js +38 -0
package/build.js
CHANGED
|
@@ -231,6 +231,26 @@ function buildInitManifest(settings) {
|
|
|
231
231
|
});
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
// Utility and composition display templates — walk each subfolder
|
|
235
|
+
for (const section of ["utilities", "compositions"]) {
|
|
236
|
+
const sectionSrc = path.join(templatesDir, section);
|
|
237
|
+
if (!fs.existsSync(sectionSrc)) continue;
|
|
238
|
+
const folders = fs.readdirSync(sectionSrc).filter(f =>
|
|
239
|
+
fs.statSync(path.join(sectionSrc, f)).isDirectory()
|
|
240
|
+
);
|
|
241
|
+
for (const folder of folders) {
|
|
242
|
+
const folderSrc = path.join(sectionSrc, folder);
|
|
243
|
+
const files = fs.readdirSync(folderSrc).filter(f => f.endsWith(".html"));
|
|
244
|
+
for (const file of files) {
|
|
245
|
+
manifest.push({
|
|
246
|
+
src: path.join(folderSrc, file),
|
|
247
|
+
dest: path.join(settings.swatchkitDir, section, folder, file),
|
|
248
|
+
transform: (content) => content.trim(),
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
234
254
|
// CSS entry point
|
|
235
255
|
manifest.push({
|
|
236
256
|
src: path.join(blueprintsDir, "main.css"),
|
|
@@ -279,6 +299,8 @@ function getInitDirs(settings) {
|
|
|
279
299
|
settings.swatchkitDir,
|
|
280
300
|
settings.tokensDir,
|
|
281
301
|
path.join(settings.swatchkitDir, "tokens"),
|
|
302
|
+
path.join(settings.swatchkitDir, "utilities"),
|
|
303
|
+
path.join(settings.swatchkitDir, "compositions"),
|
|
282
304
|
settings.cssDir,
|
|
283
305
|
path.join(settings.cssDir, "global"),
|
|
284
306
|
];
|
|
@@ -544,7 +566,7 @@ function scanSwatches(dir, scriptsCollector, exclude = []) {
|
|
|
544
566
|
const itemPath = path.join(dir, item);
|
|
545
567
|
const stat = fs.statSync(itemPath);
|
|
546
568
|
|
|
547
|
-
let name, content, id;
|
|
569
|
+
let name, content, id, description;
|
|
548
570
|
|
|
549
571
|
// Handle Component Directory
|
|
550
572
|
if (stat.isDirectory()) {
|
|
@@ -555,6 +577,12 @@ function scanSwatches(dir, scriptsCollector, exclude = []) {
|
|
|
555
577
|
id = item;
|
|
556
578
|
content = fs.readFileSync(indexFile, "utf-8");
|
|
557
579
|
|
|
580
|
+
// Optional description shown above the iframe in the main UI
|
|
581
|
+
const descriptionFile = path.join(itemPath, "description.html");
|
|
582
|
+
if (fs.existsSync(descriptionFile)) {
|
|
583
|
+
description = fs.readFileSync(descriptionFile, "utf-8");
|
|
584
|
+
}
|
|
585
|
+
|
|
558
586
|
// Find all .js files
|
|
559
587
|
const jsFiles = fs
|
|
560
588
|
.readdirSync(itemPath)
|
|
@@ -594,7 +622,7 @@ ${scriptContent}
|
|
|
594
622
|
}
|
|
595
623
|
|
|
596
624
|
if (name && content) {
|
|
597
|
-
swatches.push({ name, id, content });
|
|
625
|
+
swatches.push({ name, id, content, description: description || null });
|
|
598
626
|
}
|
|
599
627
|
});
|
|
600
628
|
|
|
@@ -791,6 +819,7 @@ function build(settings) {
|
|
|
791
819
|
return `
|
|
792
820
|
<section id="${p.id}" class="region flow">
|
|
793
821
|
<h2>${p.name} <small style="font-weight: normal; opacity: 0.6; font-size: 0.7em">(${section})</small></h2>
|
|
822
|
+
${p.description ? `<div class="swatch-description">${p.description}</div>` : ''}
|
|
794
823
|
<iframe src="${previewPath}" style="width: 100%; border: var(--stroke); min-height: 25rem; resize: vertical; overflow: auto;"></iframe>
|
|
795
824
|
<div class="swatchkit-preview-link"><a href="${previewLink}">View full screen</a></div>
|
|
796
825
|
<details>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swatchkit",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "A lightweight tool for creating HTML pattern libraries.",
|
|
5
5
|
"main": "build.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"build.js",
|
|
11
|
-
"src/
|
|
11
|
+
"src/"
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"start": "node build.js",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Colors",
|
|
3
|
+
"description": "Hex color codes that can be shared, cross-platform. They can be converted at point of usage, such as HSL for web or CMYK for print.",
|
|
4
|
+
"items": [
|
|
5
|
+
{ "name": "color-dark", "value": "#1a2420" },
|
|
6
|
+
{ "name": "color-dark-glare", "value": "#2d3830" },
|
|
7
|
+
{ "name": "color-mid", "value": "#8a9a8e" },
|
|
8
|
+
{ "name": "color-light", "value": "#f8faf7" },
|
|
9
|
+
{ "name": "color-primary", "value": "#e07a5f" }
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
CLUSTER
|
|
3
|
+
Distributes items with consistent spacing, regardless of their size.
|
|
4
|
+
|
|
5
|
+
Credit: Adapted from Every Layout (The Cluster)
|
|
6
|
+
Docs: https://every-layout.dev/layouts/cluster/
|
|
7
|
+
|
|
8
|
+
CUSTOM PROPERTIES:
|
|
9
|
+
--gutter: Space between items (default: --space-m)
|
|
10
|
+
--cluster-horizontal-alignment: Horizontal alignment (default: flex-start)
|
|
11
|
+
--cluster-vertical-alignment: Vertical alignment (default: center)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
.cluster {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-wrap: wrap;
|
|
17
|
+
gap: var(--gutter, var(--space-m));
|
|
18
|
+
justify-content: var(--cluster-horizontal-alignment, flex-start);
|
|
19
|
+
align-items: var(--cluster-vertical-alignment, center);
|
|
20
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto Grid Swatch
|
|
3
|
+
*
|
|
4
|
+
* A flexible layout that creates an auto-filling grid with configurable item sizes.
|
|
5
|
+
* Implements the "RAM" (Repeat, Auto, Minmax) pattern to adapt without media queries.
|
|
6
|
+
*
|
|
7
|
+
* Related: https://every-layout.dev/layouts/grid/
|
|
8
|
+
*
|
|
9
|
+
* Usage: <div class="grid">...</div>
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
.grid {
|
|
13
|
+
/*
|
|
14
|
+
* --gutter: Space between items
|
|
15
|
+
* --grid-min-item-size: Minimum width of an item before wrapping
|
|
16
|
+
* --grid-placement: auto-fill (default) or auto-fit
|
|
17
|
+
*/
|
|
18
|
+
display: grid;
|
|
19
|
+
grid-template-columns: repeat(
|
|
20
|
+
var(--grid-placement, auto-fill),
|
|
21
|
+
minmax(var(--grid-min-item-size, 16rem), 1fr)
|
|
22
|
+
);
|
|
23
|
+
gap: var(--gutter, var(--space-l));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* A split 50/50 layout */
|
|
27
|
+
.grid[data-layout="50-50"] {
|
|
28
|
+
--grid-placement: auto-fit;
|
|
29
|
+
--grid-min-item-size: clamp(16rem, 50vw, 33rem);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Three column grid layout */
|
|
33
|
+
.grid[data-layout="thirds"] {
|
|
34
|
+
--grid-placement: auto-fit;
|
|
35
|
+
--grid-min-item-size: clamp(16rem, 33%, 20rem);
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/* === CSS Compositions === */
|
|
2
|
+
|
|
3
|
+
/* Layout primitives based on CUBE CSS / Every Layout */
|
|
4
|
+
|
|
5
|
+
@import "flow.css";
|
|
6
|
+
@import "sidebar.css";
|
|
7
|
+
@import "wrapper.css";
|
|
8
|
+
@import "cluster.css";
|
|
9
|
+
@import "repel.css";
|
|
10
|
+
@import "switcher.css";
|
|
11
|
+
@import "prose.css";
|
|
12
|
+
@import "grid.css";
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prose Swatch
|
|
3
|
+
*
|
|
4
|
+
* A CUBE CSS "Block" designed to optimize the reading experience for long-form content.
|
|
5
|
+
* It manages spacing, line length, and typography for a comfortable rhythm.
|
|
6
|
+
*
|
|
7
|
+
* Usage: <article class="prose flow">...</article>
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
.prose {
|
|
11
|
+
/* Increase flow spacing for better reading rhythm */
|
|
12
|
+
--flow-space: var(--space-l);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Prevent large headings from breaking layout on small screens.
|
|
17
|
+
* hyphenation and break-word handling ensures text wraps gracefully.
|
|
18
|
+
*/
|
|
19
|
+
.prose :is(h1, h2, h3) {
|
|
20
|
+
overflow-wrap: anywhere;
|
|
21
|
+
hyphens: auto;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Constrain line length for optimal readability (measure).
|
|
26
|
+
* text-wrap: pretty prevents orphans and awkward breaks.
|
|
27
|
+
*/
|
|
28
|
+
.prose :is(p, li, dl, figcaption, blockquote) {
|
|
29
|
+
max-width: 60ch;
|
|
30
|
+
text-wrap: pretty;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Reduce spacing after headings to visually group them with their content.
|
|
35
|
+
*/
|
|
36
|
+
.prose :is(h1, h2, h3, h4) + *:not([class]) {
|
|
37
|
+
--flow-space: var(--space-m);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Add more breathing room around heavy elements like figures and tables.
|
|
42
|
+
*/
|
|
43
|
+
.prose :is(figure, table),
|
|
44
|
+
.prose :is(figure, table) + * {
|
|
45
|
+
--flow-space: var(--space-2xl);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Add extra space before headings to clearly separate sections.
|
|
50
|
+
*/
|
|
51
|
+
.prose * + :is(h1, h2, h3, h4):not([class]) {
|
|
52
|
+
--flow-space: var(--space-xl);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Tighter spacing for list items to keep lists cohesive.
|
|
57
|
+
*/
|
|
58
|
+
.prose :is(ul, ol):not([class]) li + li,
|
|
59
|
+
.prose :is(ul, ol):not([class]) li > :is(ol, ul) {
|
|
60
|
+
--flow-space: var(--space-xs);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Horizontal rules act as major section breaks, so give them plenty of space.
|
|
65
|
+
*/
|
|
66
|
+
.prose hr {
|
|
67
|
+
--flow-space: var(--space-2xl);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Add a border to media elements to prevent them from blending into the background,
|
|
72
|
+
* especially in light mode.
|
|
73
|
+
*/
|
|
74
|
+
.prose :is(img, picture, video) {
|
|
75
|
+
border: var(--stroke-solid);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* On larger screens, relax the aggressive wrapping rules for headings.
|
|
80
|
+
* 47.5em matches 760px, the default 'viewport-mid' token.
|
|
81
|
+
* Preferring em here to catch the case where a user adjusts their browser default font size.
|
|
82
|
+
* Note: CSS variables cannot be used in media queries in standard CSS.
|
|
83
|
+
*/
|
|
84
|
+
@media (min-width: 47.5em) {
|
|
85
|
+
.prose :is(h1, h2, h3) {
|
|
86
|
+
overflow-wrap: unset;
|
|
87
|
+
hyphens: unset;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
REPEL
|
|
3
|
+
Pushes items away from each other where space allows, stacking on small viewports.
|
|
4
|
+
|
|
5
|
+
Credit: Adapted from Every Layout (The Cluster)
|
|
6
|
+
Docs: https://every-layout.dev/layouts/cluster/
|
|
7
|
+
|
|
8
|
+
CUSTOM PROPERTIES:
|
|
9
|
+
--gutter: Space between items (default: --space-m)
|
|
10
|
+
--repel-vertical-alignment: Vertical alignment (default: center)
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
.repel {
|
|
14
|
+
display: flex;
|
|
15
|
+
flex-wrap: wrap;
|
|
16
|
+
justify-content: space-between;
|
|
17
|
+
align-items: var(--repel-vertical-alignment, center);
|
|
18
|
+
gap: var(--gutter, var(--space-m));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.repel[data-nowrap] {
|
|
22
|
+
flex-wrap: nowrap;
|
|
23
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
SIDEBAR
|
|
3
|
+
Layout with a flexible main content area and a fixed-width sidebar.
|
|
4
|
+
|
|
5
|
+
Credit: Adapted from Every Layout (The Sidebar)
|
|
6
|
+
Docs: https://every-layout.dev/layouts/sidebar/
|
|
7
|
+
|
|
8
|
+
CUSTOM PROPERTIES:
|
|
9
|
+
--gutter: Space between sidebar and content (default: --space-s-l)
|
|
10
|
+
--sidebar-target-width: Target width of sidebar (default: 20rem)
|
|
11
|
+
--sidebar-content-min-width: Min width of content before stacking (default: 50%)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
.sidebar {
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-wrap: wrap;
|
|
17
|
+
gap: var(--gutter, var(--space-s-l));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.sidebar:not([data-direction]) > :first-child {
|
|
21
|
+
flex-basis: var(--sidebar-target-width, 20rem);
|
|
22
|
+
flex-grow: 1;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.sidebar:not([data-direction]) > :last-child {
|
|
26
|
+
flex-basis: 0;
|
|
27
|
+
flex-grow: 999;
|
|
28
|
+
min-width: var(--sidebar-content-min-width, 50%);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.sidebar[data-reversed] {
|
|
32
|
+
flex-direction: row-reverse;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.sidebar[data-direction="rtl"] > :last-child {
|
|
36
|
+
flex-basis: var(--sidebar-target-width, 20rem);
|
|
37
|
+
flex-grow: 1;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.sidebar[data-direction="rtl"] > :first-child {
|
|
41
|
+
flex-basis: 0;
|
|
42
|
+
flex-grow: 999;
|
|
43
|
+
min-width: var(--sidebar-content-min-width, 50%);
|
|
44
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
SWITCHER
|
|
3
|
+
Lays out items horizontally until there is insufficient space, then stacks them.
|
|
4
|
+
Optimized for 3 items.
|
|
5
|
+
|
|
6
|
+
Credit: Adapted from Every Layout (The Switcher)
|
|
7
|
+
Docs: https://every-layout.dev/layouts/switcher/
|
|
8
|
+
|
|
9
|
+
CUSTOM PROPERTIES:
|
|
10
|
+
--gutter: Space between items (default: --space-l)
|
|
11
|
+
--switcher-target-container-width: Container breakpoint width (default: 40rem)
|
|
12
|
+
--switcher-vertical-alignment: Vertical alignment (default: flex-start)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
.switcher {
|
|
16
|
+
display: flex;
|
|
17
|
+
flex-wrap: wrap;
|
|
18
|
+
gap: var(--gutter, var(--space-l));
|
|
19
|
+
align-items: var(--switcher-vertical-alignment, flex-start);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.switcher > * {
|
|
23
|
+
flex-grow: 1;
|
|
24
|
+
flex-basis: calc(
|
|
25
|
+
(var(--switcher-target-container-width, 40rem) - 100%) * 999
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Max 3 items, so anything greater than 3 is full width */
|
|
30
|
+
.switcher > :nth-child(n + 4) {
|
|
31
|
+
flex-basis: 100%;
|
|
32
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
WRAPPER
|
|
3
|
+
|
|
4
|
+
Credit: More or less, adapted from Every Layout (The Center)
|
|
5
|
+
Docs: https://every-layout.dev/layouts/center/
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
.wrapper {
|
|
9
|
+
margin-inline: auto;
|
|
10
|
+
max-inline-size: var(--wrapper-max-width, 1360px);
|
|
11
|
+
padding-inline-start: var(--gutter);
|
|
12
|
+
padding-inline-end: var(--gutter);
|
|
13
|
+
position: relative;
|
|
14
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "Fonts",
|
|
3
|
+
"description": "Each array of fonts creates a priority-based order. The first font in the array should be the ideal font, followed by sensible, web-safe fallbacks",
|
|
4
|
+
"items": [
|
|
5
|
+
{
|
|
6
|
+
"name": "font-base",
|
|
7
|
+
"description": "System fonts for body copy and globally set text.",
|
|
8
|
+
"value": [
|
|
9
|
+
"Satoshi",
|
|
10
|
+
"Inter",
|
|
11
|
+
"Segoe UI",
|
|
12
|
+
"Roboto",
|
|
13
|
+
"Helvetica Neue",
|
|
14
|
+
"Arial",
|
|
15
|
+
"sans-serif"
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"name": "font-mono",
|
|
20
|
+
"description": "Monospace font for code samples etc",
|
|
21
|
+
"value": ["DM Mono", "monospace"]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
}
|