@iota/apps-ui-kit 0.0.0-dev-20251015065834

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 (243) hide show
  1. package/CHANGELOG.md +145 -0
  2. package/LICENSE +201 -0
  3. package/README.md +16 -0
  4. package/dist/index.d.ts +1911 -0
  5. package/dist/index.es.js +6486 -0
  6. package/dist/index.es.js.map +1 -0
  7. package/dist/index.umd.js +66 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/dist/style.css +1 -0
  10. package/package.json +80 -0
  11. package/src/lib/components/atoms/badge/Badge.tsx +37 -0
  12. package/src/lib/components/atoms/badge/badge.classes.ts +33 -0
  13. package/src/lib/components/atoms/badge/badge.enums.ts +11 -0
  14. package/src/lib/components/atoms/badge/index.ts +6 -0
  15. package/src/lib/components/atoms/button/Button.tsx +110 -0
  16. package/src/lib/components/atoms/button/button-variants/ButtonPill.tsx +23 -0
  17. package/src/lib/components/atoms/button/button-variants/ButtonUnstyled.tsx +27 -0
  18. package/src/lib/components/atoms/button/button-variants/buttonVariants.types.ts +11 -0
  19. package/src/lib/components/atoms/button/button-variants/index.ts +5 -0
  20. package/src/lib/components/atoms/button/button.classes.ts +53 -0
  21. package/src/lib/components/atoms/button/button.enums.ts +21 -0
  22. package/src/lib/components/atoms/button/index.ts +7 -0
  23. package/src/lib/components/atoms/button-segment/ButtonSegment.tsx +98 -0
  24. package/src/lib/components/atoms/button-segment/buttonSegment.classes.ts +24 -0
  25. package/src/lib/components/atoms/button-segment/buttonSegment.enums.ts +7 -0
  26. package/src/lib/components/atoms/button-segment/index.ts +5 -0
  27. package/src/lib/components/atoms/checkbox/Checkbox.tsx +124 -0
  28. package/src/lib/components/atoms/checkbox/index.ts +4 -0
  29. package/src/lib/components/atoms/divider/Divider.tsx +48 -0
  30. package/src/lib/components/atoms/divider/divider.classes.ts +11 -0
  31. package/src/lib/components/atoms/divider/divider.enums.ts +7 -0
  32. package/src/lib/components/atoms/divider/index.ts +6 -0
  33. package/src/lib/components/atoms/header/Header.tsx +73 -0
  34. package/src/lib/components/atoms/header/index.ts +4 -0
  35. package/src/lib/components/atoms/image/Image.tsx +32 -0
  36. package/src/lib/components/atoms/image/index.ts +4 -0
  37. package/src/lib/components/atoms/index.ts +26 -0
  38. package/src/lib/components/atoms/info-box/InfoBox.tsx +68 -0
  39. package/src/lib/components/atoms/info-box/index.ts +5 -0
  40. package/src/lib/components/atoms/info-box/infoBox.classes.ts +18 -0
  41. package/src/lib/components/atoms/info-box/infoBox.enums.ts +14 -0
  42. package/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx +157 -0
  43. package/src/lib/components/atoms/key-value-info/index.ts +6 -0
  44. package/src/lib/components/atoms/key-value-info/keyValue.enums.ts +7 -0
  45. package/src/lib/components/atoms/label-text/LabelText.tsx +92 -0
  46. package/src/lib/components/atoms/label-text/index.ts +5 -0
  47. package/src/lib/components/atoms/label-text/labelText.classes.ts +22 -0
  48. package/src/lib/components/atoms/label-text/labelText.enums.ts +8 -0
  49. package/src/lib/components/atoms/list-item/ListItem.tsx +88 -0
  50. package/src/lib/components/atoms/list-item/index.ts +4 -0
  51. package/src/lib/components/atoms/loading-indicator/LoadingIndicator.tsx +38 -0
  52. package/src/lib/components/atoms/loading-indicator/index.ts +4 -0
  53. package/src/lib/components/atoms/media-fallback/MediaFallback.tsx +12 -0
  54. package/src/lib/components/atoms/media-fallback/index.ts +4 -0
  55. package/src/lib/components/atoms/panel/Panel.tsx +28 -0
  56. package/src/lib/components/atoms/panel/index.ts +4 -0
  57. package/src/lib/components/atoms/placeholder/Placeholder.tsx +27 -0
  58. package/src/lib/components/atoms/placeholder/index.ts +4 -0
  59. package/src/lib/components/atoms/radio-button/RadioButton.tsx +64 -0
  60. package/src/lib/components/atoms/radio-button/index.ts +4 -0
  61. package/src/lib/components/atoms/secondary-text/SecondaryText.tsx +29 -0
  62. package/src/lib/components/atoms/secondary-text/index.ts +4 -0
  63. package/src/lib/components/atoms/skeleton/Skeleton.tsx +30 -0
  64. package/src/lib/components/atoms/skeleton/index.ts +4 -0
  65. package/src/lib/components/atoms/snackbar/Snackbar.tsx +69 -0
  66. package/src/lib/components/atoms/snackbar/index.ts +5 -0
  67. package/src/lib/components/atoms/snackbar/snackbar.classes.ts +18 -0
  68. package/src/lib/components/atoms/snackbar/snackbar.enums.tsx +9 -0
  69. package/src/lib/components/atoms/toggle/Toggle.tsx +140 -0
  70. package/src/lib/components/atoms/toggle/index.ts +6 -0
  71. package/src/lib/components/atoms/toggle/toggle.classes.ts +41 -0
  72. package/src/lib/components/atoms/toggle/toggle.enums.ts +12 -0
  73. package/src/lib/components/atoms/tooltip/Tooltip.tsx +139 -0
  74. package/src/lib/components/atoms/tooltip/index.ts +5 -0
  75. package/src/lib/components/atoms/tooltip/tooltip.classes.ts +11 -0
  76. package/src/lib/components/atoms/tooltip/tooltip.enums.ts +9 -0
  77. package/src/lib/components/atoms/video/Video.tsx +33 -0
  78. package/src/lib/components/atoms/video/index.ts +4 -0
  79. package/src/lib/components/atoms/video/video.constants.ts +31 -0
  80. package/src/lib/components/index.ts +6 -0
  81. package/src/lib/components/molecules/account/Account.tsx +195 -0
  82. package/src/lib/components/molecules/account/index.ts +4 -0
  83. package/src/lib/components/molecules/address/Address.tsx +101 -0
  84. package/src/lib/components/molecules/address/index.ts +4 -0
  85. package/src/lib/components/molecules/asset-media-renderer/AssetMediaRenderer.tsx +50 -0
  86. package/src/lib/components/molecules/asset-media-renderer/index.ts +4 -0
  87. package/src/lib/components/molecules/card/Card.tsx +70 -0
  88. package/src/lib/components/molecules/card/CardAction.tsx +78 -0
  89. package/src/lib/components/molecules/card/CardBody.tsx +73 -0
  90. package/src/lib/components/molecules/card/CardImage.tsx +43 -0
  91. package/src/lib/components/molecules/card/CardImagePlaceholder.tsx +146 -0
  92. package/src/lib/components/molecules/card/card.classes.ts +27 -0
  93. package/src/lib/components/molecules/card/card.enums.ts +26 -0
  94. package/src/lib/components/molecules/card/index.ts +8 -0
  95. package/src/lib/components/molecules/chip/Chip.tsx +146 -0
  96. package/src/lib/components/molecules/chip/chip.classes.ts +54 -0
  97. package/src/lib/components/molecules/chip/chip.enums.ts +15 -0
  98. package/src/lib/components/molecules/chip/index.ts +5 -0
  99. package/src/lib/components/molecules/display-stats/DisplayStats.tsx +142 -0
  100. package/src/lib/components/molecules/display-stats/displayStats.classes.ts +36 -0
  101. package/src/lib/components/molecules/display-stats/displayStats.enums.ts +13 -0
  102. package/src/lib/components/molecules/display-stats/index.ts +5 -0
  103. package/src/lib/components/molecules/dropdown/Dropdown.tsx +10 -0
  104. package/src/lib/components/molecules/dropdown/dropdownPosition.enums.ts +7 -0
  105. package/src/lib/components/molecules/dropdown/index.ts +5 -0
  106. package/src/lib/components/molecules/index.ts +19 -0
  107. package/src/lib/components/molecules/input/Input.tsx +261 -0
  108. package/src/lib/components/molecules/input/InputWrapper.tsx +97 -0
  109. package/src/lib/components/molecules/input/TextArea.tsx +148 -0
  110. package/src/lib/components/molecules/input/index.ts +8 -0
  111. package/src/lib/components/molecules/input/input.classes.ts +13 -0
  112. package/src/lib/components/molecules/input/input.enums.ts +14 -0
  113. package/src/lib/components/molecules/input/input.types.ts +29 -0
  114. package/src/lib/components/molecules/navbar-item/NavbarItem.tsx +47 -0
  115. package/src/lib/components/molecules/navbar-item/NavbarItemHorizontal.tsx +65 -0
  116. package/src/lib/components/molecules/navbar-item/NavbarItemVertical.tsx +54 -0
  117. package/src/lib/components/molecules/navbar-item/index.ts +5 -0
  118. package/src/lib/components/molecules/navbar-item/navbarItem.classes.ts +16 -0
  119. package/src/lib/components/molecules/navbar-item/navbarItem.enums.ts +7 -0
  120. package/src/lib/components/molecules/search/Search.tsx +219 -0
  121. package/src/lib/components/molecules/search/index.ts +5 -0
  122. package/src/lib/components/molecules/search/search.classes.ts +20 -0
  123. package/src/lib/components/molecules/search/search.enums.ts +7 -0
  124. package/src/lib/components/molecules/segmented-button/SegmentedButton.tsx +38 -0
  125. package/src/lib/components/molecules/segmented-button/index.ts +6 -0
  126. package/src/lib/components/molecules/segmented-button/segmentedButton.classes.ts +12 -0
  127. package/src/lib/components/molecules/segmented-button/segmentedButton.enums.ts +8 -0
  128. package/src/lib/components/molecules/select/Select.tsx +235 -0
  129. package/src/lib/components/molecules/select/index.ts +5 -0
  130. package/src/lib/components/molecules/select/select.enums.ts +7 -0
  131. package/src/lib/components/molecules/table-cell/TableCell.tsx +62 -0
  132. package/src/lib/components/molecules/table-cell/index.ts +4 -0
  133. package/src/lib/components/molecules/table-header-cell/TableHeaderCell.tsx +140 -0
  134. package/src/lib/components/molecules/table-header-cell/index.ts +5 -0
  135. package/src/lib/components/molecules/table-header-cell/tableHeaderCell.enums.ts +7 -0
  136. package/src/lib/components/molecules/title/Title.tsx +78 -0
  137. package/src/lib/components/molecules/title/index.ts +5 -0
  138. package/src/lib/components/molecules/title/titleClasses.constants.ts +14 -0
  139. package/src/lib/components/molecules/title/titleSize.enums.ts +7 -0
  140. package/src/lib/components/molecules/visual-asset-card/VisualAssetCard.tsx +89 -0
  141. package/src/lib/components/molecules/visual-asset-card/index.ts +5 -0
  142. package/src/lib/components/molecules/visual-asset-card/visualAssetCard.enums.ts +7 -0
  143. package/src/lib/components/organisms/accordion/Accordion.tsx +108 -0
  144. package/src/lib/components/organisms/accordion/accordion.classes.ts +4 -0
  145. package/src/lib/components/organisms/accordion/index.ts +4 -0
  146. package/src/lib/components/organisms/dialog/Dialog.tsx +157 -0
  147. package/src/lib/components/organisms/dialog/dialog.enums.ts +7 -0
  148. package/src/lib/components/organisms/dialog/index.ts +5 -0
  149. package/src/lib/components/organisms/index.ts +7 -0
  150. package/src/lib/components/organisms/navbar/Navbar.tsx +101 -0
  151. package/src/lib/components/organisms/navbar/NavbarSlideout.tsx +59 -0
  152. package/src/lib/components/organisms/navbar/index.ts +5 -0
  153. package/src/lib/components/organisms/table/Table.tsx +234 -0
  154. package/src/lib/components/organisms/table/TableContext.tsx +56 -0
  155. package/src/lib/components/organisms/table/index.ts +4 -0
  156. package/src/lib/constants/colors.constants.ts +239 -0
  157. package/src/lib/constants/index.ts +4 -0
  158. package/src/lib/enums/index.ts +5 -0
  159. package/src/lib/enums/screenSize.enums.ts +9 -0
  160. package/src/lib/enums/theme.enums.ts +8 -0
  161. package/src/lib/index.ts +10 -0
  162. package/src/lib/styles/base.css +144 -0
  163. package/src/lib/styles/components.css +735 -0
  164. package/src/lib/styles/fonts.css +7 -0
  165. package/src/lib/styles/index.css +18 -0
  166. package/src/lib/styles/utilities.css +61 -0
  167. package/src/lib/styles/variables/dark-variables.css +262 -0
  168. package/src/lib/styles/variables/general-variables.css +9 -0
  169. package/src/lib/styles/variables/light-variables.css +276 -0
  170. package/src/lib/styles/variables/names-variables.css +270 -0
  171. package/src/lib/tailwind/base.presets.ts +58 -0
  172. package/src/lib/tailwind/constants/customColors.constants.ts +13 -0
  173. package/src/lib/tailwind/constants/fontFamily.constants.ts +8 -0
  174. package/src/lib/tailwind/constants/fontSizes.constants.ts +201 -0
  175. package/src/lib/tailwind/constants/gradients.constants.ts +6 -0
  176. package/src/lib/tailwind/constants/index.ts +7 -0
  177. package/src/lib/tailwind/constants/scaling.constants.ts +41 -0
  178. package/src/lib/tailwind/constants/variableSpacing.constants.ts +66 -0
  179. package/src/lib/tailwind/helpers.ts +20 -0
  180. package/src/lib/tailwind/index.ts +5 -0
  181. package/src/lib/tailwind/plugins.ts +12 -0
  182. package/src/lib/tailwind/responsive.presets.ts +36 -0
  183. package/src/lib/tailwind/static.presets.ts +25 -0
  184. package/src/lib/tailwind/types.ts +6 -0
  185. package/src/lib/utils/format.ts +8 -0
  186. package/src/lib/utils/index.ts +4 -0
  187. package/src/storybook/blocks/Showcase.tsx +20 -0
  188. package/src/storybook/blocks/TypeSet.tsx +34 -0
  189. package/src/storybook/blocks/TypeSetItem.tsx +74 -0
  190. package/src/storybook/blocks/index.ts +6 -0
  191. package/src/storybook/constants/gradients.constants.ts +8 -0
  192. package/src/storybook/constants/index.ts +5 -0
  193. package/src/storybook/constants/typeset.constants.ts +39 -0
  194. package/src/storybook/constants/variableSpacing.constants.ts +6 -0
  195. package/src/storybook/helpers/formatGradientNames.ts +15 -0
  196. package/src/storybook/helpers/getFontSizeLabel.ts +15 -0
  197. package/src/storybook/helpers/index.ts +4 -0
  198. package/src/storybook/stories/atoms/Badge.stories.tsx +32 -0
  199. package/src/storybook/stories/atoms/Button.stories.tsx +45 -0
  200. package/src/storybook/stories/atoms/ButtonSegment.stories.tsx +45 -0
  201. package/src/storybook/stories/atoms/Checkbox.stories.tsx +34 -0
  202. package/src/storybook/stories/atoms/CustomScrollbar.stories.tsx +22 -0
  203. package/src/storybook/stories/atoms/Divider.stories.tsx +41 -0
  204. package/src/storybook/stories/atoms/Header.stories.tsx +58 -0
  205. package/src/storybook/stories/atoms/InfoBox.stories.tsx +67 -0
  206. package/src/storybook/stories/atoms/KeyValueInfo.stories.tsx +59 -0
  207. package/src/storybook/stories/atoms/LabelText.stories.tsx +55 -0
  208. package/src/storybook/stories/atoms/ListItem.stories.tsx +41 -0
  209. package/src/storybook/stories/atoms/LoadingIndicator.stories.tsx +32 -0
  210. package/src/storybook/stories/atoms/Panel.stories.tsx +36 -0
  211. package/src/storybook/stories/atoms/Placeholder.stories.tsx +33 -0
  212. package/src/storybook/stories/atoms/RadioButton.stories.tsx +51 -0
  213. package/src/storybook/stories/atoms/Skeleton.stories.tsx +33 -0
  214. package/src/storybook/stories/atoms/Snackbar.stories.tsx +43 -0
  215. package/src/storybook/stories/atoms/Toggle.stories.tsx +59 -0
  216. package/src/storybook/stories/atoms/Tooltip.stories.tsx +59 -0
  217. package/src/storybook/stories/atoms/VisualAssetCard.stories.tsx +57 -0
  218. package/src/storybook/stories/components/DocsSyncTheme.tsx +20 -0
  219. package/src/storybook/stories/components/VariableSpacingShowcase.tsx +46 -0
  220. package/src/storybook/stories/components/index.ts +5 -0
  221. package/src/storybook/stories/design-tokens/colors.stories.mdx +44 -0
  222. package/src/storybook/stories/design-tokens/icons.stories.mdx +19 -0
  223. package/src/storybook/stories/design-tokens/typeset.stories.mdx +17 -0
  224. package/src/storybook/stories/design-tokens/variable-spacing.stories.mdx +11 -0
  225. package/src/storybook/stories/molecules/Account.stories.tsx +71 -0
  226. package/src/storybook/stories/molecules/Address.stories.tsx +39 -0
  227. package/src/storybook/stories/molecules/Card.stories.tsx +112 -0
  228. package/src/storybook/stories/molecules/Chip.stories.tsx +127 -0
  229. package/src/storybook/stories/molecules/DisplayStats.stories.tsx +63 -0
  230. package/src/storybook/stories/molecules/Dropdown.stories.tsx +38 -0
  231. package/src/storybook/stories/molecules/Input.stories.tsx +239 -0
  232. package/src/storybook/stories/molecules/NavbarItem.stories.tsx +45 -0
  233. package/src/storybook/stories/molecules/Search.stories.tsx +101 -0
  234. package/src/storybook/stories/molecules/SegmentedButton.stories.tsx +108 -0
  235. package/src/storybook/stories/molecules/Select.stories.tsx +103 -0
  236. package/src/storybook/stories/molecules/TableCell.stories.tsx +46 -0
  237. package/src/storybook/stories/molecules/TableHeaderCell.stories.tsx +34 -0
  238. package/src/storybook/stories/molecules/TextArea.stories.tsx +80 -0
  239. package/src/storybook/stories/molecules/Title.stories.tsx +76 -0
  240. package/src/storybook/stories/organisms/Accordion.stories.tsx +70 -0
  241. package/src/storybook/stories/organisms/Dialog.stories.tsx +129 -0
  242. package/src/storybook/stories/organisms/Navbar.stories.tsx +78 -0
  243. package/src/storybook/stories/organisms/Table.stories.tsx +154 -0
@@ -0,0 +1,140 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { forwardRef, useRef } from 'react';
5
+ import { ToggleLabelPosition, ToggleSize } from './toggle.enums';
6
+ import {
7
+ TOGGLE,
8
+ TOGGLE_LABEL,
9
+ TOGGLE_SIZE,
10
+ TOGGLE_STATES,
11
+ TOGGLE_THUMB,
12
+ TOGGLE_THUMB_COLOR,
13
+ TOGGLE_THUMB_POSITION,
14
+ TOGGLE_THUMB_SIZE,
15
+ TOGGLE_CONTAINER,
16
+ } from './toggle.classes';
17
+ import cx from 'classnames';
18
+
19
+ interface ToggleProps {
20
+ /**
21
+ * The label for the toggle.
22
+ */
23
+ label?: string | React.ReactNode;
24
+ /**
25
+ * The state of the toggle (on or off).
26
+ */
27
+ isToggled: boolean;
28
+ /**
29
+ * Whether the label should be placed before the toggle.
30
+ */
31
+ labelPosition?: ToggleLabelPosition;
32
+ /**
33
+ * If true, the toggle will be disabled.
34
+ */
35
+ isDisabled?: boolean;
36
+ /**
37
+ * The callback to call when the toggle state changes.
38
+ */
39
+ onChange?: (isToggled: boolean, event: React.ChangeEvent<HTMLInputElement>) => void;
40
+ /**
41
+ * The name and id of the toggle input.
42
+ */
43
+ name?: string;
44
+ /**
45
+ * The size of the toggle.
46
+ */
47
+ size?: ToggleSize;
48
+ /**
49
+ * The 'data-testid' attribute value (used in e2e tests)
50
+ */
51
+ testId?: string;
52
+ }
53
+
54
+ export const Toggle = forwardRef<HTMLInputElement, ToggleProps>(
55
+ (
56
+ {
57
+ label,
58
+ isToggled,
59
+ labelPosition = ToggleLabelPosition.Right,
60
+ isDisabled = false,
61
+ onChange,
62
+ name,
63
+ size = ToggleSize.Default,
64
+ testId,
65
+ }: ToggleProps,
66
+ ref,
67
+ ) => {
68
+ const inputRef = useRef<HTMLInputElement | null>(null);
69
+
70
+ function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
71
+ const newChecked = e.target.checked;
72
+ onChange?.(newChecked, e);
73
+ }
74
+
75
+ function assignRefs(element: HTMLInputElement) {
76
+ if (ref) {
77
+ if (typeof ref === 'function') {
78
+ ref(element);
79
+ } else {
80
+ ref.current = element;
81
+ }
82
+ }
83
+ inputRef.current = element;
84
+ }
85
+
86
+ const toggleClasses = cx(TOGGLE, {
87
+ [TOGGLE_STATES.active]: isToggled && !isDisabled,
88
+ [TOGGLE_STATES.inactive]: !isToggled,
89
+ [TOGGLE_STATES.disabledActive]: isDisabled && isToggled,
90
+ [TOGGLE_STATES.disabled]: isDisabled,
91
+ [TOGGLE_SIZE[size]]: true,
92
+ });
93
+
94
+ const thumbClasses = cx(TOGGLE_THUMB, {
95
+ [TOGGLE_THUMB_POSITION[size].unchecked]: !isToggled,
96
+ [TOGGLE_THUMB_POSITION[size].checked]: isToggled,
97
+ [TOGGLE_THUMB_COLOR.unchecked]: !isToggled,
98
+ [TOGGLE_THUMB_COLOR.checked]: isToggled,
99
+ [TOGGLE_THUMB_SIZE[size]]: true,
100
+ });
101
+
102
+ const containerClasses = cx(TOGGLE_CONTAINER, {
103
+ 'flex-row-reverse': labelPosition === ToggleLabelPosition.Left,
104
+ 'cursor-not-allowed': isDisabled,
105
+ });
106
+ const labelClasses = cx(TOGGLE_LABEL, {
107
+ 'opacity-40': isDisabled && !isToggled,
108
+ });
109
+
110
+ return (
111
+ <div className={containerClasses}>
112
+ <input
113
+ id={name}
114
+ name={name}
115
+ type="checkbox"
116
+ className="sr-only"
117
+ checked={isToggled}
118
+ ref={assignRefs}
119
+ disabled={isDisabled}
120
+ onChange={handleChange}
121
+ data-testid={testId}
122
+ />
123
+
124
+ <span
125
+ role="switch"
126
+ onClick={() => inputRef.current?.click()}
127
+ className={toggleClasses}
128
+ >
129
+ <span className={thumbClasses} />
130
+ </span>
131
+
132
+ {label && (
133
+ <label htmlFor={name} className={labelClasses}>
134
+ {label}
135
+ </label>
136
+ )}
137
+ </div>
138
+ );
139
+ },
140
+ );
@@ -0,0 +1,6 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { Toggle } from './Toggle';
5
+
6
+ export * from './toggle.enums';
@@ -0,0 +1,41 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { ToggleSize } from './toggle.enums';
5
+
6
+ export const TOGGLE = 'relative inline-flex items-center p-xxs border rounded-full cursor-pointer';
7
+
8
+ export const TOGGLE_STATES = {
9
+ active: 'toggle-bg-active toggle-border-active',
10
+ inactive: 'toggle-bg-inactive toggle-border-inactive',
11
+ disabledActive: 'toggle-bg-disabled-active toggle-border-disabled-active',
12
+ disabled: 'opacity-40 cursor-not-allowed',
13
+ };
14
+
15
+ export const TOGGLE_SIZE = {
16
+ [ToggleSize.Small]: 'h-5 w-10',
17
+ [ToggleSize.Default]: 'h-6 w-12',
18
+ };
19
+
20
+ export const TOGGLE_THUMB = 'absolute rounded-full transition-all duration-200 ease-in';
21
+ export const TOGGLE_THUMB_POSITION = {
22
+ [ToggleSize.Small]: {
23
+ unchecked: 'left-1',
24
+ checked: 'left-8 -translate-x-full',
25
+ },
26
+ [ToggleSize.Default]: {
27
+ unchecked: 'left-1',
28
+ checked: 'left-10 -translate-x-full',
29
+ },
30
+ };
31
+ export const TOGGLE_THUMB_COLOR = {
32
+ unchecked: 'toggle-thumb-color',
33
+ checked: 'toggle-thumb-color-checked',
34
+ };
35
+ export const TOGGLE_THUMB_SIZE = {
36
+ [ToggleSize.Small]: 'h-3 w-3',
37
+ [ToggleSize.Default]: 'h-4 w-4',
38
+ };
39
+
40
+ export const TOGGLE_CONTAINER = 'inline-flex items-center gap-2';
41
+ export const TOGGLE_LABEL = 'text-label-lg toggle-label-color';
@@ -0,0 +1,12 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export enum ToggleSize {
5
+ Small = 'small',
6
+ Default = 'default',
7
+ }
8
+
9
+ export enum ToggleLabelPosition {
10
+ Left = 'left',
11
+ Right = 'right',
12
+ }
@@ -0,0 +1,139 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { useRef, useState, useLayoutEffect } from 'react';
5
+ import type { PropsWithChildren } from 'react';
6
+ import { createPortal } from 'react-dom';
7
+ import cx from 'classnames';
8
+ import { TooltipPosition } from './tooltip.enums';
9
+
10
+ interface TooltipProps {
11
+ text: string;
12
+ position?: TooltipPosition;
13
+ maxWidth?: string;
14
+ offset?: number;
15
+ openDelay?: number;
16
+ closeDelay?: number;
17
+ }
18
+
19
+ export function Tooltip({
20
+ text,
21
+ position = TooltipPosition.Top,
22
+ maxWidth = 'max-w-[200px]',
23
+ offset = 8,
24
+ openDelay = 0,
25
+ closeDelay = 100,
26
+ children,
27
+ }: PropsWithChildren<TooltipProps>) {
28
+ const triggerRef = useRef<HTMLDivElement>(null);
29
+ const tooltipRef = useRef<HTMLDivElement>(null);
30
+
31
+ const [visible, setVisible] = useState(false);
32
+ const [coords, setCoords] = useState<{ top: number; left: number }>({ top: 0, left: 0 });
33
+
34
+ const openTimer = useRef<ReturnType<typeof setTimeout>>();
35
+ const closeTimer = useRef<ReturnType<typeof setTimeout>>();
36
+
37
+ const clearTimers = () => {
38
+ clearTimeout(openTimer.current);
39
+ clearTimeout(closeTimer.current);
40
+ };
41
+
42
+ const open = () => {
43
+ clearTimers();
44
+ openTimer.current = setTimeout(() => setVisible(true), openDelay);
45
+ };
46
+
47
+ const close = () => {
48
+ clearTimers();
49
+ closeTimer.current = setTimeout(() => setVisible(false), closeDelay);
50
+ };
51
+
52
+ useLayoutEffect(() => {
53
+ if (!visible) return;
54
+
55
+ const rect = triggerRef.current?.getBoundingClientRect();
56
+ if (!rect) return;
57
+
58
+ const pos = {
59
+ [TooltipPosition.Top]: {
60
+ top: rect.top - offset,
61
+ left: rect.left + rect.width / 2,
62
+ transform: 'translate(-50%, -100%)',
63
+ },
64
+ [TooltipPosition.Bottom]: {
65
+ top: rect.bottom + offset,
66
+ left: rect.left + rect.width / 2,
67
+ transform: 'translate(-50%, 0)',
68
+ },
69
+ [TooltipPosition.Left]: {
70
+ top: rect.top + rect.height / 2,
71
+ left: rect.left - offset,
72
+ transform: 'translate(-100%, -50%)',
73
+ },
74
+ [TooltipPosition.Right]: {
75
+ top: rect.top + rect.height / 2,
76
+ left: rect.right + offset,
77
+ transform: 'translate(0, -50%)',
78
+ },
79
+ }[position];
80
+
81
+ setCoords({ top: pos.top, left: pos.left });
82
+ tooltipRef.current!.style.transform = pos.transform;
83
+ }, [visible, position, offset]);
84
+
85
+ useLayoutEffect(() => {
86
+ if (!visible) return;
87
+ const update = () => {
88
+ const rect = triggerRef.current?.getBoundingClientRect();
89
+ if (!rect) return;
90
+ setCoords((prev) => ({ ...prev, left: rect.left + rect.width / 2 }));
91
+ };
92
+ window.addEventListener('scroll', update, true);
93
+ window.addEventListener('resize', update);
94
+ return () => {
95
+ window.removeEventListener('scroll', update, true);
96
+ window.removeEventListener('resize', update);
97
+ };
98
+ }, [visible]);
99
+
100
+ // z-[9999999999]: needed because we must exceed the popup’s ≈2 147 483 647 z-index;
101
+ // otherwise the tooltip renders but stays invisible inside a Chrome extension
102
+ const base = 'z-[9999999999] w-max rounded p-xs tooltip-bg tooltip-text-color';
103
+
104
+ return (
105
+ <>
106
+ <div
107
+ ref={triggerRef}
108
+ className="inline-block cursor-pointer"
109
+ onMouseEnter={open}
110
+ onFocus={open}
111
+ onMouseLeave={close}
112
+ onBlur={close}
113
+ >
114
+ {children}
115
+ </div>
116
+
117
+ {visible &&
118
+ createPortal(
119
+ <div
120
+ ref={tooltipRef}
121
+ role="tooltip"
122
+ style={{
123
+ position: 'fixed',
124
+ top: coords.top,
125
+ left: coords.left,
126
+ transition: 'opacity .15s ease',
127
+ opacity: 1,
128
+ }}
129
+ className={cx(base, maxWidth)}
130
+ onMouseEnter={open}
131
+ onMouseLeave={close}
132
+ >
133
+ <p className="w-full break-words">{text}</p>
134
+ </div>,
135
+ document.body,
136
+ )}
137
+ </>
138
+ );
139
+ }
@@ -0,0 +1,5 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export * from './Tooltip';
5
+ export * from './tooltip.enums';
@@ -0,0 +1,11 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { TooltipPosition } from './tooltip.enums';
5
+
6
+ export const TOOLTIP_POSITION: Record<TooltipPosition, string> = {
7
+ [TooltipPosition.Top]: 'bottom-full left-1/2 transform -translate-x-1/2 mb-1',
8
+ [TooltipPosition.Bottom]: 'top-full left-1/2 transform -translate-x-1/2 mt-1',
9
+ [TooltipPosition.Left]: 'top-1/2 right-full transform -translate-y-1/2 mr-1',
10
+ [TooltipPosition.Right]: 'top-1/2 left-full transform -translate-y-1/2 ml-1',
11
+ };
@@ -0,0 +1,9 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export enum TooltipPosition {
5
+ Top = 'top',
6
+ Bottom = 'bottom',
7
+ Left = 'left',
8
+ Right = 'right',
9
+ }
@@ -0,0 +1,33 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import { forwardRef } from 'react';
5
+ import { VIDEO_AUTOPLAY_FLAGS, VIDEO_AUTOPLAY_FLAGS_NO_CONTROLS } from './video.constants';
6
+
7
+ export interface VideoProps {
8
+ /**
9
+ * Whether the video should autoplay.
10
+ */
11
+ isAutoPlayEnabled?: boolean;
12
+ /**
13
+ * If the video controls should be disabled.
14
+ */
15
+ disableControls?: boolean;
16
+ }
17
+
18
+ export const Video = forwardRef<
19
+ HTMLVideoElement,
20
+ React.ComponentPropsWithoutRef<'video'> & VideoProps
21
+ >(({ width = '100%', height = 'auto', isAutoPlayEnabled, disableControls, ...props }, ref) => {
22
+ const videoProps = isAutoPlayEnabled
23
+ ? disableControls
24
+ ? VIDEO_AUTOPLAY_FLAGS_NO_CONTROLS
25
+ : VIDEO_AUTOPLAY_FLAGS
26
+ : { preload: 'metadata', autoPlay: false };
27
+
28
+ return (
29
+ <video ref={ref} width={width} height={height} {...videoProps} {...props}>
30
+ Your browser does not support the video tag.
31
+ </video>
32
+ );
33
+ });
@@ -0,0 +1,4 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export * from './Video';
@@ -0,0 +1,31 @@
1
+ // Copyright (c) 2025 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export const VIDEO_AUTOPLAY_FLAGS: Partial<
5
+ Omit<React.VideoHTMLAttributes<HTMLVideoElement>, 'src'>
6
+ > = {
7
+ autoPlay: true,
8
+ muted: true,
9
+ playsInline: true,
10
+ controls: true,
11
+ controlsList: 'nodownload',
12
+ disablePictureInPicture: true,
13
+ preload: 'auto',
14
+ loop: true,
15
+ width: '100%',
16
+ height: 'auto',
17
+ };
18
+
19
+ export const VIDEO_AUTOPLAY_FLAGS_NO_CONTROLS: Partial<
20
+ Omit<React.VideoHTMLAttributes<HTMLVideoElement>, 'src'>
21
+ > = {
22
+ autoPlay: true,
23
+ muted: true,
24
+ playsInline: true,
25
+ controls: false,
26
+ disablePictureInPicture: true,
27
+ preload: 'auto',
28
+ loop: true,
29
+ width: '100%',
30
+ height: 'auto',
31
+ };
@@ -0,0 +1,6 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export * from './atoms';
5
+ export * from './molecules';
6
+ export * from './organisms';
@@ -0,0 +1,195 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ import cx from 'classnames';
5
+ import type { BadgeType } from '@/components/atoms';
6
+ import { Badge, Tooltip, TooltipPosition, ButtonUnstyled } from '@/components/atoms';
7
+ import {
8
+ LockLocked,
9
+ LockUnlocked,
10
+ MoreHoriz,
11
+ CheckmarkFilled,
12
+ RadioOff,
13
+ } from '@iota/apps-ui-icons';
14
+ import { Address } from '../address';
15
+
16
+ interface AccountProps {
17
+ /**
18
+ * The title of the account.
19
+ */
20
+ title: string;
21
+ /**
22
+ * The subtitle of the account.
23
+ */
24
+ subtitle: string;
25
+ /**
26
+ * Whether the account is unlocked.
27
+ */
28
+ isLocked?: boolean;
29
+ /**
30
+ * Handler for more options click.
31
+ */
32
+ onOptionsClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
33
+ /**
34
+ * Handler for the lock account icon click.
35
+ */
36
+ onLockAccountClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
37
+ /**
38
+ * Handle for the unlock account icon click.
39
+ */
40
+ onUnlockAccountClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
41
+ /**
42
+ * Function to render avatar content.
43
+ */
44
+ avatarContent: ({ isLocked }: { isLocked?: boolean }) => React.JSX.Element;
45
+ /**
46
+ * The onCopy event of the Address (optional).
47
+ */
48
+ onCopy?: (e: React.MouseEvent<HTMLButtonElement>) => void;
49
+ /**
50
+ * Text that need to be copied (optional).
51
+ */
52
+ copyText?: string;
53
+ /**
54
+ * The onOpen event of the Address (optional).
55
+ */
56
+ onOpen?: (e: React.MouseEvent<HTMLButtonElement>) => void;
57
+ /**
58
+ * Has copy icon (optional).
59
+ */
60
+ isCopyable?: boolean;
61
+ /**
62
+ * Has open icon (optional).
63
+ */
64
+ isExternal?: boolean;
65
+ /**
66
+ * The account is selected.
67
+ */
68
+ isSelected?: boolean;
69
+ /**
70
+ * Show the selected checkbox.
71
+ */
72
+ showSelected?: boolean;
73
+ /**
74
+ * Show background if account active (optional).
75
+ */
76
+ isActive?: boolean;
77
+ /**
78
+ * The type of the badge.
79
+ */
80
+ badgeType?: BadgeType;
81
+ /**
82
+ * The text of the badge.
83
+ */
84
+ badgeText?: string;
85
+ /**
86
+ * The tooltip text of the badge.
87
+ */
88
+ badgeTooltipText?: string;
89
+ /**
90
+ * The tooltip position of the badge.
91
+ */
92
+ badgeTooltipPosition?: TooltipPosition;
93
+ }
94
+
95
+ export function Account({
96
+ title,
97
+ subtitle,
98
+ badgeType,
99
+ badgeText,
100
+ isLocked,
101
+ avatarContent,
102
+ onOptionsClick,
103
+ onLockAccountClick,
104
+ onUnlockAccountClick,
105
+ onCopy,
106
+ copyText,
107
+ onOpen,
108
+ isCopyable,
109
+ isExternal,
110
+ isSelected,
111
+ isActive,
112
+ showSelected,
113
+ badgeTooltipText,
114
+ badgeTooltipPosition = TooltipPosition.Bottom,
115
+ }: AccountProps): React.JSX.Element {
116
+ const Avatar = avatarContent;
117
+
118
+ return (
119
+ <div
120
+ className={cx(
121
+ 'state-layer group relative flex w-full items-center justify-between space-x-3 rounded-xl px-sm py-xs hover:cursor-pointer',
122
+ isActive && 'state-active',
123
+ {
124
+ 'opacity-60': isLocked && showSelected,
125
+ },
126
+ )}
127
+ >
128
+ <div className="flex w-full items-center gap-x-3">
129
+ <div>
130
+ <Avatar isLocked={isLocked} />
131
+ </div>
132
+ <div className="flex w-full min-w-0 flex-col items-start py-xs">
133
+ <div className="flex w-full min-w-0 items-center space-x-2">
134
+ <p className="account-title-color min-w-0 max-w-full truncate font-inter text-title-md">
135
+ {title}
136
+ </p>
137
+ {badgeText && badgeType ? (
138
+ badgeTooltipText ? (
139
+ <Tooltip text={badgeTooltipText} position={badgeTooltipPosition}>
140
+ <Badge type={badgeType} label={badgeText} />
141
+ </Tooltip>
142
+ ) : (
143
+ <Badge type={badgeType} label={badgeText} />
144
+ )
145
+ ) : null}
146
+ </div>
147
+ <Address
148
+ text={subtitle}
149
+ onCopySuccess={onCopy}
150
+ copyText={copyText}
151
+ onOpen={onOpen}
152
+ isCopyable={isCopyable}
153
+ isExternal={isExternal}
154
+ />
155
+ </div>
156
+
157
+ <div className="ml-auto flex items-center space-x-2 [&_button]:h-5 [&_button]:w-5 [&_svg]:h-5 [&_svg]:w-5">
158
+ <div className="account-icon-color flex items-center space-x-2 [&_button:not(.locked)]:invisible group-hover:[&_button:not(.locked)]:visible">
159
+ {onOptionsClick && (
160
+ <ButtonUnstyled onClick={onOptionsClick}>
161
+ <MoreHoriz />
162
+ </ButtonUnstyled>
163
+ )}
164
+ {onLockAccountClick &&
165
+ onUnlockAccountClick &&
166
+ (isLocked ? (
167
+ <div className="flex items-center">
168
+ <ButtonUnstyled
169
+ onClick={onUnlockAccountClick}
170
+ testId="account-unlock"
171
+ className="locked"
172
+ >
173
+ <LockLocked />
174
+ </ButtonUnstyled>
175
+ </div>
176
+ ) : (
177
+ <ButtonUnstyled onClick={onLockAccountClick} testId="account-lock">
178
+ <LockUnlocked />
179
+ </ButtonUnstyled>
180
+ ))}
181
+ </div>
182
+ {showSelected && (
183
+ <ButtonUnstyled>
184
+ {isSelected ? (
185
+ <CheckmarkFilled className="account-check-active-color h-5 w-5" />
186
+ ) : (
187
+ <RadioOff className="account-check-inactive-color h-5 w-5" />
188
+ )}
189
+ </ButtonUnstyled>
190
+ )}
191
+ </div>
192
+ </div>
193
+ </div>
194
+ );
195
+ }
@@ -0,0 +1,4 @@
1
+ // Copyright (c) 2024 IOTA Stiftung
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ export { Account } from './Account';