mosaic-headless 1.3.0 → 1.4.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/sites/_moksa.py CHANGED
@@ -72,10 +72,22 @@ def T(tag, text, _t=None, _m=None, **st):
72
72
  "style": bp(st, _t, _m) if (st or _t or _m) else None}
73
73
 
74
74
 
75
- def box(attr, style, children, hover=None, _t=None, _m=None):
75
+ # The keyboard is a state too.
76
+ #
77
+ # `focus-visible` was verified by sweep_style_states.py to compile to
78
+ # `.M_EL<n>:FOCUS-VISIBLE` - note the UPPERCASE pseudo-class Mosaic emits, which is
79
+ # why grepping a delivered stylesheet for ":focus-visible" finds nothing at all. Of
80
+ # the seven globally usable states this page used exactly one, `hover`, which means
81
+ # every route through it was invisible to anyone not using a mouse.
82
+ FOCUS_RING = {"customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"}
83
+
84
+
85
+ def box(attr, style, children, hover=None, focus=None, _t=None, _m=None):
76
86
  s = bp(style, _t, _m) or {"&": {"_": {}}}
77
87
  if hover:
78
88
  s["hover"] = {"_": hover}
89
+ if focus:
90
+ s["focus-visible"] = {"_": focus}
79
91
  return {"type": "div", "data": {"attrID": attr}, "style": s, "children": children}
80
92
 
81
93
 
@@ -632,7 +644,8 @@ HEADER = box("mk-shell-top", {}, [
632
644
  "transitionAll": "160ms ease",
633
645
  "cursor": "pointer"},
634
646
  "_m": {"fontSize": "12px"}},
635
- "hover": {"_": {"color": {"token": "--mk-accent"}}}},
647
+ "hover": {"_": {"color": {"token": "--mk-accent"}}},
648
+ "focus-visible": {"_": FOCUS_RING}},
636
649
  "text": text}
637
650
  for i, (text, href) in enumerate(NAV)
638
651
  ]},
@@ -656,7 +669,8 @@ HEADER = box("mk-shell-top", {}, [
656
669
  "color": "rgb(255,90,54)"},
657
670
  "transitionAll": "180ms ease"}},
658
671
  "hover": {"_": {"backgroundColor": {"token": "--mk-accent"},
659
- "color": {"token": "--mk-ink"}}}},
672
+ "color": {"token": "--mk-ink"}}},
673
+ "focus-visible": {"_": FOCUS_RING}},
660
674
  "text": "START A PROJECT"},
661
675
  ]}
662
676
  ])]),
@@ -790,6 +804,7 @@ MASTHEAD = section("mk-mast", [wrap("mk-mast-in", [
790
804
  "border-bottom-color:rgb(22,24,28);"},
791
805
  fontSize="13px", fontFamily=MONO, letterSpacing="0.1em",
792
806
  radius="0px", cursor="pointer", transitionAll="180ms ease")},
807
+ "focus-visible": {"_": FOCUS_RING},
793
808
  "hover": {"_": ({"backgroundColor": {"token": "--mk-ink"},
794
809
  "customStyles": "border:1px solid rgb(22,24,28);"}
795
810
  if n == 1
@@ -937,7 +952,15 @@ STACK_SEC = section("stack", [wrap("mk-stack-in", [
937
952
  {"display": "grid", "gridCols": "160px 1fr", "columnGap": "24px",
938
953
  "alignItems": "baseline",
939
954
  "paddingTop": "18px", "paddingBottom": "18px",
940
- "customStyles": "border-top:1px solid " + RULE + ";"},
955
+ # Each row arrives on its own, staggered by pushing its
956
+ # animation-range further down the scroll rather than by a
957
+ # delay: a scroll-driven animation has no clock to delay
958
+ # against, so the offset has to live in the range.
959
+ "customStyles":
960
+ "border-top:1px solid " + RULE + ";"
961
+ "animation:mk-rise both;animation-timeline:view();"
962
+ "animation-range:entry %d%% cover %d%%;"
963
+ % (2 + i * 4, 18 + i * 4)},
941
964
  _m={"gridCols": "1fr", "rowGap": "10px",
942
965
  "paddingTop": "16px", "paddingBottom": "16px"},
943
966
  children=[
@@ -1176,7 +1199,8 @@ INDEX = box("mk-index", {}, [
1176
1199
  "fontFamily": MONO, "fontSize": "10px",
1177
1200
  "letterSpacing": "0.14em",
1178
1201
  "transitionAll": "220ms ease"}},
1179
- "hover": {"_": {"color": {"token": "--mk-ink"}}}},
1202
+ "hover": {"_": {"color": {"token": "--mk-ink"}}},
1203
+ "focus-visible": {"_": FOCUS_RING}},
1180
1204
  "text": "§" + num + " " + name}
1181
1205
  for i, (num, name, href, _tl) in enumerate(CLAUSES)
1182
1206
  ])
package/sites/moksa.json CHANGED
@@ -262,6 +262,11 @@
262
262
  "token": "--mk-accent"
263
263
  }
264
264
  }
265
+ },
266
+ "focus-visible": {
267
+ "_": {
268
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
269
+ }
265
270
  }
266
271
  },
267
272
  "text": "服務"
@@ -295,6 +300,11 @@
295
300
  "token": "--mk-accent"
296
301
  }
297
302
  }
303
+ },
304
+ "focus-visible": {
305
+ "_": {
306
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
307
+ }
298
308
  }
299
309
  },
300
310
  "text": "作品"
@@ -328,6 +338,11 @@
328
338
  "token": "--mk-accent"
329
339
  }
330
340
  }
341
+ },
342
+ "focus-visible": {
343
+ "_": {
344
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
345
+ }
331
346
  }
332
347
  },
333
348
  "text": "產品"
@@ -361,6 +376,11 @@
361
376
  "token": "--mk-accent"
362
377
  }
363
378
  }
379
+ },
380
+ "focus-visible": {
381
+ "_": {
382
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
383
+ }
364
384
  }
365
385
  },
366
386
  "text": "聯絡"
@@ -412,6 +432,11 @@
412
432
  "token": "--mk-ink"
413
433
  }
414
434
  }
435
+ },
436
+ "focus-visible": {
437
+ "_": {
438
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
439
+ }
415
440
  }
416
441
  },
417
442
  "text": "START A PROJECT"
@@ -1081,6 +1106,11 @@
1081
1106
  "token": "--mk-ink"
1082
1107
  }
1083
1108
  }
1109
+ },
1110
+ "focus-visible": {
1111
+ "_": {
1112
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1113
+ }
1084
1114
  }
1085
1115
  },
1086
1116
  "text": "§01 SERVICES"
@@ -1113,6 +1143,11 @@
1113
1143
  "token": "--mk-ink"
1114
1144
  }
1115
1145
  }
1146
+ },
1147
+ "focus-visible": {
1148
+ "_": {
1149
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1150
+ }
1116
1151
  }
1117
1152
  },
1118
1153
  "text": "§02 PROCESS"
@@ -1145,6 +1180,11 @@
1145
1180
  "token": "--mk-ink"
1146
1181
  }
1147
1182
  }
1183
+ },
1184
+ "focus-visible": {
1185
+ "_": {
1186
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1187
+ }
1148
1188
  }
1149
1189
  },
1150
1190
  "text": "§03 WORKS"
@@ -1177,6 +1217,11 @@
1177
1217
  "token": "--mk-ink"
1178
1218
  }
1179
1219
  }
1220
+ },
1221
+ "focus-visible": {
1222
+ "_": {
1223
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1224
+ }
1180
1225
  }
1181
1226
  },
1182
1227
  "text": "§04 STACK"
@@ -1209,6 +1254,11 @@
1209
1254
  "token": "--mk-ink"
1210
1255
  }
1211
1256
  }
1257
+ },
1258
+ "focus-visible": {
1259
+ "_": {
1260
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1261
+ }
1212
1262
  }
1213
1263
  },
1214
1264
  "text": "§05 PRODUCTS"
@@ -1241,6 +1291,11 @@
1241
1291
  "token": "--mk-ink"
1242
1292
  }
1243
1293
  }
1294
+ },
1295
+ "focus-visible": {
1296
+ "_": {
1297
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1298
+ }
1244
1299
  }
1245
1300
  },
1246
1301
  "text": "§06 VOICES"
@@ -1273,6 +1328,11 @@
1273
1328
  "token": "--mk-ink"
1274
1329
  }
1275
1330
  }
1331
+ },
1332
+ "focus-visible": {
1333
+ "_": {
1334
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1335
+ }
1276
1336
  }
1277
1337
  },
1278
1338
  "text": "§07 CONTACT"
@@ -1705,6 +1765,11 @@
1705
1765
  "transitionAll": "180ms ease"
1706
1766
  }
1707
1767
  },
1768
+ "focus-visible": {
1769
+ "_": {
1770
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1771
+ }
1772
+ },
1708
1773
  "hover": {
1709
1774
  "_": {
1710
1775
  "backgroundColor": {
@@ -1742,6 +1807,11 @@
1742
1807
  "transitionAll": "180ms ease"
1743
1808
  }
1744
1809
  },
1810
+ "focus-visible": {
1811
+ "_": {
1812
+ "customStyles": "outline:2px solid rgb(255,90,54);outline-offset:3px;"
1813
+ }
1814
+ },
1745
1815
  "hover": {
1746
1816
  "_": {
1747
1817
  "color": {
@@ -6315,7 +6385,7 @@
6315
6385
  "alignItems": "baseline",
6316
6386
  "paddingTop": "18px",
6317
6387
  "paddingBottom": "18px",
6318
- "customStyles": "border-top:1px solid rgba(22,24,28,.16);"
6388
+ "customStyles": "border-top:1px solid rgba(22,24,28,.16);animation:mk-rise both;animation-timeline:view();animation-range:entry 2% cover 18%;"
6319
6389
  },
6320
6390
  "_m": {
6321
6391
  "gridCols": "1fr",
@@ -6555,7 +6625,7 @@
6555
6625
  "alignItems": "baseline",
6556
6626
  "paddingTop": "18px",
6557
6627
  "paddingBottom": "18px",
6558
- "customStyles": "border-top:1px solid rgba(22,24,28,.16);"
6628
+ "customStyles": "border-top:1px solid rgba(22,24,28,.16);animation:mk-rise both;animation-timeline:view();animation-range:entry 6% cover 22%;"
6559
6629
  },
6560
6630
  "_m": {
6561
6631
  "gridCols": "1fr",
@@ -6795,7 +6865,7 @@
6795
6865
  "alignItems": "baseline",
6796
6866
  "paddingTop": "18px",
6797
6867
  "paddingBottom": "18px",
6798
- "customStyles": "border-top:1px solid rgba(22,24,28,.16);"
6868
+ "customStyles": "border-top:1px solid rgba(22,24,28,.16);animation:mk-rise both;animation-timeline:view();animation-range:entry 10% cover 26%;"
6799
6869
  },
6800
6870
  "_m": {
6801
6871
  "gridCols": "1fr",
@@ -7035,7 +7105,7 @@
7035
7105
  "alignItems": "baseline",
7036
7106
  "paddingTop": "18px",
7037
7107
  "paddingBottom": "18px",
7038
- "customStyles": "border-top:1px solid rgba(22,24,28,.16);"
7108
+ "customStyles": "border-top:1px solid rgba(22,24,28,.16);animation:mk-rise both;animation-timeline:view();animation-range:entry 14% cover 30%;"
7039
7109
  },
7040
7110
  "_m": {
7041
7111
  "gridCols": "1fr",
@@ -7275,7 +7345,7 @@
7275
7345
  "alignItems": "baseline",
7276
7346
  "paddingTop": "18px",
7277
7347
  "paddingBottom": "18px",
7278
- "customStyles": "border-top:1px solid rgba(22,24,28,.16);"
7348
+ "customStyles": "border-top:1px solid rgba(22,24,28,.16);animation:mk-rise both;animation-timeline:view();animation-range:entry 18% cover 34%;"
7279
7349
  },
7280
7350
  "_m": {
7281
7351
  "gridCols": "1fr",
package/tools/mo.py CHANGED
@@ -410,13 +410,40 @@ def cmd_css(a):
410
410
 
411
411
 
412
412
  def cmd_states(a):
413
- out = [r for r in rows("style-states")
414
- if matches(r["state"], a.grep) or matches(r["selector_template"], a.grep)]
415
- emit(out, lambda: (
416
- table(["state", "selector", "scope"],
417
- [[r["state"], r["selector_template"], r["scope"]] for r in out]),
413
+ """A state joined to whether it was ever seen to compile.
414
+
415
+ `style-states.csv` is what the source declares. `--verified` is the view that
416
+ answers the question you actually have when you are about to write one: a state
417
+ whose only host takes the whole page down is not a style you can use."""
418
+ ver = index("style-state-verification", "state")
419
+ out = []
420
+ for r in rows("style-states"):
421
+ if not (matches(r["state"], a.grep)
422
+ or matches(r["selector_template"], a.grep)):
423
+ continue
424
+ v = ver.get(r["state"], {})
425
+ status = v.get("status", "base state" if r["state"] == "&" else "")
426
+ if a.verified and status != "COMPILED":
427
+ continue
428
+ out.append({"state": r["state"], "selector": r["selector_template"],
429
+ "scope": r["scope"], "host": v.get("host", ""),
430
+ "status": status, "compiled_to": v.get("evidence", "")})
431
+
432
+ def render():
433
+ table(["state", "scope", "host", "swept", "selector"],
434
+ [[r["state"], r["scope"], r["host"], r["status"], r["selector"][:50]]
435
+ for r in out])
436
+ usable = [r for r in out
437
+ if r["scope"] == "global" and r["status"] == "COMPILED"]
418
438
  print("\n%d states. `&` is the base state; the breakpoint axis is separate "
419
- "(_ / _t / _m)." % len(out))))
439
+ "(_ / _t / _m)." % len(out))
440
+ if usable:
441
+ print("%d go on ANY element: %s"
442
+ % (len(usable), ", ".join(r["state"] for r in usable)))
443
+ print("The pseudo-class is emitted UPPERCASE (`.M_EL9:HOVER`), so grepping a "
444
+ "stylesheet\nfor `:hover` finds nothing.")
445
+
446
+ emit(out, render)
420
447
 
421
448
 
422
449
  def cmd_classes(a):
@@ -654,6 +681,8 @@ def main():
654
681
 
655
682
  p = add("states", cmd_states, "style states and their selectors")
656
683
  p.add_argument("--grep")
684
+ p.add_argument("--verified", action="store_true",
685
+ help="only states measured to compile to their promised selector")
657
686
 
658
687
  p = add("classes", cmd_classes, "element classes (theme-global)")
659
688
  p.add_argument("--grep")