@techsio/storybook-better-a11y 0.0.1 → 0.0.3

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/dist/699.js CHANGED
@@ -191,7 +191,7 @@ function isVisible(element) {
191
191
  const computed = global.getComputedStyle(element);
192
192
  return 'none' !== computed.display && 'hidden' !== computed.visibility && '0' !== computed.opacity;
193
193
  }
194
- async function runAPCACheck(context = apcaChecker_document, options = DEFAULT_APCA_OPTIONS) {
194
+ async function runAPCACheck(context = apcaChecker_document, options = DEFAULT_APCA_OPTIONS, excludeSelectors = []) {
195
195
  const { APCAcontrast, sRGBtoY, fontLookupAPCA } = await import("apca-w3");
196
196
  const apcaOptions = {
197
197
  ...DEFAULT_APCA_OPTIONS,
@@ -201,6 +201,16 @@ async function runAPCACheck(context = apcaChecker_document, options = DEFAULT_AP
201
201
  const root = context instanceof Document ? context.body : context;
202
202
  const textElements = root.querySelectorAll('p, span, div, h1, h2, h3, h4, h5, h6, a, button, label, td, th, li, input, textarea');
203
203
  textElements.forEach((element)=>{
204
+ if (excludeSelectors.length > 0) {
205
+ const isExcluded = excludeSelectors.some((selector)=>{
206
+ try {
207
+ return null !== element.closest(selector);
208
+ } catch {
209
+ return false;
210
+ }
211
+ });
212
+ if (isExcluded) return;
213
+ }
204
214
  if (!isVisible(element) || !hasReadableText(element)) return;
205
215
  const foreground = getComputedColor(element, 'color');
206
216
  const background = getEffectiveBackgroundColor(element);
@@ -381,7 +391,10 @@ const run = async (input = DEFAULT_PARAMETERS, storyId)=>{
381
391
  if (first instanceof Element) contextElement = first;
382
392
  else if ('string' == typeof first) contextElement = a11yRunner_document.querySelector(first) || a11yRunner_document;
383
393
  } else if ('string' == typeof context.include) contextElement = a11yRunner_document.querySelector(context.include) || a11yRunner_document;
384
- const apcaResult = await runAPCACheck(contextElement, input.apca);
394
+ const excludeSelectors = Array.isArray(context.exclude) ? context.exclude.filter((value)=>'string' == typeof value) : 'string' == typeof context.exclude ? [
395
+ context.exclude
396
+ ] : [];
397
+ const apcaResult = await runAPCACheck(contextElement, input.apca, excludeSelectors);
385
398
  if (apcaResult.nodes.length > 0) result.violations.push(apcaResult);
386
399
  else result.passes.push(apcaResult);
387
400
  const resultWithLinks = withLinkPaths(result, storyId);
@@ -1 +1 @@
1
- {"version":3,"file":"a11yRunner.d.ts","sourceRoot":"","sources":["../src/a11yRunner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,UAAU,CAAC;AAMrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAiC/C,eAAO,MAAM,GAAG,GAAU,OAAO,cAAc,YAAqB,EAAE,SAAS,MAAM,wBA4GpF,CAAC"}
1
+ {"version":3,"file":"a11yRunner.d.ts","sourceRoot":"","sources":["../src/a11yRunner.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAA4B,MAAM,UAAU,CAAC;AAMrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAiC/C,eAAO,MAAM,GAAG,GAAU,OAAO,cAAc,YAAqB,EAAE,SAAS,MAAM,wBAkHpF,CAAC"}
@@ -8,6 +8,6 @@ interface ApcaOptions {
8
8
  /**
9
9
  * Run APCA contrast checks on the document
10
10
  */
11
- export declare function runAPCACheck(context?: Element | Document, options?: ApcaOptions): Promise<Result>;
11
+ export declare function runAPCACheck(context?: Element | Document, options?: ApcaOptions, excludeSelectors?: string[]): Promise<Result>;
12
12
  export {};
13
13
  //# sourceMappingURL=apcaChecker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"apcaChecker.d.ts","sourceRoot":"","sources":["../src/apcaChecker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAYnD,KAAK,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACzD,KAAK,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AAEnE,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AA8OD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,GAAE,OAAO,GAAG,QAAmB,EACtC,OAAO,GAAE,WAAkC,GAC1C,OAAO,CAAC,MAAM,CAAC,CAoKjB"}
1
+ {"version":3,"file":"apcaChecker.d.ts","sourceRoot":"","sources":["../src/apcaChecker.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAc,MAAM,UAAU,CAAC;AAYnD,KAAK,oBAAoB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AACzD,KAAK,WAAW,GAAG,MAAM,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;AAEnE,UAAU,WAAW;IACnB,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,OAAO,CAAC,EAAE,WAAW,CAAC;CACvB;AA8OD;;GAEG;AACH,wBAAsB,YAAY,CAChC,OAAO,GAAE,OAAO,GAAG,QAAmB,EACtC,OAAO,GAAE,WAAkC,EAC3C,gBAAgB,GAAE,MAAM,EAAO,GAC9B,OAAO,CAAC,MAAM,CAAC,CA+KjB"}
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAkBzC,UAAU,SAAS;IACjB,IAAI,EAAE;QACJ,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC;QAC1B,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC;QAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,EAAE,QAAQ,CAAC;KAChB,EAAE,CAAC;CACL;AAED,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA+DpC,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../src/components/Tabs.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGvC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAkBzC,UAAU,SAAS;IACjB,IAAI,EAAE;QACJ,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC;QAC1B,KAAK,EAAE,KAAK,CAAC,YAAY,CAAC;QAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,IAAI,EAAE,QAAQ,CAAC;KAChB,EAAE,CAAC;CACL;AAQD,eAAO,MAAM,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,CA8DpC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"VisionSimulator.d.ts","sourceRoot":"","sources":["../../src/components/VisionSimulator.tsx"],"names":[],"mappings":"AAqCA,eAAO,MAAM,eAAe,+CAyB3B,CAAC"}
1
+ {"version":3,"file":"VisionSimulator.d.ts","sourceRoot":"","sources":["../../src/components/VisionSimulator.tsx"],"names":[],"mappings":"AA8DA,eAAO,MAAM,eAAe,+CAuC3B,CAAC"}
package/dist/manager.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import react, { Fragment, createContext, createElement, useCallback, useContext, useEffect, useMemo, useState } from "react";
2
- import { Badge, Button, EmptyTabContent, Link, Select, SyntaxHighlighter, TabsView } from "storybook/internal/components";
2
+ import { Badge, Button, EmptyTabContent, Link, SyntaxHighlighter, Tabs } from "storybook/internal/components";
3
3
  import { addons, experimental_getStatusStore, experimental_useStatusStore, types, useAddonState, useChannel, useGlobals, useParameter, useStorybookApi, useStorybookState } from "storybook/manager-api";
4
4
  import { AccessibilityIcon, CheckIcon, ChevronSmallDownIcon, CollapseIcon, CopyIcon, ExpandAltIcon, EyeCloseIcon, EyeIcon, LocationIcon, SyncIcon } from "@storybook/icons";
5
5
  import { convert, styled, themes, useTheme } from "storybook/theming";
@@ -1246,21 +1246,18 @@ const ActionsWrapper = styled.div({
1246
1246
  justifyContent: 'flex-end',
1247
1247
  gap: 6
1248
1248
  });
1249
- const Tabs = ({ tabs })=>{
1249
+ const TabPanel = ({ id, children })=>/*#__PURE__*/ createElement("div", {
1250
+ id: id
1251
+ }, children);
1252
+ const Tabs_Tabs = ({ tabs })=>{
1250
1253
  const { tab, setTab, toggleHighlight, highlighted, handleManual, allExpanded, handleCollapseAll, handleExpandAll } = useA11yContext();
1251
1254
  const theme = useTheme();
1252
- return /*#__PURE__*/ createElement(Container, null, /*#__PURE__*/ createElement(TabsView, {
1255
+ return /*#__PURE__*/ createElement(Container, null, /*#__PURE__*/ createElement(Tabs, {
1253
1256
  backgroundColor: theme.background.app,
1254
- panelProps: {
1255
- hasScrollbar: true
1256
- },
1257
- tabs: tabs.map((tab)=>({
1258
- id: tab.type,
1259
- title: tab.label,
1260
- children: tab.panel
1261
- })),
1262
1257
  selected: tab,
1263
- onSelectionChange: (key)=>setTab(key),
1258
+ actions: {
1259
+ onSelect: (id)=>setTab(id)
1260
+ },
1264
1261
  tools: /*#__PURE__*/ createElement(ActionsWrapper, null, /*#__PURE__*/ createElement(Button, {
1265
1262
  variant: "ghost",
1266
1263
  padding: "small",
@@ -1278,7 +1275,11 @@ const Tabs = ({ tabs })=>{
1278
1275
  onClick: handleManual,
1279
1276
  ariaLabel: "Rerun accessibility scan"
1280
1277
  }, /*#__PURE__*/ createElement(SyncIcon, null)))
1281
- }));
1278
+ }, tabs.map((tabItem)=>/*#__PURE__*/ createElement(TabPanel, {
1279
+ key: tabItem.type,
1280
+ id: tabItem.type,
1281
+ title: tabItem.label
1282
+ }, tabItem.panel))));
1282
1283
  };
1283
1284
  const TestDiscrepancyMessage_Wrapper = styled.div(({ theme: { color, typography, background } })=>({
1284
1285
  textAlign: 'start',
@@ -1434,7 +1435,7 @@ const A11YPanel = ()=>{
1434
1435
  if (parameters.disable || 'off' === parameters.test) return /*#__PURE__*/ react.createElement(Centered, null, /*#__PURE__*/ react.createElement("div", null, /*#__PURE__*/ react.createElement("strong", null, "Accessibility tests are disabled for this story"), /*#__PURE__*/ react.createElement("p", null, "Update", ' ', /*#__PURE__*/ react.createElement("code", null, parameters.disable ? 'parameters.a11y.disable' : 'parameters.a11y.test'), ' ', "to enable accessibility tests.")));
1435
1436
  return /*#__PURE__*/ react.createElement(react.Fragment, null, discrepancy && /*#__PURE__*/ react.createElement(TestDiscrepancyMessage, {
1436
1437
  discrepancy: discrepancy
1437
- }), 'ready' === status || 'ran' === status ? /*#__PURE__*/ react.createElement(Tabs, {
1438
+ }), 'ready' === status || 'ran' === status ? /*#__PURE__*/ react.createElement(Tabs_Tabs, {
1438
1439
  key: "tabs",
1439
1440
  tabs: tabs
1440
1441
  }) : /*#__PURE__*/ react.createElement(Centered, {
@@ -1478,30 +1479,57 @@ const ColorIcon = styled.span({
1478
1479
  }), ({ theme })=>({
1479
1480
  boxShadow: `${theme.appBorderColor} 0 0 0 1px inset`
1480
1481
  }));
1482
+ const SelectRow = styled.div(({ theme })=>({
1483
+ display: 'flex',
1484
+ alignItems: 'center',
1485
+ gap: 8,
1486
+ padding: '6px 10px',
1487
+ border: `1px solid ${theme.appBorderColor}`,
1488
+ borderRadius: theme.appBorderRadius,
1489
+ background: theme.background.content
1490
+ }));
1491
+ const SelectInput = styled.select(({ theme })=>({
1492
+ flex: 1,
1493
+ minWidth: 0,
1494
+ padding: '4px 6px',
1495
+ border: `1px solid ${theme.appBorderColor}`,
1496
+ borderRadius: theme.appBorderRadius,
1497
+ background: theme.background.app,
1498
+ color: theme.color.defaultText,
1499
+ fontSize: theme.typography.size.s2
1500
+ }));
1501
+ const ResetButton = styled(Button)({
1502
+ whiteSpace: 'nowrap'
1503
+ });
1481
1504
  const VisionSimulator = ()=>{
1482
1505
  const [globals, updateGlobals] = useGlobals();
1483
1506
  const value = globals["vision"];
1484
1507
  const options = Object.entries(filters).map(([key, { label, percentage }])=>({
1485
- title: label,
1486
- description: percentage ? `${percentage}% of users` : void 0,
1487
- icon: /*#__PURE__*/ react.createElement(ColorIcon, {
1488
- $filter: key
1489
- }),
1508
+ label: percentage ? `${label} (${percentage}% of users)` : label,
1490
1509
  value: key
1491
1510
  }));
1492
- return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(Select, {
1493
- resetLabel: "Reset color filter",
1494
- onReset: ()=>updateGlobals({
1511
+ return /*#__PURE__*/ react.createElement(react.Fragment, null, /*#__PURE__*/ react.createElement(SelectRow, {
1512
+ "aria-label": "Vision simulator"
1513
+ }, /*#__PURE__*/ react.createElement(AccessibilityIcon, null), /*#__PURE__*/ react.createElement(ColorIcon, {
1514
+ $filter: String(value || 'none')
1515
+ }), /*#__PURE__*/ react.createElement(SelectInput, {
1516
+ value: value ?? '',
1517
+ onChange: (event)=>updateGlobals({
1518
+ ["vision"]: event.target.value || void 0
1519
+ })
1520
+ }, /*#__PURE__*/ react.createElement("option", {
1521
+ value: ""
1522
+ }, "No filter"), options.map((option)=>/*#__PURE__*/ react.createElement("option", {
1523
+ key: option.value,
1524
+ value: option.value
1525
+ }, option.label))), /*#__PURE__*/ react.createElement(ResetButton, {
1526
+ variant: "ghost",
1527
+ padding: "small",
1528
+ onClick: ()=>updateGlobals({
1495
1529
  ["vision"]: void 0
1496
1530
  }),
1497
- icon: /*#__PURE__*/ react.createElement(AccessibilityIcon, null),
1498
- ariaLabel: "Vision simulator",
1499
- defaultOptions: value,
1500
- options: options,
1501
- onSelect: (selected)=>updateGlobals({
1502
- ["vision"]: selected
1503
- })
1504
- }), /*#__PURE__*/ react.createElement(Hidden, {
1531
+ ariaLabel: "Reset color filter"
1532
+ }, "Reset")), /*#__PURE__*/ react.createElement(Hidden, {
1505
1533
  dangerouslySetInnerHTML: {
1506
1534
  __html: filterDefs
1507
1535
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@techsio/storybook-better-a11y",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Storybook Accessibility addon with APCA (WCAG 3) support",
5
5
  "keywords": [
6
6
  "storybook",
@@ -12,6 +12,11 @@
12
12
  ],
13
13
  "license": "MIT",
14
14
  "type": "module",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "https://github.com/NMIT-WR/storybook-addons",
18
+ "directory": "packages/addon-a11y-apca"
19
+ },
15
20
  "exports": {
16
21
  ".": {
17
22
  "types": "./dist/index.d.ts",
@@ -33,7 +38,8 @@
33
38
  "scripts": {
34
39
  "build": "rslib build",
35
40
  "lint": "eslint .",
36
- "test": "vitest run"
41
+ "test": "vitest run",
42
+ "semantic-release": "semantic-release"
37
43
  },
38
44
  "dependencies": {
39
45
  "@storybook/global": "^5.0.0",
@@ -43,10 +49,18 @@
43
49
  "devDependencies": {
44
50
  "@types/react": "^18.2.66",
45
51
  "@types/react-dom": "^18.2.21",
52
+ "@semantic-release/changelog": "^6.0.3",
53
+ "@semantic-release/commit-analyzer": "^13.0.1",
54
+ "@semantic-release/git": "^10.0.1",
55
+ "@semantic-release/github": "^12.0.2",
56
+ "@semantic-release/npm": "^13.1.2",
57
+ "@semantic-release/release-notes-generator": "^14.1.0",
46
58
  "@radix-ui/react-tabs": "^1.0.4",
47
59
  "@storybook/icons": "^2.0.1",
60
+ "rsbuild-plugin-publint": "^0.3.3",
48
61
  "react": "^18.2.0",
49
62
  "react-dom": "^18.2.0",
63
+ "semantic-release": "^25.0.2",
50
64
  "storybook": "^10.0.0",
51
65
  "vitest-axe": "^0.1.0"
52
66
  },