@indico-data/design-system 1.0.47 → 1.0.49

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 (182) hide show
  1. package/README.md +5 -0
  2. package/jest.config.js +15 -0
  3. package/lib/components/Accordion/Accordion.d.ts +1 -1
  4. package/lib/components/Accordion/Accordion.stories.d.ts +2 -2
  5. package/lib/components/Accordion/Accordion.styles.d.ts +1 -275
  6. package/lib/components/Icon/Icon.stories.d.ts +3 -4
  7. package/lib/components/Icon/indicons.d.ts +143 -125
  8. package/lib/components/Icon/storyHelpers.d.ts +3 -813
  9. package/lib/components/ListTable/Header/Header.d.ts +1 -1
  10. package/lib/components/ListTable/Header/Header.styles.d.ts +1 -272
  11. package/lib/components/ListTable/ListTable.d.ts +1 -1
  12. package/lib/components/ListTable/ListTable.stories.d.ts +1 -1
  13. package/lib/components/ListTable/ListTable.styles.d.ts +1 -272
  14. package/lib/components/LoadingAwareContainer/LoadingAwareContainer.d.ts +15 -0
  15. package/lib/components/LoadingAwareContainer/LoadingAwareContainer.stories.d.ts +22 -0
  16. package/lib/components/LoadingAwareContainer/LoadingAwareContainer.styles.d.ts +3 -0
  17. package/lib/components/LoadingAwareContainer/index.d.ts +1 -0
  18. package/lib/components/Navigation/Drawer/Drawer.d.ts +15 -0
  19. package/lib/components/Navigation/Drawer/Drawer.stories.d.ts +6 -0
  20. package/lib/components/Navigation/Drawer/Drawer.styles.d.ts +7 -0
  21. package/lib/components/Navigation/Drawer/DrawerLinkList.d.ts +9 -0
  22. package/lib/components/Navigation/Drawer/DrawerLinkList.styles.d.ts +2 -0
  23. package/lib/components/Navigation/Drawer/__mocks__/mocks.d.ts +3 -0
  24. package/lib/components/Navigation/Drawer/__tests__/Drawer.test.d.ts +1 -0
  25. package/lib/components/Navigation/Drawer/__tests__/DrawerLinkList.test.d.ts +1 -0
  26. package/lib/components/Navigation/Drawer/index.d.ts +1 -0
  27. package/lib/components/Navigation/Drawer/types.d.ts +7 -0
  28. package/lib/components/Navigation/index.d.ts +1 -0
  29. package/lib/components/Pagination/Pagination.d.ts +1 -2
  30. package/lib/components/Pagination/Pagination.styles.d.ts +1 -272
  31. package/lib/components/Wizard/Wizard.d.ts +48 -0
  32. package/lib/components/Wizard/Wizard.stories.d.ts +29 -0
  33. package/lib/components/Wizard/Wizard.styles.d.ts +4 -0
  34. package/lib/components/Wizard/index.d.ts +2 -0
  35. package/lib/components/WizardWithSidebar/WizardWithSidebar.d.ts +58 -0
  36. package/lib/components/WizardWithSidebar/WizardWithSidebar.stories.d.ts +46 -0
  37. package/lib/components/WizardWithSidebar/WizardWithSidebar.styles.d.ts +9 -0
  38. package/lib/components/WizardWithSidebar/index.d.ts +2 -0
  39. package/lib/components/basic-section/Section/Section.d.ts +1 -1
  40. package/lib/components/basic-section/Section/Section.stories.d.ts +1 -1
  41. package/lib/components/basic-section/Section/Section.styles.d.ts +1 -272
  42. package/lib/components/basic-section/SectionBlock/SectionBlock.d.ts +1 -1
  43. package/lib/components/basic-section/SectionBlock/SectionBlock.styles.d.ts +1 -272
  44. package/lib/components/basic-section/SectionBody/SectionBody.d.ts +1 -1
  45. package/lib/components/basic-section/SectionBody/SectionBody.stories.d.ts +1 -2
  46. package/lib/components/basic-section/SectionBody/SectionBody.styles.d.ts +1 -272
  47. package/lib/components/basic-section/SectionHeader/SectionHeader.d.ts +1 -1
  48. package/lib/components/basic-section/SectionHeader/SectionHeader.stories.d.ts +1 -1
  49. package/lib/components/basic-section/SectionHeader/SectionHeader.styles.d.ts +1 -272
  50. package/lib/components/basic-section/SectionTable/SectionTable.d.ts +1 -2
  51. package/lib/components/basic-section/SectionTable/SectionTable.styles.d.ts +1 -272
  52. package/lib/components/buttons/Button/Button.styles.d.ts +1 -282
  53. package/lib/components/buttons/IconButton/IconButton.d.ts +4 -5
  54. package/lib/components/buttons/IconButton/IconButton.stories.d.ts +3 -3
  55. package/lib/components/buttons/IconButton/IconButton.styles.d.ts +2 -567
  56. package/lib/components/buttons/types.d.ts +2 -1
  57. package/lib/components/dropdowns/BorderSelect/BorderSelect.d.ts +1 -1
  58. package/lib/components/dropdowns/BorderSelect/BorderSelect.stories.d.ts +1 -1
  59. package/lib/components/dropdowns/BorderSelect/BorderSelect.styles.d.ts +2 -543
  60. package/lib/components/dropdowns/MultiCombobox/MultiCombobox.styles.d.ts +1 -84
  61. package/lib/components/dropdowns/Select/Select.d.ts +1 -1
  62. package/lib/components/dropdowns/Select/Select.stories.d.ts +1 -1
  63. package/lib/components/dropdowns/Select/Select.styles.d.ts +1 -272
  64. package/lib/components/dropdowns/SingleCombobox/SingleCombobox.styles.d.ts +1 -84
  65. package/lib/components/dropdowns/utils.d.ts +1 -2
  66. package/lib/components/index.d.ts +7 -2
  67. package/lib/components/inputs/EditableInput/EditableInput.d.ts +1 -1
  68. package/lib/components/inputs/EditableInput/EditableInput.stories.d.ts +1 -2
  69. package/lib/components/inputs/EditableInput/EditableInput.styles.d.ts +1 -272
  70. package/lib/components/inputs/NumberInput/NumberInput.styles.d.ts +1 -272
  71. package/lib/components/inputs/RadioButtons/RadioButtons.d.ts +24 -0
  72. package/lib/components/inputs/RadioButtons/RadioButtons.stories.d.ts +15 -0
  73. package/lib/components/inputs/RadioButtons/RadioButtons.styles.d.ts +14 -0
  74. package/lib/components/inputs/RadioButtons/index.d.ts +1 -0
  75. package/lib/components/inputs/RadioGroup/RadioGroup.d.ts +27 -0
  76. package/lib/components/inputs/RadioGroup/RadioGroup.stories.d.ts +16 -0
  77. package/lib/components/inputs/RadioGroup/RadioGroup.styles.d.ts +2 -0
  78. package/lib/components/inputs/RadioGroup/index.d.ts +1 -0
  79. package/lib/components/inputs/SearchInput/SearchInput.d.ts +1 -1
  80. package/lib/components/inputs/SearchInput/SearchInput.stories.d.ts +1 -1
  81. package/lib/components/inputs/SearchInput/SearchInput.styles.d.ts +1 -5
  82. package/lib/components/inputs/TextInput/TextInput.styles.d.ts +2 -543
  83. package/lib/components/inputs/index.d.ts +2 -0
  84. package/lib/components/loading-indicators/BarSpinner/BarSpinner.styles.d.ts +1 -272
  85. package/lib/components/loading-indicators/CirclePulse/CirclePulse.styles.d.ts +3 -3
  86. package/lib/components/loading-indicators/LoadingIndicator/LoadingIndicator.d.ts +10 -0
  87. package/lib/components/loading-indicators/LoadingIndicator/LoadingIndicator.stories.d.ts +11 -0
  88. package/lib/components/loading-indicators/LoadingIndicator/LoadingIndicator.styles.d.ts +8 -0
  89. package/lib/components/loading-indicators/LoadingIndicator/index.d.ts +1 -0
  90. package/lib/components/loading-indicators/LoadingList/LoadingList.d.ts +1 -2
  91. package/lib/components/loading-indicators/LoadingList/LoadingList.stories.d.ts +1 -2
  92. package/lib/components/loading-indicators/LoadingList/LoadingList.styles.d.ts +1 -272
  93. package/lib/components/loading-indicators/PercentageRing/PercentageRing.d.ts +1 -2
  94. package/lib/components/loading-indicators/PercentageRing/PercentageRing.styles.d.ts +1 -272
  95. package/lib/components/loading-indicators/RandomLoadingMessage/RandomLoadingMessage.d.ts +1 -2
  96. package/lib/components/loading-indicators/RandomLoadingMessage/RandomLoadingMessage.stories.d.ts +1 -2
  97. package/lib/components/loading-indicators/index.d.ts +1 -0
  98. package/lib/components/modals/ConfirmModal/ConfirmModal.d.ts +17 -0
  99. package/lib/components/modals/ConfirmModal/ConfirmModal.stories.d.ts +44 -0
  100. package/lib/components/modals/ConfirmModal/ConfirmModal.styles.d.ts +2 -0
  101. package/lib/components/modals/ConfirmModal/index.d.ts +1 -0
  102. package/lib/components/modals/ModalBase/ModalBase.d.ts +27 -0
  103. package/lib/components/modals/ModalBase/ModalBase.stories.d.ts +9 -0
  104. package/lib/components/modals/ModalBase/ModalBase.styles.d.ts +4 -0
  105. package/lib/components/modals/ModalBase/index.d.ts +2 -0
  106. package/lib/components/modals/index.d.ts +2 -0
  107. package/lib/components/user-feedback/Shrug/Shrug.stories.d.ts +1 -1
  108. package/lib/components/user-feedback/Shrug/Shrug.styles.d.ts +1 -272
  109. package/lib/index.d.ts +531 -270
  110. package/lib/index.esm.js +5722 -824
  111. package/lib/index.esm.js.map +1 -1
  112. package/lib/index.js +5779 -867
  113. package/lib/index.js.map +1 -1
  114. package/lib/setupTests.d.ts +1 -0
  115. package/lib/styles/globals/index.d.ts +1 -2
  116. package/lib/tokens/colors.d.ts +9 -0
  117. package/lib/tokens/typography.d.ts +12 -0
  118. package/lib/types.d.ts +147 -125
  119. package/package.json +60 -42
  120. package/src/components/Icon/Icon.tsx +1 -0
  121. package/src/components/Icon/indicons.tsx +138 -15
  122. package/src/components/ListTable/ListTable.stories.tsx +1 -1
  123. package/src/components/LoadingAwareContainer/LoadingAwareContainer.stories.tsx +45 -0
  124. package/src/components/LoadingAwareContainer/LoadingAwareContainer.styles.ts +16 -0
  125. package/src/components/LoadingAwareContainer/LoadingAwareContainer.tsx +36 -0
  126. package/src/components/LoadingAwareContainer/index.ts +1 -0
  127. package/src/components/Navigation/Drawer/Drawer.stories.tsx +44 -0
  128. package/src/components/Navigation/Drawer/Drawer.styles.ts +75 -0
  129. package/src/components/Navigation/Drawer/Drawer.tsx +108 -0
  130. package/src/components/Navigation/Drawer/DrawerLinkList.styles.ts +66 -0
  131. package/src/components/Navigation/Drawer/DrawerLinkList.tsx +64 -0
  132. package/src/components/Navigation/Drawer/__mocks__/mocks.ts +49 -0
  133. package/src/components/Navigation/Drawer/__tests__/Drawer.test.tsx +175 -0
  134. package/src/components/Navigation/Drawer/__tests__/DrawerLinkList.test.tsx +66 -0
  135. package/src/components/Navigation/Drawer/index.ts +1 -0
  136. package/src/components/Navigation/Drawer/types.ts +8 -0
  137. package/src/components/Navigation/index.ts +1 -0
  138. package/src/components/Wizard/Wizard.stories.tsx +180 -0
  139. package/src/components/Wizard/Wizard.styles.ts +72 -0
  140. package/src/components/Wizard/Wizard.tsx +211 -0
  141. package/src/components/Wizard/index.ts +2 -0
  142. package/src/components/WizardWithSidebar/WizardWithSidebar.stories.tsx +143 -0
  143. package/src/components/WizardWithSidebar/WizardWithSidebar.styles.ts +123 -0
  144. package/src/components/WizardWithSidebar/WizardWithSidebar.tsx +262 -0
  145. package/src/components/WizardWithSidebar/index.ts +2 -0
  146. package/src/components/buttons/IconButton/IconButton.styles.ts +31 -0
  147. package/src/components/buttons/IconButton/IconButton.tsx +8 -6
  148. package/src/components/buttons/types.ts +2 -1
  149. package/src/components/index.ts +16 -1
  150. package/src/components/inputs/RadioButtons/RadioButtons.stories.tsx +84 -0
  151. package/src/components/inputs/RadioButtons/RadioButtons.styles.ts +82 -0
  152. package/src/components/inputs/RadioButtons/RadioButtons.tsx +61 -0
  153. package/src/components/inputs/RadioButtons/index.tsx +1 -0
  154. package/src/components/inputs/RadioGroup/RadioGroup.stories.tsx +66 -0
  155. package/src/components/inputs/RadioGroup/RadioGroup.styles.ts +11 -0
  156. package/src/components/inputs/RadioGroup/RadioGroup.tsx +120 -0
  157. package/src/components/inputs/RadioGroup/index.ts +1 -0
  158. package/src/components/inputs/SearchInput/SearchInput.styles.ts +28 -42
  159. package/src/components/inputs/SearchInput/SearchInput.tsx +6 -4
  160. package/src/components/inputs/index.ts +2 -0
  161. package/src/components/loading-indicators/CirclePulse/CirclePulse.styles.ts +7 -7
  162. package/src/components/loading-indicators/CirclePulse/CirclePulse.tsx +3 -3
  163. package/src/components/loading-indicators/LoadingIndicator/LoadingIndicator.stories.tsx +22 -0
  164. package/src/components/loading-indicators/LoadingIndicator/LoadingIndicator.styles.ts +81 -0
  165. package/src/components/loading-indicators/LoadingIndicator/LoadingIndicator.tsx +61 -0
  166. package/src/components/loading-indicators/LoadingIndicator/index.ts +1 -0
  167. package/src/components/loading-indicators/index.ts +1 -0
  168. package/src/components/modals/ConfirmModal/ConfirmModal.stories.tsx +76 -0
  169. package/src/components/modals/ConfirmModal/ConfirmModal.styles.ts +30 -0
  170. package/src/components/modals/ConfirmModal/ConfirmModal.tsx +84 -0
  171. package/src/components/modals/ConfirmModal/index.ts +1 -0
  172. package/src/components/modals/ModalBase/ModalBase.stories.tsx +47 -0
  173. package/src/components/modals/ModalBase/ModalBase.styles.tsx +73 -0
  174. package/src/components/modals/ModalBase/ModalBase.tsx +72 -0
  175. package/src/components/modals/ModalBase/index.ts +2 -0
  176. package/src/components/modals/index.ts +2 -0
  177. package/src/index.ts +13 -0
  178. package/src/setupTests.ts +4 -0
  179. package/src/tokens/colors.ts +9 -0
  180. package/src/tokens/typography.ts +7 -1
  181. package/src/types.ts +8 -0
  182. package/tsconfig.json +1 -1
@@ -0,0 +1,11 @@
1
+ import styled from 'styled-components';
2
+
3
+ export const StyledRadioGroup = styled.div`
4
+ &.horizontal {
5
+ display: flex;
6
+
7
+ > * {
8
+ margin-right: 10px;
9
+ }
10
+ }
11
+ `;
@@ -0,0 +1,120 @@
1
+ // TODO: This component's migration was fast-tracked for Insights. Assess for potential refactor and documentation.
2
+
3
+ import React, { createContext, useContext, useRef, useState } from 'react';
4
+ import classNames from 'classnames';
5
+ import { AriaRadioGroupProps, AriaRadioProps } from '@react-types/radio';
6
+ import { useRadio, useRadioGroup } from '@react-aria/radio';
7
+ import { useFocusRing } from '@react-aria/focus';
8
+ import { useVisuallyHidden } from '@react-aria/visually-hidden';
9
+ import { RadioGroupState, useRadioGroupState } from 'react-stately';
10
+
11
+ import { PermafrostComponent } from '@/types';
12
+ import { StyledRadioGroup } from './RadioGroup.styles';
13
+
14
+ export type RadioGroupProps = PermafrostComponent & {
15
+ value?: string;
16
+ onChange?: (value: string) => void;
17
+ children: React.ReactNode;
18
+ className?: string;
19
+ } & AriaRadioGroupProps;
20
+
21
+ export const RadioContext = createContext({} as RadioGroupState);
22
+
23
+ /**
24
+ * Renders a group of radio buttons with no styling. This component is not
25
+ * designed to be user-facing, and should only be used to provide functionality.
26
+ *
27
+ * A group label must be included: either pass a string or markup into the
28
+ * `label` prop, or include an `aria-label` or `aria-labelledby` attribute.
29
+ */
30
+ export function RadioGroup(props: RadioGroupProps) {
31
+ const {
32
+ children,
33
+ className,
34
+ value,
35
+ id,
36
+ isDisabled,
37
+ isReadOnly,
38
+ label,
39
+ name,
40
+ onChange,
41
+ orientation,
42
+ defaultValue,
43
+ } = props;
44
+
45
+ const [lastFocusedValue, setLastFocusedValue] = useState<string | null>(null);
46
+
47
+ const radioGroupState = {
48
+ isDisabled: isDisabled || false,
49
+ isReadOnly: isReadOnly || false,
50
+ lastFocusedValue,
51
+ name: name || '',
52
+ selectedValue: value,
53
+ setLastFocusedValue,
54
+ setSelectedValue: onChange,
55
+ defaultValue,
56
+ };
57
+
58
+ const state = useRadioGroupState(radioGroupState);
59
+ const { radioGroupProps, labelProps } = useRadioGroup(props, state);
60
+
61
+ return (
62
+ <StyledRadioGroup
63
+ {...radioGroupProps}
64
+ className={classNames(className, { horizontal: orientation === 'horizontal' })}
65
+ data-cy={props['data-cy']}
66
+ id={id}
67
+ >
68
+ {label && (
69
+ <div className="groupLabel" {...labelProps}>
70
+ {label}
71
+ </div>
72
+ )}
73
+
74
+ <RadioContext.Provider value={state}>{children}</RadioContext.Provider>
75
+ </StyledRadioGroup>
76
+ );
77
+ }
78
+
79
+ /**
80
+ * A single radio button and its label; no styling is applied, and the native
81
+ * radio button is visually hidden.
82
+ */
83
+ export function Radio(
84
+ props: AriaRadioProps & {
85
+ className?: string;
86
+ isVisuallySelected?: (selectedValue: string) => void;
87
+ },
88
+ ) {
89
+ const { children, className, isDisabled, isVisuallySelected } = props;
90
+ const state = useContext(RadioContext);
91
+ const inputRef = useRef<HTMLInputElement>(null);
92
+
93
+ const { visuallyHiddenProps } = useVisuallyHidden();
94
+
95
+ const { inputProps } = useRadio(props, state, inputRef);
96
+ const { isFocusVisible, focusProps } = useFocusRing();
97
+
98
+ let isSelected;
99
+
100
+ if (isVisuallySelected) {
101
+ isSelected = isVisuallySelected(state.selectedValue as string);
102
+ } else {
103
+ // @ts-ignore
104
+ isSelected = state.selectedValue === props.value || state?.defaultValue === props.value;
105
+ }
106
+
107
+ return (
108
+ <label
109
+ className={classNames(className, {
110
+ disabled: isDisabled || state.isDisabled,
111
+ selected: isSelected,
112
+ focused: isFocusVisible,
113
+ })}
114
+ >
115
+ <input {...inputProps} {...visuallyHiddenProps} {...focusProps} ref={inputRef} />
116
+
117
+ {children}
118
+ </label>
119
+ );
120
+ }
@@ -0,0 +1 @@
1
+ export { Radio as AbstractRadio, RadioGroup as AbstractRadioGroup } from './RadioGroup';
@@ -1,14 +1,10 @@
1
- import styled, { css } from 'styled-components';
1
+ import styled from 'styled-components';
2
2
 
3
3
  import { TYPOGRAPHY } from '@/tokens';
4
4
 
5
5
  import { inputCommon } from '../inputsCommon.styles';
6
6
 
7
- export const StyledSearchField = styled.div<{
8
- border?: boolean;
9
- showSearchIcon?: boolean;
10
- showClearInputIcon?: boolean;
11
- }>`
7
+ export const StyledSearchField = styled.div`
12
8
  position: relative;
13
9
  background: transparent;
14
10
 
@@ -17,49 +13,39 @@ export const StyledSearchField = styled.div<{
17
13
  top: 4px;
18
14
  left: 0;
19
15
  font-size: ${TYPOGRAPHY.fontSize.subheadSmall};
20
-
21
- ${(props) =>
22
- props.border &&
23
- props.showSearchIcon &&
24
- css`
25
- top: 7px;
26
- left: 5px;
27
- `}
28
16
  }
29
17
 
30
18
  input {
31
19
  ${inputCommon};
32
-
33
20
  padding: 5px;
34
21
  font-size: ${TYPOGRAPHY.fontSize.base};
35
22
  margin-bottom: 0;
36
- ${(props) =>
37
- props.border &&
38
- css`
39
- border: 1px solid currentColor;
40
- border-radius: 4px;
41
- `}
42
- ${(props) =>
43
- props.showSearchIcon &&
44
- css`
45
- padding: 5px 5px 5px 25px;
46
- `}
47
23
  }
48
24
 
49
- ${(props) =>
50
- props.showClearInputIcon &&
51
- css`
52
- .clear-input {
53
- cursor: pointer;
54
- height: 10px;
55
- width: 10px;
56
- position: absolute;
57
- right: 10px;
58
- top: 50%;
59
- transform: translateY(-50%);
60
- &:hover {
61
- opacity: 0.5;
62
- }
63
- }
64
- `}
25
+ &.border.showSearchIcon label {
26
+ top: 7px;
27
+ left: 5px;
28
+ }
29
+
30
+ &.border input {
31
+ border: 1px solid currentColor;
32
+ border-radius: 4px;
33
+ }
34
+
35
+ &.showSearchIcon input {
36
+ padding: 5px 5px 5px 25px;
37
+ }
38
+
39
+ &.showClearInputIcon .clear-input {
40
+ cursor: pointer;
41
+ height: 10px;
42
+ width: 10px;
43
+ position: absolute;
44
+ right: 10px;
45
+ top: 50%;
46
+ transform: translateY(-50%);
47
+ &:hover {
48
+ opacity: 0.5;
49
+ }
50
+ }
65
51
  `;
@@ -2,6 +2,7 @@
2
2
 
3
3
  import React from 'react';
4
4
  import { v4 as uuid } from 'uuid';
5
+ import classNames from 'classnames';
5
6
 
6
7
  import { Icon } from '@/components/Icon';
7
8
  import { PermafrostComponent } from '@/types';
@@ -39,10 +40,11 @@ export const SearchInput = (props: Props) => {
39
40
 
40
41
  return (
41
42
  <StyledSearchField
42
- className={className}
43
- border={border}
44
- showSearchIcon={showSearchIcon}
45
- showClearInputIcon={showClearInputIcon}
43
+ className={classNames(className, {
44
+ border,
45
+ showSearchIcon,
46
+ showClearInputIcon,
47
+ })}
46
48
  data-cy={props['data-cy']}
47
49
  >
48
50
  {showSearchIcon && (
@@ -2,3 +2,5 @@ export { EditableInput } from './EditableInput';
2
2
  export { NumberInput } from './NumberInput';
3
3
  export { SearchInput } from './SearchInput';
4
4
  export { TextInput } from './TextInput';
5
+ export { Radio, RadioGroup } from './RadioButtons';
6
+ export { AbstractRadio, AbstractRadioGroup } from './RadioGroup';
@@ -23,14 +23,14 @@ const ripple = (size: string) => keyframes`
23
23
  const animationSpeed = 1.4;
24
24
 
25
25
  export const StyledLoadingIndicator = styled.div<{
26
- overallSize: string;
27
- rippleSize: string;
26
+ overallsize: string;
27
+ ripplesize: string;
28
28
  }>`
29
29
  display: grid;
30
30
  place-items: center;
31
31
 
32
- width: ${(props) => props.overallSize};
33
- height: ${(props) => props.overallSize};
32
+ width: ${(props) => props.overallsize};
33
+ height: ${(props) => props.overallsize};
34
34
 
35
35
  margin-left: auto;
36
36
  margin-right: auto;
@@ -43,7 +43,7 @@ export const StyledLoadingIndicator = styled.div<{
43
43
 
44
44
  grid-area: 1 / 1;
45
45
 
46
- animation: ${(props) => ripple(props.rippleSize)} ${animationSpeed}s
46
+ animation: ${(props) => ripple(props.ripplesize)} ${animationSpeed}s
47
47
  cubic-bezier(0, 0.2, 0.8, 1) infinite;
48
48
 
49
49
  @media (prefers-reduced-motion) {
@@ -60,7 +60,7 @@ export const StyledLoadingIndicator = styled.div<{
60
60
  }
61
61
  `;
62
62
 
63
- export const StyledMessageLoadingIndicator = styled.div<{ overallSize: string }>`
63
+ export const StyledMessageLoadingIndicator = styled.div<{ overallsize: string }>`
64
64
  display: block;
65
65
 
66
66
  > * {
@@ -71,7 +71,7 @@ export const StyledMessageLoadingIndicator = styled.div<{ overallSize: string }>
71
71
  .message {
72
72
  text-align: center;
73
73
  display: block;
74
- width: ${(props) => props.overallSize};
74
+ width: ${(props) => props.overallsize};
75
75
  margin-top: -50px;
76
76
 
77
77
  color: ${COLORS.lightFontColor};
@@ -32,8 +32,8 @@ export function CirclePulse(props: Props): React.ReactElement {
32
32
  className={className}
33
33
  data-cy={props['data-cy']}
34
34
  id={id}
35
- overallSize={returnSizeString(overallSize)}
36
- rippleSize={returnSizeString(rippleSize)}
35
+ overallsize={returnSizeString(overallSize)}
36
+ ripplesize={returnSizeString(rippleSize)}
37
37
  style={color ? { color } : { color: COLORS.curiousBlue }}
38
38
  />
39
39
  );
@@ -41,7 +41,7 @@ export function CirclePulse(props: Props): React.ReactElement {
41
41
 
42
42
  if (showRandomMessage) {
43
43
  return (
44
- <StyledMessageLoadingIndicator overallSize={returnSizeString(overallSize)}>
44
+ <StyledMessageLoadingIndicator overallsize={returnSizeString(overallSize)}>
45
45
  {loadingIndicator()}
46
46
 
47
47
  <RandomLoadingMessage />
@@ -0,0 +1,22 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+
3
+ import { LoadingIndicator } from './LoadingIndicator';
4
+
5
+ const meta = {
6
+ component: LoadingIndicator,
7
+ title: 'LoadingIndicator',
8
+ } satisfies Meta<typeof LoadingIndicator>;
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof LoadingIndicator>;
12
+
13
+ export const Normal: Story = {
14
+ args: {},
15
+ };
16
+ export const CustomColor: Story = {
17
+ args: { color: '#f0f' },
18
+ };
19
+
20
+ export const WithRandomMessage: Story = {
21
+ args: { showRandomMessage: true },
22
+ };
@@ -0,0 +1,81 @@
1
+ import styled, { keyframes } from 'styled-components';
2
+
3
+ import { COLORS, TYPOGRAPHY } from '@/tokens';
4
+
5
+ const ripple = (size: string) => keyframes`
6
+ 0% {
7
+ width: 0;
8
+ height: 0;
9
+ opacity: 0;
10
+ }
11
+
12
+ 20% {
13
+ opacity: 1;
14
+ }
15
+
16
+ 100% {
17
+ width: ${size};
18
+ height: ${size};
19
+ opacity: 0;
20
+ }
21
+ `;
22
+
23
+ const animationSpeed = 1.4;
24
+
25
+ export const StyledLoadingIndicator = styled.div<{
26
+ overallsize: string;
27
+ ripplesize: string;
28
+ }>`
29
+ display: grid;
30
+ place-items: center;
31
+
32
+ width: ${(props) => props.overallsize};
33
+ height: ${(props) => props.overallsize};
34
+
35
+ margin-left: auto;
36
+ margin-right: auto;
37
+
38
+ &:before,
39
+ &:after {
40
+ content: '';
41
+ border: 4px solid currentColor;
42
+ border-radius: 50%;
43
+
44
+ grid-area: 1 / 1;
45
+
46
+ animation: ${(props) => ripple(props.ripplesize)} ${animationSpeed}s
47
+ cubic-bezier(0, 0.2, 0.8, 1) infinite;
48
+
49
+ @media (prefers-reduced-motion) {
50
+ animation-duration: ${animationSpeed * 2}s;
51
+ }
52
+ }
53
+
54
+ &:after {
55
+ animation-delay: -${animationSpeed / 2}s;
56
+
57
+ @media (prefers-reduced-motion) {
58
+ animation-delay: -${animationSpeed}s;
59
+ }
60
+ }
61
+ `;
62
+
63
+ export const StyledMessageLoadingIndicator = styled.div<{ overallsize: string }>`
64
+ display: block;
65
+
66
+ > * {
67
+ margin-left: auto;
68
+ margin-right: auto;
69
+ }
70
+
71
+ .message {
72
+ text-align: center;
73
+ display: block;
74
+ width: ${(props) => props.overallsize};
75
+ margin-top: -50px;
76
+
77
+ color: ${COLORS.lightFontColor};
78
+ font-size: ${TYPOGRAPHY.fontSize.base};
79
+ font-style: italic;
80
+ }
81
+ `;
@@ -0,0 +1,61 @@
1
+ // TODO: This component's migration was fast-tracked for Insights. Assess for potential refactor and documentation.
2
+
3
+ import React from 'react';
4
+
5
+ import { RandomLoadingMessage } from '@/components';
6
+ import { PermafrostComponent } from '@/types';
7
+ import { COLORS } from '@/tokens';
8
+
9
+ import { StyledLoadingIndicator, StyledMessageLoadingIndicator } from './LoadingIndicator.styles';
10
+
11
+ type Props = PermafrostComponent & {
12
+ color?: string;
13
+ overallSize?: string | number;
14
+ rippleSize?: string | number;
15
+ showRandomMessage?: boolean;
16
+ };
17
+
18
+ export function LoadingIndicator(props: Props): React.ReactElement {
19
+ const {
20
+ className,
21
+ color,
22
+ id,
23
+ overallSize = '200px',
24
+ rippleSize = '76px',
25
+ showRandomMessage,
26
+ } = props;
27
+
28
+ const loadingIndicator = () => {
29
+ return (
30
+ <StyledLoadingIndicator
31
+ aria-hidden={true}
32
+ className={className}
33
+ data-cy={props['data-cy']}
34
+ id={id}
35
+ overallsize={returnSizeString(overallSize)}
36
+ ripplesize={returnSizeString(rippleSize)}
37
+ style={color ? { color } : { color: COLORS.curiousBlue }}
38
+ />
39
+ );
40
+ };
41
+
42
+ if (showRandomMessage) {
43
+ return (
44
+ <StyledMessageLoadingIndicator overallsize={returnSizeString(overallSize)}>
45
+ {loadingIndicator()}
46
+
47
+ <RandomLoadingMessage />
48
+ </StyledMessageLoadingIndicator>
49
+ );
50
+ }
51
+
52
+ return loadingIndicator();
53
+ }
54
+
55
+ function returnSizeString(size: string | number): string {
56
+ if (typeof size === 'number') {
57
+ return `${size}px`;
58
+ }
59
+
60
+ return size;
61
+ }
@@ -0,0 +1 @@
1
+ export { LoadingIndicator } from './LoadingIndicator';
@@ -4,3 +4,4 @@ export { CirclePulse } from './CirclePulse';
4
4
  export { RandomLoadingMessage } from './RandomLoadingMessage';
5
5
  export { PercentageRing } from './PercentageRing';
6
6
  export { LoadingList } from './LoadingList';
7
+ export { LoadingIndicator } from './LoadingIndicator';
@@ -0,0 +1,76 @@
1
+ import React, { useState } from 'react';
2
+ import type { Meta, StoryObj } from '@storybook/react';
3
+
4
+ import { ConfirmModal } from './ConfirmModal';
5
+
6
+ const meta = {
7
+ component: ConfirmModal,
8
+ title: 'Modals/ConfirmModal',
9
+ args: {
10
+ title: 'Im sorry, Dave. Im afraid I cant do that.',
11
+ message: 'This mission is too important for me to allow you to jeopardize it.',
12
+ confirmText: 'I dont know what youre talking about, Hal.',
13
+ rejectText: 'I dont know what youre talking about, Hal.',
14
+ },
15
+ argTypes: {
16
+ open: { control: { disable: true } },
17
+ className: { control: { disable: true } },
18
+ describedBy: { control: { disable: true } },
19
+ modalNode: { control: { disable: true } },
20
+ width: { control: { disable: true } },
21
+ },
22
+ } satisfies Meta<typeof ConfirmModal>;
23
+
24
+ export default meta;
25
+ type Story = StoryObj<typeof ConfirmModal>;
26
+
27
+ function StoryRender(props: any) {
28
+ const [isOpen, setIsOpen] = useState<boolean>(props.open);
29
+
30
+ const handleOpen = () => {
31
+ setIsOpen(true);
32
+ };
33
+
34
+ const handleClose = () => {
35
+ setIsOpen(false);
36
+ };
37
+
38
+ return (
39
+ <>
40
+ <button type="button" onClick={handleOpen}>
41
+ Open the pod bay doors, HAL.
42
+ </button>
43
+
44
+ <ConfirmModal {...props} open={isOpen} responseHandler={handleClose} />
45
+ </>
46
+ );
47
+ }
48
+
49
+ export const Base: Story = {
50
+ args: {
51
+ processing: false,
52
+ },
53
+ render: (args) => {
54
+ return <StoryRender {...args} />;
55
+ },
56
+ };
57
+
58
+ export const Open: Story = {
59
+ args: {
60
+ open: true,
61
+ processing: false,
62
+ },
63
+ render: (args) => {
64
+ return <StoryRender {...args} />;
65
+ },
66
+ };
67
+
68
+ export const processing: Story = {
69
+ args: {
70
+ open: true,
71
+ processing: true,
72
+ },
73
+ render: (args) => {
74
+ return <StoryRender {...args} />;
75
+ },
76
+ };
@@ -0,0 +1,30 @@
1
+ import styled from 'styled-components';
2
+
3
+ import { COLORS, TYPOGRAPHY } from '@/tokens';
4
+
5
+ export const StyledConfirmModal = styled.div`
6
+ padding: 20px;
7
+
8
+ .title {
9
+ margin: 30px 16px;
10
+ font-size: ${TYPOGRAPHY.fontSize.display};
11
+ text-align: center;
12
+ color: ${COLORS.lightFontColor};
13
+ }
14
+
15
+ .message {
16
+ text-align: center;
17
+ padding-bottom: 16px;
18
+ }
19
+
20
+ .actions {
21
+ text-align: center;
22
+ padding-bottom: 40px;
23
+
24
+ button {
25
+ min-width: 300px;
26
+ display: block;
27
+ margin: 16px auto 0;
28
+ }
29
+ }
30
+ `;
@@ -0,0 +1,84 @@
1
+ // TODO: This component's migration was fast-tracked for Insights. Assess for potential refactor and documentation.
2
+
3
+ import React from 'react';
4
+
5
+ import { v4 as uuid } from 'uuid';
6
+
7
+ import { Button, LoadingAwareContainer, ModalBase } from '@/components';
8
+ import { ModalBaseProps } from '../ModalBase';
9
+ import { PermafrostComponent } from '@/types';
10
+
11
+ import { StyledConfirmModal } from './ConfirmModal.styles';
12
+
13
+ type Props = PermafrostComponent &
14
+ Pick<ModalBaseProps, 'open'> & {
15
+ describedBy?: string;
16
+ clickOutsideHandler(e?: React.SyntheticEvent): void;
17
+ confirmText?: string;
18
+ message?: string | React.ReactNode;
19
+ modalNode?: string;
20
+ processing?: boolean;
21
+ rejectText?: string;
22
+ responseHandler(response: boolean, event: React.SyntheticEvent): void;
23
+ title?: string | React.ReactNode;
24
+ width?: number;
25
+ };
26
+
27
+ export function ConfirmModal(props: Props) {
28
+ const id = uuid();
29
+ const {
30
+ className,
31
+ clickOutsideHandler,
32
+ confirmText,
33
+ describedBy,
34
+ message,
35
+ modalNode,
36
+ open,
37
+ processing,
38
+ rejectText,
39
+ responseHandler,
40
+ title,
41
+ width,
42
+ } = props;
43
+
44
+ return (
45
+ <ModalBase
46
+ className={className}
47
+ clickToDismiss={clickOutsideHandler}
48
+ data-cy={props['data-cy']}
49
+ describedBy={describedBy}
50
+ id={props.id}
51
+ labelElement={id}
52
+ node={modalNode}
53
+ open={open}
54
+ >
55
+ <StyledConfirmModal style={{ width: width || 555 }}>
56
+ {title && (
57
+ <div id={id} className="title">
58
+ {title || 'Please confirm'}
59
+ </div>
60
+ )}
61
+
62
+ {message && <div className="message">{message}</div>}
63
+
64
+ <LoadingAwareContainer isLoading={processing} className="actions">
65
+ <Button
66
+ variant="cta"
67
+ className="confirm"
68
+ onClick={(event) => responseHandler(true, event)}
69
+ >
70
+ {confirmText || 'Yes'}
71
+ </Button>
72
+
73
+ <Button
74
+ variant="normal"
75
+ className="reject"
76
+ onClick={(event) => responseHandler(false, event)}
77
+ >
78
+ {rejectText || 'No'}
79
+ </Button>
80
+ </LoadingAwareContainer>
81
+ </StyledConfirmModal>
82
+ </ModalBase>
83
+ );
84
+ }
@@ -0,0 +1 @@
1
+ export { ConfirmModal } from './ConfirmModal';