@heliosgraphics/ui 2.0.0-alpha.93 → 2.0.0-alpha.95

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 (76) hide show
  1. package/components/Breadcrumb/Breadcrumb.tsx +25 -23
  2. package/components/Button/Button.tsx +177 -179
  3. package/components/Checkbox/Checkbox.tsx +54 -60
  4. package/components/Confirm/Confirm.tsx +1 -1
  5. package/components/Dialog/Dialog.meta.ts +4 -0
  6. package/components/Dialog/Dialog.module.css +47 -37
  7. package/components/Dialog/Dialog.tsx +12 -47
  8. package/components/Dialog/Dialog.types.ts +1 -0
  9. package/components/Donut/Donut.tsx +4 -6
  10. package/components/Dropdown/Dropdown.module.css +20 -10
  11. package/components/Dropdown/Dropdown.tsx +7 -4
  12. package/components/Flex/Flex.meta.ts +2 -0
  13. package/components/Flex/Flex.tsx +3 -3
  14. package/components/Flex/Flex.types.ts +3 -1
  15. package/components/Flex/Flex.utils.ts +36 -1
  16. package/components/Flex/index.ts +0 -2
  17. package/components/Heading/Heading.tsx +3 -3
  18. package/components/Heading/components/H1/H1.tsx +2 -1
  19. package/components/Heading/components/H2/H2.tsx +2 -1
  20. package/components/Heading/components/H3/H3.tsx +2 -1
  21. package/components/Heading/components/H4/H4.tsx +2 -1
  22. package/components/Heading/components/H5/H5.tsx +2 -1
  23. package/components/Heading/components/H6/H6.tsx +2 -1
  24. package/components/Icon/Icon.tsx +3 -3
  25. package/components/Input/Input.tsx +5 -2
  26. package/components/Layout/components/LayoutAside/components/LayoutAsideContent/LayoutAsideContent.tsx +0 -2
  27. package/components/Layout/components/LayoutAside/components/LayoutAsideFooter/LayoutAsideFooter.tsx +0 -2
  28. package/components/Loading/Loading.tsx +8 -4
  29. package/components/Masonry/Masonry.meta.ts +1 -5
  30. package/components/Masonry/Masonry.tsx +27 -14
  31. package/components/Masonry/Masonry.types.ts +4 -4
  32. package/components/Menu/components/MenuFilter/MenuFilter.tsx +0 -2
  33. package/components/Overlay/Overlay.module.css +42 -18
  34. package/components/Overlay/Overlay.tsx +8 -3
  35. package/components/Pie/Pie.tsx +1 -0
  36. package/components/Pill/Pill.tsx +2 -2
  37. package/components/Progress/Progress.meta.ts +4 -0
  38. package/components/Progress/Progress.tsx +8 -2
  39. package/components/Progress/Progress.types.ts +1 -0
  40. package/components/Radio/Radio.tsx +57 -63
  41. package/components/Range/Range.meta.ts +26 -0
  42. package/components/Range/Range.module.css +68 -0
  43. package/components/Range/Range.tsx +47 -0
  44. package/components/Range/Range.types.ts +13 -0
  45. package/components/Range/index.ts +1 -0
  46. package/components/Segments/components/SegmentButton/SegmentButton.tsx +2 -1
  47. package/components/Select/Select.meta.ts +4 -0
  48. package/components/Select/Select.tsx +2 -0
  49. package/components/Select/Select.types.ts +1 -0
  50. package/components/Separator/Separator.tsx +25 -20
  51. package/components/Separator/components/VerticalSeparator/VerticalSeparator.tsx +1 -1
  52. package/components/Setup/Setup.tsx +0 -13
  53. package/components/Setup/css/feat.responsive.css +402 -0
  54. package/components/Slider/Slider.meta.ts +4 -0
  55. package/components/Slider/Slider.tsx +2 -2
  56. package/components/Slider/Slider.types.ts +1 -0
  57. package/components/Spacer/Spacer.tsx +3 -3
  58. package/components/Tabs/Tabs.tsx +19 -5
  59. package/components/Text/Text.tsx +3 -3
  60. package/components/Text/components/Div/Div.tsx +2 -1
  61. package/components/Text/components/Micro/Micro.tsx +2 -1
  62. package/components/Text/components/P/P.tsx +2 -1
  63. package/components/Text/components/Small/Small.tsx +2 -1
  64. package/components/Text/components/Tiny/Tiny.tsx +2 -1
  65. package/components/Tile/Tile.tsx +10 -1
  66. package/components/Tooltip/Tooltip.module.css +13 -0
  67. package/components/Tooltip/Tooltip.tsx +5 -3
  68. package/components/Tooltip/Tooltip.types.ts +1 -0
  69. package/components/Tooltip/components/TooltipContent/TooltipContent.tsx +11 -2
  70. package/components/Tooltip/components/TooltipTrigger/TooltipTrigger.tsx +4 -2
  71. package/components/shared/ResultList/ResultList.tsx +2 -2
  72. package/constants/components.ts +4 -2
  73. package/constants/meta.ts +9 -9
  74. package/globals.d.ts +12 -0
  75. package/index.ts +1 -0
  76. package/package.json +9 -8
@@ -1,24 +1,37 @@
1
1
  "use client"
2
2
 
3
- import { Masonry as MasonryPlock } from "react-plock"
4
- import { Children, type ReactElement, type FC } from "react"
3
+ import { type FC, useMemo } from "react"
5
4
  import type { MasonryProps } from "./Masonry.types"
6
5
 
7
- export const Masonry: FC<MasonryProps> = ({ children, columns, gap, breakpoints, useBalancedLayout }) => {
6
+ export const Masonry: FC<MasonryProps> = ({
7
+ children,
8
+ columns = [1, 2, 3],
9
+ gap = [2, 4, 6],
10
+ breakpoints = [0, 640, 960],
11
+ }) => {
12
+ const id: string = useMemo(() => `masonry-${Math.random().toString(36).slice(2, 8)}`, [])
13
+
8
14
  if (!children) return null
9
15
 
10
- const mappedChildren = Children.toArray(children).map((child) => <div className="Row">{child}</div>) as ReactElement[]
16
+ const mediaStyles = `
17
+ .${id} { column-count: ${columns[0]}; column-gap: ${gap[0]}px; }
18
+ .${id} > * { break-inside: avoid; margin-bottom: ${gap[0]}px; }
19
+
20
+ @media (min-width: ${breakpoints[1]}px) {
21
+ .${id} { column-count: ${columns[1]}; column-gap: ${gap[1]}px; }
22
+ .${id} > * { margin-bottom: ${gap[1]}px; }
23
+ }
24
+
25
+ @media (min-width: ${breakpoints[2]}px) {
26
+ .${id} { column-count: ${columns[2]}; column-gap: ${gap[2]}px; }
27
+ .${id} > * { margin-bottom: ${gap[2]}px; }
28
+ }
29
+ `
11
30
 
12
31
  return (
13
- <MasonryPlock
14
- items={mappedChildren}
15
- render={(item) => <>{item}</>}
16
- config={{
17
- columns: columns,
18
- gap: gap,
19
- media: breakpoints,
20
- useBalancedLayout: Boolean(useBalancedLayout),
21
- }}
22
- />
32
+ <>
33
+ <style dangerouslySetInnerHTML={{ __html: mediaStyles }} />
34
+ <div className={id}>{children}</div>
35
+ </>
23
36
  )
24
37
  }
@@ -1,10 +1,10 @@
1
1
  import type { PropsWithChildren } from "react"
2
+ import type { HeliosScaleType } from "../../types/scale"
2
3
 
3
4
  export interface MasonryBaseProps {
4
- columns: [number, number, number]
5
- gap: [number, number, number]
6
- breakpoints: [number, number, number]
7
- useBalancedLayout?: boolean
5
+ columns?: [number, number, number]
6
+ gap?: [HeliosScaleType, HeliosScaleType, HeliosScaleType]
7
+ breakpoints?: [number, number, number]
8
8
  }
9
9
 
10
10
  export type MasonryProps = PropsWithChildren<MasonryBaseProps>
@@ -1,5 +1,3 @@
1
- "use client"
2
-
3
1
  import type { FC } from "react"
4
2
  import { Input } from "../../../Input"
5
3
  import { getClasses } from "@heliosgraphics/utils"
@@ -7,18 +7,50 @@
7
7
  height: 100%;
8
8
  overflow: auto;
9
9
  width: 100%;
10
+
11
+ display: grid;
12
+ opacity: 1;
13
+ transition:
14
+ opacity var(--speed-md) ease-in-out,
15
+ display var(--speed-md) ease-in-out allow-discrete;
16
+ }
17
+
18
+ .overlay[data-open="false"] {
19
+ display: none;
20
+ opacity: 0;
21
+ }
22
+
23
+ @starting-style {
24
+ .overlay[data-open="true"] {
25
+ opacity: 0;
26
+ }
10
27
  }
11
28
 
12
29
  .overlay__content {
13
30
  height: 100%;
14
- opacity: 0;
31
+ opacity: 1;
32
+ transform: translateY(0);
15
33
 
16
- animation: animOverlayContent var(--speed-sm) ease-in-out forwards 120ms;
17
- transform: translateY(-24px);
34
+ transition:
35
+ opacity var(--speed-sm) ease-in-out,
36
+ transform var(--speed-sm) ease-in-out;
37
+ transition-delay: 120ms;
18
38
 
19
39
  pointer-events: none;
20
40
  }
21
41
 
42
+ .overlay[data-open="false"] .overlay__content {
43
+ opacity: 0;
44
+ transform: translateY(-24px);
45
+ }
46
+
47
+ @starting-style {
48
+ .overlay[data-open="true"] .overlay__content {
49
+ opacity: 0;
50
+ transform: translateY(-24px);
51
+ }
52
+ }
53
+
22
54
  .overlay__contentCentered {
23
55
  align-content: center;
24
56
  }
@@ -36,26 +68,18 @@
36
68
  height: 100%;
37
69
  width: 100%;
38
70
 
39
- animation: animOverlayBackground var(--speed-md) ease-in-out forwards;
40
71
  background-color: rgba(0, 0, 0, 0.85);
72
+ opacity: 1;
73
+
74
+ transition: opacity var(--speed-md) ease-in-out;
41
75
  }
42
76
 
43
- @keyframes animOverlayBackground {
44
- 0% {
45
- opacity: 0;
46
- }
47
- 100% {
48
- opacity: 1;
49
- }
77
+ .overlay[data-open="false"] .overlay__layer {
78
+ opacity: 0;
50
79
  }
51
80
 
52
- @keyframes animOverlayContent {
53
- 0% {
81
+ @starting-style {
82
+ .overlay[data-open="true"] .overlay__layer {
54
83
  opacity: 0;
55
- transform: translateY(-24px);
56
- }
57
- 100% {
58
- opacity: 1;
59
- transform: translateY(0);
60
84
  }
61
85
  }
@@ -4,8 +4,6 @@ import type { OverlayProps } from "./Overlay.types"
4
4
  import { getClasses } from "@heliosgraphics/utils"
5
5
 
6
6
  export const Overlay: FC<OverlayProps> = ({ onClose, isCentered, children, isOpen }) => {
7
- if (!isOpen) return null
8
-
9
7
  const hideFunction = (event: MouseEvent<HTMLDivElement>): void => {
10
8
  event.preventDefault()
11
9
  event.stopPropagation()
@@ -18,7 +16,14 @@ export const Overlay: FC<OverlayProps> = ({ onClose, isCentered, children, isOpe
18
16
  })
19
17
 
20
18
  return (
21
- <section className={styles.overlay} data-ui-component="Overlay">
19
+ <section
20
+ className={styles.overlay}
21
+ role="dialog"
22
+ aria-modal="true"
23
+ aria-hidden={!isOpen}
24
+ data-ui-component="Overlay"
25
+ data-open={isOpen}
26
+ >
22
27
  <div className={contentClasses}>{children}</div>
23
28
  <div className={styles.overlay__layer} onClick={hideFunction} />
24
29
  </section>
@@ -19,6 +19,7 @@ export const Pie: FC<PieProps> = ({ color, size, data }) => {
19
19
  aria-label={`Pie chart with ${data.length} segments`}
20
20
  data-ui-component="Pie"
21
21
  >
22
+ <title>{data.map((item) => `${item.name}: ${item.value}`).join(", ")}</title>
22
23
  {data.map((item, index) => {
23
24
  const thisData: Array<PieItem> = data.slice(0, index)
24
25
  const thisSize = thisData?.reduce((a, b) => a + b.value, 0)
@@ -7,11 +7,11 @@ import styles from "./Pill.module.css"
7
7
  import { memo, type FC } from "react"
8
8
  import type { PillProps } from "./Pill.types"
9
9
 
10
- const PILL_ICON_SIZE: Record<string, number> = {
10
+ const PILL_ICON_SIZE = {
11
11
  tiny: 12,
12
12
  small: 16,
13
13
  normal: 24,
14
- }
14
+ } as const satisfies Record<string, number>
15
15
 
16
16
  export const Pill: FC<PillProps> = memo(
17
17
  ({
@@ -11,6 +11,10 @@ export const meta: HeliosAttributeMeta<ProgressProps> = {
11
11
  ],
12
12
  _status: "nominal",
13
13
  _category: "core",
14
+ "aria-label": {
15
+ type: "string",
16
+ isOptional: true,
17
+ },
14
18
  isSmall: {
15
19
  type: "boolean",
16
20
  isOptional: true,
@@ -4,7 +4,13 @@ import { getColorClasses } from "../../utils/colors"
4
4
  import type { FC } from "react"
5
5
  import type { ProgressProps } from "./Progress.types"
6
6
 
7
- export const Progress: FC<ProgressProps> = ({ color = "blue", isSmall, max = 100, value = 0 }) => {
7
+ export const Progress: FC<ProgressProps> = ({
8
+ "aria-label": ariaLabel,
9
+ color = "blue",
10
+ isSmall,
11
+ max = 100,
12
+ value = 0,
13
+ }) => {
8
14
  const progressColorClasses: Array<string> = getColorClasses(color, "dark")
9
15
  const progressClasses: string = getClasses(styles.progress, ...progressColorClasses, {
10
16
  [styles.progressSmall]: isSmall,
@@ -15,7 +21,7 @@ export const Progress: FC<ProgressProps> = ({ color = "blue", isSmall, max = 100
15
21
  className={progressClasses}
16
22
  max={max}
17
23
  value={value}
18
- aria-label={`Progress: ${value} of ${max}`}
24
+ aria-label={ariaLabel ?? `Progress: ${value} of ${max}`}
19
25
  data-ui-component="Progress"
20
26
  />
21
27
  )
@@ -1,6 +1,7 @@
1
1
  import type { HeliosColorType } from "../../types/colors"
2
2
 
3
3
  export interface ProgressProps {
4
+ "aria-label"?: string
4
5
  isSmall?: boolean
5
6
  color: HeliosColorType
6
7
  max: number
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
 
3
- import { useId, memo } from "react"
3
+ import { useId } from "react"
4
4
  import { getClasses } from "@heliosgraphics/utils"
5
5
  import { getColorClasses } from "../../utils/colors"
6
6
  import { Flex } from "../Flex"
@@ -9,69 +9,63 @@ import styles from "./Radio.module.css"
9
9
  import type { FC } from "react"
10
10
  import type { RadioProps } from "./Radio.types"
11
11
 
12
- export const Radio: FC<RadioProps> = memo(
13
- ({
14
- color = "gray",
15
- isChecked,
16
- isVertical,
17
- isLabelHidden = false,
18
- isSmall,
19
- description,
20
- isDisabled,
21
- isRequired,
22
- onChange,
23
- label,
24
- name,
25
- value,
26
- }) => {
27
- const radioId: string = useId()
12
+ export const Radio: FC<RadioProps> = ({
13
+ color = "gray",
14
+ isChecked,
15
+ isVertical,
16
+ isLabelHidden = false,
17
+ isSmall,
18
+ description,
19
+ isDisabled,
20
+ isRequired,
21
+ onChange,
22
+ label,
23
+ name,
24
+ value,
25
+ }) => {
26
+ const radioId: string = useId()
28
27
 
29
- const colorClasses = getColorClasses(color, "dark")
30
- const radioClasses = getClasses(styles.radio, ...colorClasses, {
31
- [styles.radioDisabled]: isDisabled,
32
- [styles.radioSmall]: isSmall,
33
- })
28
+ const colorClasses = getColorClasses(color, "dark")
29
+ const radioClasses = getClasses(styles.radio, ...colorClasses, {
30
+ [styles.radioDisabled]: isDisabled,
31
+ [styles.radioSmall]: isSmall,
32
+ })
34
33
 
35
- const radioLabelClasses = getClasses(styles.radio__radioLabel, "flex gap-4", {
36
- "flex-x-center flex-column": isVertical,
37
- "flex-y-center": !isVertical,
38
- })
34
+ const radioLabelClasses = getClasses(styles.radio__radioLabel, "flex gap-4", {
35
+ "flex-x-center flex-column": isVertical,
36
+ "flex-y-center": !isVertical,
37
+ })
39
38
 
40
- return (
41
- <div className={radioClasses} data-ui-component="Radio">
42
- <label className={radioLabelClasses} htmlFor={radioId}>
43
- <span className={styles.radio__mark}>
44
- <input
45
- type="radio"
46
- checked={isChecked}
47
- onChange={onChange}
48
- disabled={isDisabled}
49
- required={isRequired}
50
- aria-label={isLabelHidden ? label : undefined}
51
- id={radioId}
52
- name={name}
53
- value={value}
54
- />
55
- <div className={styles.radio__radioMark} />
56
- </span>
57
- {!isLabelHidden && (
58
- <Flex isColumn={true}>
59
- <Text
60
- type={isSmall ? "tiny" : "small"}
61
- fontWeight="medium"
62
- emphasis={isDisabled ? "tertiary" : "inherit"}
63
- >
64
- {label}
39
+ return (
40
+ <div className={radioClasses} data-ui-component="Radio">
41
+ <label className={radioLabelClasses} htmlFor={radioId}>
42
+ <span className={styles.radio__mark}>
43
+ <input
44
+ type="radio"
45
+ checked={isChecked}
46
+ onChange={onChange}
47
+ disabled={isDisabled}
48
+ required={isRequired}
49
+ aria-label={isLabelHidden ? label : undefined}
50
+ id={radioId}
51
+ name={name}
52
+ value={value}
53
+ />
54
+ <div className={styles.radio__radioMark} />
55
+ </span>
56
+ {!isLabelHidden && (
57
+ <Flex isColumn={true}>
58
+ <Text type={isSmall ? "tiny" : "small"} fontWeight="medium" emphasis={isDisabled ? "tertiary" : "inherit"}>
59
+ {label}
60
+ </Text>
61
+ {description && (
62
+ <Text type="tiny" emphasis="secondary">
63
+ {description}
65
64
  </Text>
66
- {description && (
67
- <Text type="tiny" emphasis="secondary">
68
- {description}
69
- </Text>
70
- )}
71
- </Flex>
72
- )}
73
- </label>
74
- </div>
75
- )
76
- },
77
- )
65
+ )}
66
+ </Flex>
67
+ )}
68
+ </label>
69
+ </div>
70
+ )
71
+ }
@@ -0,0 +1,26 @@
1
+ import type { HeliosAttributeMeta } from "../../types/meta"
2
+ import type { RangeProps } from "./Range.types"
3
+
4
+ export const meta: HeliosAttributeMeta<RangeProps> = {
5
+ _patterns: [
6
+ {
7
+ id: "ui-range-default",
8
+ description: "default",
9
+ content: `<Range value={3} min={0} max={100} step={1} label={LABEL} onChange={FUNCTION} isDisabled={IS_DISABLED}/>`,
10
+ },
11
+ ],
12
+ _status: "experimental",
13
+ _category: "core",
14
+ isDisabled: { type: "boolean", isOptional: true },
15
+ isLabelHidden: { type: "boolean", isOptional: true },
16
+ label: { type: "string" },
17
+ max: { type: "number", isOptional: true, default: 100 },
18
+ min: { type: "number", isOptional: true, default: 0 },
19
+ name: { type: "string", isOptional: true },
20
+ onChange: {
21
+ type: "(event?: ChangeEvent<HTMLInputElement>) => unknown",
22
+ isOptional: true,
23
+ },
24
+ step: { type: "number", isOptional: true, default: 1 },
25
+ value: { type: "number", isOptional: true },
26
+ }
@@ -0,0 +1,68 @@
1
+ .range {
2
+ width: 100%;
3
+ }
4
+
5
+ .range__input {
6
+ width: 100%;
7
+ height: 4px;
8
+ margin: var(--space-3) 0;
9
+
10
+ appearance: none;
11
+ background: var(--ui-bg-soft-gray);
12
+ border-radius: var(--radius-sm);
13
+ outline: none;
14
+ transition: all var(--speed-sm) var(--ease-in-out-sine);
15
+ cursor: pointer;
16
+ }
17
+
18
+ .range__input::-webkit-slider-thumb {
19
+ appearance: none;
20
+ width: 18px;
21
+ height: 18px;
22
+
23
+ background: var(--ui-text-primary);
24
+ border: 2px solid var(--ui-bg-primary);
25
+ border-radius: var(--radius-round);
26
+ box-shadow: 0 0 0 1px var(--ui-border-primary);
27
+ cursor: pointer;
28
+ transition: all var(--speed-sm) var(--ease-in-out-sine);
29
+ }
30
+
31
+ .range__input::-moz-range-thumb {
32
+ width: 18px;
33
+ height: 18px;
34
+
35
+ background: var(--ui-text-primary);
36
+ border: 2px solid var(--ui-bg-primary);
37
+ border-radius: var(--radius-round);
38
+ box-shadow: 0 0 0 1px var(--ui-border-primary);
39
+ cursor: pointer;
40
+ transition: all var(--speed-sm) var(--ease-in-out-sine);
41
+ }
42
+
43
+ .range__input:focus::-webkit-slider-thumb {
44
+ box-shadow: 0 0 0 4px var(--ui-border-secondary);
45
+ }
46
+
47
+ .range__input:focus::-moz-range-thumb {
48
+ box-shadow: 0 0 0 4px var(--ui-border-secondary);
49
+ }
50
+
51
+ .range__input::-webkit-slider-runnable-track {
52
+ height: 4px;
53
+
54
+ background: var(--ui-bg-soft-gray);
55
+ border-radius: var(--radius-sm);
56
+ }
57
+
58
+ .range__input::-moz-range-track {
59
+ height: 4px;
60
+
61
+ background: var(--ui-bg-soft-gray);
62
+ border-radius: var(--radius-sm);
63
+ }
64
+
65
+ .rangeDisabled {
66
+ pointer-events: none;
67
+ opacity: 0.5;
68
+ }
@@ -0,0 +1,47 @@
1
+ "use client"
2
+
3
+ import { useId } from "react"
4
+ import { getClasses } from "@heliosgraphics/utils"
5
+ import { InputLabel } from "../shared/InputLabel"
6
+ import styles from "./Range.module.css"
7
+ import type { FC } from "react"
8
+ import type { RangeProps } from "./Range.types"
9
+
10
+ export const Range: FC<RangeProps> = ({
11
+ isDisabled,
12
+ isLabelHidden = false,
13
+ label,
14
+ max = 100,
15
+ min = 0,
16
+ name,
17
+ onChange,
18
+ step = 1,
19
+ value,
20
+ }) => {
21
+ const htmlFor: string = useId()
22
+
23
+ const rangeClasses: string = getClasses(styles.range, {
24
+ [styles.rangeDisabled]: isDisabled,
25
+ })
26
+
27
+ return (
28
+ <div className={rangeClasses} data-ui-component="Range">
29
+ <InputLabel id={htmlFor} label={label} isDisabled={!!isDisabled} isHidden={!!isLabelHidden} />
30
+ <input
31
+ className={styles.range__input}
32
+ disabled={isDisabled}
33
+ id={htmlFor}
34
+ max={max}
35
+ min={min}
36
+ name={name}
37
+ onChange={onChange}
38
+ step={step}
39
+ type="range"
40
+ value={value}
41
+ aria-valuemin={min}
42
+ aria-valuemax={max}
43
+ aria-valuenow={value}
44
+ />
45
+ </div>
46
+ )
47
+ }
@@ -0,0 +1,13 @@
1
+ import type { ChangeEventHandler } from "react"
2
+
3
+ export interface RangeProps {
4
+ isDisabled?: boolean
5
+ isLabelHidden?: boolean
6
+ label: string
7
+ max?: number
8
+ min?: number
9
+ name?: string
10
+ onChange?: ChangeEventHandler<HTMLInputElement>
11
+ step?: number
12
+ value?: number
13
+ }
@@ -0,0 +1 @@
1
+ export { Range } from "./Range"
@@ -1,10 +1,11 @@
1
1
  import styles from "./SegmentButton.module.css"
2
2
  import { getClasses } from "@heliosgraphics/utils"
3
3
  import { Icon } from "../../../Icon"
4
+ import type { FC } from "react"
4
5
  import type { HeliosIconType } from "../../../../types/icons"
5
6
  import type { SegmentButtonProps } from "./SegmentButton.types"
6
7
 
7
- export const SegmentButton = ({ isActive, value, icon, iconLeft, iconRight, onClick, ref }: SegmentButtonProps) => {
8
+ export const SegmentButton: FC<SegmentButtonProps> = ({ isActive, value, icon, iconLeft, iconRight, onClick, ref }) => {
8
9
  const segmentButtonClasses: string = getClasses(styles.segmentButton, {
9
10
  [styles.segmentButtonActive]: isActive,
10
11
  })
@@ -32,6 +32,10 @@ export const meta: HeliosAttributeMeta<SelectProps> = {
32
32
  onChange: {
33
33
  type: "ChangeEventHandler<HTMLSelectElement>",
34
34
  },
35
+ isRequired: {
36
+ type: "boolean",
37
+ isOptional: true,
38
+ },
35
39
  selectedValue: {
36
40
  type: "string",
37
41
  isOptional: true,
@@ -14,6 +14,7 @@ export const Select: FC<SelectProps> = ({
14
14
  isLabelHidden,
15
15
  isSmall,
16
16
  isDisabled,
17
+ isRequired,
17
18
  items,
18
19
  label,
19
20
  }) => {
@@ -35,6 +36,7 @@ export const Select: FC<SelectProps> = ({
35
36
  id={htmlFor}
36
37
  value={selectedValue}
37
38
  disabled={isDisabled}
39
+ required={isRequired}
38
40
  aria-label={isLabelHidden ? label : undefined}
39
41
  >
40
42
  {items?.map((item) => {
@@ -9,6 +9,7 @@ export type SelectItem = {
9
9
  export interface SelectProps {
10
10
  isDisabled?: boolean
11
11
  isLabelHidden?: boolean
12
+ isRequired?: boolean
12
13
  isSmall?: boolean
13
14
  items: Array<SelectItem>
14
15
  label: string
@@ -3,27 +3,32 @@ import { VerticalSeparator } from "./components/VerticalSeparator"
3
3
  import styles from "./Separator.module.css"
4
4
  import { getClasses } from "@heliosgraphics/utils"
5
5
  import type { SeparatorProps } from "./Separator.types"
6
- import { memo, type FC } from "react"
6
+ import type { FC } from "react"
7
7
 
8
- export const Separator: FC<SeparatorProps> = memo(
9
- ({ className, emphasis = "primary", isVertical, height, lineStyle = "solid", width }) => {
10
- const separatorClasses: string = getClasses(className, {
11
- [styles.separatorPrimary]: emphasis === "primary",
12
- [styles.separatorSecondary]: emphasis === "secondary",
13
- [styles.separatorTertiary]: emphasis === "tertiary",
14
- })
8
+ export const Separator: FC<SeparatorProps> = ({
9
+ className,
10
+ emphasis = "primary",
11
+ isVertical,
12
+ height,
13
+ lineStyle = "solid",
14
+ width,
15
+ }) => {
16
+ const separatorClasses: string = getClasses(className, {
17
+ [styles.separatorPrimary]: emphasis === "primary",
18
+ [styles.separatorSecondary]: emphasis === "secondary",
19
+ [styles.separatorTertiary]: emphasis === "tertiary",
20
+ })
15
21
 
16
- const separatorProps: SeparatorProps = {
17
- className: separatorClasses,
18
- emphasis,
19
- ...(isVertical !== undefined && { isVertical }),
20
- ...(height !== undefined && { height }),
21
- lineStyle,
22
- ...(width !== undefined && { width }),
23
- }
22
+ const separatorProps: SeparatorProps = {
23
+ className: separatorClasses,
24
+ emphasis,
25
+ ...(isVertical !== undefined && { isVertical }),
26
+ ...(height !== undefined && { height }),
27
+ lineStyle,
28
+ ...(width !== undefined && { width }),
29
+ }
24
30
 
25
- if (isVertical) return <VerticalSeparator {...separatorProps} />
31
+ if (isVertical) return <VerticalSeparator {...separatorProps} />
26
32
 
27
- return <HorizontalSeparator {...separatorProps} />
28
- },
29
- )
33
+ return <HorizontalSeparator {...separatorProps} />
34
+ }
@@ -16,5 +16,5 @@ export const VerticalSeparator: FC<VerticalSeparatorProps> = ({ height, classNam
16
16
  height: height ? `${height ?? 0}px` : "auto",
17
17
  }
18
18
 
19
- return <HRMarkup style={verticalStyle} className={hrClassNames} />
19
+ return <HRMarkup style={verticalStyle} className={hrClassNames} aria-orientation="vertical" />
20
20
  }