@eccenca/gui-elements 25.1.0-rc.2 → 25.1.0-rc.4

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 (41) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/components/Button/Button.js +1 -1
  3. package/dist/cjs/components/Button/Button.js.map +1 -1
  4. package/dist/cjs/components/MultiSelect/MultiSelect.js +24 -6
  5. package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
  6. package/dist/cjs/components/Tooltip/Tooltip.js +11 -7
  7. package/dist/cjs/components/Tooltip/Tooltip.js.map +1 -1
  8. package/dist/esm/components/Button/Button.js +1 -1
  9. package/dist/esm/components/Button/Button.js.map +1 -1
  10. package/dist/esm/components/MultiSelect/MultiSelect.js +25 -7
  11. package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
  12. package/dist/esm/components/Tooltip/Tooltip.js +11 -7
  13. package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
  14. package/dist/types/components/MultiSelect/MultiSelect.d.ts +1 -0
  15. package/package.json +1 -1
  16. package/src/_shame.scss +1 -35
  17. package/src/cmem/markdown/Markdown.stories.tsx +2 -2
  18. package/src/common/scss/_accessibility-defaults.scss +101 -0
  19. package/src/components/Application/_header.scss +21 -9
  20. package/src/components/Application/_sidebar.scss +6 -0
  21. package/src/components/Application/_toolbar.scss +3 -3
  22. package/src/components/AutoSuggestion/AutoSuggestion.scss +3 -1
  23. package/src/components/Badge/Badge.test.tsx +22 -0
  24. package/src/components/Button/Button.test.tsx +16 -2
  25. package/src/components/Button/Button.tsx +1 -1
  26. package/src/components/Checkbox/checkbox.scss +9 -1
  27. package/src/components/Dialog/dialog.scss +10 -2
  28. package/src/components/Link/link.scss +5 -6
  29. package/src/components/MultiSelect/MultiSelect.tsx +37 -9
  30. package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +40 -1
  31. package/src/components/MultiSuggestField/_multisuggestfield.scss +18 -0
  32. package/src/components/MultiSuggestField/tests/MultiSuggestField.test.tsx +88 -3
  33. package/src/components/RadioButton/radiobutton.scss +5 -1
  34. package/src/components/Tag/tag.scss +2 -2
  35. package/src/components/TextField/textfield.scss +20 -0
  36. package/src/components/Tooltip/Tooltip.test.tsx +40 -5
  37. package/src/components/Tooltip/Tooltip.tsx +14 -10
  38. package/src/components/Typography/typography.scss +10 -4
  39. package/src/configuration/stories/customproperties.stories.tsx +4 -0
  40. package/src/extensions/codemirror/_codemirror.scss +18 -28
  41. package/src/index.scss +1 -0
@@ -30,8 +30,6 @@ $tag-round-adjustment: 0 !default;
30
30
  @import "~@blueprintjs/core/src/components/tag/tag";
31
31
 
32
32
  .#{$eccgui}-tag__item {
33
- --eccgui-tag-border-width: 1px;
34
-
35
33
  flex-grow: 0;
36
34
  flex-shrink: 0;
37
35
  min-width: calc(#{$tag-height} - 2px);
@@ -141,6 +139,8 @@ $tag-round-adjustment: 0 !default;
141
139
  }
142
140
 
143
141
  .#{$ns}-tag {
142
+ --eccgui-tag-border-width: 1px;
143
+
144
144
  border-style: solid;
145
145
  border-width: var(--eccgui-tag-border-width);
146
146
 
@@ -103,6 +103,8 @@ $eccgui-map-intent-bgcolors: (
103
103
  }
104
104
 
105
105
  .#{$ns}-input {
106
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};
107
+
106
108
  .#{$ns}-input-group[class*="#{$eccgui}-intent--"] & {
107
109
  animation-duration: 1s;
108
110
  animation-delay: 0.5s;
@@ -111,16 +113,23 @@ $eccgui-map-intent-bgcolors: (
111
113
  @each $each-intent, $each-bgcolor in $eccgui-map-intent-bgcolors {
112
114
  .#{$ns}-input-group.#{$ns}-intent-#{$each-intent} & {
113
115
  background-color: eccgui-color-var("semantic", $each-intent, "100");
116
+
117
+ --#{$eccgui}-a11y-outline-color: eccgui-color-var("semantic", $each-intent, "900");
118
+
114
119
  animation-name: intent-state-flash-#{$each-intent};
115
120
  }
116
121
  }
117
122
 
118
123
  .#{$ns}-input-group.#{$eccgui}-intent--info & {
119
124
  @include pt-input-intent($eccgui-color-info-text);
125
+
126
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-info-text};
120
127
  }
121
128
 
122
129
  .#{$ns}-input-group.#{$eccgui}-intent--accent & {
123
130
  @include pt-input-intent($eccgui-color-primary);
131
+
132
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
124
133
  }
125
134
 
126
135
  .#{$ns}-input-group.#{$eccgui}-intent--neutral & {
@@ -138,6 +147,10 @@ $eccgui-map-intent-bgcolors: (
138
147
 
139
148
  text-decoration: line-through $eccgui-color-danger-text 2px;
140
149
  }
150
+
151
+ &:focus-visible {
152
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-static;
153
+ }
141
154
  }
142
155
 
143
156
  .#{$eccgui}-textarea {
@@ -151,16 +164,23 @@ $eccgui-map-intent-bgcolors: (
151
164
  @each $each-intent, $each-bgcolor in $eccgui-map-intent-bgcolors {
152
165
  &.#{$eccgui}-intent--#{$each-intent} {
153
166
  background-color: eccgui-color-var("semantic", $each-intent, "100");
167
+
168
+ --#{$eccgui}-a11y-outline-color: eccgui-color-var("semantic", $each-intent, "900");
169
+
154
170
  animation-name: intent-state-flash-#{$each-intent};
155
171
  }
156
172
  }
157
173
 
158
174
  &.#{$eccgui}-intent--info {
159
175
  @include pt-input-intent($eccgui-color-info-text);
176
+
177
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-info-text};
160
178
  }
161
179
 
162
180
  &.#{$eccgui}-intent--accent {
163
181
  @include pt-input-intent($eccgui-color-primary);
182
+
183
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
164
184
  }
165
185
 
166
186
  &.#{$eccgui}-intent--neutral {
@@ -1,5 +1,6 @@
1
1
  import React from "react";
2
2
  import { fireEvent, render, screen, waitFor } from "@testing-library/react";
3
+ import userEvent from "@testing-library/user-event";
3
4
 
4
5
  import "@testing-library/jest-dom";
5
6
 
@@ -45,19 +46,53 @@ describe("Tooltip", () => {
45
46
  fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper--placeholder`)[0]);
46
47
  checkForPlaceholderClass(container, 1);
47
48
  await waitFor(() => {
48
- expect(screen.queryAllByText(TooltipStory.args.content)).toHaveLength(0);
49
49
  checkForPlaceholderClass(container, 0);
50
50
  });
51
+ expect(screen.queryAllByText(TooltipStory.args.content as string)).toHaveLength(0);
51
52
  });
52
53
  it("should be displayed on two continues mouse hover when placeholder is used", async () => {
53
54
  const { container } = render(<Tooltip {...TooltipStory.args} usePlaceholder={true} />);
54
55
  fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
55
56
  checkForPlaceholderClass(container, 1);
56
- await waitFor(async () => {
57
- expect(screen.queryAllByText(TooltipStory.args.content)).toHaveLength(0);
57
+ await waitFor(() => {
58
+ checkForPlaceholderClass(container, 0);
59
+ });
60
+ expect(screen.queryAllByText(TooltipStory.args.content as string)).toHaveLength(0);
61
+ fireEvent.mouseEnter(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
62
+ expect(await screen.findByText(TooltipStory.args.content as string)).toBeVisible();
63
+ });
64
+ it("should be displayed on focus when no placeholder is used", async () => {
65
+ // Blueprint ignores focus events with null relatedTarget (page-refocus guard), so we tab
66
+ // from a preceding element to produce a non-null relatedTarget.
67
+ render(
68
+ <>
69
+ <button>previous element</button>
70
+ <Tooltip {...TooltipStory.args} usePlaceholder={false} />
71
+ </>
72
+ );
73
+ const user = userEvent.setup();
74
+ await user.tab(); // focuses "previous element"
75
+ await user.tab(); // focuses tooltip target, relatedTarget is non-null → Blueprint opens
76
+ expect(await screen.findByText(TooltipStory.args.content as string)).toBeVisible();
77
+ });
78
+ it("should be displayed after keyboard focus when placeholder is used", async () => {
79
+ // Use a focusable button child so refocus() can call .focus() on it after the swap.
80
+ // Tab from a preceding element so relatedTarget is non-null when Blueprint handles focus.
81
+ const { container } = render(
82
+ <>
83
+ <button>previous element</button>
84
+ <Tooltip {...TooltipStory.args} usePlaceholder={true}>
85
+ <button>tooltip target</button>
86
+ </Tooltip>
87
+ </>
88
+ );
89
+ const user = userEvent.setup();
90
+ await user.tab(); // focuses "previous element"
91
+ await user.tab(); // focuses placeholder inner button, triggers focusin swap
92
+ checkForPlaceholderClass(container, 1);
93
+ await waitFor(() => {
58
94
  checkForPlaceholderClass(container, 0);
59
- fireEvent.mouseOver(container.getElementsByClassName(`${eccgui}-tooltip__wrapper`)[0]);
60
- expect(await screen.findByText(TooltipStory.args.content)).toBeVisible();
61
95
  });
96
+ expect(await screen.findByText(TooltipStory.args.content as string)).toBeVisible();
62
97
  });
63
98
  });
@@ -50,7 +50,7 @@ export interface TooltipProps extends Omit<BlueprintTooltipProps, "position"> {
50
50
  swapPlaceholderDelay?: number;
51
51
  }
52
52
 
53
- export type TooltipSize = "small" | "medium" | "large"
53
+ export type TooltipSize = "small" | "medium" | "large";
54
54
 
55
55
  export const Tooltip = ({
56
56
  children,
@@ -100,15 +100,19 @@ export const Tooltip = ({
100
100
  }, swapDelayTime);
101
101
  if (placeholderRef.current !== null) {
102
102
  const eventType = ev.type === "focusin" ? "focusout" : "mouseleave";
103
- (placeholderRef.current as HTMLElement).addEventListener(eventType, () => {
104
- if (
105
- (eventType === "focusout" && eventMemory.current === "afterfocus") ||
106
- (eventType === "mouseleave" && eventMemory.current === "afterhover")
107
- ) {
108
- eventMemory.current = null;
109
- }
110
- clearTimeout(swapDelay.current as NodeJS.Timeout);
111
- });
103
+ const innerFocusTarget = (placeholderRef.current as HTMLElement).querySelector("[tabindex='0']")
104
+ ?.children[0];
105
+ if (innerFocusTarget) {
106
+ (innerFocusTarget as HTMLElement).addEventListener(eventType, () => {
107
+ if (
108
+ (eventType === "focusout" && eventMemory.current === "afterfocus") ||
109
+ (eventType === "mouseleave" && eventMemory.current === "afterhover")
110
+ ) {
111
+ eventMemory.current = null;
112
+ }
113
+ clearTimeout(swapDelay.current as NodeJS.Timeout);
114
+ });
115
+ }
112
116
  }
113
117
  };
114
118
  (placeholderRef.current as HTMLElement).addEventListener("mouseenter", swap);
@@ -13,20 +13,26 @@ html {
13
13
 
14
14
  body {
15
15
  font-family: $eccgui-font-family-default;
16
- font-weight: $eccgui-font-weight-regular;
17
- text-rendering: optimizelegibility;
18
- -webkit-font-smoothing: antialiased;
19
- -moz-osx-font-smoothing: grayscale;
16
+
20
17
  // User-facing text may contain Unicode symbols (e.g. "★") that fall outside the primary font stack.
21
18
  // Browsers pick different system fallback fonts for such characters, causing glyphs to render at
22
19
  // different optical sizes (smaller in Firefox). font-size-adjust normalises the fallback font size
23
20
  // by matching the primary font's x-height, reducing the visual size discrepancy across browsers.
24
21
  font-size-adjust: from-font;
22
+ font-weight: $eccgui-font-weight-regular;
23
+ text-rendering: optimizelegibility;
24
+ -webkit-font-smoothing: antialiased;
25
+ -moz-osx-font-smoothing: grayscale;
25
26
  }
26
27
 
27
28
  code {
28
29
  font-family: $eccgui-font-family-monospace;
29
30
  font-size: 0.9em;
31
+
32
+ .#{$eccgui}-typography__contentblock &,
33
+ &.#{$eccgui}-typography__text {
34
+ background-color: $eccgui-color-workspace-background;
35
+ }
30
36
  }
31
37
 
32
38
  strong {
@@ -34,6 +34,10 @@ const groups: { title: string; filterName: (name: string) => boolean }[] = [
34
34
  title: "Color aliases",
35
35
  filterName: (name) => name.startsWith(`--${eccgui}-color`) && !name.startsWith(`--${eccgui}-color-palette`),
36
36
  },
37
+ {
38
+ title: "Accessibility",
39
+ filterName: (name) => name.startsWith(`--${eccgui}-a11y`),
40
+ },
37
41
  {
38
42
  title: "Opacity",
39
43
  filterName: (name) => name.startsWith(`--${eccgui}-opacity`),
@@ -19,13 +19,13 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
19
19
 
20
20
  &__toolbar {
21
21
  position: absolute;
22
- z-index: 3;
23
- left: 1px;
24
- right: 1px;
25
22
  top: 1px;
26
- border-radius: $pt-border-radius $pt-border-radius 0 0;
27
- border-bottom: solid 1px $eccgui-color-codeeditor-separation;
23
+ right: 1px;
24
+ left: 1px;
25
+ z-index: 3;
28
26
  background-color: $eccgui-color-codeeditor-background;
27
+ border-bottom: solid 1px $eccgui-color-codeeditor-separation;
28
+ border-radius: $pt-border-radius $pt-border-radius 0 0;
29
29
  }
30
30
 
31
31
  &--has-toolbar {
@@ -37,9 +37,9 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
37
37
  &__preview {
38
38
  position: absolute;
39
39
  top: calc(#{$eccgui-size-codeeditor-toolbar-height} + 1px) !important;
40
- left: 1px;
41
40
  right: 1px;
42
41
  bottom: 1px;
42
+ left: 1px;
43
43
  z-index: 2;
44
44
  padding: $button-padding;
45
45
  overflow-y: auto;
@@ -50,12 +50,12 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
50
50
  .cm-editor {
51
51
  width: 100%;
52
52
  height: $eccgui-size-codeeditor-height;
53
- clip-path: unset !important; // we may check later why they set inset(0) now
54
53
  background-color: $eccgui-color-codeeditor-background;
55
54
  border-radius: $pt-border-radius;
56
55
 
57
56
  // get them a "border" like input boxes from blueprintjs
58
57
  box-shadow: input-transition-shadow($input-shadow-color-focus), $pt-input-box-shadow;
58
+ clip-path: unset !important; // we may check later why they set inset(0) now
59
59
 
60
60
  &.#{eccgui}-disabled {
61
61
  @extend .#{$ns}-input, .#{$ns}-disabled;
@@ -89,7 +89,7 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
89
89
  }
90
90
 
91
91
  &.#{eccgui}-intent--primary {
92
- @include pt-input-intent($eccgui-color-info-text);
92
+ @include pt-input-intent($eccgui-color-primary);
93
93
  }
94
94
 
95
95
  &.#{eccgui}-intent--info {
@@ -97,7 +97,7 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
97
97
  }
98
98
 
99
99
  &.#{eccgui}-intent--accent {
100
- @include pt-input-intent($eccgui-color-primary);
100
+ @include pt-input-intent($eccgui-color-accent);
101
101
  }
102
102
 
103
103
  &.#{eccgui}-intent--neutral {
@@ -124,39 +124,29 @@ $eccgui-size-codeeditor-toolbar-height: $button-height !default;
124
124
  }
125
125
 
126
126
  &.cm-focused {
127
- outline: none;
128
- box-shadow: input-transition-shadow($input-shadow-color-focus, true), $input-box-shadow-focus;
127
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-accent};
128
+ --#{$eccgui}-a11y-outline-offset: 0;
129
+
130
+ @extend .#{$eccgui}-a11y-focus-by-keyboard-static;
129
131
 
130
132
  &.#{eccgui}-intent--warning {
131
- box-shadow: input-transition-shadow($eccgui-color-warning-text, true), $input-box-shadow-focus;
133
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-warning-text};
132
134
  }
133
135
 
134
136
  &.#{eccgui}-intent--success {
135
- box-shadow: input-transition-shadow($eccgui-color-success-text, true), $input-box-shadow-focus;
137
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-success-text};
136
138
  }
137
139
 
138
140
  &.#{eccgui}-intent--danger {
139
- box-shadow: input-transition-shadow($eccgui-color-danger-text, true), $input-box-shadow-focus;
141
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-danger-text};
140
142
  }
141
143
 
142
144
  &.#{eccgui}-intent--primary {
143
- box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
145
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-primary};
144
146
  }
145
147
 
146
148
  &.#{eccgui}-intent--info {
147
- box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
148
- }
149
-
150
- &.#{eccgui}-intent--accent {
151
- box-shadow: input-transition-shadow($eccgui-color-warning-text, true), $input-box-shadow-focus;
152
- }
153
-
154
- &.#{eccgui}-intent--neutral {
155
- box-shadow: input-transition-shadow($eccgui-color-workspace-text, true), $input-box-shadow-focus;
156
- }
157
-
158
- &.#{eccgui}-intent--edited {
159
- box-shadow: input-transition-shadow($eccgui-color-info-text, true), $input-box-shadow-focus;
149
+ --#{$eccgui}-a11y-outline-color: #{$eccgui-color-info-text};
160
150
  }
161
151
 
162
152
  &.#{eccgui}-intent--removed {
package/src/index.scss CHANGED
@@ -61,6 +61,7 @@ $prefix-carbon: $prefix;
61
61
 
62
62
  // == Load basic components styles =============================================
63
63
 
64
+ @import "./common/scss/accessibility-defaults";
64
65
  @import "./components";
65
66
 
66
67
  // set more readable variable for prefix