@a.nemreen/a11y 0.1.3 → 0.1.6

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/README.md CHANGED
@@ -75,6 +75,10 @@ Accessibility.mount();
75
75
 
76
76
  [https://nemreen.info/a11y](https://nemreen.info/a11y)
77
77
 
78
+ ## Architecture
79
+
80
+ [arc42](docs/architecture/README.md) (what to document) and [C4](docs/architecture/c4/README.md) (how to visualize it) — goals, context, building blocks, runtime, decisions, and known risks.
81
+
78
82
  ## License
79
83
 
80
84
  MIT © [Ahmed Nemreen](https://nemreen.info)
package/dist/index.cjs CHANGED
@@ -475,7 +475,8 @@ function createSkipLink(options = {}) {
475
475
  position: absolute;
476
476
  inset-inline-start: 1rem;
477
477
  top: 1rem;
478
- z-index: 10000;
478
+ z-index: 2147483647;
479
+ pointer-events: auto;
479
480
  padding: 0.5rem 1rem;
480
481
  border-radius: 0.375rem;
481
482
  background: #fff;
@@ -660,7 +661,10 @@ function getCopy(locale) {
660
661
 
661
662
  // src/icons.ts
662
663
  var ICONS = {
663
- access: '<path d="M12 2a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm-1 7h2l1.5 4H16l-1 2h-1.2L12.5 11h-1L10.2 15H9l-1-2h1.5L11 9Zm-5.5 9.5L8 14l1.2 1.6L12 12l2.8 3.6L16 14l2.5 4.5H5.5Z"/>',
664
+ /**
665
+ * GDS access icon (exact markup from the design system).
666
+ */
667
+ access: '<path fill="currentColor" d="M16.853 8.265a.75.75 0 0 1 .294 1.47l-4.397.88v2.24l1.946 4.867a.75.75 0 1 1-1.392.556L12 15.02l-1.304 3.258a.75.75 0 1 1-1.392-.556l1.946-4.867v-2.24l-4.397-.88a.75.75 0 1 1 .294-1.47l4.853.97zM12 5.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5"/><path fill="currentColor" fill-rule="evenodd" d="M12 1.25c5.937 0 10.75 4.813 10.75 10.75S17.937 22.75 12 22.75 1.25 17.937 1.25 12 6.063 1.25 12 1.25m0 1.5a9.25 9.25 0 1 0 0 18.5 9.25 9.25 0 0 0 0-18.5" clip-rule="evenodd"/>',
664
668
  close: '<path d="M6.7 6.7a1 1 0 0 1 1.4 0L12 10.6l3.9-3.9a1 1 0 1 1 1.4 1.4L13.4 12l3.9 3.9a1 1 0 0 1-1.4 1.4L12 13.4l-3.9 3.9a1 1 0 0 1-1.4-1.4L10.6 12 6.7 8.1a1 1 0 0 1 0-1.4Z"/>',
665
669
  flash: '<path d="M13 2 4 14h7l-1 8 10-14h-7l1-6Z"/>',
666
670
  eye: '<path d="M12 5c-5 0-9 4.5-10 7 1 2.5 5 7 10 7s9-4.5 10-7c-1-2.5-5-7-10-7Zm0 11a4 4 0 1 1 0-8 4 4 0 0 1 0 8Z"/>',
@@ -702,6 +706,9 @@ var STROKE_ICONS = /* @__PURE__ */ new Set([
702
706
  ]);
703
707
  function iconSvg(name, size = 18) {
704
708
  const path = ICONS[name] ?? ICONS.access;
709
+ if (name === "access") {
710
+ return `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="a11y-icon" width="${size}" height="${size}" aria-hidden="true" focusable="false">${path}</svg>`;
711
+ }
705
712
  if (STROKE_ICONS.has(name)) {
706
713
  return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${path}</svg>`;
707
714
  }
@@ -761,6 +768,8 @@ var A11yWidget = class {
761
768
  e.preventDefault();
762
769
  this.draggingMask = true;
763
770
  };
771
+ this.topObserver = null;
772
+ this.topFrame = 0;
764
773
  this.ctrl = ctrl;
765
774
  this.position = options.position ?? "end";
766
775
  this.stack = Math.max(0, options.stack ?? 0);
@@ -778,11 +787,16 @@ var A11yWidget = class {
778
787
  document.addEventListener("keydown", this.onKeyDown);
779
788
  document.addEventListener("pointermove", this.onPointerMove);
780
789
  document.addEventListener("pointerup", this.onPointerUp);
790
+ this.keepOnTop();
781
791
  this.render();
782
792
  }
783
793
  destroy() {
784
794
  this.unsub?.();
785
795
  this.unsub = null;
796
+ this.topObserver?.disconnect();
797
+ this.topObserver = null;
798
+ if (this.topFrame) cancelAnimationFrame(this.topFrame);
799
+ this.topFrame = 0;
786
800
  this.rootEl?.removeEventListener("click", this.onRootClick);
787
801
  this.rootEl?.removeEventListener("pointerdown", this.onRootPointerDown);
788
802
  document.removeEventListener("keydown", this.onKeyDown);
@@ -792,6 +806,25 @@ var A11yWidget = class {
792
806
  this.rootEl?.remove();
793
807
  this.rootEl = null;
794
808
  }
809
+ /** Stay the last child so equal-z-index overlays appended later cannot cover us. */
810
+ keepOnTop() {
811
+ const parent = this.rootEl?.parentElement;
812
+ if (!parent || !this.rootEl) return;
813
+ const bump = () => {
814
+ if (!this.rootEl || this.rootEl.parentElement !== parent) return;
815
+ if (parent.lastElementChild === this.rootEl) return;
816
+ parent.appendChild(this.rootEl);
817
+ };
818
+ this.topObserver = new MutationObserver(() => {
819
+ if (this.topFrame) return;
820
+ this.topFrame = requestAnimationFrame(() => {
821
+ this.topFrame = 0;
822
+ bump();
823
+ });
824
+ });
825
+ this.topObserver.observe(parent, { childList: true });
826
+ bump();
827
+ }
795
828
  copy() {
796
829
  return getCopy(this.ctrl.locale);
797
830
  }
package/dist/index.d.cts CHANGED
@@ -142,9 +142,13 @@ declare class A11yWidget {
142
142
  private onPointerUp;
143
143
  private onRootClick;
144
144
  private onRootPointerDown;
145
+ private topObserver;
146
+ private topFrame;
145
147
  constructor(ctrl: A11yController, options?: A11yWidgetOptions);
146
148
  mount(): void;
147
149
  destroy(): void;
150
+ /** Stay the last child so equal-z-index overlays appended later cannot cover us. */
151
+ private keepOnTop;
148
152
  private copy;
149
153
  private fabBottom;
150
154
  private activeChips;
package/dist/index.d.ts CHANGED
@@ -142,9 +142,13 @@ declare class A11yWidget {
142
142
  private onPointerUp;
143
143
  private onRootClick;
144
144
  private onRootPointerDown;
145
+ private topObserver;
146
+ private topFrame;
145
147
  constructor(ctrl: A11yController, options?: A11yWidgetOptions);
146
148
  mount(): void;
147
149
  destroy(): void;
150
+ /** Stay the last child so equal-z-index overlays appended later cannot cover us. */
151
+ private keepOnTop;
148
152
  private copy;
149
153
  private fabBottom;
150
154
  private activeChips;
package/dist/index.js CHANGED
@@ -473,7 +473,8 @@ function createSkipLink(options = {}) {
473
473
  position: absolute;
474
474
  inset-inline-start: 1rem;
475
475
  top: 1rem;
476
- z-index: 10000;
476
+ z-index: 2147483647;
477
+ pointer-events: auto;
477
478
  padding: 0.5rem 1rem;
478
479
  border-radius: 0.375rem;
479
480
  background: #fff;
@@ -658,7 +659,10 @@ function getCopy(locale) {
658
659
 
659
660
  // src/icons.ts
660
661
  var ICONS = {
661
- access: '<path d="M12 2a3 3 0 1 1 0 6 3 3 0 0 1 0-6Zm-1 7h2l1.5 4H16l-1 2h-1.2L12.5 11h-1L10.2 15H9l-1-2h1.5L11 9Zm-5.5 9.5L8 14l1.2 1.6L12 12l2.8 3.6L16 14l2.5 4.5H5.5Z"/>',
662
+ /**
663
+ * GDS access icon (exact markup from the design system).
664
+ */
665
+ access: '<path fill="currentColor" d="M16.853 8.265a.75.75 0 0 1 .294 1.47l-4.397.88v2.24l1.946 4.867a.75.75 0 1 1-1.392.556L12 15.02l-1.304 3.258a.75.75 0 1 1-1.392-.556l1.946-4.867v-2.24l-4.397-.88a.75.75 0 1 1 .294-1.47l4.853.97zM12 5.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5"/><path fill="currentColor" fill-rule="evenodd" d="M12 1.25c5.937 0 10.75 4.813 10.75 10.75S17.937 22.75 12 22.75 1.25 17.937 1.25 12 6.063 1.25 12 1.25m0 1.5a9.25 9.25 0 1 0 0 18.5 9.25 9.25 0 0 0 0-18.5" clip-rule="evenodd"/>',
662
666
  close: '<path d="M6.7 6.7a1 1 0 0 1 1.4 0L12 10.6l3.9-3.9a1 1 0 1 1 1.4 1.4L13.4 12l3.9 3.9a1 1 0 0 1-1.4 1.4L12 13.4l-3.9 3.9a1 1 0 0 1-1.4-1.4L10.6 12 6.7 8.1a1 1 0 0 1 0-1.4Z"/>',
663
667
  flash: '<path d="M13 2 4 14h7l-1 8 10-14h-7l1-6Z"/>',
664
668
  eye: '<path d="M12 5c-5 0-9 4.5-10 7 1 2.5 5 7 10 7s9-4.5 10-7c-1-2.5-5-7-10-7Zm0 11a4 4 0 1 1 0-8 4 4 0 0 1 0 8Z"/>',
@@ -700,6 +704,9 @@ var STROKE_ICONS = /* @__PURE__ */ new Set([
700
704
  ]);
701
705
  function iconSvg(name, size = 18) {
702
706
  const path = ICONS[name] ?? ICONS.access;
707
+ if (name === "access") {
708
+ return `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="a11y-icon" width="${size}" height="${size}" aria-hidden="true" focusable="false">${path}</svg>`;
709
+ }
703
710
  if (STROKE_ICONS.has(name)) {
704
711
  return `<svg class="a11y-icon" width="${size}" height="${size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">${path}</svg>`;
705
712
  }
@@ -759,6 +766,8 @@ var A11yWidget = class {
759
766
  e.preventDefault();
760
767
  this.draggingMask = true;
761
768
  };
769
+ this.topObserver = null;
770
+ this.topFrame = 0;
762
771
  this.ctrl = ctrl;
763
772
  this.position = options.position ?? "end";
764
773
  this.stack = Math.max(0, options.stack ?? 0);
@@ -776,11 +785,16 @@ var A11yWidget = class {
776
785
  document.addEventListener("keydown", this.onKeyDown);
777
786
  document.addEventListener("pointermove", this.onPointerMove);
778
787
  document.addEventListener("pointerup", this.onPointerUp);
788
+ this.keepOnTop();
779
789
  this.render();
780
790
  }
781
791
  destroy() {
782
792
  this.unsub?.();
783
793
  this.unsub = null;
794
+ this.topObserver?.disconnect();
795
+ this.topObserver = null;
796
+ if (this.topFrame) cancelAnimationFrame(this.topFrame);
797
+ this.topFrame = 0;
784
798
  this.rootEl?.removeEventListener("click", this.onRootClick);
785
799
  this.rootEl?.removeEventListener("pointerdown", this.onRootPointerDown);
786
800
  document.removeEventListener("keydown", this.onKeyDown);
@@ -790,6 +804,25 @@ var A11yWidget = class {
790
804
  this.rootEl?.remove();
791
805
  this.rootEl = null;
792
806
  }
807
+ /** Stay the last child so equal-z-index overlays appended later cannot cover us. */
808
+ keepOnTop() {
809
+ const parent = this.rootEl?.parentElement;
810
+ if (!parent || !this.rootEl) return;
811
+ const bump = () => {
812
+ if (!this.rootEl || this.rootEl.parentElement !== parent) return;
813
+ if (parent.lastElementChild === this.rootEl) return;
814
+ parent.appendChild(this.rootEl);
815
+ };
816
+ this.topObserver = new MutationObserver(() => {
817
+ if (this.topFrame) return;
818
+ this.topFrame = requestAnimationFrame(() => {
819
+ this.topFrame = 0;
820
+ bump();
821
+ });
822
+ });
823
+ this.topObserver.observe(parent, { childList: true });
824
+ bump();
825
+ }
793
826
  copy() {
794
827
  return getCopy(this.ctrl.locale);
795
828
  }
package/dist/styles.css CHANGED
@@ -279,6 +279,13 @@ html {
279
279
  --a11y-fab-size: 3.5rem;
280
280
  --a11y-fab-edge: 2rem;
281
281
  --a11y-fab-stack-step: 4.25rem;
282
+ /* Beat host overlays (modals, CDK, 2147483000 FABs). Override via --a11y-z. */
283
+ --a11y-z: 2147483647;
284
+ position: fixed;
285
+ inset: 0;
286
+ z-index: var(--a11y-z);
287
+ isolation: isolate;
288
+ pointer-events: none;
282
289
  /* Isolate widget chrome from page font-scale / spacing modes */
283
290
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
284
291
  font-size: 14px;
@@ -294,6 +301,12 @@ html {
294
301
  word-spacing: normal;
295
302
  }
296
303
 
304
+ .a11y-fab,
305
+ .a11y-layer,
306
+ .a11y-mask-toolbar {
307
+ pointer-events: auto;
308
+ }
309
+
297
310
  .a11y-fab {
298
311
  position: fixed;
299
312
  z-index: 390;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a.nemreen/a11y",
3
- "version": "0.1.3",
3
+ "version": "0.1.6",
4
4
  "description": "Framework-agnostic accessibility tools widget — profiles, readable experience, visual filters. Works with Angular, React, Vue, and plain HTML.",
5
5
  "author": {
6
6
  "name": "Ahmed Nemreen",
@@ -24,8 +24,15 @@
24
24
  "exports": {
25
25
  ".": {
26
26
  "types": "./dist/index.d.ts",
27
- "import": "./dist/index.js",
28
- "require": "./dist/index.cjs"
27
+ "import": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "require": {
32
+ "types": "./dist/index.d.cts",
33
+ "default": "./dist/index.cjs"
34
+ },
35
+ "default": "./dist/index.js"
29
36
  },
30
37
  "./styles.css": "./dist/styles.css"
31
38
  },