@shipfox/react-ui 0.2.0 → 0.4.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 (323) hide show
  1. package/.storybook/preview.tsx +1 -1
  2. package/.turbo/turbo-build.log +2 -2
  3. package/.turbo/turbo-check.log +3 -3
  4. package/.turbo/turbo-type.log +1 -1
  5. package/CHANGELOG.md +17 -0
  6. package/dist/components/alert/alert.d.ts +18 -0
  7. package/dist/components/alert/alert.d.ts.map +1 -0
  8. package/dist/components/alert/alert.js +123 -0
  9. package/dist/components/alert/alert.js.map +1 -0
  10. package/dist/components/alert/alert.stories.js +112 -0
  11. package/dist/components/alert/alert.stories.js.map +1 -0
  12. package/dist/components/alert/index.d.ts +2 -0
  13. package/dist/components/alert/index.d.ts.map +1 -0
  14. package/dist/components/alert/index.js +3 -0
  15. package/dist/components/alert/index.js.map +1 -0
  16. package/dist/components/avatar/avatar-group.d.ts +18 -0
  17. package/dist/components/avatar/avatar-group.d.ts.map +1 -0
  18. package/dist/components/avatar/avatar-group.js +132 -0
  19. package/dist/components/avatar/avatar-group.js.map +1 -0
  20. package/dist/components/avatar/avatar.d.ts +24 -0
  21. package/dist/components/avatar/avatar.d.ts.map +1 -0
  22. package/dist/components/avatar/avatar.js +165 -0
  23. package/dist/components/avatar/avatar.js.map +1 -0
  24. package/dist/components/avatar/avatar.stories.js +267 -0
  25. package/dist/components/avatar/avatar.stories.js.map +1 -0
  26. package/dist/components/avatar/index.d.ts +3 -0
  27. package/dist/components/avatar/index.d.ts.map +1 -0
  28. package/dist/components/avatar/index.js +4 -0
  29. package/dist/components/avatar/index.js.map +1 -0
  30. package/dist/components/badge/badge.d.ts +48 -0
  31. package/dist/components/badge/badge.d.ts.map +1 -0
  32. package/dist/components/badge/badge.js +72 -0
  33. package/dist/components/badge/badge.js.map +1 -0
  34. package/dist/components/badge/badge.stories.js +802 -0
  35. package/dist/components/badge/badge.stories.js.map +1 -0
  36. package/dist/components/badge/icon-badge.d.ts +9 -0
  37. package/dist/components/badge/icon-badge.d.ts.map +1 -0
  38. package/dist/components/badge/icon-badge.js +32 -0
  39. package/dist/components/badge/icon-badge.js.map +1 -0
  40. package/dist/components/badge/index.d.ts +5 -0
  41. package/dist/components/badge/index.d.ts.map +1 -0
  42. package/dist/components/badge/index.js +6 -0
  43. package/dist/components/badge/index.js.map +1 -0
  44. package/dist/components/badge/status-badge.d.ts +9 -0
  45. package/dist/components/badge/status-badge.d.ts.map +1 -0
  46. package/dist/components/badge/status-badge.js +29 -0
  47. package/dist/components/badge/status-badge.js.map +1 -0
  48. package/dist/components/badge/user-badge.d.ts +8 -0
  49. package/dist/components/badge/user-badge.d.ts.map +1 -0
  50. package/dist/components/badge/user-badge.js +24 -0
  51. package/dist/components/badge/user-badge.js.map +1 -0
  52. package/dist/components/{button.d.ts → button/button.d.ts} +1 -1
  53. package/dist/components/button/button.d.ts.map +1 -0
  54. package/dist/components/{button.js → button/button.js} +2 -2
  55. package/dist/components/button/button.js.map +1 -0
  56. package/dist/components/{button.stories.js → button/button.stories.js} +1 -1
  57. package/dist/components/button/button.stories.js.map +1 -0
  58. package/dist/components/button/index.d.ts +2 -0
  59. package/dist/components/button/index.d.ts.map +1 -0
  60. package/dist/components/button/index.js +3 -0
  61. package/dist/components/button/index.js.map +1 -0
  62. package/dist/components/checkbox/checkbox-label.d.ts +14 -0
  63. package/dist/components/checkbox/checkbox-label.d.ts.map +1 -0
  64. package/dist/components/checkbox/checkbox-label.js +82 -0
  65. package/dist/components/checkbox/checkbox-label.js.map +1 -0
  66. package/dist/components/checkbox/checkbox-links.d.ts +18 -0
  67. package/dist/components/checkbox/checkbox-links.d.ts.map +1 -0
  68. package/dist/components/checkbox/checkbox-links.js +58 -0
  69. package/dist/components/checkbox/checkbox-links.js.map +1 -0
  70. package/dist/components/checkbox/checkbox.d.ts +9 -0
  71. package/dist/components/checkbox/checkbox.d.ts.map +1 -0
  72. package/dist/components/checkbox/checkbox.js +49 -0
  73. package/dist/components/checkbox/checkbox.js.map +1 -0
  74. package/dist/components/checkbox/checkbox.stories.js +566 -0
  75. package/dist/components/checkbox/checkbox.stories.js.map +1 -0
  76. package/dist/components/checkbox/index.d.ts +4 -0
  77. package/dist/components/checkbox/index.d.ts.map +1 -0
  78. package/dist/components/checkbox/index.js +5 -0
  79. package/dist/components/checkbox/index.js.map +1 -0
  80. package/dist/components/code-block/code-block-footer.d.ts +26 -0
  81. package/dist/components/code-block/code-block-footer.d.ts.map +1 -0
  82. package/dist/components/code-block/code-block-footer.js +86 -0
  83. package/dist/components/code-block/code-block-footer.js.map +1 -0
  84. package/dist/components/code-block/code-block.d.ts +50 -0
  85. package/dist/components/code-block/code-block.d.ts.map +1 -0
  86. package/dist/components/code-block/code-block.js +142 -0
  87. package/dist/components/code-block/code-block.js.map +1 -0
  88. package/dist/components/code-block/code-block.stories.js +341 -0
  89. package/dist/components/code-block/code-block.stories.js.map +1 -0
  90. package/dist/components/code-block/code-content.d.ts +11 -0
  91. package/dist/components/code-block/code-content.d.ts.map +1 -0
  92. package/dist/components/code-block/code-content.js +29 -0
  93. package/dist/components/code-block/code-content.js.map +1 -0
  94. package/dist/components/code-block/code-copy-button.d.ts +11 -0
  95. package/dist/components/code-block/code-copy-button.d.ts.map +1 -0
  96. package/dist/components/code-block/code-copy-button.js +49 -0
  97. package/dist/components/code-block/code-copy-button.js.map +1 -0
  98. package/dist/components/code-block/code-tabs.d.ts +16 -0
  99. package/dist/components/code-block/code-tabs.d.ts.map +1 -0
  100. package/dist/components/code-block/code-tabs.js +98 -0
  101. package/dist/components/code-block/code-tabs.js.map +1 -0
  102. package/dist/components/code-block/index.d.ts +4 -0
  103. package/dist/components/code-block/index.d.ts.map +1 -0
  104. package/dist/components/code-block/index.js +5 -0
  105. package/dist/components/code-block/index.js.map +1 -0
  106. package/dist/components/dynamic-item/dynamic-item.d.ts +13 -0
  107. package/dist/components/dynamic-item/dynamic-item.d.ts.map +1 -0
  108. package/dist/components/dynamic-item/dynamic-item.js +43 -0
  109. package/dist/components/dynamic-item/dynamic-item.js.map +1 -0
  110. package/dist/components/dynamic-item/dynamic-item.stories.js +375 -0
  111. package/dist/components/dynamic-item/dynamic-item.stories.js.map +1 -0
  112. package/dist/components/dynamic-item/index.d.ts +2 -0
  113. package/dist/components/dynamic-item/index.d.ts.map +1 -0
  114. package/dist/components/dynamic-item/index.js +3 -0
  115. package/dist/components/dynamic-item/index.js.map +1 -0
  116. package/dist/components/icon/custom/index.d.ts +3 -0
  117. package/dist/components/icon/custom/index.d.ts.map +1 -1
  118. package/dist/components/icon/custom/index.js +3 -0
  119. package/dist/components/icon/custom/index.js.map +1 -1
  120. package/dist/components/icon/custom/shipfox-logo.d.ts +8 -0
  121. package/dist/components/icon/custom/shipfox-logo.d.ts.map +1 -0
  122. package/dist/components/icon/custom/shipfox-logo.js +22 -0
  123. package/dist/components/icon/custom/shipfox-logo.js.map +1 -0
  124. package/dist/components/icon/custom/slack-logo.d.ts +6 -0
  125. package/dist/components/icon/custom/slack-logo.d.ts.map +1 -0
  126. package/dist/components/icon/custom/slack-logo.js +34 -0
  127. package/dist/components/icon/custom/slack-logo.js.map +1 -0
  128. package/dist/components/icon/custom/stripe-logo.d.ts +8 -0
  129. package/dist/components/icon/custom/stripe-logo.d.ts.map +1 -0
  130. package/dist/components/icon/custom/stripe-logo.js +24 -0
  131. package/dist/components/icon/custom/stripe-logo.js.map +1 -0
  132. package/dist/components/icon/icon.d.ts +13 -1
  133. package/dist/components/icon/icon.d.ts.map +1 -1
  134. package/dist/components/icon/icon.js +15 -3
  135. package/dist/components/icon/icon.js.map +1 -1
  136. package/dist/components/icon/icon.stories.js +6 -3
  137. package/dist/components/icon/icon.stories.js.map +1 -1
  138. package/dist/components/index.d.ts +12 -1
  139. package/dist/components/index.d.ts.map +1 -1
  140. package/dist/components/index.js +13 -2
  141. package/dist/components/index.js.map +1 -1
  142. package/dist/components/inline-tips/index.d.ts +2 -0
  143. package/dist/components/inline-tips/index.d.ts.map +1 -0
  144. package/dist/components/inline-tips/index.js +3 -0
  145. package/dist/components/inline-tips/index.js.map +1 -0
  146. package/dist/components/inline-tips/inline-tips.d.ts +19 -0
  147. package/dist/components/inline-tips/inline-tips.d.ts.map +1 -0
  148. package/dist/components/inline-tips/inline-tips.js +98 -0
  149. package/dist/components/inline-tips/inline-tips.js.map +1 -0
  150. package/dist/components/inline-tips/inline-tips.stories.js +214 -0
  151. package/dist/components/inline-tips/inline-tips.stories.js.map +1 -0
  152. package/dist/components/input/index.d.ts +2 -0
  153. package/dist/components/input/index.d.ts.map +1 -0
  154. package/dist/components/input/index.js +3 -0
  155. package/dist/components/input/index.js.map +1 -0
  156. package/dist/components/input/input.d.ts.map +1 -0
  157. package/dist/components/{input.js → input/input.js} +2 -2
  158. package/dist/components/input/input.js.map +1 -0
  159. package/dist/components/{input.stories.js → input/input.stories.js} +1 -1
  160. package/dist/components/input/input.stories.js.map +1 -0
  161. package/dist/components/item/index.d.ts +2 -0
  162. package/dist/components/item/index.d.ts.map +1 -0
  163. package/dist/components/item/index.js +3 -0
  164. package/dist/components/item/index.js.map +1 -0
  165. package/dist/components/item/item.d.ts +32 -0
  166. package/dist/components/item/item.d.ts.map +1 -0
  167. package/dist/components/item/item.js +120 -0
  168. package/dist/components/item/item.js.map +1 -0
  169. package/dist/components/item/item.stories.js +232 -0
  170. package/dist/components/item/item.stories.js.map +1 -0
  171. package/dist/components/label/index.d.ts +2 -0
  172. package/dist/components/label/index.d.ts.map +1 -0
  173. package/dist/components/label/index.js +3 -0
  174. package/dist/components/label/index.js.map +1 -0
  175. package/dist/components/label/label.d.ts +7 -0
  176. package/dist/components/label/label.d.ts.map +1 -0
  177. package/dist/components/label/label.js +13 -0
  178. package/dist/components/label/label.js.map +1 -0
  179. package/dist/components/label/label.stories.js +105 -0
  180. package/dist/components/label/label.stories.js.map +1 -0
  181. package/dist/components/moving-border/moving-border.d.ts +9 -0
  182. package/dist/components/moving-border/moving-border.d.ts.map +1 -0
  183. package/dist/components/moving-border/moving-border.js +54 -0
  184. package/dist/components/moving-border/moving-border.js.map +1 -0
  185. package/dist/components/textarea/textarea.js +1 -1
  186. package/dist/components/textarea/textarea.js.map +1 -1
  187. package/dist/components/theme/index.d.ts +2 -0
  188. package/dist/components/theme/index.d.ts.map +1 -0
  189. package/dist/components/theme/index.js +3 -0
  190. package/dist/components/theme/index.js.map +1 -0
  191. package/dist/components/{theme-provider.d.ts → theme/theme-provider.d.ts} +1 -1
  192. package/dist/components/theme/theme-provider.d.ts.map +1 -0
  193. package/dist/components/{theme-provider.js → theme/theme-provider.js} +1 -1
  194. package/dist/components/theme/theme-provider.js.map +1 -0
  195. package/dist/components/toast/index.d.ts +3 -0
  196. package/dist/components/toast/index.d.ts.map +1 -0
  197. package/dist/components/toast/index.js +4 -0
  198. package/dist/components/toast/index.js.map +1 -0
  199. package/dist/components/toast/toast-custom.d.ts +19 -0
  200. package/dist/components/toast/toast-custom.d.ts.map +1 -0
  201. package/dist/components/toast/toast-custom.js +134 -0
  202. package/dist/components/toast/toast-custom.js.map +1 -0
  203. package/dist/components/toast/toast.d.ts +5 -0
  204. package/dist/components/toast/toast.d.ts.map +1 -0
  205. package/dist/components/toast/toast.js +40 -0
  206. package/dist/components/toast/toast.js.map +1 -0
  207. package/dist/components/toast/toast.stories.js +326 -0
  208. package/dist/components/toast/toast.stories.js.map +1 -0
  209. package/dist/components/tooltip/index.d.ts +2 -0
  210. package/dist/components/tooltip/index.d.ts.map +1 -0
  211. package/dist/components/tooltip/index.js +3 -0
  212. package/dist/components/tooltip/index.js.map +1 -0
  213. package/dist/components/tooltip/tooltip.d.ts +20 -0
  214. package/dist/components/tooltip/tooltip.d.ts.map +1 -0
  215. package/dist/components/tooltip/tooltip.js +98 -0
  216. package/dist/components/tooltip/tooltip.js.map +1 -0
  217. package/dist/components/tooltip/tooltip.stories.js +560 -0
  218. package/dist/components/tooltip/tooltip.stories.js.map +1 -0
  219. package/dist/hooks/index.d.ts +3 -0
  220. package/dist/hooks/index.d.ts.map +1 -1
  221. package/dist/hooks/index.js +3 -0
  222. package/dist/hooks/index.js.map +1 -1
  223. package/dist/hooks/useResolvedTheme.d.ts +2 -0
  224. package/dist/hooks/useResolvedTheme.d.ts.map +1 -0
  225. package/dist/hooks/useResolvedTheme.js +24 -0
  226. package/dist/hooks/useResolvedTheme.js.map +1 -0
  227. package/dist/hooks/useShikiHighlight.d.ts +28 -0
  228. package/dist/hooks/useShikiHighlight.d.ts.map +1 -0
  229. package/dist/hooks/useShikiHighlight.js +106 -0
  230. package/dist/hooks/useShikiHighlight.js.map +1 -0
  231. package/dist/hooks/useShikiStyleInjection.d.ts +2 -0
  232. package/dist/hooks/useShikiStyleInjection.d.ts.map +1 -0
  233. package/dist/hooks/useShikiStyleInjection.js +34 -0
  234. package/dist/hooks/useShikiStyleInjection.js.map +1 -0
  235. package/dist/utils/avatar.d.ts +3 -0
  236. package/dist/utils/avatar.d.ts.map +1 -0
  237. package/dist/utils/avatar.js +32 -0
  238. package/dist/utils/avatar.js.map +1 -0
  239. package/dist/utils/index.d.ts +1 -0
  240. package/dist/utils/index.d.ts.map +1 -1
  241. package/dist/utils/index.js +1 -0
  242. package/dist/utils/index.js.map +1 -1
  243. package/index.css +130 -7
  244. package/package.json +7 -4
  245. package/src/assets/illustration-1.svg +92 -0
  246. package/src/assets/illustration-2.svg +14 -0
  247. package/src/assets/illustration-gradient.svg +7049 -0
  248. package/src/components/alert/alert.stories.tsx +77 -0
  249. package/src/components/alert/alert.tsx +144 -0
  250. package/src/components/alert/index.ts +1 -0
  251. package/src/components/avatar/avatar-group.tsx +186 -0
  252. package/src/components/avatar/avatar.stories.tsx +179 -0
  253. package/src/components/avatar/avatar.tsx +219 -0
  254. package/src/components/avatar/index.ts +2 -0
  255. package/src/components/badge/badge.stories.tsx +468 -0
  256. package/src/components/badge/badge.tsx +147 -0
  257. package/src/components/badge/icon-badge.tsx +43 -0
  258. package/src/components/badge/index.ts +4 -0
  259. package/src/components/badge/status-badge.tsx +43 -0
  260. package/src/components/badge/user-badge.tsx +34 -0
  261. package/src/components/{button.tsx → button/button.tsx} +1 -1
  262. package/src/components/button/index.ts +1 -0
  263. package/src/components/checkbox/checkbox-label.tsx +125 -0
  264. package/src/components/checkbox/checkbox-links.tsx +90 -0
  265. package/src/components/checkbox/checkbox.stories.tsx +375 -0
  266. package/src/components/checkbox/checkbox.tsx +71 -0
  267. package/src/components/checkbox/index.ts +3 -0
  268. package/src/components/code-block/code-block-footer.tsx +173 -0
  269. package/src/components/code-block/code-block.stories.tsx +323 -0
  270. package/src/components/code-block/code-block.tsx +283 -0
  271. package/src/components/code-block/code-content.tsx +60 -0
  272. package/src/components/code-block/code-copy-button.tsx +73 -0
  273. package/src/components/code-block/code-tabs.tsx +170 -0
  274. package/src/components/code-block/index.ts +3 -0
  275. package/src/components/dynamic-item/dynamic-item.stories.tsx +261 -0
  276. package/src/components/dynamic-item/dynamic-item.tsx +68 -0
  277. package/src/components/dynamic-item/index.ts +1 -0
  278. package/src/components/icon/custom/index.ts +3 -0
  279. package/src/components/icon/custom/shipfox-logo.tsx +20 -0
  280. package/src/components/icon/custom/slack-logo.tsx +35 -0
  281. package/src/components/icon/custom/stripe-logo.tsx +27 -0
  282. package/src/components/icon/icon.stories.tsx +3 -1
  283. package/src/components/icon/icon.tsx +29 -1
  284. package/src/components/index.ts +12 -1
  285. package/src/components/inline-tips/index.ts +1 -0
  286. package/src/components/inline-tips/inline-tips.stories.tsx +126 -0
  287. package/src/components/inline-tips/inline-tips.tsx +132 -0
  288. package/src/components/input/index.ts +1 -0
  289. package/src/components/{input.tsx → input/input.tsx} +1 -1
  290. package/src/components/item/index.ts +1 -0
  291. package/src/components/item/item.stories.tsx +150 -0
  292. package/src/components/item/item.tsx +182 -0
  293. package/src/components/label/index.ts +1 -0
  294. package/src/components/label/label.stories.tsx +67 -0
  295. package/src/components/label/label.tsx +15 -0
  296. package/src/components/moving-border/moving-border.tsx +67 -0
  297. package/src/components/textarea/textarea.tsx +1 -1
  298. package/src/components/theme/index.ts +1 -0
  299. package/src/components/toast/index.ts +2 -0
  300. package/src/components/toast/toast-custom.tsx +154 -0
  301. package/src/components/toast/toast.stories.tsx +369 -0
  302. package/src/components/toast/toast.tsx +41 -0
  303. package/src/components/tooltip/index.ts +1 -0
  304. package/src/components/tooltip/tooltip.stories.tsx +284 -0
  305. package/src/components/tooltip/tooltip.tsx +121 -0
  306. package/src/hooks/index.ts +3 -0
  307. package/src/hooks/useResolvedTheme.ts +34 -0
  308. package/src/hooks/useShikiHighlight.ts +140 -0
  309. package/src/hooks/useShikiStyleInjection.ts +34 -0
  310. package/src/utils/avatar.ts +27 -0
  311. package/src/utils/index.ts +1 -0
  312. package/dist/components/button.d.ts.map +0 -1
  313. package/dist/components/button.js.map +0 -1
  314. package/dist/components/button.stories.js.map +0 -1
  315. package/dist/components/input.d.ts.map +0 -1
  316. package/dist/components/input.js.map +0 -1
  317. package/dist/components/input.stories.js.map +0 -1
  318. package/dist/components/theme-provider.d.ts.map +0 -1
  319. package/dist/components/theme-provider.js.map +0 -1
  320. /package/dist/components/{input.d.ts → input/input.d.ts} +0 -0
  321. /package/src/components/{button.stories.tsx → button/button.stories.tsx} +0 -0
  322. /package/src/components/{input.stories.tsx → input/input.stories.tsx} +0 -0
  323. /package/src/components/{theme-provider.tsx → theme/theme-provider.tsx} +0 -0
@@ -0,0 +1,73 @@
1
+ import {Icon} from 'components/icon';
2
+ import {useCopyToClipboard} from 'hooks/useCopyToClipboard';
3
+ import type {ComponentProps} from 'react';
4
+ import {useEffect, useRef, useState} from 'react';
5
+ import {cn} from 'utils/cn';
6
+
7
+ type CodeCopyButtonProps = Omit<ComponentProps<'button'>, 'onCopy'> & {
8
+ content: string;
9
+ onCopy?: (content: string) => void;
10
+ onError?: (error: Error) => void;
11
+ timeout?: number;
12
+ children?: React.ReactNode;
13
+ };
14
+
15
+ export function CodeCopyButton({
16
+ content,
17
+ onCopy,
18
+ onError,
19
+ timeout = 2000,
20
+ children,
21
+ className,
22
+ ...props
23
+ }: CodeCopyButtonProps) {
24
+ const [isCopied, setIsCopied] = useState(false);
25
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
26
+
27
+ const {copy} = useCopyToClipboard({
28
+ text: content,
29
+ onCopy: () => {
30
+ setIsCopied(true);
31
+ onCopy?.(content);
32
+
33
+ if (timeoutRef.current) {
34
+ clearTimeout(timeoutRef.current);
35
+ }
36
+
37
+ timeoutRef.current = setTimeout(() => {
38
+ setIsCopied(false);
39
+ }, timeout);
40
+ },
41
+ });
42
+
43
+ useEffect(() => {
44
+ return () => {
45
+ if (timeoutRef.current) {
46
+ clearTimeout(timeoutRef.current);
47
+ }
48
+ };
49
+ }, []);
50
+
51
+ const handleClick = async () => {
52
+ try {
53
+ await copy();
54
+ } catch (error) {
55
+ onError?.(error instanceof Error ? error : new Error('Failed to copy'));
56
+ }
57
+ };
58
+
59
+ return (
60
+ <button
61
+ type="button"
62
+ aria-label={isCopied ? 'Copied' : 'Copy to clipboard'}
63
+ className={cn(
64
+ 'flex shrink-0 cursor-pointer items-center justify-center rounded-6 bg-transparent text-foreground-neutral-muted transition-colors hover:bg-background-components-hover active:bg-background-components-pressed p-4',
65
+ className,
66
+ )}
67
+ onClick={handleClick}
68
+ {...props}
69
+ >
70
+ {children ?? <Icon name={isCopied ? 'check' : 'copy'} className="size-16" />}
71
+ </button>
72
+ );
73
+ }
@@ -0,0 +1,170 @@
1
+ import * as Tabs from '@radix-ui/react-tabs';
2
+ import {useControllableState} from '@radix-ui/react-use-controllable-state';
3
+ import {CodeContent} from 'components/code-block/code-content';
4
+ import {CodeCopyButton} from 'components/code-block/code-copy-button';
5
+ import {useResolvedTheme} from 'hooks/useResolvedTheme';
6
+ import {useShikiHighlightMultiple} from 'hooks/useShikiHighlight';
7
+ import {useShikiStyleInjection} from 'hooks/useShikiStyleInjection';
8
+ import type {ComponentProps} from 'react';
9
+ import {useMemo} from 'react';
10
+ import {cn} from 'utils/cn';
11
+
12
+ export type CodeTabsProps = Omit<ComponentProps<typeof Tabs.Root>, 'children'> & {
13
+ codes: Record<string, string>;
14
+ lang?: string;
15
+ themes?: {
16
+ light: string;
17
+ dark: string;
18
+ };
19
+ copyButton?: boolean;
20
+ onCopy?: (content: string) => void;
21
+ syntaxHighlighting?: boolean;
22
+ lineNumbers?: boolean;
23
+ };
24
+
25
+ function CodeTabsContent({
26
+ codes,
27
+ lang = 'bash',
28
+ themes = {
29
+ light: 'vitesse-light',
30
+ dark: 'vitesse-dark',
31
+ },
32
+ copyButton = true,
33
+ onCopy,
34
+ syntaxHighlighting = false,
35
+ lineNumbers = false,
36
+ activeValue,
37
+ }: {
38
+ codes: Record<string, string>;
39
+ lang?: string;
40
+ themes?: {light: string; dark: string};
41
+ copyButton?: boolean;
42
+ onCopy?: (content: string) => void;
43
+ syntaxHighlighting?: boolean;
44
+ lineNumbers?: boolean;
45
+ activeValue: string;
46
+ }) {
47
+ const resolvedTheme = useResolvedTheme();
48
+ const codesKeys = useMemo(() => Object.keys(codes), [codes]);
49
+
50
+ useShikiStyleInjection(syntaxHighlighting);
51
+
52
+ const {highlightedCodes, isLoading} = useShikiHighlightMultiple({
53
+ codes,
54
+ lang,
55
+ themes,
56
+ resolvedTheme,
57
+ syntaxHighlighting,
58
+ });
59
+
60
+ const activeCode = codes[activeValue] ?? '';
61
+
62
+ return (
63
+ <>
64
+ <Tabs.List
65
+ className={cn(
66
+ 'relative flex w-full flex-row items-center justify-between gap-12 overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:hidden bg-background-components-pressed dark:bg-background-contrast-base px-16 py-8',
67
+ 'border-b border-border-contrast-bottom',
68
+ 'after:absolute after:bottom-0 after:left-0 after:right-0 after:h-px',
69
+ 'after:bg-border-neutral-base',
70
+ 'dark:after:bg-border-contrast-top',
71
+ 'after:shadow-separator-inset',
72
+ )}
73
+ >
74
+ <div className="flex flex-row gap-12">
75
+ {codesKeys.map((code) => (
76
+ <Tabs.Trigger
77
+ key={code}
78
+ value={code}
79
+ className={cn(
80
+ 'relative px-8 py-4 text-xs leading-20 font-medium text-foreground-neutral-muted transition-colors',
81
+ 'data-[state=active]:text-foreground-neutral-base',
82
+ 'hover:text-foreground-neutral-base',
83
+ 'data-[state=active]:z-10',
84
+ 'data-[state=active]:after:absolute data-[state=active]:after:-bottom-9 data-[state=active]:after:left-0 data-[state=active]:after:right-0',
85
+ 'data-[state=active]:after:h-2 data-[state=active]:after:bg-foreground-neutral-base',
86
+ )}
87
+ >
88
+ {code}
89
+ </Tabs.Trigger>
90
+ ))}
91
+ </div>
92
+
93
+ {copyButton && <CodeCopyButton content={activeCode} onCopy={onCopy} className="shrink-0" />}
94
+ </Tabs.List>
95
+ <div className="w-full px-4 pb-4 pt-8">
96
+ {Object.entries(codes).map(([code, rawCode]) => (
97
+ <Tabs.Content key={code} value={code} className="w-full">
98
+ <div
99
+ className={cn(
100
+ 'flex min-h-0 min-w-0 w-full shrink-0 rounded-8 border border-border-contrast-bottom bg-background-neutral-base dark:bg-background-contrast-subtle font-code',
101
+ '[&_pre]:py-12 [&_pre]:font-code',
102
+ '[&_pre]:m-0 [&_pre]:px-0 [&_pre]:bg-transparent',
103
+ '[&_code]:w-full [&_code]:overflow-x-auto [&_code]:bg-transparent [&_code]:font-code [&_code]:text-xs [&_code]:leading-20 [&_code]:text-foreground-neutral-base',
104
+ lineNumbers &&
105
+ '[&_code]:grid [&_code]:[counter-reset:line] [&_code]:[counter-increment:line_0] [&_.line]:before:content-[counter(line)] [&_.line]:before:inline-block [&_.line]:before:[counter-increment:line] [&_.line]:before:w-16 [&_.line]:before:mr-16 [&_.line]:before:text-xs [&_.line]:before:text-right [&_.line]:before:text-foreground-neutral-subtle [&_.line]:before:font-code [&_.line]:before:select-none',
106
+ '[&_.line]:block [&_.line]:px-12 [&_.line]:w-full [&_.line]:relative [&_.line]:font-code [&_.line]:min-h-[1.25rem]',
107
+ )}
108
+ >
109
+ <CodeContent
110
+ code={rawCode}
111
+ highlightedCode={highlightedCodes[code]}
112
+ isLoading={isLoading}
113
+ syntaxHighlighting={syntaxHighlighting}
114
+ lineNumbers={lineNumbers}
115
+ />
116
+ </div>
117
+ </Tabs.Content>
118
+ ))}
119
+ </div>
120
+ </>
121
+ );
122
+ }
123
+
124
+ export function CodeTabs({
125
+ codes,
126
+ lang = 'bash',
127
+ themes = {
128
+ light: 'vitesse-light',
129
+ dark: 'vitesse-dark',
130
+ },
131
+ className,
132
+ defaultValue,
133
+ value: controlledValue,
134
+ onValueChange: controlledOnValueChange,
135
+ copyButton = true,
136
+ onCopy,
137
+ syntaxHighlighting = false,
138
+ lineNumbers = false,
139
+ ...props
140
+ }: CodeTabsProps) {
141
+ const firstKey = useMemo(() => Object.keys(codes)[0] ?? '', [codes]);
142
+ const [value, onValueChange] = useControllableState({
143
+ defaultProp: defaultValue ?? firstKey,
144
+ prop: controlledValue,
145
+ onChange: controlledOnValueChange,
146
+ });
147
+
148
+ return (
149
+ <Tabs.Root
150
+ className={cn(
151
+ 'w-full overflow-hidden rounded-12 bg-background-components-pressed dark:bg-background-contrast-base shadow-button-neutral',
152
+ className,
153
+ )}
154
+ value={value}
155
+ onValueChange={onValueChange}
156
+ {...props}
157
+ >
158
+ <CodeTabsContent
159
+ codes={codes}
160
+ lang={lang}
161
+ themes={themes}
162
+ copyButton={copyButton}
163
+ onCopy={onCopy}
164
+ syntaxHighlighting={syntaxHighlighting}
165
+ lineNumbers={lineNumbers}
166
+ activeValue={value ?? firstKey}
167
+ />
168
+ </Tabs.Root>
169
+ );
170
+ }
@@ -0,0 +1,3 @@
1
+ export * from './code-block';
2
+ export * from './code-block-footer';
3
+ export * from './code-tabs';
@@ -0,0 +1,261 @@
1
+ import type {Meta, StoryObj} from '@storybook/react';
2
+ import {Button} from 'components/button/button';
3
+ import {ItemTitle} from 'components/item';
4
+ import {cn} from 'utils/cn';
5
+ import illustration1 from '../../assets/illustration-1.svg';
6
+ import illustration2 from '../../assets/illustration-2.svg';
7
+ import illustrationBg from '../../assets/illustration-gradient.svg';
8
+ import {Avatar} from '../avatar/avatar';
9
+ import {AvatarGroup, AvatarGroupTooltip} from '../avatar/avatar-group';
10
+ import {Icon} from '../icon/icon';
11
+ import {MovingBorder} from '../moving-border/moving-border';
12
+ import {DynamicItem} from './dynamic-item';
13
+
14
+ const meta = {
15
+ title: 'Components/DynamicItem',
16
+ component: DynamicItem,
17
+ tags: ['autodocs'],
18
+ } satisfies Meta<typeof DynamicItem>;
19
+
20
+ export default meta;
21
+ type Story = StoryObj<typeof meta>;
22
+
23
+ export const OrganizationItem: Story = {
24
+ args: {},
25
+ render: () => (
26
+ <div className="flex flex-col gap-16 w-full max-w-476">
27
+ <DynamicItem
28
+ variant="default"
29
+ leftElement={<Avatar content="logo" logoName="slack" radius="rounded" size="xl" />}
30
+ title="Slack"
31
+ description="3 members"
32
+ rightElement={
33
+ <AvatarGroup size="md">
34
+ <Avatar content="image" fallback="John Doe">
35
+ <AvatarGroupTooltip>John Doe</AvatarGroupTooltip>
36
+ </Avatar>
37
+ <Avatar content="image" fallback="Jane Smith">
38
+ <AvatarGroupTooltip>Jane Smith</AvatarGroupTooltip>
39
+ </Avatar>
40
+ <Avatar content="image" fallback="Bob Johnson">
41
+ <AvatarGroupTooltip>Bob Johnson</AvatarGroupTooltip>
42
+ </Avatar>
43
+ </AvatarGroup>
44
+ }
45
+ />
46
+ <DynamicItem
47
+ variant="default"
48
+ leftElement={<Avatar content="logo" logoName="stripe" radius="rounded" size="xl" />}
49
+ title="Stripe"
50
+ description="2 members"
51
+ rightElement={
52
+ <AvatarGroup size="md">
53
+ <Avatar content="image" fallback="Alice Brown">
54
+ <AvatarGroupTooltip>Alice Brown</AvatarGroupTooltip>
55
+ </Avatar>
56
+ <Avatar content="image" fallback="Carlos Vega">
57
+ <AvatarGroupTooltip>Carlos Vega</AvatarGroupTooltip>
58
+ </Avatar>
59
+ </AvatarGroup>
60
+ }
61
+ />
62
+ <DynamicItem
63
+ variant="default"
64
+ leftElement={<Avatar content="logo" logoName="shipfox" radius="rounded" size="xl" />}
65
+ title="Shipfox"
66
+ description="9 members"
67
+ rightElement={
68
+ <AvatarGroup size="md" maxVisible={4} animateOnHover>
69
+ <Avatar content="image" fallback="Linda Tran">
70
+ <AvatarGroupTooltip>Linda Tran</AvatarGroupTooltip>
71
+ </Avatar>
72
+ <Avatar content="image" fallback="Michael Chen">
73
+ <AvatarGroupTooltip>Michael Chen</AvatarGroupTooltip>
74
+ </Avatar>
75
+ <Avatar content="image" fallback="Sarah Williams">
76
+ <AvatarGroupTooltip>Sarah Williams</AvatarGroupTooltip>
77
+ </Avatar>
78
+ <Avatar content="image" fallback="David Lee">
79
+ <AvatarGroupTooltip>David Lee</AvatarGroupTooltip>
80
+ </Avatar>
81
+ <Avatar content="image" fallback="Emily Davis">
82
+ <AvatarGroupTooltip>Emily Davis</AvatarGroupTooltip>
83
+ </Avatar>
84
+ <Avatar content="image" fallback="James Wilson">
85
+ <AvatarGroupTooltip>James Wilson</AvatarGroupTooltip>
86
+ </Avatar>
87
+ <Avatar content="image" fallback="Olivia Martinez">
88
+ <AvatarGroupTooltip>Olivia Martinez</AvatarGroupTooltip>
89
+ </Avatar>
90
+ <Avatar content="image" fallback="Noah Anderson">
91
+ <AvatarGroupTooltip>Noah Anderson</AvatarGroupTooltip>
92
+ </Avatar>
93
+ <Avatar content="image" fallback="Sophia Taylor">
94
+ <AvatarGroupTooltip>Sophia Taylor</AvatarGroupTooltip>
95
+ </Avatar>
96
+ </AvatarGroup>
97
+ }
98
+ />
99
+ </div>
100
+ ),
101
+ };
102
+
103
+ export const ConnectGithubAccountItem: Story = {
104
+ args: {},
105
+ render: () => (
106
+ <div className="flex flex-col gap-16 w-full max-w-476">
107
+ <DynamicItem
108
+ variant="default"
109
+ leftElement={
110
+ <div className="relative">
111
+ <Avatar content="logoPlaceholder" logoName="slack" radius="full" size="lg" />
112
+ <Avatar
113
+ content="logoPlaceholder"
114
+ logoName="github"
115
+ radius="full"
116
+ size="2xs"
117
+ logoClassName="p-0"
118
+ className="absolute bottom-0 left-27"
119
+ />
120
+ </div>
121
+ }
122
+ title="Slack"
123
+ description="Connect Github organization"
124
+ rightElement={
125
+ <Button variant="primary" size="sm">
126
+ Connect
127
+ </Button>
128
+ }
129
+ />
130
+
131
+ <DynamicItem
132
+ variant="default"
133
+ leftElement={
134
+ <div className="relative">
135
+ <Avatar content="logoPlaceholder" logoName="slack" radius="full" size="lg" />
136
+ <Avatar
137
+ content="logo"
138
+ logoName="github"
139
+ radius="full"
140
+ size="2xs"
141
+ logoClassName="p-0"
142
+ className="absolute bottom-0 left-27"
143
+ />
144
+ </div>
145
+ }
146
+ title="Slack"
147
+ description="Personal account (kye-nguyen)"
148
+ rightElement={
149
+ <Button variant="primary" size="sm">
150
+ Change account
151
+ </Button>
152
+ }
153
+ />
154
+
155
+ <DynamicItem
156
+ variant="default"
157
+ leftElement={
158
+ <div className="relative">
159
+ <Avatar content="logoPlaceholder" logoName="slack" radius="full" size="lg" />
160
+ <Avatar
161
+ content="logo"
162
+ logoName="github"
163
+ radius="full"
164
+ size="2xs"
165
+ logoClassName="p-0"
166
+ className="absolute bottom-0 left-27"
167
+ />
168
+ </div>
169
+ }
170
+ title="Slack"
171
+ description="Organization (slack-github)"
172
+ rightElement={
173
+ <Button variant="secondary" size="sm">
174
+ Change account
175
+ </Button>
176
+ }
177
+ />
178
+ </div>
179
+ ),
180
+ };
181
+
182
+ export const WithCustomElementsItem: Story = {
183
+ args: {},
184
+ render: () => {
185
+ return (
186
+ <div className="flex flex-col gap-16 w-full max-w-672">
187
+ <DynamicItem
188
+ variant="default"
189
+ leftElement={
190
+ <div className="flex shrink-0 items-center justify-center text-tag-success-icon">
191
+ <Icon name="checkCircleSolid" size="sm" />
192
+ </div>
193
+ }
194
+ title="Give access to your Github organizations"
195
+ description="We'll use this permission to sync your organization's."
196
+ action={
197
+ <div className="flex gap-8 mx-auto sm:mx-0">
198
+ <Button variant="primary" size="sm">
199
+ Github access
200
+ </Button>
201
+ <Button variant="transparentMuted" size="sm">
202
+ Skip for now
203
+ </Button>
204
+ </div>
205
+ }
206
+ rightElement={
207
+ <img
208
+ src={illustration1}
209
+ alt="illustration-1"
210
+ className="hidden sm:block absolute overflow-clip right-2 top-1/2 -translate-y-1/2 -translate-x-46 w-fit object-contain"
211
+ />
212
+ }
213
+ />
214
+ <div className="relative">
215
+ <img
216
+ src={illustration2}
217
+ alt="illustration-2"
218
+ className="hidden sm:block absolute overflow-clip right-2 top-1/2 -translate-y-1/2 translate-x-8 w-fit object-contain z-50"
219
+ />
220
+ <div className={cn('relative overflow-hidden bg-transparent p-1 rounded-8')}>
221
+ <div className="absolute inset-0" style={{borderRadius: 'calc(0.5rem * 0.96)'}}>
222
+ <MovingBorder duration={6000} rx="30%" ry="30%">
223
+ <div className="h-100 w-200 bg-[radial-gradient(#ff9e7a_40%,transparent_60%)]" />
224
+ </MovingBorder>
225
+ </div>
226
+ <div
227
+ className="relative"
228
+ style={{
229
+ borderRadius: 'calc(0.5rem * 0.96)',
230
+ }}
231
+ >
232
+ <DynamicItem
233
+ variant="default"
234
+ title={
235
+ <div className="flex items-center gap-6">
236
+ <span className="flex shrink-0 items-center justify-center text-tag-success-icon w-16 h-16">
237
+ <Icon
238
+ name="money"
239
+ size="sm"
240
+ color="var(--foreground-neutral-subtle, #a1a1aa)"
241
+ />
242
+ </span>
243
+ <ItemTitle>6000 free credits/month to run your jobs</ItemTitle>
244
+ </div>
245
+ }
246
+ description="~500 builds/month. No payment required."
247
+ rightElement={
248
+ <img
249
+ src={illustrationBg}
250
+ alt="illustration-bg"
251
+ className="hidden sm:block absolute overflow-clip right-4 w-fit object-contain scale-105"
252
+ />
253
+ }
254
+ />
255
+ </div>
256
+ </div>
257
+ </div>
258
+ </div>
259
+ );
260
+ },
261
+ };
@@ -0,0 +1,68 @@
1
+ import type {ReactNode} from 'react';
2
+ import {cn} from 'utils/cn';
3
+ import {
4
+ Item,
5
+ ItemActions,
6
+ ItemContent,
7
+ ItemDescription,
8
+ ItemMedia,
9
+ type ItemProps,
10
+ ItemTitle,
11
+ } from '../item/item';
12
+
13
+ export type DynamicItemProps = Omit<ItemProps, 'variant' | 'children' | 'title'> & {
14
+ variant?: 'default' | 'neutral';
15
+ leftElement?: ReactNode;
16
+ title?: ReactNode;
17
+ description?: string;
18
+ action?: ReactNode;
19
+ rightElement?: ReactNode;
20
+ contentClassName?: string;
21
+ };
22
+
23
+ export function DynamicItem({
24
+ className,
25
+ variant = 'default',
26
+ leftElement,
27
+ title,
28
+ description,
29
+ action,
30
+ rightElement,
31
+ contentClassName,
32
+ ...props
33
+ }: DynamicItemProps) {
34
+ const hasLeftSide = Boolean(leftElement);
35
+ const hasRightSide = Boolean(rightElement);
36
+ const hasContent = Boolean(title || description || action);
37
+
38
+ return (
39
+ <Item variant={variant} className={className} {...props}>
40
+ <div
41
+ className={cn(
42
+ 'relative flex flex-col sm:flex-row justify-center items-center gap-16 min-h-64 px-12 py-12',
43
+ contentClassName,
44
+ )}
45
+ >
46
+ {hasLeftSide && (
47
+ <ItemMedia className={cn('self-center sm:self-start pt-2')}>{leftElement}</ItemMedia>
48
+ )}
49
+
50
+ {hasContent && (
51
+ <ItemContent className="text-center sm:text-left">
52
+ {title && typeof title === 'string' ? <ItemTitle>{title}</ItemTitle> : title}
53
+ {description && <ItemDescription>{description}</ItemDescription>}
54
+ {action && (
55
+ <ItemActions className={cn('mt-8 flex flex-wrap items-center gap-16')}>
56
+ {action}
57
+ </ItemActions>
58
+ )}
59
+ </ItemContent>
60
+ )}
61
+
62
+ {hasRightSide && (
63
+ <ItemActions className="self-center sm:ml-auto">{rightElement}</ItemActions>
64
+ )}
65
+ </div>
66
+ </Item>
67
+ );
68
+ }
@@ -0,0 +1 @@
1
+ export * from './dynamic-item';
@@ -6,6 +6,9 @@ export * from './component-line';
6
6
  export * from './ellipse-mini-solid';
7
7
  export * from './info-tooltip-fill';
8
8
  export * from './resize';
9
+ export * from './shipfox-logo';
10
+ export * from './slack-logo';
9
11
  export * from './spinner';
12
+ export * from './stripe-logo';
10
13
  export * from './thunder';
11
14
  export * from './x-circle-solid';
@@ -0,0 +1,20 @@
1
+ import type {RemixiconComponentType} from '@remixicon/react';
2
+ import type {ComponentProps} from 'react';
3
+
4
+ type ShipfoxLogoProps = ComponentProps<RemixiconComponentType> & {
5
+ color?: string;
6
+ };
7
+
8
+ export function ShipfoxLogo({color = '#FF4B00', ...props}: ShipfoxLogoProps) {
9
+ return (
10
+ <svg viewBox="0 0 88 88" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
11
+ <title>Shipfox Logo</title>
12
+ <path
13
+ fillRule="evenodd"
14
+ clipRule="evenodd"
15
+ d="M17.9759 32.3751L39.0987 74.1549C41.1536 78.2196 46.847 78.2196 48.902 74.1549L70.0247 32.3751L81.2835 38.122C84.6511 39.8409 85.3794 44.4228 82.7171 47.1406L47.9008 82.684C45.7466 84.8831 42.254 84.8831 40.0999 82.684L5.28351 47.1406C2.62124 44.4227 3.34957 39.8409 6.7171 38.122L17.9759 32.3751ZM44.0003 19.0912L73.0051 4.28593C77.7786 1.84936 82.8214 7.06388 80.3737 11.9054L70.0247 32.3751L44.0003 19.0912ZM44.0003 19.0912L14.9955 4.28593C10.2221 1.84936 5.17926 7.06388 7.62699 11.9054L17.9759 32.3751L44.0003 19.0912Z"
16
+ fill={color}
17
+ />
18
+ </svg>
19
+ );
20
+ }
@@ -0,0 +1,35 @@
1
+ import type {RemixiconComponentType} from '@remixicon/react';
2
+ import type {ComponentProps} from 'react';
3
+
4
+ type SlackLogoProps = ComponentProps<RemixiconComponentType>;
5
+
6
+ export function SlackLogo(props: SlackLogoProps) {
7
+ return (
8
+ <svg
9
+ viewBox="0 0 28 28"
10
+ fill="none"
11
+ xmlns="http://www.w3.org/2000/svg"
12
+ aria-hidden="true"
13
+ focusable="false"
14
+ {...props}
15
+ >
16
+ <title>Slack Logo</title>
17
+ <path
18
+ d="M6.66988 17.376C6.66988 18.8336 5.4918 20.0117 4.03416 20.0117C2.57653 20.0117 1.39844 18.8336 1.39844 17.376C1.39844 15.9183 2.57653 14.7402 4.03416 14.7402H6.66988V17.376ZM7.98775 17.376C7.98775 15.9183 9.16583 14.7402 10.6235 14.7402C12.0811 14.7402 13.2592 15.9183 13.2592 17.376V23.9653C13.2592 25.4229 12.0811 26.601 10.6235 26.601C9.16583 26.601 7.98775 25.4229 7.98775 23.9653V17.376Z"
19
+ fill="#E01E5A"
20
+ />
21
+ <path
22
+ d="M10.6279 6.66102C9.17271 6.66102 7.99661 5.48492 7.99661 4.02973C7.99661 2.57455 9.17271 1.39844 10.6279 1.39844C12.0831 1.39844 13.2592 2.57455 13.2592 4.02973V6.66102H10.6279ZM10.6279 7.99661C12.0831 7.99661 13.2592 9.17271 13.2592 10.6279C13.2592 12.0831 12.0831 13.2592 10.6279 13.2592H4.02973C2.57455 13.2592 1.39844 12.0831 1.39844 10.6279C1.39844 9.17271 2.57455 7.99661 4.02973 7.99661H10.6279Z"
23
+ fill="#36C5F0"
24
+ />
25
+ <path
26
+ d="M21.3295 10.6279C21.3295 9.17271 22.5076 7.99661 23.9653 7.99661C25.4229 7.99661 26.601 9.17271 26.601 10.6279C26.601 12.0831 25.4229 13.2592 23.9653 13.2592H21.3295V10.6279ZM20.0117 10.6279C20.0117 12.0831 18.8336 13.2592 17.376 13.2592C15.9183 13.2592 14.7402 12.0831 14.7402 10.6279V4.02973C14.7402 2.57455 15.9183 1.39844 17.376 1.39844C18.8336 1.39844 20.0117 2.57455 20.0117 4.02973V10.6279Z"
27
+ fill="#2EB67D"
28
+ />
29
+ <path
30
+ d="M17.3715 21.3295C18.8267 21.3295 20.0028 22.5076 20.0028 23.9653C20.0028 25.4229 18.8267 26.601 17.3715 26.601C15.9163 26.601 14.7402 25.4229 14.7402 23.9653V21.3295H17.3715ZM17.3715 20.0117C15.9163 20.0117 14.7402 18.8336 14.7402 17.376C14.7402 15.9183 15.9163 14.7402 17.3715 14.7402H23.9697C25.4249 14.7402 26.601 15.9183 26.601 17.376C26.601 18.8336 25.4249 20.0117 23.9697 20.0117H17.3715Z"
31
+ fill="#ECB22E"
32
+ />
33
+ </svg>
34
+ );
35
+ }
@@ -0,0 +1,27 @@
1
+ import type {RemixiconComponentType} from '@remixicon/react';
2
+ import type {ComponentProps} from 'react';
3
+
4
+ type StripeLogoProps = ComponentProps<RemixiconComponentType> & {
5
+ color?: string;
6
+ };
7
+
8
+ export function StripeLogo({color = '#6772E5', ...props}: StripeLogoProps) {
9
+ return (
10
+ <svg
11
+ viewBox="0 0 28 28"
12
+ fill="none"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ aria-hidden="true"
15
+ focusable="false"
16
+ {...props}
17
+ >
18
+ <title>Stripe Logo</title>
19
+ <path
20
+ fillRule="evenodd"
21
+ clipRule="evenodd"
22
+ d="M12.3115 9.17663C12.3115 8.15771 13.1593 7.76352 14.5293 7.76352C16.7967 7.81251 19.0215 8.38821 21.0281 9.44512V3.29438C18.959 2.48126 16.7523 2.07592 14.5293 2.10068C9.24873 2.10068 5.70703 4.86665 5.70703 9.48529C5.70703 16.7115 15.63 15.5379 15.63 18.6526C15.63 19.8709 14.5888 20.2487 13.1236 20.2487C10.9631 20.2487 8.17253 19.3547 5.9837 18.1647V24.3958C8.23725 25.3764 10.6668 25.888 13.1244 25.8997C18.5514 25.8997 22.2925 23.2185 22.2925 18.5195C22.2925 10.7206 12.3115 12.1137 12.3115 9.17812V9.17663Z"
23
+ fill={color}
24
+ />
25
+ </svg>
26
+ );
27
+ }