@akonwi/mica 0.2.2 → 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.
Files changed (2) hide show
  1. package/mica.css +38 -10
  2. package/package.json +1 -1
package/mica.css CHANGED
@@ -644,16 +644,9 @@
644
644
  border-inline-start: 1px solid var(--color-border-strong);
645
645
  }
646
646
 
647
- :where(m-segmented) > :where(label) > :where(input[type="radio"]) {
648
- position: absolute;
649
- inline-size: 1px;
650
- block-size: 1px;
651
- margin: -1px;
652
- padding: 0;
653
- overflow: hidden;
654
- clip-path: inset(50%);
655
- white-space: nowrap;
656
- }
647
+ /* The radio itself is hidden but focusable and announced — the label
648
+ is the visible control. Shares the one hiding rule at the end of
649
+ this layer (see "visually hidden"). */
657
650
 
658
651
  :where(m-segmented) > :where(label):has(> input:checked) {
659
652
  background: var(--color-primary);
@@ -1611,6 +1604,41 @@
1611
1604
  :where(m-error[active]) {
1612
1605
  display: block;
1613
1606
  }
1607
+
1608
+ /* --- visually hidden: off-screen, still announced ------------------ *
1609
+ *
1610
+ * The one utility mica ships, and an accessibility primitive rather
1611
+ * than a style: content that assistive tech must reach but sighted
1612
+ * users must not see. `display: none` and `inline-size: 0` would drop
1613
+ * it from the accessibility tree; this keeps a 1px box in flow-ish
1614
+ * and clips it away.
1615
+ *
1616
+ * An attribute, not a class: `class` stays the app's, `data-*` is
1617
+ * valid HTML and needs no React `HTMLAttributes` augmentation, and
1618
+ * `.visually-hidden`/`.sr-only` are the most copy-pasted names in
1619
+ * accessibility — a consumer arriving with their own copy is the
1620
+ * likely case. Lives at the end of this layer, not a new one, because
1621
+ * the layer list is a published contract; being last lets it beat the
1622
+ * element rules it is applied to (`caption`, `legend`, headings).
1623
+ *
1624
+ * <caption data-visually-hidden>Standings</caption>
1625
+ * <a href="#main" data-visually-hidden="focusable">Skip to content</a>
1626
+ *
1627
+ * The `focusable` variant is the skip-link primitive: hidden until it
1628
+ * takes focus, then it simply stops being hidden — no undo rule, so
1629
+ * the element keeps whatever styling the app gave it. */
1630
+ [data-visually-hidden]:not([data-visually-hidden="focusable"]),
1631
+ [data-visually-hidden="focusable"]:not(:focus, :focus-within),
1632
+ :where(m-segmented) > :where(label) > :where(input[type="radio"]) {
1633
+ position: absolute;
1634
+ inline-size: 1px;
1635
+ block-size: 1px;
1636
+ margin: -1px;
1637
+ padding: 0;
1638
+ overflow: hidden;
1639
+ clip-path: inset(50%);
1640
+ white-space: nowrap;
1641
+ }
1614
1642
  }
1615
1643
 
1616
1644
  /* ------------------------------------------------------------------ *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@akonwi/mica",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Custom elements. Native behavior. Nearly no JavaScript.",
5
5
  "keywords": [
6
6
  "css",