@syncedco/flow 0.1.4 → 0.3.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/bin/synced-flow.mjs +687 -17
- package/components.css +348 -1
- package/docs/api-contract.md +3 -3
- package/docs/native-components.md +20 -0
- package/docs/patterns.md +13 -0
- package/docs/recipes.md +4 -3
- package/docs/system-primitives.md +8 -4
- package/docs/tokens.md +5 -1
- package/layout.css +89 -0
- package/package.json +1 -1
- package/skills/synced-flow/SKILL.md +23 -6
- package/src/tokens.mjs +10 -0
- package/styles.css +457 -1
- package/tokens.css +19 -0
- package/utilities.css +1 -0
package/components.css
CHANGED
|
@@ -802,6 +802,257 @@
|
|
|
802
802
|
overflow: hidden;
|
|
803
803
|
}
|
|
804
804
|
|
|
805
|
+
.sf-progress {
|
|
806
|
+
accent-color: var(--sf-progress-colour, var(--sf-colour-primary));
|
|
807
|
+
block-size: var(--sf-progress-size, .625rem);
|
|
808
|
+
inline-size: 100%;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
.sf-progress::-webkit-progress-bar {
|
|
812
|
+
background: var(--sf-colour-surface-alt);
|
|
813
|
+
border-radius: var(--sf-radius-full);
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
.sf-progress::-webkit-progress-value,
|
|
817
|
+
.sf-progress::-moz-progress-bar {
|
|
818
|
+
background: var(--sf-progress-colour, var(--sf-colour-primary));
|
|
819
|
+
border-radius: var(--sf-radius-full);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.sf-skeleton {
|
|
823
|
+
background: color-mix(in oklch, var(--sf-colour-surface-alt) 82%, var(--sf-colour-foreground));
|
|
824
|
+
border-radius: var(--sf-skeleton-radius, var(--sf-radius-md));
|
|
825
|
+
color: transparent;
|
|
826
|
+
min-block-size: var(--sf-skeleton-block-size, 1em);
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
830
|
+
.sf-skeleton {
|
|
831
|
+
animation: sf-skeleton-pulse 1.4s var(--sf-ease-standard) infinite alternate;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
@keyframes sf-skeleton-pulse {
|
|
836
|
+
to { opacity: .62; }
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
.sf-filter-bar {
|
|
840
|
+
align-items: end;
|
|
841
|
+
background: var(--sf-colour-surface);
|
|
842
|
+
border: 1px solid var(--sf-colour-border);
|
|
843
|
+
border-radius: var(--sf-radius-panel);
|
|
844
|
+
display: flex;
|
|
845
|
+
flex-wrap: wrap;
|
|
846
|
+
gap: var(--sf-space-xs);
|
|
847
|
+
padding: var(--sf-space-s);
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
.sf-filter-bar > :where(.sf-field, form, label) {
|
|
851
|
+
flex: 1 1 min(100%, 14rem);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.sf-filter-bar > :where(.sf-button, button, a) {
|
|
855
|
+
flex: 0 0 auto;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.sf-data-table {
|
|
859
|
+
border-collapse: collapse;
|
|
860
|
+
inline-size: 100%;
|
|
861
|
+
min-inline-size: var(--sf-data-table-min, 44rem);
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.sf-data-table :where(th, td) {
|
|
865
|
+
border-block-end: 1px solid var(--sf-colour-border);
|
|
866
|
+
padding-block: var(--sf-data-table-padding-block, var(--sf-space-xs));
|
|
867
|
+
padding-inline: var(--sf-data-table-padding-inline, var(--sf-space-s));
|
|
868
|
+
text-align: start;
|
|
869
|
+
vertical-align: middle;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
.sf-data-table :where(th) {
|
|
873
|
+
background: var(--sf-colour-surface-alt);
|
|
874
|
+
color: var(--sf-colour-muted);
|
|
875
|
+
font-size: var(--sf-step--1);
|
|
876
|
+
font-weight: 800;
|
|
877
|
+
}
|
|
878
|
+
|
|
879
|
+
.sf-data-table :where(tbody tr:hover) {
|
|
880
|
+
background: color-mix(in oklch, var(--sf-colour-primary) 6%, transparent);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.sf-data-table[data-density="compact"] {
|
|
884
|
+
--sf-data-table-padding-block: var(--sf-space-2xs);
|
|
885
|
+
--sf-data-table-padding-inline: var(--sf-space-xs);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
.sf-data-table :where(th button, .sf-table-sort) {
|
|
889
|
+
align-items: center;
|
|
890
|
+
color: inherit;
|
|
891
|
+
display: inline-flex;
|
|
892
|
+
font: inherit;
|
|
893
|
+
font-weight: inherit;
|
|
894
|
+
gap: var(--sf-space-3xs);
|
|
895
|
+
padding: 0;
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
.sf-data-table :where(th button, .sf-table-sort)[aria-sort]::after {
|
|
899
|
+
color: var(--sf-colour-subtle);
|
|
900
|
+
content: "\2195";
|
|
901
|
+
font-size: var(--sf-step--2);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
.sf-data-table :where(th button, .sf-table-sort)[aria-sort="ascending"]::after { content: "\2191"; }
|
|
905
|
+
.sf-data-table :where(th button, .sf-table-sort)[aria-sort="descending"]::after { content: "\2193"; }
|
|
906
|
+
|
|
907
|
+
.sf-data-table tr[data-clickable="true"] {
|
|
908
|
+
cursor: pointer;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
.sf-data-table tr[data-clickable="true"]:focus-within {
|
|
912
|
+
outline: 0.125rem solid var(--sf-colour-ring);
|
|
913
|
+
outline-offset: -0.125rem;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
@container (max-width: 38rem) {
|
|
917
|
+
.sf-table-wrap[data-view="cards"] {
|
|
918
|
+
border: 0;
|
|
919
|
+
overflow: visible;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table,
|
|
923
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table :where(thead, tbody, tr, th, td) {
|
|
924
|
+
display: block;
|
|
925
|
+
min-inline-size: 0;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table thead {
|
|
929
|
+
display: none;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table tr {
|
|
933
|
+
background: var(--sf-colour-surface);
|
|
934
|
+
border: 1px solid var(--sf-colour-border);
|
|
935
|
+
border-radius: var(--sf-radius-panel);
|
|
936
|
+
margin-block-end: var(--sf-space-xs);
|
|
937
|
+
padding: var(--sf-space-xs);
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table td {
|
|
941
|
+
align-items: center;
|
|
942
|
+
border: 0;
|
|
943
|
+
display: flex;
|
|
944
|
+
gap: var(--sf-space-s);
|
|
945
|
+
justify-content: space-between;
|
|
946
|
+
padding-block: var(--sf-space-2xs);
|
|
947
|
+
padding-inline: 0;
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
.sf-table-wrap[data-view="cards"] .sf-data-table td::before {
|
|
951
|
+
color: var(--sf-colour-muted);
|
|
952
|
+
content: attr(data-label);
|
|
953
|
+
font-size: var(--sf-step--1);
|
|
954
|
+
font-weight: 800;
|
|
955
|
+
}
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.sf-status {
|
|
959
|
+
align-items: center;
|
|
960
|
+
background: var(--sf-status-bg, var(--sf-colour-surface-alt));
|
|
961
|
+
border: 1px solid var(--sf-status-border, var(--sf-colour-border));
|
|
962
|
+
border-radius: var(--sf-radius-full);
|
|
963
|
+
color: var(--sf-status-colour, var(--sf-colour-foreground));
|
|
964
|
+
display: inline-flex;
|
|
965
|
+
font-size: var(--sf-step--1);
|
|
966
|
+
font-weight: 700;
|
|
967
|
+
gap: var(--sf-space-3xs);
|
|
968
|
+
line-height: 1;
|
|
969
|
+
min-block-size: 1.75rem;
|
|
970
|
+
padding-inline: .7em;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
.sf-status[data-size="sm"] {
|
|
974
|
+
font-size: var(--sf-step--2);
|
|
975
|
+
min-block-size: 1.35rem;
|
|
976
|
+
padding-inline: .55em;
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
.sf-status::before {
|
|
980
|
+
background: currentColor;
|
|
981
|
+
block-size: .42em;
|
|
982
|
+
border-radius: var(--sf-radius-full);
|
|
983
|
+
content: "";
|
|
984
|
+
inline-size: .42em;
|
|
985
|
+
}
|
|
986
|
+
|
|
987
|
+
.sf-status[data-tone="success"] {
|
|
988
|
+
--sf-status-bg: var(--sf-colour-success-soft);
|
|
989
|
+
--sf-status-border: color-mix(in oklch, var(--sf-colour-success) 34%, transparent);
|
|
990
|
+
--sf-status-colour: color-mix(in oklch, var(--sf-colour-success) 76%, var(--sf-colour-foreground));
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.sf-status[data-tone="warning"] {
|
|
994
|
+
--sf-status-bg: var(--sf-colour-warning-soft);
|
|
995
|
+
--sf-status-border: color-mix(in oklch, var(--sf-colour-warning) 38%, transparent);
|
|
996
|
+
--sf-status-colour: color-mix(in oklch, var(--sf-colour-warning) 70%, var(--sf-colour-foreground));
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.sf-status[data-tone="danger"] {
|
|
1000
|
+
--sf-status-bg: var(--sf-colour-danger-soft);
|
|
1001
|
+
--sf-status-border: color-mix(in oklch, var(--sf-colour-danger) 34%, transparent);
|
|
1002
|
+
--sf-status-colour: color-mix(in oklch, var(--sf-colour-danger) 76%, var(--sf-colour-foreground));
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
.sf-status[data-tone="info"] {
|
|
1006
|
+
--sf-status-bg: var(--sf-colour-info-soft);
|
|
1007
|
+
--sf-status-border: color-mix(in oklch, var(--sf-colour-info) 34%, transparent);
|
|
1008
|
+
--sf-status-colour: color-mix(in oklch, var(--sf-colour-info) 76%, var(--sf-colour-foreground));
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
.sf-data-list {
|
|
1012
|
+
display: grid;
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
.sf-data-list > * {
|
|
1016
|
+
align-items: center;
|
|
1017
|
+
border-block-end: 1px solid var(--sf-colour-border);
|
|
1018
|
+
display: flex;
|
|
1019
|
+
flex-wrap: wrap;
|
|
1020
|
+
gap: var(--sf-space-xs);
|
|
1021
|
+
justify-content: space-between;
|
|
1022
|
+
padding-block: var(--sf-space-xs);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
.sf-data-list > :last-child {
|
|
1026
|
+
border-block-end: 0;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
.sf-empty-state {
|
|
1030
|
+
align-items: center;
|
|
1031
|
+
background: var(--sf-colour-surface-alt);
|
|
1032
|
+
border: 1px dashed var(--sf-colour-border-strong);
|
|
1033
|
+
border-radius: var(--sf-radius-panel);
|
|
1034
|
+
color: var(--sf-colour-muted);
|
|
1035
|
+
display: grid;
|
|
1036
|
+
gap: var(--sf-space-xs);
|
|
1037
|
+
justify-items: center;
|
|
1038
|
+
padding: var(--sf-space-l);
|
|
1039
|
+
text-align: center;
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
.sf-settings-section,
|
|
1043
|
+
.sf-detail-panel {
|
|
1044
|
+
background: var(--sf-colour-surface);
|
|
1045
|
+
border: 1px solid var(--sf-colour-border);
|
|
1046
|
+
border-radius: var(--sf-radius-panel);
|
|
1047
|
+
display: grid;
|
|
1048
|
+
gap: var(--sf-space-s);
|
|
1049
|
+
padding: var(--sf-space-m);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.sf-detail-panel {
|
|
1053
|
+
background: var(--sf-colour-surface-alt);
|
|
1054
|
+
}
|
|
1055
|
+
|
|
805
1056
|
.sf-nav {
|
|
806
1057
|
align-items: center;
|
|
807
1058
|
display: flex;
|
|
@@ -880,6 +1131,13 @@
|
|
|
880
1131
|
gap: var(--sf-form-gap, var(--sf-space-s-m));
|
|
881
1132
|
}
|
|
882
1133
|
|
|
1134
|
+
.sf-form[data-density="compact"],
|
|
1135
|
+
.sf-field[data-density="compact"] {
|
|
1136
|
+
--sf-form-gap: var(--sf-space-xs);
|
|
1137
|
+
--sf-input-block-size: 2.25rem;
|
|
1138
|
+
--sf-input-padding-inline: var(--sf-space-xs);
|
|
1139
|
+
}
|
|
1140
|
+
|
|
883
1141
|
.sf-fieldset {
|
|
884
1142
|
border: 1px solid var(--sf-colour-border);
|
|
885
1143
|
border-radius: var(--sf-radius-panel);
|
|
@@ -945,6 +1203,45 @@
|
|
|
945
1203
|
transition: background-color var(--sf-duration-fast) var(--sf-ease-standard), border-color var(--sf-duration-fast) var(--sf-ease-standard), box-shadow var(--sf-duration-fast) var(--sf-ease-standard);
|
|
946
1204
|
}
|
|
947
1205
|
|
|
1206
|
+
.sf-search {
|
|
1207
|
+
position: relative;
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
.sf-search::before {
|
|
1211
|
+
block-size: .75em;
|
|
1212
|
+
border: 0.125em solid currentColor;
|
|
1213
|
+
border-radius: var(--sf-radius-full);
|
|
1214
|
+
color: var(--sf-colour-subtle);
|
|
1215
|
+
content: "";
|
|
1216
|
+
inline-size: .75em;
|
|
1217
|
+
inset-block-start: 50%;
|
|
1218
|
+
inset-inline-start: var(--sf-space-xs);
|
|
1219
|
+
line-height: 1;
|
|
1220
|
+
position: absolute;
|
|
1221
|
+
transform: translateY(-58%);
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
.sf-search::after {
|
|
1225
|
+
background: var(--sf-colour-subtle);
|
|
1226
|
+
block-size: .125em;
|
|
1227
|
+
content: "";
|
|
1228
|
+
inline-size: .45em;
|
|
1229
|
+
inset-block-start: 50%;
|
|
1230
|
+
inset-inline-start: calc(var(--sf-space-xs) + .58em);
|
|
1231
|
+
position: absolute;
|
|
1232
|
+
transform: translateY(120%) rotate(45deg);
|
|
1233
|
+
transform-origin: inline-start center;
|
|
1234
|
+
}
|
|
1235
|
+
|
|
1236
|
+
.sf-search > .sf-input {
|
|
1237
|
+
padding-inline-start: var(--sf-space-l);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
.sf-help[data-density="compact"],
|
|
1241
|
+
.sf-error[data-density="compact"] {
|
|
1242
|
+
font-size: var(--sf-step--2);
|
|
1243
|
+
}
|
|
1244
|
+
|
|
948
1245
|
.sf-textarea {
|
|
949
1246
|
min-block-size: var(--sf-textarea-block-size, 8rem);
|
|
950
1247
|
padding-block: var(--sf-space-xs);
|
|
@@ -1065,7 +1362,7 @@
|
|
|
1065
1362
|
.sf-dialog::backdrop,
|
|
1066
1363
|
.sf-popover::backdrop,
|
|
1067
1364
|
.sf-drawer::backdrop {
|
|
1068
|
-
background:
|
|
1365
|
+
background: var(--sf-colour-backdrop);
|
|
1069
1366
|
}
|
|
1070
1367
|
|
|
1071
1368
|
.sf-dialog__header,
|
|
@@ -1091,6 +1388,11 @@
|
|
|
1091
1388
|
justify-content: flex-end;
|
|
1092
1389
|
}
|
|
1093
1390
|
|
|
1391
|
+
.sf-dialog[data-layout="form"] .sf-dialog__body {
|
|
1392
|
+
display: grid;
|
|
1393
|
+
gap: var(--sf-space-s);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1094
1396
|
.sf-popover,
|
|
1095
1397
|
.sf-menu-popover,
|
|
1096
1398
|
.sf-tooltip,
|
|
@@ -1144,6 +1446,16 @@
|
|
|
1144
1446
|
background: var(--sf-colour-surface-alt);
|
|
1145
1447
|
}
|
|
1146
1448
|
|
|
1449
|
+
.sf-menu :where(a, button)[data-variant="danger"],
|
|
1450
|
+
.sf-menu-popover :where(a, button)[data-variant="danger"] {
|
|
1451
|
+
color: var(--sf-colour-danger);
|
|
1452
|
+
}
|
|
1453
|
+
|
|
1454
|
+
.sf-menu :where(a, button)[data-variant="danger"]:hover,
|
|
1455
|
+
.sf-menu-popover :where(a, button)[data-variant="danger"]:hover {
|
|
1456
|
+
background: var(--sf-colour-danger-soft);
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1147
1459
|
.sf-tooltip {
|
|
1148
1460
|
border-radius: var(--sf-radius-md);
|
|
1149
1461
|
box-shadow: var(--sf-shadow-md);
|
|
@@ -1170,6 +1482,16 @@
|
|
|
1170
1482
|
top: var(--sf-space-s);
|
|
1171
1483
|
}
|
|
1172
1484
|
|
|
1485
|
+
.sf-toast-stack {
|
|
1486
|
+
display: grid;
|
|
1487
|
+
gap: var(--sf-space-xs);
|
|
1488
|
+
inline-size: min(100% - (var(--sf-gutter) * 2), var(--sf-toast-width, 24rem));
|
|
1489
|
+
inset-block-start: var(--sf-space-s);
|
|
1490
|
+
inset-inline-end: var(--sf-space-s);
|
|
1491
|
+
position: fixed;
|
|
1492
|
+
z-index: 50;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1173
1495
|
.sf-banner {
|
|
1174
1496
|
block-size: auto;
|
|
1175
1497
|
border-radius: var(--sf-radius-lg);
|
|
@@ -1283,14 +1605,21 @@
|
|
|
1283
1605
|
|
|
1284
1606
|
.sf-tab {
|
|
1285
1607
|
border-block-end: 0.125rem solid transparent;
|
|
1608
|
+
border-radius: var(--sf-radius-full);
|
|
1286
1609
|
color: var(--sf-colour-muted);
|
|
1287
1610
|
display: inline-flex;
|
|
1611
|
+
gap: var(--sf-space-2xs);
|
|
1288
1612
|
font-weight: 800;
|
|
1289
1613
|
padding-block: var(--sf-space-xs);
|
|
1290
1614
|
padding-inline: var(--sf-space-s);
|
|
1291
1615
|
text-decoration: none;
|
|
1292
1616
|
}
|
|
1293
1617
|
|
|
1618
|
+
.sf-tab[data-variant="pill"] {
|
|
1619
|
+
border: 1px solid transparent;
|
|
1620
|
+
padding-block: var(--sf-space-2xs);
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1294
1623
|
.sf-tab:hover,
|
|
1295
1624
|
.sf-tab[aria-selected="true"],
|
|
1296
1625
|
.sf-tab[data-state="active"] {
|
|
@@ -1298,6 +1627,24 @@
|
|
|
1298
1627
|
color: var(--sf-colour-foreground);
|
|
1299
1628
|
}
|
|
1300
1629
|
|
|
1630
|
+
.sf-tab[data-variant="pill"]:hover,
|
|
1631
|
+
.sf-tab[data-variant="pill"][aria-selected="true"],
|
|
1632
|
+
.sf-tab[data-variant="pill"][data-state="active"] {
|
|
1633
|
+
background: var(--sf-colour-primary-soft);
|
|
1634
|
+
border-color: var(--sf-colour-primary-soft-border);
|
|
1635
|
+
color: var(--sf-colour-primary);
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
.sf-tab__count {
|
|
1639
|
+
background: var(--sf-colour-surface-alt);
|
|
1640
|
+
border: 1px solid var(--sf-colour-border);
|
|
1641
|
+
border-radius: var(--sf-radius-full);
|
|
1642
|
+
color: var(--sf-colour-muted);
|
|
1643
|
+
font-size: var(--sf-step--2);
|
|
1644
|
+
line-height: 1;
|
|
1645
|
+
padding: .25em .55em;
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1301
1648
|
.sf-tab-panel {
|
|
1302
1649
|
background: var(--sf-colour-surface);
|
|
1303
1650
|
border: 1px solid var(--sf-colour-border);
|
package/docs/api-contract.md
CHANGED
|
@@ -13,9 +13,9 @@ These are intended for application code and examples.
|
|
|
13
13
|
| Imports | `@syncedco/flow/styles.css`, `tokens.css`, `reset.css`, `base.css`, `defaults.css`, `layout.css`, `components.css`, `utilities.css` |
|
|
14
14
|
| Tokens | Unlayered `--sf-*` custom properties emitted by `tokens.css` |
|
|
15
15
|
| Theme config | `theme.fonts`, `theme.colours`, `theme.darkColours`, `theme.radii`, `theme.layout`, `theme.components` |
|
|
16
|
-
| Layout classes | `sf-container`, `sf-section`, `sf-stack`, `sf-flow`, `sf-cluster`, `sf-repel`, `sf-toolbar`, `sf-app-shell`, `sf-app-sidebar`, `sf-app-main`, `sf-auto-grid`, `sf-switcher`, `sf-sidebar`, `sf-split`, `sf-frame`, `sf-cover`, `sf-metric-grid`, `sf-pipeline` |
|
|
17
|
-
| Components | `sf-button`, `sf-icon`, `sf-icon-button`, `sf-avatar`, `sf-chart`, `sf-meter`, `sf-card`, `sf-surface`, `sf-hero`, `sf-nav`, `sf-form`, `sf-field`, `sf-input`, `sf-select`, `sf-textarea`, `sf-check`, `sf-alert`, `sf-badge`, `sf-section-header`, `sf-kicker` |
|
|
18
|
-
| Native components | `sf-dialog`, `sf-popover`, `sf-tooltip`, `sf-drawer`, `sf-drawer--stack`, `sf-disclosure`, `sf-accordion`, `sf-tabs`, `sf-menu`, `sf-breadcrumb`, `sf-pagination` |
|
|
16
|
+
| Layout classes | `sf-container`, `sf-section`, `sf-stack`, `sf-flow`, `sf-cluster`, `sf-repel`, `sf-toolbar`, `sf-app-shell`, `sf-app-header`, `sf-app-sidebar`, `sf-app-backdrop`, `sf-app-main`, `sf-auto-grid`, `sf-switcher`, `sf-sidebar`, `sf-split`, `sf-frame`, `sf-cover`, `sf-metric-grid`, `sf-pipeline` |
|
|
17
|
+
| Components | `sf-button`, `sf-icon`, `sf-icon-button`, `sf-avatar`, `sf-chart`, `sf-meter`, `sf-progress`, `sf-skeleton`, `sf-filter-bar`, `sf-search`, `sf-data-table`, `sf-table-sort`, `sf-status`, `sf-data-list`, `sf-empty-state`, `sf-settings-section`, `sf-detail-panel`, `sf-card`, `sf-surface`, `sf-hero`, `sf-nav`, `sf-form`, `sf-field`, `sf-input`, `sf-select`, `sf-textarea`, `sf-check`, `sf-alert`, `sf-badge`, `sf-section-header`, `sf-kicker` |
|
|
18
|
+
| Native components | `sf-dialog`, `sf-popover`, `sf-tooltip`, `sf-drawer`, `sf-drawer--stack`, `sf-disclosure`, `sf-accordion`, `sf-tabs`, `sf-tab__count`, `sf-menu`, `sf-breadcrumb`, `sf-pagination`, `sf-toast-stack` |
|
|
19
19
|
| Website patterns | `sf-logo-cloud`, `sf-feature`, `sf-stats`, `sf-testimonial`, `sf-pricing-grid`, `sf-price-card`, `sf-faq`, `sf-cta`, `sf-footer` |
|
|
20
20
|
| Utilities | `sf-prose`, `sf-link`, `sf-link-subtle`, `sf-link-plain`, `sf-list-*`, `sf-push-*`, `sf-focus-ring`, `sf-touch-target`, `sf-skip-link`, `sr-only`, `not-sr-only` |
|
|
21
21
|
| CLI | `synced-flow init`, `agents install`, `agents status`, `skill`, `add defaults`, `build`, `watch`, `lint`, `doctor`, `tokens`, `catalog`, `suggest`, `pattern`, `recipe`, `theme init`, `theme validate` |
|
|
@@ -128,6 +128,26 @@ Use `sf-nav--mobile` with a popover drawer for mobile navigation. Use
|
|
|
128
128
|
</nav>
|
|
129
129
|
```
|
|
130
130
|
|
|
131
|
+
## Native Date And Time Inputs
|
|
132
|
+
|
|
133
|
+
Use browser-native inputs for simple date, time, month, week, and datetime
|
|
134
|
+
fields. Synced Flow styles the control shell with `sf-input`; validation,
|
|
135
|
+
range rules, and custom scheduling behavior belong to the app.
|
|
136
|
+
|
|
137
|
+
```html
|
|
138
|
+
<form class="sf-filter-bar" action="/app/reports" method="get">
|
|
139
|
+
<label class="sf-field">
|
|
140
|
+
<span class="sf-label">From</span>
|
|
141
|
+
<input class="sf-input" name="from" type="date">
|
|
142
|
+
</label>
|
|
143
|
+
<label class="sf-field">
|
|
144
|
+
<span class="sf-label">To</span>
|
|
145
|
+
<input class="sf-input" name="to" type="date">
|
|
146
|
+
</label>
|
|
147
|
+
<button class="sf-button" type="submit">Apply</button>
|
|
148
|
+
</form>
|
|
149
|
+
```
|
|
150
|
+
|
|
131
151
|
## Scroll And Sticky
|
|
132
152
|
|
|
133
153
|
Use CSS scroll snap and sticky positioning for full-page sections and sticky
|
package/docs/patterns.md
CHANGED
|
@@ -18,6 +18,19 @@ pnpm exec synced-flow pattern scroll-viewport-sections --json
|
|
|
18
18
|
| `scroll-viewport-with-spy` | Scroll snap panels with optional IntersectionObserver active-state notes. |
|
|
19
19
|
| `native-dialog-react` | Native `<dialog>` markup plus React/Next fallback shape. |
|
|
20
20
|
| `popover-drawer-layout` | Popover-backed drawer or filter panel with `sf-drawer--stack`. |
|
|
21
|
+
| `app-shell-layout` | Fixed header, sidebar, collapsed state, and mobile drawer app shell. |
|
|
22
|
+
| `row-action-menu` | Native popover row actions with destructive menu item styling. |
|
|
23
|
+
| `tabs-with-counts` | Pill tabs with compact count chips. |
|
|
24
|
+
| `data-table-actions` | Sortable header controls, clickable rows, and responsive card fallback. |
|
|
25
|
+
| `search-field` | Labelled native search input with icon shell and compact density. |
|
|
26
|
+
| `modal-form` | Native dialog layout for form body and footer actions. |
|
|
27
|
+
| `toast-stack` | Fixed app notification stack layout. |
|
|
28
|
+
| `filter-toolbar` | Search, filters, and actions above app lists and tables. |
|
|
29
|
+
| `date-filter-form` | Native date/time inputs inside filter forms. |
|
|
30
|
+
| `active-filter-tags` | Visible selected filter tags with remove and clear actions. |
|
|
31
|
+
| `data-table` | Native responsive table markup with status pills. |
|
|
32
|
+
| `empty-state` | No-results and first-run states with clear next actions. |
|
|
33
|
+
| `settings-section` | Settings/detail sections for account, team, billing, and security screens. |
|
|
21
34
|
|
|
22
35
|
Pattern JSON includes:
|
|
23
36
|
|
package/docs/recipes.md
CHANGED
|
@@ -160,12 +160,13 @@ The recipe includes:
|
|
|
160
160
|
- Generic account initials using `sf-avatar`
|
|
161
161
|
- Inline SVG and native meter analytics using `sf-chart` and `sf-meter`
|
|
162
162
|
- traditional SaaS app shell with persistent desktop navigation and a visible stacked mobile navigation rail
|
|
163
|
-
- KPI cards, theme-aware toolbar, filter/search form,
|
|
163
|
+
- KPI cards, theme-aware toolbar, filter/search form, native date input, active filter tags, data table, status pills, progress, skeleton loading, empty state, and activity list
|
|
164
164
|
|
|
165
165
|
It uses Synced Flow primitives such as `sf-app-shell`, `sf-app-sidebar`,
|
|
166
166
|
`sf-app-main`, `sf-toolbar`, `sf-metric-grid`, `sf-panel-grid`, `sf-icon`,
|
|
167
|
-
`sf-chart`, `sf-chart--wide`, `sf-meter`, `sf-
|
|
168
|
-
`sf-table-
|
|
167
|
+
`sf-chart`, `sf-chart--wide`, `sf-meter`, `sf-progress`, `sf-skeleton`,
|
|
168
|
+
`sf-card`, `sf-form`, `sf-filter-bar`, `sf-data-table`, `sf-status`,
|
|
169
|
+
`sf-data-list`, `sf-empty-state`, `sf-detail-panel`, and `sf-table-wrap`.
|
|
169
170
|
|
|
170
171
|
## Documentation Page
|
|
171
172
|
|
|
@@ -14,6 +14,8 @@ Use the `--sf-*` variables as the stable CSS foundation.
|
|
|
14
14
|
| Space | `--sf-space-s`, `--sf-space-m-l`, `--sf-space-xl-2xl` | Fluid padding, margin, and gaps. |
|
|
15
15
|
| Radius | `--sf-radius-control`, `--sf-radius-panel`, `--sf-radius-full` | Controls, panels, pills. |
|
|
16
16
|
| Colour | `--sf-colour-background`, `--sf-colour-surface`, `--sf-colour-primary` | Semantic UI colour roles. |
|
|
17
|
+
| App colour | `--sf-colour-surface-hover`, `--sf-colour-surface-raised-2`, `--sf-colour-border-subtle`, `--sf-colour-backdrop` | App surfaces, hover states, subtle dividers, and overlays. |
|
|
18
|
+
| Categorical colour | `--sf-colour-categorical-1` ... `--sf-colour-categorical-6` | Charts, stages, labels, and recurring data accents. |
|
|
17
19
|
| State | `--sf-colour-success`, `--sf-colour-warning`, `--sf-colour-danger`, `--sf-colour-info` | Feedback and notices. |
|
|
18
20
|
| Motion | `--sf-duration-fast`, `--sf-duration-normal`, `--sf-ease-standard` | Consistent transitions. |
|
|
19
21
|
| Component | `--sf-button-*`, `--sf-card-*`, `--sf-input-*`, `--sf-alert-*` | Reusable component defaults. |
|
|
@@ -36,7 +38,7 @@ These classes are the first choice for page structure.
|
|
|
36
38
|
| `sf-cluster` | Wrapping inline groups such as actions or tags. |
|
|
37
39
|
| `sf-repel` | Space-between layout that wraps safely. |
|
|
38
40
|
| `sf-toolbar` | Dense app/page toolbar that wraps actions safely. |
|
|
39
|
-
| `sf-app-shell`, `sf-app-sidebar`, `sf-app-sidebar__brand`, `sf-app-main` | Product app shell with
|
|
41
|
+
| `sf-app-shell`, `sf-app-header`, `sf-app-sidebar`, `sf-app-sidebar__brand`, `sf-app-backdrop`, `sf-app-main` | Product app shell with optional fixed header, collapsed sidebar, mobile drawer, and main workspace. |
|
|
40
42
|
| `sf-split` | Responsive two-column layout. |
|
|
41
43
|
| `sf-split--reverse` | Reverses split layout visual order. |
|
|
42
44
|
| `sf-auto-grid`, `sf-panel-grid`, `sf-metric-grid`, `sf-pipeline` | Responsive card, metric, and operational grids. |
|
|
@@ -62,14 +64,16 @@ These cover the common UI elements needed for a simple site.
|
|
|
62
64
|
| `sf-nav`, `sf-nav__list`, `sf-nav__link` | Navigation basics. |
|
|
63
65
|
| `sf-nav--mobile`, `sf-menu`, `sf-breadcrumb`, `sf-pagination` | Mobile, menu, breadcrumb, and paginated navigation. |
|
|
64
66
|
| `sf-dialog`, `sf-dialog__header`, `sf-dialog__body`, `sf-dialog__footer` | Native `<dialog>` styling. |
|
|
65
|
-
| `sf-popover`, `sf-tooltip`, `sf-tooltip-trigger`, `sf-menu-popover`, `sf-toast`, `sf-banner`, `sf-drawer` | Popover-backed native overlays. |
|
|
67
|
+
| `sf-popover`, `sf-tooltip`, `sf-tooltip-trigger`, `sf-menu-popover`, `sf-toast`, `sf-toast-stack`, `sf-banner`, `sf-drawer` | Popover-backed native overlays and app feedback stacks. |
|
|
66
68
|
| `sf-disclosure`, `sf-accordion` | Native `details`/`summary` disclosure patterns. |
|
|
67
|
-
| `sf-tabs`, `sf-tab-list`, `sf-tab`, `sf-tab-panel` | HTML/CSS-first tab styling. |
|
|
69
|
+
| `sf-tabs`, `sf-tab-list`, `sf-tab`, `sf-tab__count`, `sf-tab-panel` | HTML/CSS-first tab styling, including counted pill tabs. |
|
|
68
70
|
| `sf-form`, `sf-fieldset`, `sf-field`, `sf-label`, `sf-help`, `sf-error` | Form structure and messaging. |
|
|
69
|
-
| `sf-input`, `sf-select`, `sf-textarea`, `sf-check` | Form controls. |
|
|
71
|
+
| `sf-input`, `sf-select`, `sf-textarea`, `sf-search`, `sf-check` | Form controls, including search input shell. |
|
|
70
72
|
| `sf-alert`, `sf-alert--info`, `sf-alert--success`, `sf-alert--warning`, `sf-alert--danger`, `sf-alert__title` | Notices and feedback. |
|
|
71
73
|
| `sf-section-header`, `sf-kicker`, `sf-badge`, `sf-avatar` | Common marketing/content and account patterns. |
|
|
72
74
|
| `sf-chart`, `sf-chart__plot`, `sf-chart__svg`, `sf-chart__legend`, `sf-meter-list`, `sf-meter` | Lightweight chart shells for app-owned SVG charts and native meter bars. |
|
|
75
|
+
| `sf-progress`, `sf-skeleton` | Native progress bars and CSS-only loading placeholders for async app states. |
|
|
76
|
+
| `sf-filter-bar`, `sf-data-table`, `sf-table-sort`, `sf-status`, `sf-data-list`, `sf-empty-state`, `sf-settings-section`, `sf-detail-panel` | Lean application primitives for filters, operational data, status, empty states, and settings/detail screens. |
|
|
73
77
|
|
|
74
78
|
## Utility Classes
|
|
75
79
|
|
package/docs/tokens.md
CHANGED
|
@@ -75,6 +75,7 @@ The generated core includes enough semantic variables for common website UI:
|
|
|
75
75
|
|
|
76
76
|
- surfaces: `--sf-colour-background`, `--sf-colour-surface`,
|
|
77
77
|
`--sf-colour-surface-alt`, `--sf-colour-surface-raised`,
|
|
78
|
+
`--sf-colour-surface-raised-2`, `--sf-colour-surface-hover`,
|
|
78
79
|
`--sf-colour-surface-inset`
|
|
79
80
|
- text and links: `--sf-colour-foreground`, `--sf-colour-muted`,
|
|
80
81
|
`--sf-colour-subtle`, `--sf-colour-link`, `--sf-colour-link-hover`
|
|
@@ -82,8 +83,11 @@ The generated core includes enough semantic variables for common website UI:
|
|
|
82
83
|
`--sf-colour-primary-foreground`, `--sf-colour-primary-soft`
|
|
83
84
|
- state feedback: `--sf-colour-success`, `--sf-colour-warning`,
|
|
84
85
|
`--sf-colour-danger`, `--sf-colour-info`, plus matching soft variants
|
|
85
|
-
- structure: `--sf-colour-border`, `--sf-colour-border
|
|
86
|
+
- structure: `--sf-colour-border-subtle`, `--sf-colour-border`,
|
|
87
|
+
`--sf-colour-border-strong`, `--sf-colour-backdrop`,
|
|
86
88
|
`--sf-radius-control`, `--sf-radius-panel`, `--sf-shadow-*`
|
|
89
|
+
- data accents: `--sf-colour-categorical-1` through
|
|
90
|
+
`--sf-colour-categorical-6`
|
|
87
91
|
|
|
88
92
|
For class-level usage, see [System primitives](system-primitives.md).
|
|
89
93
|
|
package/layout.css
CHANGED
|
@@ -95,11 +95,47 @@
|
|
|
95
95
|
}
|
|
96
96
|
|
|
97
97
|
.sf-app-shell {
|
|
98
|
+
--sf-app-header-height: 4rem;
|
|
99
|
+
--sf-app-sidebar-collapsed-width: 4.75rem;
|
|
98
100
|
background: var(--sf-colour-background);
|
|
99
101
|
color: var(--sf-colour-foreground);
|
|
100
102
|
display: grid;
|
|
101
103
|
grid-template-columns: minmax(14rem, var(--sf-app-sidebar-width, 16rem)) minmax(0, 1fr);
|
|
102
104
|
min-block-size: 100dvh;
|
|
105
|
+
position: relative;
|
|
106
|
+
transition: grid-template-columns var(--sf-duration-normal) var(--sf-ease-standard);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.sf-app-header {
|
|
110
|
+
align-items: center;
|
|
111
|
+
background: var(--sf-colour-surface);
|
|
112
|
+
border-block-end: 1px solid var(--sf-colour-border);
|
|
113
|
+
display: flex;
|
|
114
|
+
gap: var(--sf-space-s);
|
|
115
|
+
grid-column: 1 / -1;
|
|
116
|
+
justify-content: space-between;
|
|
117
|
+
min-block-size: var(--sf-app-header-height);
|
|
118
|
+
padding-inline: var(--sf-space-s-m);
|
|
119
|
+
z-index: 20;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.sf-app-shell[data-layout~="fixed-header"] {
|
|
123
|
+
grid-template-rows: var(--sf-app-header-height) minmax(0, 1fr);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.sf-app-shell[data-layout~="fixed-header"] .sf-app-header {
|
|
127
|
+
inset-block-start: 0;
|
|
128
|
+
position: sticky;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.sf-app-shell[data-layout~="fixed-header"] .sf-app-sidebar {
|
|
132
|
+
inset-block-start: var(--sf-app-header-height);
|
|
133
|
+
max-block-size: calc(100dvh - var(--sf-app-header-height));
|
|
134
|
+
min-block-size: calc(100dvh - var(--sf-app-header-height));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.sf-app-shell[data-collapsed="true"] {
|
|
138
|
+
grid-template-columns: var(--sf-app-sidebar-collapsed-width) minmax(0, 1fr);
|
|
103
139
|
}
|
|
104
140
|
|
|
105
141
|
.sf-app-sidebar {
|
|
@@ -115,6 +151,7 @@
|
|
|
115
151
|
padding: var(--sf-space-s);
|
|
116
152
|
position: sticky;
|
|
117
153
|
inset-block-start: 0;
|
|
154
|
+
transition: transform var(--sf-duration-normal) var(--sf-ease-standard), inline-size var(--sf-duration-normal) var(--sf-ease-standard);
|
|
118
155
|
}
|
|
119
156
|
|
|
120
157
|
.sf-app-sidebar__brand {
|
|
@@ -134,6 +171,58 @@
|
|
|
134
171
|
padding: var(--sf-app-main-padding, var(--sf-space-m-l));
|
|
135
172
|
}
|
|
136
173
|
|
|
174
|
+
.sf-app-shell[data-collapsed="true"] .sf-app-sidebar {
|
|
175
|
+
overflow-x: hidden;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.sf-app-shell[data-collapsed="true"] .sf-app-sidebar__brand,
|
|
179
|
+
.sf-app-shell[data-collapsed="true"] .sf-app-sidebar .sf-nav__link {
|
|
180
|
+
justify-content: center;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.sf-app-shell[data-collapsed="true"] [data-hide-collapsed="true"] {
|
|
184
|
+
display: none;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.sf-app-backdrop {
|
|
188
|
+
display: none;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@media (max-width: 48rem) {
|
|
192
|
+
.sf-app-shell[data-mobile="drawer"] {
|
|
193
|
+
display: block;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.sf-app-shell[data-mobile="drawer"] .sf-app-header {
|
|
197
|
+
position: sticky;
|
|
198
|
+
inset-block-start: 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.sf-app-shell[data-mobile="drawer"] .sf-app-sidebar {
|
|
202
|
+
box-shadow: var(--sf-shadow-xl);
|
|
203
|
+
inline-size: min(18rem, calc(100vw - var(--sf-space-l)));
|
|
204
|
+
inset-block: 0;
|
|
205
|
+
inset-inline-start: 0;
|
|
206
|
+
max-block-size: none;
|
|
207
|
+
min-block-size: 100dvh;
|
|
208
|
+
position: fixed;
|
|
209
|
+
transform: translateX(-100%);
|
|
210
|
+
z-index: 30;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-sidebar {
|
|
214
|
+
transform: translateX(0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.sf-app-shell[data-mobile="drawer"][data-sidebar-open="true"] .sf-app-backdrop {
|
|
218
|
+
background: var(--sf-colour-backdrop);
|
|
219
|
+
display: block;
|
|
220
|
+
inset: 0;
|
|
221
|
+
position: fixed;
|
|
222
|
+
z-index: 25;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
137
226
|
.sf-grid {
|
|
138
227
|
display: grid;
|
|
139
228
|
gap: var(--sf-grid-gap, var(--sf-gutter));
|