@stackoverflow/stacks 2.0.8 → 2.1.0-rc.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 (103) hide show
  1. package/LICENSE.MD +1 -1
  2. package/README.md +7 -9
  3. package/dist/css/stacks.css +234 -214
  4. package/dist/css/stacks.min.css +1 -1
  5. package/dist/js/stacks.js +1 -1
  6. package/lib/atomic/misc.less +1 -1
  7. package/lib/components/activity-indicator/activity-indicator.a11y.test.ts +2 -3
  8. package/lib/components/activity-indicator/activity-indicator.less +5 -5
  9. package/lib/components/activity-indicator/activity-indicator.visual.test.ts +2 -3
  10. package/lib/components/anchor/anchor.a11y.test.ts +2 -4
  11. package/lib/components/anchor/anchor.visual.test.ts +2 -4
  12. package/lib/components/avatar/avatar.a11y.test.ts +2 -3
  13. package/lib/components/avatar/avatar.visual.test.ts +2 -3
  14. package/lib/components/award-bling/award-bling.a11y.test.ts +2 -4
  15. package/lib/components/award-bling/award-bling.visual.test.ts +2 -4
  16. package/lib/components/badge/badge.a11y.test.ts +7 -16
  17. package/lib/components/badge/badge.visual.test.ts +8 -21
  18. package/lib/components/banner/banner.a11y.test.ts +2 -3
  19. package/lib/components/banner/banner.visual.test.ts +2 -3
  20. package/lib/components/block-link/block-link.a11y.test.ts +4 -9
  21. package/lib/components/block-link/block-link.less +7 -10
  22. package/lib/components/block-link/block-link.visual.test.ts +4 -9
  23. package/lib/components/breadcrumbs/breadcrumbs.a11y.test.ts +2 -3
  24. package/lib/components/breadcrumbs/breadcrumbs.visual.test.ts +2 -3
  25. package/lib/components/button/button.a11y.test.ts +2 -3
  26. package/lib/components/button/button.less +70 -35
  27. package/lib/components/button/button.visual.test.ts +2 -3
  28. package/lib/components/card/card.a11y.test.ts +2 -3
  29. package/lib/components/card/card.visual.test.ts +3 -6
  30. package/lib/components/check-control/check-control.a11y.test.ts +2 -4
  31. package/lib/components/check-control/check-control.visual.test.ts +2 -4
  32. package/lib/components/check-group/check-group.a11y.test.ts +2 -4
  33. package/lib/components/check-group/check-group.visual.test.ts +2 -4
  34. package/lib/components/checkbox_radio/checkbox_radio.a11y.test.ts +2 -4
  35. package/lib/components/checkbox_radio/checkbox_radio.less +1 -13
  36. package/lib/components/checkbox_radio/checkbox_radio.visual.test.ts +2 -4
  37. package/lib/components/code-block/code-block.a11y.test.ts +2 -4
  38. package/lib/components/code-block/code-block.visual.test.ts +2 -4
  39. package/lib/components/description/description.a11y.test.ts +2 -4
  40. package/lib/components/description/description.visual.test.ts +2 -4
  41. package/lib/components/empty-state/empty-state.a11y.test.ts +2 -3
  42. package/lib/components/empty-state/empty-state.visual.test.ts +2 -3
  43. package/lib/components/expandable/expandable.a11y.test.ts +2 -3
  44. package/lib/components/expandable/expandable.visual.test.ts +2 -3
  45. package/lib/components/input-fill/input-fill.a11y.test.ts +2 -3
  46. package/lib/components/input-fill/input-fill.visual.test.ts +2 -3
  47. package/lib/components/input-message/input-message.a11y.test.ts +2 -3
  48. package/lib/components/input-message/input-message.visual.test.ts +2 -3
  49. package/lib/components/input_textarea/input_textarea.a11y.test.ts +4 -7
  50. package/lib/components/input_textarea/input_textarea.less +2 -20
  51. package/lib/components/input_textarea/input_textarea.visual.test.ts +4 -7
  52. package/lib/components/label/label.a11y.test.ts +2 -3
  53. package/lib/components/label/label.visual.test.ts +2 -3
  54. package/lib/components/link/link.a11y.test.ts +2 -3
  55. package/lib/components/link/link.visual.test.ts +2 -3
  56. package/lib/components/link-preview/link-preview.a11y.test.ts +2 -3
  57. package/lib/components/link-preview/link-preview.visual.test.ts +3 -3
  58. package/lib/components/menu/menu.a11y.test.ts +2 -3
  59. package/lib/components/menu/menu.visual.test.ts +2 -3
  60. package/lib/components/modal/modal.a11y.test.ts +2 -3
  61. package/lib/components/modal/modal.visual.test.ts +2 -3
  62. package/lib/components/navigation/navigation.a11y.test.ts +2 -3
  63. package/lib/components/navigation/navigation.less +3 -1
  64. package/lib/components/navigation/navigation.visual.test.ts +3 -6
  65. package/lib/components/notice/notice.a11y.test.ts +2 -3
  66. package/lib/components/notice/notice.visual.test.ts +2 -3
  67. package/lib/components/page-title/page-title.a11y.test.ts +2 -3
  68. package/lib/components/page-title/page-title.visual.test.ts +2 -3
  69. package/lib/components/pagination/pagination.a11y.test.ts +2 -3
  70. package/lib/components/pagination/pagination.less +9 -0
  71. package/lib/components/pagination/pagination.visual.test.ts +2 -3
  72. package/lib/components/progress-bar/progress-bar.a11y.test.ts +7 -18
  73. package/lib/components/progress-bar/progress-bar.less +1 -1
  74. package/lib/components/progress-bar/progress-bar.visual.test.ts +7 -18
  75. package/lib/components/select/select.less +1 -15
  76. package/lib/components/spinner/spinner.a11y.test.ts +2 -3
  77. package/lib/components/spinner/spinner.visual.test.ts +4 -7
  78. package/lib/components/table/table.a11y.test.ts +3 -4
  79. package/lib/components/table/table.visual.test.ts +2 -3
  80. package/lib/components/tag/tag.a11y.test.ts +2 -3
  81. package/lib/components/tag/tag.less +27 -21
  82. package/lib/components/tag/tag.visual.test.ts +3 -6
  83. package/lib/components/toast/toast.a11y.test.ts +2 -3
  84. package/lib/components/toast/toast.visual.test.ts +2 -3
  85. package/lib/components/toggle-switch/toggle-switch.a11y.test.ts +3 -6
  86. package/lib/components/toggle-switch/toggle-switch.less +5 -16
  87. package/lib/components/toggle-switch/toggle-switch.visual.test.ts +3 -7
  88. package/lib/components/topbar/topbar.less +61 -39
  89. package/lib/components/topbar/topbar.visual.test.ts +188 -0
  90. package/lib/components/uploader/uploader.less +1 -1
  91. package/lib/exports/__snapshots__/color-mixins.less.test.ts.snap +12 -0
  92. package/lib/exports/__snapshots__/color.less.test.ts.snap +45 -0
  93. package/lib/exports/color-mixins.less +2 -0
  94. package/lib/exports/color-sets.less +44 -7
  95. package/lib/exports/mixins.less +33 -0
  96. package/lib/input-utils.less +0 -3
  97. package/lib/test/a11y-test-utils.ts +94 -0
  98. package/lib/test/assertions.ts +10 -3
  99. package/lib/test/test-utils.ts +152 -300
  100. package/lib/test/visual-test-utils.ts +58 -0
  101. package/lib/tsconfig.json +3 -3
  102. package/package.json +12 -13
  103. package/lib/components/popover/tooltip.visual.test.ts +0 -31
@@ -110,6 +110,39 @@
110
110
  }
111
111
 
112
112
 
113
+ /**
114
+ * Focus styles for the given context.
115
+ *
116
+ * Usage example:
117
+ * .focus-styles(true, true);
118
+ *
119
+ * @inset: boolean - whether the focus style be placed inside the element.
120
+ * @border: boolean - whether the element's border color change to match the focus style.
121
+ */
122
+ .focus-styles(@inset: false, @border: false) {
123
+ & when not (@inset) and not (@border) {
124
+ box-shadow: 0 0 0 var(--su-static2) var(--focus-neutral), 0 0 0 var(--su-static4) var(--focus-theme);
125
+ }
126
+
127
+ & when not (@inset) and (@border) {
128
+ border-color: var(--focus-neutral) !important;
129
+ box-shadow: 0 0 0 var(--su-static1) var(--focus-neutral), 0 0 0 calc(var(--su-static4) - var(--su-static1)) var(--focus-theme);
130
+ }
131
+
132
+ & when (@inset) and not (@border) {
133
+ box-shadow: inset 0 0 0 var(--su-static2) var(--focus-theme), inset 0 0 0 var(--su-static4) var(--focus-neutral);
134
+ }
135
+
136
+ & when (@inset) and (@border) {
137
+ border-color: var(--focus-theme) !important;
138
+ box-shadow: inset 0 0 0 var(--su-static1) var(--focus-theme), inset 0 0 0 calc(var(--su-static4) - var(--su-static1)) var(--focus-neutral);
139
+ }
140
+
141
+ // We include a 2px transparent outline to ensure Windows High Contrast Forced Color Mode
142
+ // includes outlines as expected See https://blogs.windows.com/msedgedev/2020/09/17/styling-for-windows-high-contrast-with-new-standards-for-forced-colors/
143
+ outline: var(--su-static2) solid transparent !important;
144
+ }
145
+
113
146
  // =============================================================================
114
147
  // -- COLORS
115
148
  // The following mixins let us do color math on the browser. They take a
@@ -17,19 +17,16 @@
17
17
 
18
18
  .has-error & {
19
19
  --_@{prefix}-bc: var(--red-400);
20
- --_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-error);
21
20
  @error();
22
21
  }
23
22
 
24
23
  .has-success & {
25
24
  --_@{prefix}-bc: var(--green-400);
26
- --_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-success);
27
25
  @success();
28
26
  }
29
27
 
30
28
  .has-warning & {
31
29
  --_@{prefix}-bc: var(--yellow-500);
32
- --_@{prefix}-bs-focus: 0 0 0 var(--su-static4) var(--focus-ring-warning);
33
30
  @warning();
34
31
  }
35
32
  }
@@ -0,0 +1,94 @@
1
+ import { html, fixture, expect } from "@open-wc/testing";
2
+ import { screen } from "@testing-library/dom";
3
+ import axe from "axe-core";
4
+ import registerAPCACheck from "apca-check";
5
+ import { generateTestVariations, type TestVariationArgs } from "./test-utils";
6
+ import type { AdditionalAssertion } from "./assertions";
7
+
8
+ type A11yTestArgs = TestVariationArgs & {
9
+ /**
10
+ * Additional assertions to run against the test element
11
+ */
12
+ additionalAssertions?: AdditionalAssertion[];
13
+ };
14
+
15
+ // register Stack APCA conformance threshold function
16
+ // see also https://stackoverflow.design/product/base/color-fundamentals/#accessibility-standards
17
+ const customConformanceThresholdFn = (fontSize: string): number | null => {
18
+ // if the font size is 32px or larger, we use a 45Lc threshold
19
+ // otherwise, we use a 60Lc threshold
20
+ return parseFloat(fontSize) >= 32 ? 45 : 60;
21
+ };
22
+ registerAPCACheck("custom", customConformanceThresholdFn);
23
+
24
+ const scheduleA11yTest = ({
25
+ element,
26
+ testid,
27
+ theme,
28
+ additionalAssertions = [],
29
+ }: {
30
+ element: ReturnType<typeof html>;
31
+ testid: string;
32
+ theme: string[];
33
+ additionalAssertions?: AdditionalAssertion[];
34
+ }) => {
35
+ it(`a11y: ${testid} should be accessible`, async () => {
36
+ await fixture(element);
37
+ const el = screen.getByTestId(testid);
38
+
39
+ document.body.className = "";
40
+
41
+ if (theme?.length) {
42
+ const prefixedThemes = theme.map((t) => `theme-${t}`);
43
+ document.body.classList.add(...prefixedThemes);
44
+ }
45
+
46
+ const highcontrast = theme?.includes("highcontrast");
47
+
48
+ axe.configure({
49
+ rules: [
50
+ // for non-high contrast, we disable WCAG 2.1 AA (4.5:1)
51
+ // and use a Stacks-specific APCA custom level instead
52
+ { id: "color-contrast", enabled: false },
53
+ {
54
+ id: "color-contrast-apca-custom",
55
+ enabled: !highcontrast,
56
+ },
57
+ // for high contrast, we check against WCAG 2.1 AAA (7:1)
58
+ { id: "color-contrast-enhanced", enabled: highcontrast },
59
+ ],
60
+ });
61
+
62
+ await expect(el).to.be.accessible();
63
+ el.remove();
64
+ });
65
+
66
+ additionalAssertions.forEach((assertion) => {
67
+ it(`a11y: ${testid} ${assertion.description}`, async () => {
68
+ await fixture(element);
69
+ const el = screen.getByTestId(testid);
70
+ await assertion.assertion(el);
71
+ el.remove();
72
+ });
73
+ });
74
+ };
75
+
76
+ const runA11yTests = (args: A11yTestArgs) => {
77
+ const testVariations = generateTestVariations(args);
78
+ testVariations.forEach((variation) => {
79
+ if (variation.skipped) {
80
+ it.skip(`a11y: ${variation.testid} (skipped)`, () => {
81
+ return;
82
+ });
83
+ return;
84
+ }
85
+
86
+ scheduleA11yTest({
87
+ ...variation,
88
+ additionalAssertions: args.additionalAssertions,
89
+ });
90
+ });
91
+ };
92
+
93
+ export type { AdditionalAssertion };
94
+ export { runA11yTests };
@@ -1,10 +1,14 @@
1
1
  import { expect } from "@open-wc/testing";
2
2
  import Color from "colorjs.io";
3
- import type { AdditionalAssertion } from "./test-utils";
3
+
4
+ type AdditionalAssertion = {
5
+ description: string;
6
+ assertion: (node: HTMLElement) => Promise<void> | void;
7
+ };
4
8
 
5
9
  // TODO: evaluate if we can do this check against all the components
6
10
  // automatically instead of having to add the assertion manually
7
- export const WCAGNonTextContrast: AdditionalAssertion = {
11
+ const WCAGNonTextContrast: AdditionalAssertion = {
8
12
  description:
9
13
  "should pass WCAG22 1.4.11 non-text-contrast success criterion (https://www.w3.org/TR/WCAG22/#non-text-contrast)",
10
14
  assertion: (node) => {
@@ -18,7 +22,7 @@ export const WCAGNonTextContrast: AdditionalAssertion = {
18
22
  selectedNodeStyles.getPropertyValue("background-color")
19
23
  );
20
24
 
21
- // we are specificng WCAG21 because of colorjs.io API
25
+ // we are specifing WCAG21 because of colorjs.io API
22
26
  // WCAG21 and WCAG22 algoirthms are the same
23
27
  const WCAGcontrast = bgSelectedNodeColor.contrast(
24
28
  bgBodyColor,
@@ -27,3 +31,6 @@ export const WCAGNonTextContrast: AdditionalAssertion = {
27
31
  expect(WCAGcontrast).to.be.at.least(3);
28
32
  },
29
33
  };
34
+
35
+ export type { AdditionalAssertion };
36
+ export { WCAGNonTextContrast };