@scality/core-ui 0.196.0 → 0.198.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 (42) hide show
  1. package/dist/components/buttonv2/Buttonv2.component.d.ts +22 -4
  2. package/dist/components/buttonv2/Buttonv2.component.d.ts.map +1 -1
  3. package/dist/components/buttonv2/Buttonv2.component.js +7 -10
  4. package/dist/components/buttonv2/CopyButton.component.d.ts +1 -1
  5. package/dist/components/buttonv2/CopyButton.component.d.ts.map +1 -1
  6. package/dist/components/icon/Icon.component.d.ts +5 -0
  7. package/dist/components/icon/Icon.component.d.ts.map +1 -1
  8. package/dist/components/icon/Icon.component.js +10 -5
  9. package/dist/components/iconhelper/IconHelper.d.ts +8 -1
  10. package/dist/components/iconhelper/IconHelper.d.ts.map +1 -1
  11. package/dist/components/iconhelper/IconHelper.js +19 -1
  12. package/dist/components/navbar/Navbar.component.d.ts +15 -4
  13. package/dist/components/navbar/Navbar.component.d.ts.map +1 -1
  14. package/dist/components/navbar/Navbar.component.js +21 -17
  15. package/dist/components/sidebar/Sidebar.component.d.ts.map +1 -1
  16. package/dist/components/sidebar/Sidebar.component.js +1 -1
  17. package/dist/components/statusicon/StatusIcon.component.js +5 -5
  18. package/dist/components/tablev2/TableSync.d.ts.map +1 -1
  19. package/dist/components/tablev2/TableSync.js +1 -1
  20. package/dist/components/tablev2/Tablev2.component.js +1 -1
  21. package/dist/components/tooltip/Tooltip.component.d.ts.map +1 -1
  22. package/dist/components/tooltip/Tooltip.component.js +8 -0
  23. package/dist/style/theme.d.ts +1 -0
  24. package/dist/style/theme.d.ts.map +1 -1
  25. package/dist/style/theme.js +4 -0
  26. package/package.json +3 -3
  27. package/src/lib/components/banner/Banner.component.test.tsx +11 -12
  28. package/src/lib/components/buttonv2/Buttonv2.component.tsx +41 -29
  29. package/src/lib/components/buttonv2/CopyButton.component.tsx +1 -1
  30. package/src/lib/components/charts/barchart/Barchart.test.tsx +3 -1
  31. package/src/lib/components/icon/Icon.component.tsx +16 -5
  32. package/src/lib/components/iconhelper/IconHelper.test.tsx +10 -8
  33. package/src/lib/components/iconhelper/IconHelper.tsx +33 -1
  34. package/src/lib/components/navbar/Navbar.component.tsx +47 -28
  35. package/src/lib/components/sidebar/Sidebar.component.tsx +1 -0
  36. package/src/lib/components/statusicon/StatusIcon.component.tsx +5 -5
  37. package/src/lib/components/tablev2/TableSync.tsx +1 -2
  38. package/src/lib/components/tablev2/Tablev2.component.tsx +1 -1
  39. package/src/lib/components/tooltip/Tooltip.component.tsx +11 -0
  40. package/src/lib/style/theme.ts +5 -0
  41. package/stories/Button/button.stories.tsx +14 -21
  42. package/stories/navbar.stories.tsx +1 -0
@@ -1,18 +1,36 @@
1
- import { ButtonHTMLAttributes } from 'react';
1
+ import type { ButtonHTMLAttributes } from 'react';
2
2
  import { Loader } from '../loader/Loader.component';
3
3
  import { Props as TooltipProps } from '../tooltip/Tooltip.component';
4
4
  export declare const FocusVisibleStyle: import("styled-components").FlattenInterpolation<import("styled-components").ThemeProps<import("styled-components").DefaultTheme>>;
5
- export type Props = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'size' | 'label'> & {
5
+ /** Props used by ButtonStyled for styling (no tooltip) */
6
+ type ButtonStyledProps = Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'size' | 'label'> & {
6
7
  variant?: 'primary' | 'secondary' | 'danger' | 'outline';
7
8
  size?: 'default' | 'inline';
8
9
  disabled?: boolean;
9
10
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
10
11
  icon?: React.ReactNode;
11
12
  label?: React.ReactNode;
12
- tooltip?: Omit<TooltipProps, 'children'>;
13
13
  isLoading?: boolean;
14
14
  };
15
- export declare const ButtonStyled: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, Props, never>;
15
+ /** Button with a visible label - tooltip is optional */
16
+ type ButtonWithLabel = ButtonStyledProps & {
17
+ label: React.ReactNode;
18
+ tooltip?: Omit<TooltipProps, 'children'>;
19
+ };
20
+ /** Icon-only button - requires either string tooltip OR explicit aria-label */
21
+ type IconOnlyButton = ButtonStyledProps & {
22
+ label?: never;
23
+ } & ({
24
+ tooltip: Omit<TooltipProps, 'children'> & {
25
+ overlay: string;
26
+ };
27
+ 'aria-label'?: string;
28
+ } | {
29
+ tooltip: Omit<TooltipProps, 'children'>;
30
+ 'aria-label': string;
31
+ });
32
+ export type Props = ButtonWithLabel | IconOnlyButton;
33
+ export declare const ButtonStyled: import("styled-components").StyledComponent<"button", import("styled-components").DefaultTheme, ButtonStyledProps, never>;
16
34
  export declare const ButtonLabel: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {}, never>;
17
35
  export declare const ButtonIcon: import("styled-components").StyledComponent<"span", import("styled-components").DefaultTheme, {
18
36
  label: React.ReactNode;
@@ -1 +1 @@
1
- {"version":3,"file":"Buttonv2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/Buttonv2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAI7C,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAW,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE9E,eAAO,MAAM,iBAAiB,oIAI7B,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,IAAI,CACtB,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,GAAG,OAAO,CACjB,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzD,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AACF,eAAO,MAAM,YAAY,+GA0KxB,CAAC;AACF,eAAO,MAAM,WAAW,0GAIvB,CAAC;AACF,eAAO,MAAM,UAAU;WAAwB,KAAK,CAAC,SAAS;SAS7D,CAAC;AAEF,eAAO,MAAM,YAAY;;;SAaxB,CAAC;AAEF,iBAAS,MAAM,CAAC,EACd,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,OAAO,EACP,OAAO,EACP,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CAqDP;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"Buttonv2.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/Buttonv2.component.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAIlD,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AACpD,OAAO,EAAW,KAAK,IAAI,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE9E,eAAO,MAAM,iBAAiB,oIAI7B,CAAC;AAEF,0DAA0D;AAC1D,KAAK,iBAAiB,GAAG,IAAI,CAC3B,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,MAAM,GAAG,OAAO,CACjB,GAAG;IACF,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;IACzD,IAAI,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC/D,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,wDAAwD;AACxD,KAAK,eAAe,GAAG,iBAAiB,GAAG;IACzC,KAAK,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;CAC1C,CAAC;AAEF,+EAA+E;AAC/E,KAAK,cAAc,GAAG,iBAAiB,GAAG;IACxC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,GAAG,CACA;IACE,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GACD;IACE,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IACxC,YAAY,EAAE,MAAM,CAAC;CACtB,CACJ,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG,eAAe,GAAG,cAAc,CAAC;AACrD,eAAO,MAAM,YAAY,2HA0KxB,CAAC;AACF,eAAO,MAAM,WAAW,0GAIvB,CAAC;AACF,eAAO,MAAM,UAAU;WAAwB,KAAK,CAAC,SAAS;SAS7D,CAAC;AAEF,eAAO,MAAM,YAAY;;;SAaxB,CAAC;AAEF,iBAAS,MAAM,CAAC,EACd,OAAO,EACP,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,IAAI,EACJ,OAAO,EACP,OAAO,EACP,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CA2CP;AAED,OAAO,EAAE,MAAM,EAAE,CAAC"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import styled, { css } from 'styled-components';
3
3
  import { spacing } from '../../spacing';
4
4
  import { fontSize, fontWeight } from '../../style/theme';
@@ -207,14 +207,11 @@ function Button({ variant, size, disabled, label, icon, onClick, tooltip, isLoad
207
207
  if (!icon && !label) {
208
208
  console.warn('Please specify either icon or label prop for the button component.');
209
209
  }
210
- if (!label && icon && !tooltip) {
211
- console.warn('Please specify the tooltip for the standalone icon button.');
212
- }
213
- return (_jsx(Tooltip, { placement: tooltip ? tooltip.placement : undefined, overlay: tooltip && tooltip.overlay, overlayStyle: tooltip && tooltip.overlayStyle, children: _jsx(ButtonStyled, { className: "sc-button", variant: variant, disabled: isLoading || disabled, label: label, icon: icon, onClick: onClick, size: size, ...rest, children: _jsxs(_Fragment, { children: [icon &&
214
- (isLoading ? (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })) : (_jsx(ButtonIcon, { label: label, "aria-label": tooltip &&
215
- tooltip.overlay &&
216
- typeof tooltip.overlay === 'string'
217
- ? tooltip.overlay
218
- : undefined, children: icon }))), !icon && isLoading && (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })), _jsx(ButtonLabel, { children: label })] }) }) }));
210
+ // For icon-only buttons, use tooltip.overlay as aria-label (typed as string for IconOnlyButton)
211
+ const buttonAriaLabel = !label && icon && (tooltip === null || tooltip === void 0 ? void 0 : tooltip.overlay)
212
+ ? tooltip.overlay
213
+ : undefined;
214
+ return (_jsx(Tooltip, { placement: tooltip ? tooltip.placement : undefined, overlay: tooltip && tooltip.overlay, overlayStyle: tooltip && tooltip.overlayStyle, children: _jsxs(ButtonStyled, { className: "sc-button", variant: variant, disabled: isLoading || disabled, label: label, icon: icon, onClick: onClick, size: size, "aria-label": buttonAriaLabel, ...rest, children: [icon &&
215
+ (isLoading ? (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })) : (_jsx(ButtonIcon, { label: label, children: icon }))), !icon && isLoading && (_jsx(ButtonLoader, { size: "small", variant: variant, label: label })), _jsx(ButtonLabel, { children: label })] }) }));
219
216
  }
220
217
  export { Button };
@@ -11,5 +11,5 @@ export declare const CopyButton: ({ label, textToCopy, copyAsHtml, variant, ...p
11
11
  textToCopy: string;
12
12
  copyAsHtml?: boolean;
13
13
  variant?: "outline" | "ghost";
14
- } & Props) => import("react/jsx-runtime").JSX.Element;
14
+ } & Omit<Props, "tooltip" | "label">) => import("react/jsx-runtime").JSX.Element;
15
15
  //# sourceMappingURL=CopyButton.component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CopyButton.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/CopyButton.component.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAErD,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,YAAY;iBASQ,MAAM,WAAW,OAAO;;CAoCxD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,sDAMxB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC/B,GAAG,KAAK,4CA+CR,CAAC"}
1
+ {"version":3,"file":"CopyButton.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/buttonv2/CopyButton.component.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAErD,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AACpD,eAAO,MAAM,YAAY;iBASQ,MAAM,WAAW,OAAO;;CAoCxD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,sDAMxB;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;CAC/B,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,4CA+CnC,CAAC"}
@@ -18,6 +18,11 @@ type Props = {
18
18
  name: IconName;
19
19
  size?: SizeProp;
20
20
  color?: IconColor | CSSProperties['color'];
21
+ /**
22
+ * Accessible label for meaningful icons.
23
+ * When provided, the icon is announced to screen readers.
24
+ * When omitted, the icon is decorative (hidden from assistive technologies).
25
+ */
21
26
  ariaLabel?: string;
22
27
  withWrapper?: boolean;
23
28
  style?: CSSProperties;
@@ -1 +1 @@
1
- {"version":3,"file":"Icon.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/icon/Icon.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE7D,OAAO,EACL,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAC9B,MAAM,EACN,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAc/D,CAAC;AAkBF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,WAAW,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC;AAC1C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF,eAAO,MAAM,WAAW;UAAsB,QAAQ;SAiCrD,CAAC;AA6DF,iBAAS,IAAI,CAAC,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,2CAU7C;AAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"Icon.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/icon/Icon.component.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mCAAmC,CAAC;AAE7D,OAAO,EACL,aAAa,EAKd,MAAM,OAAO,CAAC;AAEf,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAKxC,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,MAAM,CAC9B,MAAM,EACN,CAAC,CAAC,KAAK,EAAE,SAAS,KAAK,GAAG,CAAC,OAAO,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAc/D,CAAC;AAkBF,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,SAAS,GAAG,MAAM,OAAO,WAAW,CAAC;AACzE,MAAM,MAAM,SAAS,GAAG,MAAM,WAAW,CAAC;AAC1C,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,CAAC;IAChB,KAAK,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;IAC3C;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAC5C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAiBF,eAAO,MAAM,WAAW;UAAsB,QAAQ;SAiCrD,CAAC;AAmEF,iBAAS,IAAI,CAAC,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,EAAE,KAAK,2CAU7C;AAED,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC"}
@@ -15,8 +15,8 @@ export const customIcons = {
15
15
  };
16
16
  customIcons['Remote-user'].displayName = 'RemoteUser';
17
17
  customIcons['Remote-group'].displayName = 'RemoteGroup';
18
- customIcons['Bucket'].displayName = 'Bucket';
19
- customIcons['Buckets'].displayName = 'Buckets';
18
+ customIcons.Bucket.displayName = 'Bucket';
19
+ customIcons.Buckets.displayName = 'Buckets';
20
20
  const IconStyled = styled(FontAwesomeIcon) `
21
21
  ${(props) => {
22
22
  const theme = props.theme;
@@ -71,7 +71,7 @@ export const IconWrapper = styled.div `
71
71
  align-items: center;
72
72
  border-radius: 100%;
73
73
  `;
74
- function NonWrappedIcon({ name, size = '1x', color, ariaLabel = '', title, ...rest }) {
74
+ function NonWrappedIcon({ name, size = '1x', color, ariaLabel, title, ...rest }) {
75
75
  var _a;
76
76
  const iconInfo = iconTable[name] || customIcons[name];
77
77
  if (!iconInfo)
@@ -98,11 +98,16 @@ function NonWrappedIcon({ name, size = '1x', color, ariaLabel = '', title, ...re
98
98
  });
99
99
  return () => setIcon(undefined);
100
100
  }, [name, iconInfo]);
101
+ // Icons are decorative by default (aria-hidden: true)
102
+ // If ariaLabel is provided, the icon is meaningful (aria-hidden: false)
103
+ const accessibilityProps = ariaLabel
104
+ ? { 'aria-hidden': false, 'aria-label': ariaLabel }
105
+ : { 'aria-hidden': true };
101
106
  if (!icon && !customIcons[name]) {
102
- return (_jsx(DelayedFallback, { "aria-label": `${name} ${ariaLabel}`, children: _jsx(Loader, { size: "base" }) }));
107
+ return (_jsx(DelayedFallback, { ...accessibilityProps, children: _jsx(Loader, { size: "base" }) }));
103
108
  }
104
109
  const IconComponent = (_a = customIcons[name]) !== null && _a !== void 0 ? _a : IconStyled;
105
- return (_jsx(IconComponent, { color: color, icon: icon, size: size, title: title, "aria-label": `${name} ${ariaLabel}`, ...rest }));
110
+ return (_jsx(IconComponent, { color: color, icon: icon, size: size, title: title, ...accessibilityProps, ...rest }));
106
111
  }
107
112
  function Icon({ withWrapper, ...props }) {
108
113
  if (withWrapper) {
@@ -4,8 +4,15 @@ type IconHelpProps = {
4
4
  tooltipMessage: ReactNode;
5
5
  placement?: Position;
6
6
  overlayStyle?: CSSProperties;
7
+ /**
8
+ * Accessible label for the help button.
9
+ * Should describe what information the tooltip provides.
10
+ * Example: "More info about Veeam application"
11
+ */
12
+ 'aria-label'?: string;
13
+ /** @deprecated Use aria-label instead */
7
14
  title?: string;
8
15
  };
9
- export declare const IconHelp: ({ tooltipMessage, overlayStyle, placement, title, }: IconHelpProps) => import("react/jsx-runtime").JSX.Element;
16
+ export declare const IconHelp: ({ tooltipMessage, overlayStyle, placement, "aria-label": ariaLabel, title, }: IconHelpProps) => import("react/jsx-runtime").JSX.Element;
10
17
  export {};
11
18
  //# sourceMappingURL=IconHelper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"IconHelper.d.ts","sourceRoot":"","sources":["../../../src/lib/components/iconhelper/IconHelper.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAW,MAAM,8BAA8B,CAAC;AAEjE,KAAK,aAAa,GAAG;IACnB,cAAc,EAAE,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,qDAKtB,aAAa,4CAQf,CAAC"}
1
+ {"version":3,"file":"IconHelper.d.ts","sourceRoot":"","sources":["../../../src/lib/components/iconhelper/IconHelper.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD,OAAO,EAAE,QAAQ,EAAW,MAAM,8BAA8B,CAAC;AAEjE,KAAK,aAAa,GAAG;IACnB,cAAc,EAAE,SAAS,CAAC;IAC1B,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAoBF,eAAO,MAAM,QAAQ,GAAI,8EAMtB,aAAa,4CAaf,CAAC"}
@@ -1,4 +1,22 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import styled from 'styled-components';
2
3
  import { Icon } from '../icon/Icon.component';
3
4
  import { Tooltip } from '../tooltip/Tooltip.component';
4
- export const IconHelp = ({ tooltipMessage, overlayStyle, placement = 'right', title, }) => (_jsx(Tooltip, { overlay: tooltipMessage, placement: placement, overlayStyle: overlayStyle, children: _jsx(Icon, { name: "Info", color: "buttonSecondary", title: title }) }));
5
+ const HelpButton = styled.button `
6
+ display: inline-flex;
7
+ background: none;
8
+ border: none;
9
+ padding: 0;
10
+ margin: 0;
11
+ cursor: pointer;
12
+ color: inherit;
13
+ font: inherit; /* Inherit font sizing */
14
+ vertical-align: text-bottom; /* Align with text */
15
+ line-height: 1;
16
+ &:focus-visible {
17
+ outline: 2px dashed ${(props) => props.theme.selectedActive};
18
+ outline-offset: 2px;
19
+ border-radius: 2px;
20
+ }
21
+ `;
22
+ export const IconHelp = ({ tooltipMessage, overlayStyle, placement = 'right', 'aria-label': ariaLabel, title, }) => (_jsx(Tooltip, { overlay: tooltipMessage, placement: placement, overlayStyle: overlayStyle, children: _jsx(HelpButton, { type: "button", "aria-label": ariaLabel || title || 'More information', children: _jsx(Icon, { name: "Info", color: "buttonSecondary" }) }) }));
@@ -1,8 +1,19 @@
1
- import { Item } from '../dropdown/Dropdown.component';
2
- type Action = {
3
- type: string;
4
- items?: Array<Item>;
1
+ import { type Item } from '../dropdown/Dropdown.component';
2
+ import { type Props as ButtonProps } from '../buttonv2/Buttonv2.component';
3
+ type ButtonAction = {
4
+ type: 'button';
5
+ } & ButtonProps;
6
+ type DropdownAction = {
7
+ type: 'dropdown';
8
+ items: Array<Item>;
9
+ text?: string;
10
+ icon?: JSX.Element;
5
11
  };
12
+ type CustomAction = {
13
+ type: 'custom';
14
+ render: React.ComponentType;
15
+ };
16
+ type Action = DropdownAction | ButtonAction | CustomAction;
6
17
  type Actions = Array<Action>;
7
18
  type Tab = {
8
19
  title?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Navbar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/navbar/Navbar.component.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAY,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAGhE,KAAK,MAAM,GAAG;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;CACrB,CAAC;AACF,KAAK,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;AAC7B,KAAK,GAAG,GAAG;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;CACnB,CAAC;AA4JF,iBAAS,MAAM,CAAC,EACd,aAAa,EACb,IAAI,EACJ,IAAS,EACT,YAAiB,EACjB,GAAG,IAAI,EACR,EAAE,KAAK,2CAwDP;AAED,eAAO,MAAM,MAAM,eAAS,CAAC"}
1
+ {"version":3,"file":"Navbar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/navbar/Navbar.component.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAY,KAAK,IAAI,EAAE,MAAM,gCAAgC,CAAC;AAErE,OAAO,EAA6B,KAAK,KAAK,IAAI,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAEtG,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,QAAQ,CAAC;CAChB,GAAG,WAAW,CAAC;AAChB,KAAK,cAAc,GAAG;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACpB,CAAC;AAEF,KAAK,YAAY,GAAG;IAClB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAEF,KAAK,MAAM,GAAG,cAAc,GAAG,YAAY,GAAG,YAAY,CAAC;AAC3D,KAAK,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;AAC7B,KAAK,GAAG,GAAG;IACT,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACtB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAClB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,EAAE,OAAO,CAAC;IACtB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;CACnB,CAAC;AAmKF,iBAAS,MAAM,CAAC,EACd,aAAa,EACb,IAAI,EACJ,IAAS,EACT,YAAiB,EACjB,GAAG,IAAI,EACR,EAAE,KAAK,2CAuDP;AAED,eAAO,MAAM,MAAM,eAAS,CAAC"}
@@ -13,7 +13,7 @@ const NavbarContainer = styled.div `
13
13
  display: flex;
14
14
  justify-content: space-between;
15
15
  ${css `
16
- background-color: ${getThemePropSelector('backgroundLevel1')};
16
+ background-color: ${getThemePropSelector('navbarBackground')};
17
17
  color: ${getThemePropSelector('textPrimary')};
18
18
  .fas,
19
19
  .sc-trigger-text {
@@ -100,7 +100,7 @@ const NavbarMenuItem = styled.div `
100
100
  align-items: center;
101
101
  .sc-dropdown {
102
102
  .trigger {
103
- background-color: ${getThemePropSelector('backgroundLevel1')};
103
+ background-color: ${getThemePropSelector('navbarBackground')};
104
104
  &:hover {
105
105
  background-color: ${getThemePropSelector('highlight')};
106
106
  }
@@ -117,7 +117,7 @@ const NavbarMenuItem = styled.div `
117
117
  border-radius: 0;
118
118
  height: ${navbarHeight};
119
119
  font-size: ${fontSize.base};
120
- background-color: ${getThemePropSelector('backgroundLevel1')};
120
+ background-color: ${getThemePropSelector('navbarBackground')};
121
121
  &:hover {
122
122
  background-color: ${getThemePropSelector('highlight')};
123
123
  }
@@ -139,20 +139,26 @@ const LogoContainer = styled.div `
139
139
  height: 2.143rem;
140
140
  }
141
141
  `;
142
- const getActionRenderer = ({ type, items = null, ...rest }, index) => {
143
- if (type === 'dropdown') {
144
- return items ? (_jsx(Dropdown, { size: "larger", variant: "backgroundLevel1", items: items, caret: false, ...rest }, `navbar_right_action_${index}`)) : null;
145
- }
146
- else if (type === 'button') {
147
- return _jsx(Button, { ...rest }, `navbar_right_action_${index}`);
148
- }
149
- else if (type === 'custom') {
150
- return _jsx(rest.render, {}, `navbar_right_action_${index}`);
142
+ const getActionRenderer = (action, index) => {
143
+ switch (action.type) {
144
+ case 'dropdown': {
145
+ const { type, items, ...rest } = action;
146
+ return (_jsx(Dropdown, { size: "larger", variant: "backgroundLevel1", items: items, caret: false, ...rest }, `navbar_right_action_${index}`));
147
+ }
148
+ case 'button': {
149
+ const { type, ...rest } = action;
150
+ return _jsx(Button, { ...rest }, `navbar_right_action_${index}`);
151
+ }
152
+ case 'custom': {
153
+ const CustomComponent = action.render;
154
+ return _jsx(CustomComponent, {}, `navbar_right_action_${index}`);
155
+ }
156
+ default:
157
+ return null;
151
158
  }
152
- return null;
153
159
  };
154
160
  function NavBar({ onToggleClick, logo, tabs = [], rightActions = [], ...rest }) {
155
- return (_jsxs(NavbarContainer, { className: "sc-navbar", ...rest, children: [_jsxs(NavbarMenu, { children: [onToggleClick && (_jsx(NavbarMenuItem, { onClick: onToggleClick, children: _jsx(Button, { icon: _jsx(Icon, { name: "Lat-menu" }), title: "Main Menu" }) })), _jsx(NavbarMenuItem, { children: _jsx(LogoContainer, { className: "sc-logo", children: logo ? logo : _jsx(Logo, {}) }) })] }), tabs.length ? (_jsx(NavbarTabs, { children: tabs.map(({ link, title, selected, onClick, render }, index) => {
161
+ return (_jsxs(NavbarContainer, { className: "sc-navbar", ...rest, children: [_jsxs(NavbarMenu, { children: [onToggleClick && (_jsx(NavbarMenuItem, { onClick: onToggleClick, children: _jsx(Button, { icon: _jsx(Icon, { name: "Lat-menu" }), tooltip: { overlay: "Toggle Main Menu" } }) })), _jsx(NavbarMenuItem, { children: _jsx(LogoContainer, { className: "sc-logo", children: logo ? logo : _jsx(Logo, {}) }) })] }), tabs.length ? (_jsx(NavbarTabs, { children: tabs.map(({ link, title, selected, onClick, render }, index) => {
156
162
  if (render) {
157
163
  return (_jsx(Fragment, { children: render }, `navbar_tab_item_${index}`));
158
164
  }
@@ -162,8 +168,6 @@ function NavBar({ onToggleClick, logo, tabs = [], rightActions = [], ...rest })
162
168
  role: 'tab',
163
169
  key: `navbar_tab_item_${index}`,
164
170
  })) : (_jsx(TabItem, { onClick: onClick, role: "tab", selected: !!selected, "aria-selected": selected, children: _jsx("span", { children: title }) }, `navbar_tab_item_${index}`));
165
- }) })) : null, rightActions.length ? (_jsx(NavbarMenu, { children: _jsx(NavbarMenuItem, { children: rightActions.map((action, index) =>
166
- //@ts-ignore too costly to type this one now
167
- getActionRenderer(action, index)) }) })) : null] }));
171
+ }) })) : null, rightActions.length ? (_jsx(NavbarMenu, { children: _jsx(NavbarMenuItem, { children: rightActions.map((action, index) => getActionRenderer(action, index)) }) })) : null] }));
168
172
  }
169
173
  export const Navbar = NavBar;
@@ -1 +1 @@
1
- {"version":3,"file":"Sidebar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/sidebar/Sidebar.component.tsx"],"names":[],"mappings":"AAaA,KAAK,IAAI,GAAG;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACpB,CAAC;AACF,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AACF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAyIF,iBAAS,OAAO,CAAC,EACf,QAAQ,EACR,OAAO,EACP,aAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CA8DP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"Sidebar.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/sidebar/Sidebar.component.tsx"],"names":[],"mappings":"AAaA,KAAK,IAAI,GAAG;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;CACpB,CAAC;AACF,KAAK,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;AACzB,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;IACf,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;CAC5B,CAAC;AACF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAyIF,iBAAS,OAAO,CAAC,EACf,QAAQ,EACR,OAAO,EACP,aAAa,EACb,SAAS,EACT,GAAG,IAAI,EACR,EAAE,KAAK,2CA+DP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -141,7 +141,7 @@ function Sidebar({ expanded, actions, onToggleClick, hoverable, ...rest }) {
141
141
  return (_jsx(Wrapper, { onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), hoverable: hoverable, hovered: hovered, expanded: expanded, children: _jsxs(SidebarContainer, { expanded: expanded, className: "sc-sidebar", hoverable: hoverable, hovered: hovered, ...rest, children: [onToggleClick && (_jsx(MenuItemIcon, { children: _jsx(Button, { icon: _jsx(Icon, { size: "lg", name: "Lat-menu" }), onClick: () => {
142
142
  setHovered(false);
143
143
  onToggleClick();
144
- } }) })), actions.map(({ active, label, onClick, icon = null, ...actionRest }, index) => {
144
+ }, tooltip: { overlay: "Toggle sidebar" } }) })), actions.map(({ active, label, onClick, icon = null, ...actionRest }, index) => {
145
145
  return (_jsxs(SidebarItem, { className: "sc-sidebar-item", active: active, title: label, onClick: onClick, onKeyDown: (event) => {
146
146
  if (event.key === ' ' ||
147
147
  event.key === 'Enter' ||
@@ -20,27 +20,27 @@ export const StatusIcon = ({ status }) => {
20
20
  return {
21
21
  color: 'statusHealthy',
22
22
  name: 'Check-circle',
23
- label: 'Healthy status icon',
23
+ label: 'Healthy status',
24
24
  };
25
25
  case STATUS_WARNING:
26
26
  return {
27
27
  color: 'statusWarning',
28
28
  name: 'Times-circle',
29
- label: 'Warning status icon',
29
+ label: 'Warning status',
30
30
  };
31
31
  case STATUS_CRITICAL:
32
32
  return {
33
33
  color: 'statusCritical',
34
34
  name: 'Times-circle',
35
- label: 'Critical status icon',
35
+ label: 'Critical status',
36
36
  };
37
37
  default:
38
38
  return {
39
39
  color: 'textTertiary',
40
40
  name: 'Info',
41
- label: 'Information status icon',
41
+ label: 'Information status',
42
42
  };
43
43
  }
44
44
  })();
45
- return _jsx(Icon, { color: icon.color, name: icon.name, "aria-label": icon.label });
45
+ return _jsx(Icon, { color: icon.color, name: icon.name, ariaLabel: icon.label });
46
46
  };
@@ -1 +1 @@
1
- {"version":3,"file":"TableSync.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/TableSync.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAK7C,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC,CAAC;AAO7D,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,cAAc,EACd,OAAe,EACf,GAAG,IAAI,EACR,EAAE,cAAc,2CAchB"}
1
+ {"version":3,"file":"TableSync.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tablev2/TableSync.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAK7C,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,SAAS,CAAC,CAAC;AAO7D,wBAAgB,SAAS,CAAC,EACxB,MAAM,EACN,cAAc,EACd,OAAe,EACf,GAAG,IAAI,EACR,EAAE,cAAc,2CAahB"}
@@ -7,5 +7,5 @@ const TableSyncContainer = styled.div `
7
7
  align-items: center;
8
8
  `;
9
9
  export function TableSync({ onSync, tooltipOverlay, loading = false, ...rest }) {
10
- return (_jsx(TableSyncContainer, { children: _jsx(Button, { icon: _jsx(Icon, { name: "Sync" }), tooltip: tooltipOverlay ? { overlay: tooltipOverlay } : undefined, onClick: onSync, "aria-label": "Synchronize table data", role: "button", isLoading: loading, ...rest }) }));
10
+ return (_jsx(TableSyncContainer, { children: _jsx(Button, { icon: _jsx(Icon, { name: "Sync" }), tooltip: tooltipOverlay ? { overlay: tooltipOverlay } : { overlay: "Synchronize table data" }, onClick: onSync, role: "button", isLoading: loading, ...rest }) }));
11
11
  }
@@ -24,7 +24,7 @@ export const useTableContext = () => {
24
24
  return tableProps; //Todo figure out a way to transfer the type to the context provider
25
25
  };
26
26
  export const EmptyCell = ({ tooltipContent, mr = 4, }) => {
27
- return (_jsx(Box, { mr: mr, children: _jsx(Tooltip, { overlay: _jsx(TooltipContent, { children: tooltipContent || 'unknown' }), children: _jsx(Icon, { name: "Minus" }) }) }));
27
+ return (_jsx(Box, { mr: mr, children: _jsx(Tooltip, { overlay: _jsx(TooltipContent, { children: tooltipContent || 'unknown' }), children: _jsx(Icon, { name: "Minus", ariaLabel: "Unknown" }) }) }));
28
28
  };
29
29
  const DefaultRenderer = ({ value }) => {
30
30
  const { rowHeight } = useTableContext();
@@ -1 +1 @@
1
- {"version":3,"file":"Tooltip.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tooltip/Tooltip.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAY,MAAM,OAAO,CAAC;AAMhD,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,eAAO,MAAM,IAAI,SAAS,CAAC;AAC3B,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,UAAU,CAAC;AAC7B,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,OAAO,aAAa,CAAC;AAClC,MAAM,MAAM,QAAQ,GAChB,OAAO,GAAG,GACV,OAAO,MAAM,GACb,OAAO,IAAI,GACX,OAAO,KAAK,GACZ,OAAO,QAAQ,GACf,OAAO,MAAM,GACb,OAAO,UAAU,GACjB,OAAO,QAAQ,GACf,OAAO,SAAS,GAChB,OAAO,WAAW,GAClB,OAAO,OAAO,GACd,OAAO,SAAS,CAAC;AACrB,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AA0CF,iBAAS,OAAO,CAAC,EACf,SAAe,EACf,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,GAAG,IAAI,EACR,EAAE,KAAK,2CAsCP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"Tooltip.component.d.ts","sourceRoot":"","sources":["../../../src/lib/components/tooltip/Tooltip.component.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAY,MAAM,OAAO,CAAC;AAMhD,eAAO,MAAM,GAAG,QAAQ,CAAC;AACzB,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,eAAO,MAAM,IAAI,SAAS,CAAC;AAC3B,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,MAAM,YAAY,CAAC;AAChC,eAAO,MAAM,KAAK,UAAU,CAAC;AAC7B,eAAO,MAAM,UAAU,gBAAgB,CAAC;AACxC,eAAO,MAAM,QAAQ,cAAc,CAAC;AACpC,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,WAAW,iBAAiB,CAAC;AAC1C,eAAO,MAAM,SAAS,eAAe,CAAC;AACtC,eAAO,MAAM,OAAO,aAAa,CAAC;AAClC,MAAM,MAAM,QAAQ,GAChB,OAAO,GAAG,GACV,OAAO,MAAM,GACb,OAAO,IAAI,GACX,OAAO,KAAK,GACZ,OAAO,QAAQ,GACf,OAAO,MAAM,GACb,OAAO,UAAU,GACjB,OAAO,QAAQ,GACf,OAAO,SAAS,GAChB,OAAO,WAAW,GAClB,OAAO,OAAO,GACd,OAAO,SAAS,CAAC;AACrB,MAAM,MAAM,KAAK,GAAG;IAClB,SAAS,CAAC,EAAE,QAAQ,CAAC;IACrB,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AA0CF,iBAAS,OAAO,CAAC,EACf,SAAe,EACf,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,GAAG,IAAI,EACR,EAAE,KAAK,2CAiDP;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
@@ -62,6 +62,14 @@ function Tooltip({ placement = TOP, overlayStyle, children, overlay, ...rest })
62
62
  setIsTooltipVisible(true);
63
63
  }, onPointerLeave: () => {
64
64
  setIsTooltipVisible(false);
65
+ }, onFocus: () => {
66
+ setIsTooltipVisible(true);
67
+ }, onBlur: () => {
68
+ setIsTooltipVisible(false);
69
+ }, onKeyDown: (e) => {
70
+ if (e.key === 'Escape') {
71
+ setIsTooltipVisible(false);
72
+ }
65
73
  }, children: _jsx("div", { ref: refs.setReference, children: children }) }), isTooltipVisible &&
66
74
  overlay &&
67
75
  createPortal(_jsx(TooltipOverLayContainer, { ref: refs.setFloating, className: "sc-tooltip-overlay", placement: placement, style: { ...floatingStyles, ...overlayStyle }, children: _jsx(TooltipText, { className: "sc-tooltip-overlay-text", children: overlay }) }), document.body)] }));
@@ -46,6 +46,7 @@ export type CoreUITheme = {
46
46
  backgroundLevel2: string;
47
47
  backgroundLevel3: string;
48
48
  backgroundLevel4: string;
49
+ navbarBackground: string;
49
50
  textPrimary: string;
50
51
  textSecondary: string;
51
52
  textTertiary: string;
@@ -1 +1 @@
1
- {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/style/theme.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/lib/style/theme.ts"],"names":[],"mappings":"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"}
@@ -55,6 +55,7 @@ export const coreUIAvailableThemes = {
55
55
  backgroundLevel2: '#323245',
56
56
  backgroundLevel3: '#232331',
57
57
  backgroundLevel4: '#1B1B27',
58
+ navbarBackground: '#121219',
58
59
  textPrimary: '#EAEAEA',
59
60
  textSecondary: '#B5B5B5',
60
61
  textTertiary: '#DFDFDF',
@@ -80,6 +81,7 @@ export const coreUIAvailableThemes = {
80
81
  backgroundLevel2: '#F0F0F4',
81
82
  backgroundLevel3: '#E4E6EC',
82
83
  backgroundLevel4: '#FAFAF6',
84
+ navbarBackground: '#FCFCFC',
83
85
  textPrimary: '#0D0D0D',
84
86
  textSecondary: '#4F506D',
85
87
  textTertiary: '#DFDFDF', // TO CHECK
@@ -105,6 +107,7 @@ export const coreUIAvailableThemes = {
105
107
  backgroundLevel2: '#272020',
106
108
  backgroundLevel3: '#201B1A',
107
109
  backgroundLevel4: '#191515',
110
+ navbarBackground: '#120F0F',
108
111
  textPrimary: '#EAEAEA',
109
112
  textSecondary: '#A4ACB4',
110
113
  textTertiary: '#DFDFDF',
@@ -130,6 +133,7 @@ export const coreUIAvailableThemes = {
130
133
  backgroundLevel2: '#323245',
131
134
  backgroundLevel3: '#232331',
132
135
  backgroundLevel4: '#1B1B27',
136
+ navbarBackground: '#121219',
133
137
  textPrimary: '#EAEAEA',
134
138
  textSecondary: '#B5B5B5',
135
139
  textTertiary: '#DFDFDF',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scality/core-ui",
3
- "version": "0.196.0",
3
+ "version": "0.198.0",
4
4
  "description": "Scality common React component library",
5
5
  "author": "Scality Engineering",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -39,9 +39,9 @@
39
39
  "@babel/preset-typescript": "^7.16.7",
40
40
  "@chromatic-com/storybook": "^1.9.0",
41
41
  "@storybook/addon-actions": "^8.6.14",
42
- "@storybook/addon-essentials": "^8.6.14",
42
+ "@storybook/addon-essentials": "^8.6.15",
43
43
  "@storybook/addon-mdx-gfm": "^8.6.14",
44
- "@storybook/addon-storysource": "^8.6.14",
44
+ "@storybook/addon-storysource": "^8.6.15",
45
45
  "@storybook/addon-webpack5-compiler-swc": "^1.0.5",
46
46
  "@storybook/blocks": "^8.6.14",
47
47
  "@storybook/manager-api": "^8.6.14",
@@ -1,9 +1,9 @@
1
- import React from 'react';
2
1
  import '@testing-library/jest-dom';
3
2
  import { render, screen, waitFor } from '@testing-library/react';
4
- import { Banner } from './Banner.component';
5
- import { Icon } from '../icon/Icon.component';
3
+ import React from 'react';
6
4
  import { getWrapper } from '../../testUtils';
5
+ import { Icon } from '../icon/Icon.component';
6
+ import { Banner } from './Banner.component';
7
7
 
8
8
  describe('Banner', () => {
9
9
  const { Wrapper } = getWrapper();
@@ -28,31 +28,30 @@ describe('Banner', () => {
28
28
  });
29
29
 
30
30
  it('should render with default icon when withDefaultIcon is true', async () => {
31
- render(
31
+ const { container } = render(
32
32
  <Banner variant="base" withDefaultIcon>
33
33
  Message with default icon
34
34
  </Banner>,
35
- { wrapper: Wrapper }
35
+ { wrapper: Wrapper },
36
36
  );
37
37
  expect(screen.getByText('Message with default icon')).toBeInTheDocument();
38
-
38
+ // Icon is decorative (aria-hidden), verify it's rendered via DOM query
39
39
  await waitFor(() => {
40
- expect(screen.getByLabelText('Info-circle')).toBeInTheDocument();
40
+ expect(container.querySelector('svg[data-icon="circle-info"]')).toBeInTheDocument();
41
41
  });
42
42
  });
43
43
 
44
44
  it('should render with custom icon when icon prop is provided', async () => {
45
- render(
45
+ const { container } = render(
46
46
  <Banner variant="danger" icon={<Icon name="Check-circle" />}>
47
47
  Message with custom icon
48
48
  </Banner>,
49
- { wrapper: Wrapper }
49
+ { wrapper: Wrapper },
50
50
  );
51
51
  expect(screen.getByText('Message with custom icon')).toBeInTheDocument();
52
-
52
+ // Icon is decorative (aria-hidden), verify it's rendered via DOM query
53
53
  await waitFor(() => {
54
- expect(screen.getByLabelText('Check-circle')).toBeInTheDocument();
54
+ expect(container.querySelector('svg[data-icon="circle-check"]')).toBeInTheDocument();
55
55
  });
56
-
57
56
  });
58
57
  });
@@ -1,4 +1,4 @@
1
- import { ButtonHTMLAttributes } from 'react';
1
+ import type { ButtonHTMLAttributes } from 'react';
2
2
  import styled, { css } from 'styled-components';
3
3
  import { spacing } from '../../spacing';
4
4
  import { fontSize, fontWeight } from '../../style/theme';
@@ -11,7 +11,8 @@ export const FocusVisibleStyle = css`
11
11
  z-index: 1000;
12
12
  `;
13
13
 
14
- export type Props = Omit<
14
+ /** Props used by ButtonStyled for styling (no tooltip) */
15
+ type ButtonStyledProps = Omit<
15
16
  ButtonHTMLAttributes<HTMLButtonElement>,
16
17
  'size' | 'label'
17
18
  > & {
@@ -21,10 +22,31 @@ export type Props = Omit<
21
22
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
22
23
  icon?: React.ReactNode;
23
24
  label?: React.ReactNode;
24
- tooltip?: Omit<TooltipProps, 'children'>;
25
25
  isLoading?: boolean;
26
26
  };
27
- export const ButtonStyled = styled.button<Props>`
27
+
28
+ /** Button with a visible label - tooltip is optional */
29
+ type ButtonWithLabel = ButtonStyledProps & {
30
+ label: React.ReactNode;
31
+ tooltip?: Omit<TooltipProps, 'children'>;
32
+ };
33
+
34
+ /** Icon-only button - requires either string tooltip OR explicit aria-label */
35
+ type IconOnlyButton = ButtonStyledProps & {
36
+ label?: never;
37
+ } & (
38
+ | {
39
+ tooltip: Omit<TooltipProps, 'children'> & { overlay: string };
40
+ 'aria-label'?: string;
41
+ }
42
+ | {
43
+ tooltip: Omit<TooltipProps, 'children'>;
44
+ 'aria-label': string;
45
+ }
46
+ );
47
+
48
+ export type Props = ButtonWithLabel | IconOnlyButton;
49
+ export const ButtonStyled = styled.button<ButtonStyledProps>`
28
50
  -webkit-appearance: none;
29
51
  -moz-appearance: none;
30
52
  appearance: none;
@@ -243,9 +265,11 @@ function Button({
243
265
  );
244
266
  }
245
267
 
246
- if (!label && icon && !tooltip) {
247
- console.warn('Please specify the tooltip for the standalone icon button.');
248
- }
268
+ // For icon-only buttons, use tooltip.overlay as aria-label (typed as string for IconOnlyButton)
269
+ const buttonAriaLabel =
270
+ !label && icon && tooltip?.overlay
271
+ ? (tooltip.overlay as string)
272
+ : undefined;
249
273
 
250
274
  return (
251
275
  <Tooltip
@@ -261,31 +285,19 @@ function Button({
261
285
  icon={icon}
262
286
  onClick={onClick}
263
287
  size={size}
288
+ aria-label={buttonAriaLabel}
264
289
  {...rest}
265
290
  >
266
- <>
267
- {icon &&
268
- (isLoading ? (
269
- <ButtonLoader size="small" variant={variant} label={label} />
270
- ) : (
271
- <ButtonIcon
272
- label={label}
273
- aria-label={
274
- tooltip &&
275
- tooltip.overlay &&
276
- typeof tooltip.overlay === 'string'
277
- ? tooltip.overlay
278
- : undefined
279
- }
280
- >
281
- {icon}
282
- </ButtonIcon>
283
- ))}
284
- {!icon && isLoading && (
291
+ {icon &&
292
+ (isLoading ? (
285
293
  <ButtonLoader size="small" variant={variant} label={label} />
286
- )}
287
- <ButtonLabel>{label}</ButtonLabel>
288
- </>
294
+ ) : (
295
+ <ButtonIcon label={label}>{icon}</ButtonIcon>
296
+ ))}
297
+ {!icon && isLoading && (
298
+ <ButtonLoader size="small" variant={variant} label={label} />
299
+ )}
300
+ <ButtonLabel>{label}</ButtonLabel>
289
301
  </ButtonStyled>
290
302
  </Tooltip>
291
303
  );
@@ -63,7 +63,7 @@ export const CopyButton = ({
63
63
  textToCopy: string;
64
64
  copyAsHtml?: boolean;
65
65
  variant?: 'outline' | 'ghost';
66
- } & Props) => {
66
+ } & Omit<Props, 'tooltip' | 'label'>) => {
67
67
  const { copy, copyStatus } = useClipboard();
68
68
  return (
69
69
  <Button
@@ -413,7 +413,9 @@ describe('Barchart', () => {
413
413
  expect(screen.getByText('Test Secondary Title')).toBeInTheDocument();
414
414
  expect(screen.getByText('Test Right Title')).toBeInTheDocument();
415
415
  await waitFor(() => {
416
- expect(screen.getByRole('img', { name: /Info/i })).toBeInTheDocument();
416
+ expect(
417
+ screen.getByRole('button', { name: /More information/i }),
418
+ ).toBeInTheDocument();
417
419
  });
418
420
  });
419
421
  describe('formatDate', () => {
@@ -44,8 +44,8 @@ export const customIcons: Record<
44
44
 
45
45
  customIcons['Remote-user'].displayName = 'RemoteUser';
46
46
  customIcons['Remote-group'].displayName = 'RemoteGroup';
47
- customIcons['Bucket'].displayName = 'Bucket';
48
- customIcons['Buckets'].displayName = 'Buckets';
47
+ customIcons.Bucket.displayName = 'Bucket';
48
+ customIcons.Buckets.displayName = 'Buckets';
49
49
 
50
50
  const IconStyled = styled(FontAwesomeIcon)`
51
51
  ${(props) => {
@@ -64,6 +64,11 @@ type Props = {
64
64
  name: IconName;
65
65
  size?: SizeProp;
66
66
  color?: IconColor | CSSProperties['color'];
67
+ /**
68
+ * Accessible label for meaningful icons.
69
+ * When provided, the icon is announced to screen readers.
70
+ * When omitted, the icon is decorative (hidden from assistive technologies).
71
+ */
67
72
  ariaLabel?: string;
68
73
  withWrapper?: boolean;
69
74
  style?: CSSProperties;
@@ -125,7 +130,7 @@ function NonWrappedIcon({
125
130
  name,
126
131
  size = '1x',
127
132
  color,
128
- ariaLabel = '',
133
+ ariaLabel,
129
134
  title,
130
135
  ...rest
131
136
  }: Omit<Props, 'withWrapper'>) {
@@ -159,9 +164,15 @@ function NonWrappedIcon({
159
164
  return () => setIcon(undefined);
160
165
  }, [name, iconInfo]);
161
166
 
167
+ // Icons are decorative by default (aria-hidden: true)
168
+ // If ariaLabel is provided, the icon is meaningful (aria-hidden: false)
169
+ const accessibilityProps = ariaLabel
170
+ ? { 'aria-hidden': false as const, 'aria-label': ariaLabel }
171
+ : { 'aria-hidden': true as const };
172
+
162
173
  if (!icon && !customIcons[name]) {
163
174
  return (
164
- <DelayedFallback aria-label={`${name} ${ariaLabel}`}>
175
+ <DelayedFallback {...accessibilityProps}>
165
176
  <Loader size="base" />
166
177
  </DelayedFallback>
167
178
  );
@@ -174,7 +185,7 @@ function NonWrappedIcon({
174
185
  icon={icon}
175
186
  size={size}
176
187
  title={title}
177
- aria-label={`${name} ${ariaLabel}`}
188
+ {...accessibilityProps}
178
189
  {...rest}
179
190
  />
180
191
  );
@@ -7,20 +7,20 @@ import { IconHelp } from './IconHelper';
7
7
 
8
8
  describe('IconHelper', () => {
9
9
  const selectors = {
10
- icon: () => screen.getByRole('img'),
10
+ helpButton: () => screen.getByRole('button', { name: /Info/i }),
11
11
  };
12
12
  const renderIcon = (tooltipMessage: React.ReactNode) => {
13
13
  const { Wrapper } = getWrapper();
14
14
  render(
15
15
  <Wrapper>
16
- <IconHelp tooltipMessage={tooltipMessage} title="Info" />
16
+ <IconHelp tooltipMessage={tooltipMessage} aria-label="Info" />
17
17
  </Wrapper>,
18
18
  );
19
19
  };
20
20
  it('should render correctly', async () => {
21
21
  renderIcon('This is a tooltip');
22
22
  await waitFor(() => {
23
- expect(selectors.icon()).toBeInTheDocument();
23
+ expect(selectors.helpButton()).toBeInTheDocument();
24
24
  });
25
25
  });
26
26
  it('should display tooltip on hover', async () => {
@@ -28,25 +28,27 @@ describe('IconHelper', () => {
28
28
  renderIcon(tooltipMessage);
29
29
 
30
30
  await waitFor(() => {
31
- expect(selectors.icon()).toBeInTheDocument();
31
+ expect(selectors.helpButton()).toBeInTheDocument();
32
32
  });
33
- userEvent.hover(selectors.icon());
33
+ userEvent.hover(selectors.helpButton());
34
34
  await waitFor(() => {
35
35
  expect(screen.getByText(tooltipMessage)).toBeVisible();
36
36
  });
37
37
  });
38
- it('should render with title prop (passed to FontAwesome as native tooltip)', async () => {
38
+ it('should render with aria-label prop for accessibility', async () => {
39
39
  const { Wrapper } = getWrapper();
40
40
  render(
41
41
  <Wrapper>
42
42
  <IconHelp
43
43
  tooltipMessage={'This is a tooltip'}
44
- title="Info Helper Testing"
44
+ aria-label="Info Helper Testing"
45
45
  />
46
46
  </Wrapper>,
47
47
  );
48
48
  await waitFor(() => {
49
- expect(screen.getByRole('img', { name: /Info/i })).toBeInTheDocument();
49
+ expect(
50
+ screen.getByRole('button', { name: /Info Helper Testing/i }),
51
+ ).toBeInTheDocument();
50
52
  });
51
53
  });
52
54
  });
@@ -1,4 +1,5 @@
1
1
  import { CSSProperties, ReactNode } from 'react';
2
+ import styled from 'styled-components';
2
3
  import { Icon } from '../icon/Icon.component';
3
4
  import { Position, Tooltip } from '../tooltip/Tooltip.component';
4
5
 
@@ -6,13 +7,39 @@ type IconHelpProps = {
6
7
  tooltipMessage: ReactNode;
7
8
  placement?: Position;
8
9
  overlayStyle?: CSSProperties;
10
+ /**
11
+ * Accessible label for the help button.
12
+ * Should describe what information the tooltip provides.
13
+ * Example: "More info about Veeam application"
14
+ */
15
+ 'aria-label'?: string;
16
+ /** @deprecated Use aria-label instead */
9
17
  title?: string;
10
18
  };
11
19
 
20
+ const HelpButton = styled.button`
21
+ display: inline-flex;
22
+ background: none;
23
+ border: none;
24
+ padding: 0;
25
+ margin: 0;
26
+ cursor: pointer;
27
+ color: inherit;
28
+ font: inherit; /* Inherit font sizing */
29
+ vertical-align: text-bottom; /* Align with text */
30
+ line-height: 1;
31
+ &:focus-visible {
32
+ outline: 2px dashed ${(props) => props.theme.selectedActive};
33
+ outline-offset: 2px;
34
+ border-radius: 2px;
35
+ }
36
+ `;
37
+
12
38
  export const IconHelp = ({
13
39
  tooltipMessage,
14
40
  overlayStyle,
15
41
  placement = 'right',
42
+ 'aria-label': ariaLabel,
16
43
  title,
17
44
  }: IconHelpProps) => (
18
45
  <Tooltip
@@ -20,6 +47,11 @@ export const IconHelp = ({
20
47
  placement={placement}
21
48
  overlayStyle={overlayStyle}
22
49
  >
23
- <Icon name="Info" color="buttonSecondary" title={title} />
50
+ <HelpButton
51
+ type="button"
52
+ aria-label={ariaLabel || title || 'More information'}
53
+ >
54
+ <Icon name="Info" color="buttonSecondary" />
55
+ </HelpButton>
24
56
  </Tooltip>
25
57
  );
@@ -4,13 +4,26 @@ import { Logo } from '../../icons/branding';
4
4
  import { spacing } from '../../spacing';
5
5
  import { fontSize, navbarHeight, navbarItemWidth } from '../../style/theme';
6
6
  import { getThemePropSelector } from '../../utils';
7
- import { Dropdown, Item } from '../dropdown/Dropdown.component';
7
+ import { Dropdown, type Item } from '../dropdown/Dropdown.component';
8
8
  import { Icon } from '../icon/Icon.component';
9
- import { Button, FocusVisibleStyle } from '../buttonv2/Buttonv2.component';
10
- type Action = {
11
- type: string;
12
- items?: Array<Item>;
9
+ import { Button, FocusVisibleStyle, type Props as ButtonProps } from '../buttonv2/Buttonv2.component';
10
+
11
+ type ButtonAction = {
12
+ type: 'button';
13
+ } & ButtonProps;
14
+ type DropdownAction = {
15
+ type: 'dropdown';
16
+ items: Array<Item>;
17
+ text?: string;
18
+ icon?: JSX.Element;
19
+ };
20
+
21
+ type CustomAction = {
22
+ type: 'custom';
23
+ render: React.ComponentType;
13
24
  };
25
+
26
+ type Action = DropdownAction | ButtonAction | CustomAction;
14
27
  type Actions = Array<Action>;
15
28
  type Tab = {
16
29
  title?: string;
@@ -30,7 +43,7 @@ const NavbarContainer = styled.div`
30
43
  display: flex;
31
44
  justify-content: space-between;
32
45
  ${css`
33
- background-color: ${getThemePropSelector('backgroundLevel1')};
46
+ background-color: ${getThemePropSelector('navbarBackground')};
34
47
  color: ${getThemePropSelector('textPrimary')};
35
48
  .fas,
36
49
  .sc-trigger-text {
@@ -118,7 +131,7 @@ const NavbarMenuItem = styled.div`
118
131
  align-items: center;
119
132
  .sc-dropdown {
120
133
  .trigger {
121
- background-color: ${getThemePropSelector('backgroundLevel1')};
134
+ background-color: ${getThemePropSelector('navbarBackground')};
122
135
  &:hover {
123
136
  background-color: ${getThemePropSelector('highlight')};
124
137
  }
@@ -135,7 +148,7 @@ const NavbarMenuItem = styled.div`
135
148
  border-radius: 0;
136
149
  height: ${navbarHeight};
137
150
  font-size: ${fontSize.base};
138
- background-color: ${getThemePropSelector('backgroundLevel1')};
151
+ background-color: ${getThemePropSelector('navbarBackground')};
139
152
  &:hover {
140
153
  background-color: ${getThemePropSelector('highlight')};
141
154
  }
@@ -159,25 +172,32 @@ const LogoContainer = styled.div`
159
172
  }
160
173
  `;
161
174
 
162
- const getActionRenderer = ({ type, items = null, ...rest }, index) => {
163
- if (type === 'dropdown') {
164
- return items ? (
165
- <Dropdown
166
- key={`navbar_right_action_${index}`}
167
- size="larger"
168
- variant="backgroundLevel1"
169
- items={items}
170
- caret={false}
171
- {...rest}
172
- />
173
- ) : null;
174
- } else if (type === 'button') {
175
- return <Button key={`navbar_right_action_${index}`} {...rest} />;
176
- } else if (type === 'custom') {
177
- return <rest.render key={`navbar_right_action_${index}`} />;
175
+ const getActionRenderer = (action: Action, index: number) => {
176
+ switch (action.type) {
177
+ case 'dropdown': {
178
+ const { type, items, ...rest } = action;
179
+ return (
180
+ <Dropdown
181
+ key={`navbar_right_action_${index}`}
182
+ size="larger"
183
+ variant="backgroundLevel1"
184
+ items={items}
185
+ caret={false}
186
+ {...rest}
187
+ />
188
+ );
189
+ }
190
+ case 'button': {
191
+ const { type, ...rest } = action;
192
+ return <Button key={`navbar_right_action_${index}`} {...rest} />;
193
+ }
194
+ case 'custom': {
195
+ const CustomComponent = action.render;
196
+ return <CustomComponent key={`navbar_right_action_${index}`} />;
197
+ }
198
+ default:
199
+ return null;
178
200
  }
179
-
180
- return null;
181
201
  };
182
202
 
183
203
  function NavBar({
@@ -192,7 +212,7 @@ function NavBar({
192
212
  <NavbarMenu>
193
213
  {onToggleClick && (
194
214
  <NavbarMenuItem onClick={onToggleClick}>
195
- <Button icon={<Icon name="Lat-menu" />} title="Main Menu" />
215
+ <Button icon={<Icon name="Lat-menu" />} tooltip={{overlay: "Toggle Main Menu"}} />
196
216
  </NavbarMenuItem>
197
217
  )}
198
218
  <NavbarMenuItem>
@@ -234,7 +254,6 @@ function NavBar({
234
254
  <NavbarMenu>
235
255
  <NavbarMenuItem>
236
256
  {rightActions.map((action, index) =>
237
- //@ts-ignore too costly to type this one now
238
257
  getActionRenderer(action, index),
239
258
  )}
240
259
  </NavbarMenuItem>
@@ -196,6 +196,7 @@ function Sidebar({
196
196
  setHovered(false);
197
197
  onToggleClick();
198
198
  }}
199
+ tooltip={{overlay: "Toggle sidebar"}}
199
200
  />
200
201
  </MenuItemIcon>
201
202
  )}
@@ -26,30 +26,30 @@ export const StatusIcon = ({ status }: { status: Status }) => {
26
26
  return {
27
27
  color: 'statusHealthy',
28
28
  name: 'Check-circle',
29
- label: 'Healthy status icon',
29
+ label: 'Healthy status',
30
30
  };
31
31
 
32
32
  case STATUS_WARNING:
33
33
  return {
34
34
  color: 'statusWarning',
35
35
  name: 'Times-circle',
36
- label: 'Warning status icon',
36
+ label: 'Warning status',
37
37
  };
38
38
 
39
39
  case STATUS_CRITICAL:
40
40
  return {
41
41
  color: 'statusCritical',
42
42
  name: 'Times-circle',
43
- label: 'Critical status icon',
43
+ label: 'Critical status',
44
44
  };
45
45
  default:
46
46
  return {
47
47
  color: 'textTertiary',
48
48
  name: 'Info',
49
- label: 'Information status icon',
49
+ label: 'Information status',
50
50
  };
51
51
  }
52
52
  })();
53
53
 
54
- return <Icon color={icon.color} name={icon.name} aria-label={icon.label} />;
54
+ return <Icon color={icon.color} name={icon.name} ariaLabel={icon.label} />;
55
55
  };
@@ -24,9 +24,8 @@ export function TableSync({
24
24
  <TableSyncContainer>
25
25
  <Button
26
26
  icon={<Icon name="Sync" />}
27
- tooltip={tooltipOverlay ? { overlay: tooltipOverlay } : undefined}
27
+ tooltip={tooltipOverlay ? { overlay: tooltipOverlay } : {overlay: "Synchronize table data"}}
28
28
  onClick={onSync}
29
- aria-label="Synchronize table data"
30
29
  role="button"
31
30
  isLoading={loading}
32
31
  {...rest}
@@ -139,7 +139,7 @@ export const EmptyCell = ({
139
139
  <Tooltip
140
140
  overlay={<TooltipContent>{tooltipContent || 'unknown'}</TooltipContent>}
141
141
  >
142
- <Icon name="Minus" />
142
+ <Icon name="Minus" ariaLabel="Unknown" />
143
143
  </Tooltip>
144
144
  </Box>
145
145
  );
@@ -101,6 +101,17 @@ function Tooltip({
101
101
  onPointerLeave={() => {
102
102
  setIsTooltipVisible(false);
103
103
  }}
104
+ onFocus={() => {
105
+ setIsTooltipVisible(true);
106
+ }}
107
+ onBlur={() => {
108
+ setIsTooltipVisible(false);
109
+ }}
110
+ onKeyDown={(e) => {
111
+ if (e.key === 'Escape') {
112
+ setIsTooltipVisible(false);
113
+ }
114
+ }}
104
115
  >
105
116
  <div ref={refs.setReference}>{children}</div>
106
117
  </TooltipContainer>
@@ -49,6 +49,7 @@ export type CoreUITheme = {
49
49
  backgroundLevel2: string;
50
50
  backgroundLevel3: string;
51
51
  backgroundLevel4: string;
52
+ navbarBackground: string;
52
53
  textPrimary: string;
53
54
  textSecondary: string;
54
55
  textTertiary: string;
@@ -84,6 +85,7 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
84
85
  backgroundLevel2: '#323245',
85
86
  backgroundLevel3: '#232331',
86
87
  backgroundLevel4: '#1B1B27',
88
+ navbarBackground: '#121219',
87
89
  textPrimary: '#EAEAEA',
88
90
  textSecondary: '#B5B5B5',
89
91
  textTertiary: '#DFDFDF',
@@ -109,6 +111,7 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
109
111
  backgroundLevel2: '#F0F0F4',
110
112
  backgroundLevel3: '#E4E6EC',
111
113
  backgroundLevel4: '#FAFAF6',
114
+ navbarBackground: '#FCFCFC',
112
115
  textPrimary: '#0D0D0D',
113
116
  textSecondary: '#4F506D',
114
117
  textTertiary: '#DFDFDF', // TO CHECK
@@ -134,6 +137,7 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
134
137
  backgroundLevel2: '#272020',
135
138
  backgroundLevel3: '#201B1A',
136
139
  backgroundLevel4: '#191515',
140
+ navbarBackground: '#120F0F',
137
141
  textPrimary: '#EAEAEA',
138
142
  textSecondary: '#A4ACB4',
139
143
  textTertiary: '#DFDFDF',
@@ -159,6 +163,7 @@ export const coreUIAvailableThemes: Record<CoreUIThemeName, CoreUITheme> = {
159
163
  backgroundLevel2: '#323245',
160
164
  backgroundLevel3: '#232331',
161
165
  backgroundLevel4: '#1B1B27',
166
+ navbarBackground: '#121219',
162
167
  textPrimary: '#EAEAEA',
163
168
  textSecondary: '#B5B5B5',
164
169
  textTertiary: '#DFDFDF',
@@ -1,7 +1,10 @@
1
1
  import { action } from '@storybook/addon-actions';
2
2
  import React from 'react';
3
3
  import { Form, FormGroup, FormSection, Icon, Stack } from '../../src/lib';
4
- import { Button } from '../../src/lib/components/buttonv2/Buttonv2.component';
4
+ import {
5
+ Button,
6
+ Props as ButtonProps,
7
+ } from '../../src/lib/components/buttonv2/Buttonv2.component';
5
8
  import { Input } from '../../src/lib/next';
6
9
  import { iconArgType } from '../controls';
7
10
 
@@ -9,9 +12,10 @@ export default {
9
12
  title: 'Components/Button',
10
13
  component: Button,
11
14
  args: {
15
+ label: 'Button',
12
16
  onClick: action('Button clicked'),
13
17
  },
14
- render: ({ icon, ...args }) => {
18
+ render: ({ icon, ...args }: { icon?: string } & ButtonProps) => {
15
19
  return <Button {...args} icon={icon && <Icon name={icon} />} />;
16
20
  },
17
21
  argTypes: {
@@ -176,7 +180,7 @@ export const ButtonDisabled = {
176
180
  width: '120px',
177
181
  },
178
182
  overlay: 'The button is disabled',
179
- placement: 'top',
183
+ placement: 'top' as const,
180
184
  },
181
185
  },
182
186
  };
@@ -189,10 +193,10 @@ export const ButtonLoading = {
189
193
  };
190
194
 
191
195
  export const IconButtonWithTooltip = {
192
- render: ({ ...args }) => {
196
+ render: (args: ButtonProps) => {
193
197
  return (
194
198
  <Stack gap="r32" style={{ height: '5rem' }}>
195
- <Button icon={<Icon name="Delete"></Icon>} {...args} />
199
+ <Button {...args} />
196
200
  <Button
197
201
  variant="secondary"
198
202
  icon={<Icon name="Sync"></Icon>}
@@ -201,16 +205,12 @@ export const IconButtonWithTooltip = {
201
205
  width: '80px',
202
206
  },
203
207
  overlay: 'Bound status',
204
- placement: 'top',
208
+ placement: 'top' as const,
205
209
  }}
206
210
  />
207
211
 
208
- <Button {...args} icon={<Icon name="Delete"></Icon>} variant="danger" />
209
- <Button
210
- {...args}
211
- icon={<Icon name="Delete"></Icon>}
212
- variant="outline"
213
- />
212
+ <Button {...args} variant="danger" />
213
+ <Button {...args} icon={<Icon name="Delete"></Icon>} variant="outline" />
214
214
  </Stack>
215
215
  );
216
216
  },
@@ -222,7 +222,7 @@ export const IconButtonWithTooltip = {
222
222
  width: '80px',
223
223
  },
224
224
  overlay: 'Entity deletion',
225
- placement: 'top',
225
+ placement: 'top' as const,
226
226
  },
227
227
  },
228
228
  };
@@ -234,9 +234,7 @@ export const GhostButtons = {
234
234
  <Button
235
235
  icon={<i className="fas fa-sync" />}
236
236
  tooltip={{
237
- overlayStyle: {
238
- width: '80px',
239
- },
237
+
240
238
  overlay: 'Refresh the metrics',
241
239
  placement: 'top',
242
240
  }}
@@ -244,18 +242,13 @@ export const GhostButtons = {
244
242
  <Button
245
243
  icon={<i className="fas fa-file-export" />}
246
244
  tooltip={{
247
- overlayStyle: {
248
- width: '120px',
249
- },
250
245
  overlay: 'Export the data in predefined format',
251
- placement: 'top',
252
246
  }}
253
247
  />
254
248
  <Button
255
249
  icon={<i className="fas fa-calendar-week" />}
256
250
  tooltip={{
257
251
  overlayStyle: {
258
- width: '120px',
259
252
  },
260
253
  overlay: 'Metric over a period',
261
254
  placement: 'top',
@@ -123,6 +123,7 @@ const rightActions = [
123
123
  {
124
124
  type: 'button',
125
125
  icon: <i className="fas fa-sun" />,
126
+ tooltip: { overlay: 'Toggle Theme' },
126
127
  onClick: action('Theme toggle clicked'),
127
128
  },
128
129
  {