@syncedco/flow 0.1.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.
Files changed (90) hide show
  1. package/CODE_OF_CONDUCT.md +26 -0
  2. package/CONTRIBUTING.md +54 -0
  3. package/LICENSE +21 -0
  4. package/README.md +334 -0
  5. package/SECURITY.md +30 -0
  6. package/SUPPORT.md +32 -0
  7. package/TRADEMARKS.md +14 -0
  8. package/base.css +100 -0
  9. package/bin/synced-flow.mjs +4639 -0
  10. package/components.css +1392 -0
  11. package/defaults.css +26 -0
  12. package/dist/config.d.ts +94 -0
  13. package/dist/config.js +3 -0
  14. package/dist/index.d.ts +45 -0
  15. package/dist/index.js +67 -0
  16. package/docs/accessibility-css.md +133 -0
  17. package/docs/ai-usage.md +112 -0
  18. package/docs/api-contract.md +81 -0
  19. package/docs/base-styling.md +113 -0
  20. package/docs/build-a-site-walkthrough.md +122 -0
  21. package/docs/cli-reference.md +230 -0
  22. package/docs/config-reference.md +81 -0
  23. package/docs/css-optimisation.md +117 -0
  24. package/docs/migration-from-tailwind.md +60 -0
  25. package/docs/native-components.md +156 -0
  26. package/docs/patterns.md +32 -0
  27. package/docs/presets.md +60 -0
  28. package/docs/quick-start.md +252 -0
  29. package/docs/recipes.md +285 -0
  30. package/docs/release-readiness.md +63 -0
  31. package/docs/system-primitives.md +150 -0
  32. package/docs/tailwind-comparison.md +66 -0
  33. package/docs/tokens.md +79 -0
  34. package/docs/website-patterns.md +114 -0
  35. package/docs/why-synced-flow.md +99 -0
  36. package/docs/wordpress.md +66 -0
  37. package/examples/README.md +16 -0
  38. package/examples/astro/package.json +19 -0
  39. package/examples/astro/src/pages/index.astro +85 -0
  40. package/examples/astro/src/styles/synced-flow.css +2 -0
  41. package/examples/astro/src/styles/synced-flow.generated.css +206 -0
  42. package/examples/astro/synced-flow.config.mjs +9 -0
  43. package/examples/next/app/layout.tsx +14 -0
  44. package/examples/next/app/page.tsx +92 -0
  45. package/examples/next/app/synced-flow.css +2 -0
  46. package/examples/next/app/synced-flow.generated.css +205 -0
  47. package/examples/next/package.json +19 -0
  48. package/examples/next/synced-flow.config.mjs +9 -0
  49. package/examples/plain-html/index.html +384 -0
  50. package/examples/plain-html/package.json +15 -0
  51. package/examples/plain-html/synced-flow.config.mjs +9 -0
  52. package/examples/plain-html/synced-flow.css +2 -0
  53. package/examples/plain-html/synced-flow.generated.css +205 -0
  54. package/examples/templates/README.md +22 -0
  55. package/examples/templates/blog-index.html +41 -0
  56. package/examples/templates/coming-soon.html +27 -0
  57. package/examples/templates/portfolio-scroll.html +45 -0
  58. package/examples/templates/saas-dashboard.html +171 -0
  59. package/examples/templates/saas-landing.html +104 -0
  60. package/examples/vite/index.html +2 -0
  61. package/examples/vite/package.json +20 -0
  62. package/examples/vite/src/main.jsx +27 -0
  63. package/examples/vite/src/synced-flow.css +2 -0
  64. package/examples/vite/src/synced-flow.generated.css +205 -0
  65. package/examples/vite/synced-flow.config.mjs +9 -0
  66. package/examples/wordpress/assets/css/synced-flow.css +641 -0
  67. package/examples/wordpress/functions.php +13 -0
  68. package/examples/wordpress/package.json +15 -0
  69. package/examples/wordpress/parts/footer.html +12 -0
  70. package/examples/wordpress/parts/header.html +10 -0
  71. package/examples/wordpress/patterns/contact-cta.php +28 -0
  72. package/examples/wordpress/patterns/feature-grid.php +38 -0
  73. package/examples/wordpress/patterns/landing-hero.php +45 -0
  74. package/examples/wordpress/synced-flow.config.mjs +11 -0
  75. package/examples/wordpress/templates/front-page.html +11 -0
  76. package/examples/wordpress/templates/index.html +27 -0
  77. package/examples/wordpress/theme.json +19 -0
  78. package/layout.css +365 -0
  79. package/package.json +93 -0
  80. package/reset.css +13 -0
  81. package/skills/synced-flow/SKILL.md +151 -0
  82. package/src/config.ts +98 -0
  83. package/src/index.ts +75 -0
  84. package/src/presets.d.mts +21 -0
  85. package/src/presets.mjs +171 -0
  86. package/src/tokens.mjs +138 -0
  87. package/src/utility-tokens.mjs +47 -0
  88. package/styles.css +2313 -0
  89. package/tokens.css +198 -0
  90. package/utilities.css +255 -0
@@ -0,0 +1,28 @@
1
+ <?php
2
+ /**
3
+ * Title: Synced Flow contact CTA
4
+ * Slug: synced-flow/contact-cta
5
+ * Categories: synced-flow
6
+ */
7
+ ?>
8
+ <!-- wp:group {"tagName":"section","className":"sf-section","anchor":"contact"} -->
9
+ <section class="wp-block-group sf-section" id="contact">
10
+ <!-- wp:group {"className":"sf-container sf-cta"} -->
11
+ <div class="wp-block-group sf-container sf-cta">
12
+ <!-- wp:heading {"className":"sf-text-h2"} -->
13
+ <h2 class="sf-text-h2">Ready to build a WordPress site with Synced Flow?</h2>
14
+ <!-- /wp:heading -->
15
+ <!-- wp:paragraph {"className":"sf-prose"} -->
16
+ <p class="sf-prose">Use this pattern as a starting point for contact, booking, or newsletter sections.</p>
17
+ <!-- /wp:paragraph -->
18
+ <!-- wp:buttons {"className":"sf-cluster"} -->
19
+ <div class="wp-block-buttons sf-cluster">
20
+ <!-- wp:button {"className":"sf-button sf-button--default"} -->
21
+ <div class="wp-block-button sf-button sf-button--default"><a class="wp-block-button__link wp-element-button" href="mailto:hello@example.com">Contact us</a></div>
22
+ <!-- /wp:button -->
23
+ </div>
24
+ <!-- /wp:buttons -->
25
+ </div>
26
+ <!-- /wp:group -->
27
+ </section>
28
+ <!-- /wp:group -->
@@ -0,0 +1,38 @@
1
+ <?php
2
+ /**
3
+ * Title: Synced Flow feature grid
4
+ * Slug: synced-flow/feature-grid
5
+ * Categories: synced-flow
6
+ */
7
+ ?>
8
+ <!-- wp:group {"tagName":"section","className":"sf-section"} -->
9
+ <section class="wp-block-group sf-section">
10
+ <!-- wp:group {"className":"sf-container sf-stack"} -->
11
+ <div class="wp-block-group sf-container sf-stack">
12
+ <!-- wp:group {"className":"sf-section-header"} -->
13
+ <div class="wp-block-group sf-section-header">
14
+ <!-- wp:paragraph {"className":"sf-kicker"} -->
15
+ <p class="sf-kicker">Patterns</p>
16
+ <!-- /wp:paragraph -->
17
+ <!-- wp:heading {"className":"sf-text-h2"} -->
18
+ <h2 class="sf-text-h2">Use block markup with Synced Flow classes.</h2>
19
+ <!-- /wp:heading -->
20
+ </div>
21
+ <!-- /wp:group -->
22
+ <!-- wp:group {"className":"sf-auto-grid"} -->
23
+ <div class="wp-block-group sf-auto-grid">
24
+ <!-- wp:group {"className":"sf-card sf-card--interactive sf-stack"} -->
25
+ <article class="wp-block-group sf-card sf-card--interactive sf-stack"><h3 class="sf-text-h4">Templates</h3><p class="sf-text-muted">Scan block template HTML.</p></article>
26
+ <!-- /wp:group -->
27
+ <!-- wp:group {"className":"sf-card sf-card--interactive sf-stack"} -->
28
+ <article class="wp-block-group sf-card sf-card--interactive sf-stack"><h3 class="sf-text-h4">Patterns</h3><p class="sf-text-muted">Scan PHP patterns and includes.</p></article>
29
+ <!-- /wp:group -->
30
+ <!-- wp:group {"className":"sf-card sf-card--interactive sf-stack"} -->
31
+ <article class="wp-block-group sf-card sf-card--interactive sf-stack"><h3 class="sf-text-h4">Guardrails</h3><p class="sf-text-muted">Run build, lint, and doctor before release.</p></article>
32
+ <!-- /wp:group -->
33
+ </div>
34
+ <!-- /wp:group -->
35
+ </div>
36
+ <!-- /wp:group -->
37
+ </section>
38
+ <!-- /wp:group -->
@@ -0,0 +1,45 @@
1
+ <?php
2
+ /**
3
+ * Title: Synced Flow landing hero
4
+ * Slug: synced-flow/landing-hero
5
+ * Categories: synced-flow
6
+ */
7
+ ?>
8
+ <!-- wp:group {"tagName":"section","className":"sf-section"} -->
9
+ <section class="wp-block-group sf-section">
10
+ <!-- wp:group {"className":"sf-container sf-split"} -->
11
+ <div class="wp-block-group sf-container sf-split">
12
+ <!-- wp:group {"className":"sf-stack"} -->
13
+ <div class="wp-block-group sf-stack">
14
+ <!-- wp:paragraph {"className":"sf-kicker"} -->
15
+ <p class="sf-kicker">WordPress ready</p>
16
+ <!-- /wp:paragraph -->
17
+ <!-- wp:heading {"level":1,"className":"sf-text-display"} -->
18
+ <h1 class="sf-text-display">A fluid WordPress front page without page-specific CSS.</h1>
19
+ <!-- /wp:heading -->
20
+ <!-- wp:paragraph {"className":"sf-text-lead sf-prose"} -->
21
+ <p class="sf-text-lead sf-prose">Use Synced Flow classes in block templates, parts, and PHP patterns.</p>
22
+ <!-- /wp:paragraph -->
23
+ <!-- wp:buttons {"className":"sf-cluster"} -->
24
+ <div class="wp-block-buttons sf-cluster">
25
+ <!-- wp:button {"className":"sf-button sf-button--default"} -->
26
+ <div class="wp-block-button sf-button sf-button--default"><a class="wp-block-button__link wp-element-button" href="#contact">Start a project</a></div>
27
+ <!-- /wp:button -->
28
+ </div>
29
+ <!-- /wp:buttons -->
30
+ </div>
31
+ <!-- /wp:group -->
32
+ <!-- wp:group {"className":"sf-card sf-stack"} -->
33
+ <div class="wp-block-group sf-card sf-stack">
34
+ <!-- wp:paragraph {"className":"sf-badge"} -->
35
+ <p class="sf-badge">Included</p>
36
+ <!-- /wp:paragraph -->
37
+ <!-- wp:list {"className":"sf-list-disc"} -->
38
+ <ul class="sf-list-disc"><li>enqueue-ready CSS</li><li>block theme templates</li><li>PHP pattern scanning</li></ul>
39
+ <!-- /wp:list -->
40
+ </div>
41
+ <!-- /wp:group -->
42
+ </div>
43
+ <!-- /wp:group -->
44
+ </section>
45
+ <!-- /wp:group -->
@@ -0,0 +1,11 @@
1
+ import { defineConfig } from '@syncedco/flow/config'
2
+ import { themePresets } from '@syncedco/flow/presets'
3
+
4
+ export default defineConfig({
5
+ scan: ['templates', 'parts', 'patterns', 'assets'],
6
+ out: 'assets/css/synced-flow.css',
7
+ includeCore: true,
8
+ includeDefaults: true,
9
+ responsiveVariants: false,
10
+ theme: themePresets.synced,
11
+ })
@@ -0,0 +1,11 @@
1
+ <!-- wp:template-part {"slug":"header","tagName":"header"} /-->
2
+
3
+ <!-- wp:main {"className":"sf-stack"} -->
4
+ <main class="sf-stack">
5
+ <!-- wp:pattern {"slug":"synced-flow/landing-hero"} /-->
6
+ <!-- wp:pattern {"slug":"synced-flow/feature-grid"} /-->
7
+ <!-- wp:pattern {"slug":"synced-flow/contact-cta"} /-->
8
+ </main>
9
+ <!-- /wp:main -->
10
+
11
+ <!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
@@ -0,0 +1,27 @@
1
+ <!-- wp:template-part {"slug":"header","tagName":"header"} /-->
2
+
3
+ <!-- wp:group {"tagName":"main","className":"sf-section"} -->
4
+ <main class="wp-block-group sf-section">
5
+ <!-- wp:group {"className":"sf-container sf-stack"} -->
6
+ <div class="wp-block-group sf-container sf-stack">
7
+ <!-- wp:query-title {"type":"archive","className":"sf-text-display"} /-->
8
+ <!-- wp:query {"query":{"perPage":6,"pages":0,"offset":0,"postType":"post","order":"desc","orderBy":"date"}} -->
9
+ <div class="wp-block-query">
10
+ <!-- wp:post-template {"className":"sf-auto-grid"} -->
11
+ <!-- wp:group {"tagName":"article","className":"sf-card sf-card--interactive sf-stack"} -->
12
+ <article class="wp-block-group sf-card sf-card--interactive sf-stack">
13
+ <!-- wp:post-date {"className":"sf-meta"} /-->
14
+ <!-- wp:post-title {"isLink":true,"className":"sf-text-h4"} /-->
15
+ <!-- wp:post-excerpt {"className":"sf-text-muted"} /-->
16
+ </article>
17
+ <!-- /wp:group -->
18
+ <!-- /wp:post-template -->
19
+ <!-- wp:query-pagination {"className":"sf-pagination"} /-->
20
+ </div>
21
+ <!-- /wp:query -->
22
+ </div>
23
+ <!-- /wp:group -->
24
+ </main>
25
+ <!-- /wp:group -->
26
+
27
+ <!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
@@ -0,0 +1,19 @@
1
+ {
2
+ "$schema": "https://schemas.wp.org/trunk/theme.json",
3
+ "version": 3,
4
+ "settings": {
5
+ "appearanceTools": true,
6
+ "layout": {
7
+ "contentSize": "72rem",
8
+ "wideSize": "90rem"
9
+ }
10
+ },
11
+ "styles": {
12
+ "spacing": {
13
+ "blockGap": "var(--space-s-l)"
14
+ },
15
+ "typography": {
16
+ "fontFamily": "var(--sf-font-sans)"
17
+ }
18
+ }
19
+ }
package/layout.css ADDED
@@ -0,0 +1,365 @@
1
+ /* Generated by @syncedco/flow. Edit src/tokens.mjs or scripts/build-css.mjs, then run pnpm build. */
2
+ @layer reset, tokens, base, app, layout, components, utilities;
3
+ @layer layout {
4
+ .sf-container {
5
+ inline-size: min(100% - (var(--sf-gutter) * 2), var(--sf-container-max));
6
+ margin-inline: auto;
7
+ }
8
+
9
+ .sf-container--narrow { --sf-container-max: var(--sf-container-narrow); }
10
+ .sf-container--wide { --sf-container-max: var(--sf-container-wide); }
11
+ .sf-container--full { --sf-container-max: 100%; }
12
+
13
+ .sf-rail-shell {
14
+ --sf-rail-size: 4.25rem;
15
+ min-block-size: 100svh;
16
+ }
17
+
18
+ .sf-rail-shell__body {
19
+ min-inline-size: 0;
20
+ }
21
+
22
+ .sf-rail-shell__rail {
23
+ align-items: center;
24
+ background:
25
+ repeating-linear-gradient(-45deg, color-mix(in oklch, var(--sf-colour-foreground) 9%, transparent) 0 .0625rem, transparent .0625rem .4375rem),
26
+ color-mix(in oklch, var(--sf-colour-background) 92%, black);
27
+ border-inline-end: 1px solid var(--sf-colour-border);
28
+ display: none;
29
+ justify-items: center;
30
+ }
31
+
32
+ .sf-rail-shell__mark,
33
+ .sf-rail-shell__label {
34
+ color: var(--sf-colour-primary);
35
+ font-weight: 900;
36
+ }
37
+
38
+ .sf-rail-shell__label {
39
+ font-family: var(--sf-font-mono);
40
+ font-size: var(--sf-step--2);
41
+ letter-spacing: .18em;
42
+ text-transform: uppercase;
43
+ transform: rotate(-90deg);
44
+ white-space: nowrap;
45
+ }
46
+
47
+ .sf-rail-shell__label::before {
48
+ background: currentColor;
49
+ block-size: .25rem;
50
+ border-radius: var(--sf-radius-full);
51
+ box-shadow: 0 0 .875rem currentColor;
52
+ content: "";
53
+ display: inline-block;
54
+ inline-size: .25rem;
55
+ margin-inline-end: var(--sf-space-xs);
56
+ }
57
+
58
+ .sf-section { padding-block: var(--sf-section-space, var(--sf-region)); }
59
+ .sf-section--compact { --sf-section-space: var(--sf-space-l-xl); }
60
+ .sf-section--spacious { --sf-section-space: var(--sf-space-2xl-3xl); }
61
+
62
+ .sf-stack {
63
+ display: flex;
64
+ flex-direction: column;
65
+ gap: var(--sf-stack-space, var(--sf-space-s));
66
+ }
67
+
68
+ .sf-stack--tight { --sf-stack-space: var(--sf-space-2xs-xs); }
69
+ .sf-stack--loose { --sf-stack-space: var(--sf-space-m-xl); }
70
+
71
+ .sf-flow > * + * { margin-block-start: var(--sf-flow-space, var(--sf-space-s)); }
72
+
73
+ .sf-cluster {
74
+ align-items: var(--sf-cluster-align, center);
75
+ display: flex;
76
+ flex-wrap: wrap;
77
+ gap: var(--sf-cluster-space, var(--sf-space-s));
78
+ justify-content: var(--sf-cluster-justify, flex-start);
79
+ }
80
+
81
+ .sf-repel {
82
+ align-items: center;
83
+ display: flex;
84
+ flex-wrap: wrap;
85
+ gap: var(--sf-space-s);
86
+ justify-content: space-between;
87
+ }
88
+
89
+ .sf-toolbar {
90
+ align-items: center;
91
+ display: flex;
92
+ flex-wrap: wrap;
93
+ gap: var(--sf-space-s);
94
+ justify-content: space-between;
95
+ }
96
+
97
+ .sf-app-shell {
98
+ background: var(--sf-colour-background);
99
+ color: var(--sf-colour-foreground);
100
+ display: grid;
101
+ grid-template-columns: minmax(14rem, var(--sf-app-sidebar-width, 16rem)) minmax(0, 1fr);
102
+ min-block-size: 100dvh;
103
+ }
104
+
105
+ .sf-app-sidebar {
106
+ align-self: start;
107
+ background: var(--sf-colour-surface);
108
+ border-inline-end: 1px solid var(--sf-colour-border);
109
+ display: flex;
110
+ flex-direction: column;
111
+ gap: var(--sf-space-s);
112
+ max-block-size: 100dvh;
113
+ min-block-size: 100dvh;
114
+ overflow: auto;
115
+ padding: var(--sf-space-s);
116
+ position: sticky;
117
+ inset-block-start: 0;
118
+ }
119
+
120
+ .sf-app-sidebar__brand {
121
+ align-items: center;
122
+ display: flex;
123
+ gap: var(--sf-space-xs);
124
+ padding-block-end: var(--sf-space-s);
125
+ }
126
+
127
+ .sf-app-sidebar > footer {
128
+ border-block-start: 1px solid var(--sf-colour-border);
129
+ padding-block-start: var(--sf-space-s);
130
+ }
131
+
132
+ .sf-app-main {
133
+ min-inline-size: 0;
134
+ padding: var(--sf-app-main-padding, var(--sf-space-m-l));
135
+ }
136
+
137
+ .sf-grid {
138
+ display: grid;
139
+ gap: var(--sf-grid-gap, var(--sf-gutter));
140
+ grid-template-columns: repeat(var(--sf-grid-columns), minmax(0, 1fr));
141
+ }
142
+
143
+ .sf-grid--2 { --sf-grid-columns: 2; }
144
+ .sf-grid--3 { --sf-grid-columns: 3; }
145
+ .sf-grid--4 { --sf-grid-columns: 4; }
146
+
147
+ .sf-auto-grid {
148
+ display: grid;
149
+ gap: var(--sf-grid-gap, var(--sf-gutter));
150
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sf-auto-grid-min, 16rem)), 1fr));
151
+ }
152
+
153
+ .sf-auto-grid--xs { --sf-auto-grid-min: 8rem; }
154
+ .sf-auto-grid--sm { --sf-auto-grid-min: 12rem; }
155
+ .sf-auto-grid--lg { --sf-auto-grid-min: 20rem; }
156
+
157
+ .sf-split {
158
+ display: grid;
159
+ gap: var(--sf-split-gap, var(--sf-gutter));
160
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sf-split-min, 24rem)), 1fr));
161
+ }
162
+
163
+ .sf-split--reverse > :first-child { order: 2; }
164
+ .sf-split--reverse > :last-child { order: 1; }
165
+
166
+ .sf-centre {
167
+ box-sizing: content-box;
168
+ margin-inline: auto;
169
+ max-inline-size: var(--sf-centre-size, 65ch);
170
+ }
171
+
172
+ .sf-centre--narrow { --sf-centre-size: 48ch; }
173
+ .sf-centre--wide { --sf-centre-size: 80ch; }
174
+
175
+ .sf-sidebar {
176
+ display: flex;
177
+ flex-wrap: wrap;
178
+ gap: var(--sf-gutter);
179
+ }
180
+
181
+ .sf-sidebar > :first-child {
182
+ flex-basis: var(--sf-sidebar-width, 20rem);
183
+ flex-grow: 1;
184
+ }
185
+
186
+ .sf-sidebar > :last-child {
187
+ flex-basis: 0;
188
+ flex-grow: 999;
189
+ min-inline-size: min(100%, var(--sf-sidebar-content-min, 50%));
190
+ }
191
+
192
+ .sf-switcher {
193
+ display: flex;
194
+ flex-wrap: wrap;
195
+ gap: var(--sf-gutter);
196
+ }
197
+
198
+ .sf-switcher > * {
199
+ flex-basis: calc((var(--sf-switcher-threshold, 42rem) - 100%) * 999);
200
+ flex-grow: 1;
201
+ }
202
+
203
+ .sf-frame {
204
+ aspect-ratio: var(--sf-frame-ratio, 16 / 9);
205
+ overflow: hidden;
206
+ }
207
+
208
+ .sf-frame > :where(img, video, iframe) {
209
+ block-size: 100%;
210
+ inline-size: 100%;
211
+ object-fit: cover;
212
+ }
213
+
214
+ .sf-frame--square { --sf-frame-ratio: 1; }
215
+ .sf-frame--portrait { --sf-frame-ratio: 4 / 5; }
216
+ .sf-frame--wide { --sf-frame-ratio: 21 / 9; }
217
+
218
+ .sf-cover {
219
+ display: flex;
220
+ flex-direction: column;
221
+ min-block-size: var(--sf-cover-min, 100svh);
222
+ padding-block: var(--sf-region);
223
+ }
224
+
225
+ .sf-cover > :where(:first-child:not(.sf-cover__centre)) { margin-block-end: auto; }
226
+ .sf-cover > :where(:last-child:not(.sf-cover__centre)) { margin-block-start: auto; }
227
+
228
+ .sf-panel-grid {
229
+ container-type: inline-size;
230
+ display: grid;
231
+ gap: var(--sf-grid-gap, var(--sf-gutter));
232
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sf-panel-min, 18rem)), 1fr));
233
+ }
234
+
235
+ .sf-metric-grid,
236
+ .sf-pipeline {
237
+ display: grid;
238
+ gap: var(--sf-space-s);
239
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sf-panel-min, 11rem)), 1fr));
240
+ }
241
+
242
+ .sf-pipeline {
243
+ --sf-panel-min: 10rem;
244
+ }
245
+
246
+ .sf-scroll-viewport,
247
+ .sf-scroll-snap-y {
248
+ block-size: var(--sf-scroll-viewport-size, 100svh);
249
+ overflow-y: auto;
250
+ scroll-padding-block: var(--sf-scroll-padding, var(--sf-space-l));
251
+ scroll-snap-type: y proximity;
252
+ }
253
+
254
+ :where(.sf-scroll-viewport, .sf-scroll-snap-y)[data-snap="mandatory"] {
255
+ --sf-scroll-snap-stop: always;
256
+ scroll-snap-type: y mandatory;
257
+ }
258
+ .sf-scroll-viewport[data-size="preview"] {
259
+ --sf-scroll-margin: 0;
260
+ --sf-scroll-padding: 0;
261
+ --sf-scroll-viewport-size: min(32rem, 80svh);
262
+ --sf-scroll-panel-min: min(32rem, 80svh);
263
+ }
264
+
265
+ .sf-scroll-panel {
266
+ align-content: center;
267
+ display: grid;
268
+ min-block-size: var(--sf-scroll-panel-min, 100svh);
269
+ scroll-margin-block: var(--sf-scroll-margin, var(--sf-space-l));
270
+ scroll-snap-align: start;
271
+ scroll-snap-stop: var(--sf-scroll-snap-stop, normal);
272
+ }
273
+
274
+ .sf-sticky-top {
275
+ position: sticky;
276
+ inset-block-start: var(--sf-sticky-offset, 0);
277
+ z-index: var(--sf-sticky-z, 20);
278
+ }
279
+
280
+ .sf-media-object {
281
+ align-items: var(--sf-media-object-align, start);
282
+ display: grid;
283
+ gap: var(--sf-space-s-m);
284
+ grid-template-columns: auto minmax(0, 1fr);
285
+ }
286
+
287
+ .sf-aside-rail {
288
+ display: grid;
289
+ gap: var(--sf-gutter);
290
+ grid-template-columns: minmax(0, 1fr);
291
+ }
292
+
293
+ .sf-chapter {
294
+ align-items: var(--sf-chapter-align, center);
295
+ display: grid;
296
+ gap: var(--sf-chapter-gap, var(--sf-space-xl-2xl));
297
+ grid-template-columns: minmax(0, 1fr);
298
+ }
299
+
300
+ .sf-chapter__copy {
301
+ max-inline-size: var(--sf-chapter-copy, 24rem);
302
+ }
303
+
304
+ @media (min-width: 48rem) {
305
+ .sf-rail-shell {
306
+ display: grid;
307
+ grid-template-columns: var(--sf-rail-size) minmax(0, 1fr);
308
+ }
309
+
310
+ .sf-rail-shell__rail {
311
+ block-size: 100svh;
312
+ display: grid;
313
+ grid-template-rows: 3.5rem repeat(var(--sf-rail-items, 5), 1fr);
314
+ inset-block-start: 0;
315
+ position: sticky;
316
+ }
317
+
318
+ .sf-aside-rail {
319
+ grid-template-columns: minmax(0, 1fr) minmax(14rem, 22rem);
320
+ }
321
+
322
+ .sf-aside-rail[data-rail="start"] {
323
+ grid-template-columns: minmax(14rem, 22rem) minmax(0, 1fr);
324
+ }
325
+
326
+ .sf-chapter {
327
+ grid-template-columns: minmax(18rem, .42fr) minmax(0, 1fr);
328
+ }
329
+ }
330
+
331
+ @media (max-width: 56rem) {
332
+ .sf-app-shell {
333
+ grid-template-columns: 1fr;
334
+ }
335
+
336
+ .sf-app-main {
337
+ --sf-app-main-padding: var(--sf-space-s);
338
+ }
339
+
340
+ .sf-app-sidebar {
341
+ border-block-end: 1px solid var(--sf-colour-border);
342
+ border-inline-end: 0;
343
+ max-block-size: none;
344
+ min-block-size: auto;
345
+ position: static;
346
+ }
347
+
348
+ .sf-app-sidebar > footer {
349
+ margin-block-start: 0;
350
+ }
351
+ }
352
+
353
+ @supports (animation-timeline: view()) {
354
+ .sf-scroll-panel[data-view-progress] {
355
+ view-timeline-name: --sf-panel;
356
+ view-timeline-axis: block;
357
+ }
358
+ }
359
+
360
+ @container (min-width: 42rem) {
361
+ .sf-panel-grid[data-density="featured"] > :first-child {
362
+ grid-column: span 2;
363
+ }
364
+ }
365
+ }
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@syncedco/flow",
3
+ "version": "0.1.0",
4
+ "description": "AI-native fluid CSS design system for brand-consistent websites and agency builds.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "keywords": [
8
+ "css",
9
+ "design-system",
10
+ "fluid-css",
11
+ "design-tokens",
12
+ "oklch",
13
+ "cli",
14
+ "ai",
15
+ "wordpress",
16
+ "nextjs",
17
+ "astro",
18
+ "vite"
19
+ ],
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/SyncedCo/synced-flow.git"
23
+ },
24
+ "homepage": "https://syncedco.com",
25
+ "bugs": {
26
+ "url": "https://github.com/SyncedCo/synced-flow/issues"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "sideEffects": [
32
+ "**/*.css"
33
+ ],
34
+ "exports": {
35
+ ".": {
36
+ "types": "./dist/index.d.ts",
37
+ "import": "./dist/index.js"
38
+ },
39
+ "./config": {
40
+ "types": "./dist/config.d.ts",
41
+ "import": "./dist/config.js"
42
+ },
43
+ "./presets": {
44
+ "types": "./src/presets.d.mts",
45
+ "import": "./src/presets.mjs"
46
+ },
47
+ "./tokens": "./src/tokens.mjs",
48
+ "./tokens.css": "./tokens.css",
49
+ "./reset.css": "./reset.css",
50
+ "./base.css": "./base.css",
51
+ "./defaults.css": "./defaults.css",
52
+ "./layout.css": "./layout.css",
53
+ "./components.css": "./components.css",
54
+ "./utilities.css": "./utilities.css",
55
+ "./styles.css": "./styles.css"
56
+ },
57
+ "files": [
58
+ "*.css",
59
+ "bin",
60
+ "dist",
61
+ "docs",
62
+ "examples",
63
+ "skills",
64
+ "src",
65
+ "CODE_OF_CONDUCT.md",
66
+ "CONTRIBUTING.md",
67
+ "LICENSE",
68
+ "SECURITY.md",
69
+ "SUPPORT.md",
70
+ "TRADEMARKS.md"
71
+ ],
72
+ "bin": {
73
+ "synced-flow": "bin/synced-flow.mjs"
74
+ },
75
+ "scripts": {
76
+ "build": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
77
+ "build:css": "node scripts/build-css.mjs",
78
+ "check": "node scripts/build-css.mjs --check && tsc --noEmit && node scripts/guardrails.mjs",
79
+ "guardrails": "node scripts/guardrails.mjs",
80
+ "clean": "rm -rf dist",
81
+ "prepack": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
82
+ "prepare": "node scripts/build-css.mjs && tsc -p tsconfig.build.json",
83
+ "test": "pnpm build && node --test tests/*.test.mjs",
84
+ "type-check": "tsc --noEmit"
85
+ },
86
+ "devDependencies": {
87
+ "@types/node": "^22.15.21",
88
+ "typescript": "^5.8.3"
89
+ },
90
+ "engines": {
91
+ "node": ">=20"
92
+ }
93
+ }
package/reset.css ADDED
@@ -0,0 +1,13 @@
1
+ /* Generated by @syncedco/flow. Edit src/tokens.mjs or scripts/build-css.mjs, then run pnpm build. */
2
+ @layer reset, tokens, base, app, layout, components, utilities;
3
+ @layer reset {
4
+ *, *::before, *::after { box-sizing: border-box; }
5
+ *:where(:not(dialog)) { margin: 0; }
6
+ html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }
7
+ body { min-block-size: 100%; }
8
+ img, picture, video, canvas, svg { display: block; max-inline-size: 100%; }
9
+ img, video { block-size: auto; }
10
+ input, button, textarea, select { font: inherit; }
11
+ button, input:where([type="button"], [type="submit"], [type="reset"]) { appearance: button; }
12
+ [hidden]:where(:not([hidden="until-found"])) { display: none !important; }
13
+ }