@node-core/ui-components 1.0.1-1b9af3ec9e0268bfc734b2489cbc584fa3edf026 → 1.0.1-1ccf19c1836415b6ec7bc2d63ffba4686b390ca9

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 (264) hide show
  1. package/Common/AlertBox/index.module.css +46 -47
  2. package/Common/AlertBox/index.stories.tsx +73 -0
  3. package/Common/AlertBox/index.tsx +24 -0
  4. package/Common/AvatarGroup/Avatar/index.module.css +30 -50
  5. package/Common/AvatarGroup/Avatar/index.stories.tsx +22 -0
  6. package/Common/AvatarGroup/Avatar/index.tsx +67 -0
  7. package/Common/AvatarGroup/Overlay/index.module.css +21 -28
  8. package/Common/AvatarGroup/Overlay/index.stories.tsx +33 -0
  9. package/Common/AvatarGroup/Overlay/index.tsx +37 -0
  10. package/Common/AvatarGroup/__tests__/index.test.jsx +55 -0
  11. package/Common/AvatarGroup/index.module.css +11 -12
  12. package/Common/AvatarGroup/index.stories.tsx +56 -0
  13. package/Common/AvatarGroup/index.tsx +83 -0
  14. package/Common/Badge/index.module.css +26 -34
  15. package/Common/Badge/index.stories.tsx +38 -0
  16. package/Common/Badge/index.tsx +35 -0
  17. package/Common/BadgeGroup/index.module.css +51 -75
  18. package/Common/BadgeGroup/index.stories.tsx +35 -0
  19. package/Common/BadgeGroup/index.tsx +35 -0
  20. package/Common/Banner/index.module.css +27 -30
  21. package/Common/Banner/index.stories.tsx +29 -0
  22. package/Common/Banner/index.tsx +18 -0
  23. package/Common/BaseActiveLink/__tests__/index.test.jsx +52 -0
  24. package/Common/BaseActiveLink/index.tsx +34 -0
  25. package/Common/BaseButton/index.module.css +102 -332
  26. package/Common/BaseButton/index.stories.tsx +67 -0
  27. package/Common/BaseButton/index.tsx +59 -0
  28. package/Common/BaseCodeBox/index.module.css +58 -76
  29. package/Common/BaseCodeBox/index.stories.tsx +39 -0
  30. package/Common/BaseCodeBox/index.tsx +122 -0
  31. package/Common/BaseCrossLink/index.module.css +39 -57
  32. package/Common/BaseCrossLink/index.stories.tsx +38 -0
  33. package/Common/BaseCrossLink/index.tsx +46 -0
  34. package/Common/BaseLinkTabs/index.module.css +33 -67
  35. package/Common/BaseLinkTabs/index.stories.tsx +34 -0
  36. package/Common/BaseLinkTabs/index.tsx +53 -0
  37. package/Common/BasePagination/Ellipsis/index.module.css +8 -14
  38. package/Common/BasePagination/Ellipsis/index.stories.tsx +10 -0
  39. package/Common/BasePagination/Ellipsis/index.tsx +11 -0
  40. package/Common/BasePagination/PaginationListItem/__tests__/index.test.jsx +58 -0
  41. package/Common/BasePagination/PaginationListItem/index.module.css +21 -36
  42. package/Common/BasePagination/PaginationListItem/index.stories.tsx +40 -0
  43. package/Common/BasePagination/PaginationListItem/index.tsx +39 -0
  44. package/Common/BasePagination/PrevNextArrow.tsx +15 -0
  45. package/Common/BasePagination/__tests__/index.test.jsx +180 -0
  46. package/Common/BasePagination/index.module.css +26 -27
  47. package/Common/BasePagination/index.stories.tsx +67 -0
  48. package/Common/BasePagination/index.tsx +77 -0
  49. package/Common/BasePagination/useGetPageElements.tsx +132 -0
  50. package/Common/Blockquote/index.module.css +23 -44
  51. package/Common/Blockquote/index.stories.tsx +45 -0
  52. package/Common/Blockquote/index.tsx +11 -0
  53. package/Common/Breadcrumbs/BreadcrumbHomeLink/index.module.css +3 -3
  54. package/Common/Breadcrumbs/BreadcrumbHomeLink/index.tsx +30 -0
  55. package/Common/Breadcrumbs/BreadcrumbItem/index.module.css +27 -38
  56. package/Common/Breadcrumbs/BreadcrumbItem/index.tsx +42 -0
  57. package/Common/Breadcrumbs/BreadcrumbLink/index.module.css +16 -26
  58. package/Common/Breadcrumbs/BreadcrumbLink/index.tsx +37 -0
  59. package/Common/Breadcrumbs/BreadcrumbRoot/index.module.css +7 -8
  60. package/Common/Breadcrumbs/BreadcrumbRoot/index.tsx +20 -0
  61. package/Common/Breadcrumbs/BreadcrumbTruncatedItem/index.tsx +9 -0
  62. package/Common/Breadcrumbs/index.stories.tsx +94 -0
  63. package/Common/Breadcrumbs/index.tsx +81 -0
  64. package/Common/CodeTabs/index.module.css +36 -47
  65. package/Common/CodeTabs/index.stories.tsx +73 -0
  66. package/Common/CodeTabs/index.tsx +16 -0
  67. package/Common/DataTag/index.module.css +32 -30
  68. package/Common/DataTag/index.stories.tsx +40 -0
  69. package/Common/DataTag/index.tsx +39 -0
  70. package/Common/GlowingBackdrop/index.module.css +28 -126
  71. package/Common/GlowingBackdrop/index.stories.tsx +10 -0
  72. package/Common/GlowingBackdrop/index.tsx +13 -0
  73. package/Common/LanguageDropDown/index.module.css +42 -140
  74. package/Common/LanguageDropDown/index.stories.tsx +19 -0
  75. package/Common/LanguageDropDown/index.tsx +56 -0
  76. package/Common/Modal/index.module.css +62 -217
  77. package/Common/Modal/index.stories.tsx +32 -0
  78. package/Common/Modal/index.tsx +48 -0
  79. package/Common/NodejsLogo/index.module.css +4 -3
  80. package/Common/NodejsLogo/index.stories.tsx +14 -0
  81. package/Common/NodejsLogo/index.tsx +26 -0
  82. package/Common/Notification/index.module.css +17 -101
  83. package/Common/Notification/index.stories.tsx +36 -0
  84. package/Common/Notification/index.tsx +34 -0
  85. package/Common/Preview/index.module.css +65 -269
  86. package/Common/Preview/index.stories.tsx +44 -0
  87. package/Common/Preview/index.tsx +25 -0
  88. package/Common/Select/__tests__/index.test.jsx +67 -0
  89. package/Common/Select/index.module.css +127 -294
  90. package/Common/Select/index.stories.tsx +111 -0
  91. package/Common/Select/index.tsx +187 -0
  92. package/Common/Separator/index.module.css +10 -7
  93. package/Common/Separator/index.stories.tsx +32 -0
  94. package/Common/Separator/index.tsx +27 -0
  95. package/Common/Skeleton/index.module.css +21 -118
  96. package/Common/Skeleton/index.tsx +39 -0
  97. package/Common/Tabs/__tests__/index.test.jsx +52 -0
  98. package/Common/Tabs/index.module.css +40 -58
  99. package/Common/Tabs/index.stories.tsx +50 -0
  100. package/Common/Tabs/index.tsx +54 -0
  101. package/Common/ThemeToggle/__tests__/index.test.jsx +35 -0
  102. package/Common/ThemeToggle/index.module.css +11 -18
  103. package/Common/ThemeToggle/index.stories.tsx +10 -0
  104. package/Common/ThemeToggle/index.tsx +15 -0
  105. package/Common/Tooltip/index.module.css +29 -119
  106. package/Common/Tooltip/index.stories.tsx +73 -0
  107. package/Common/Tooltip/index.tsx +48 -0
  108. package/Containers/Article/index.module.css +58 -127
  109. package/Containers/Article/index.stories.tsx +39 -0
  110. package/Containers/Article/index.tsx +9 -0
  111. package/Containers/DocSideBar/index.tsx +0 -0
  112. package/Containers/Footer/index.module.css +36 -51
  113. package/Containers/Footer/index.stories.tsx +27 -0
  114. package/Containers/Footer/index.tsx +95 -0
  115. package/Containers/MetaBar/__tests__/index.test.jsx +63 -0
  116. package/Containers/MetaBar/index.module.css +69 -101
  117. package/Containers/MetaBar/index.stories.tsx +80 -0
  118. package/Containers/MetaBar/index.tsx +72 -0
  119. package/Containers/NavBar/NavItem/index.module.css +36 -50
  120. package/Containers/NavBar/NavItem/index.stories.tsx +38 -0
  121. package/Containers/NavBar/NavItem/index.tsx +44 -0
  122. package/Containers/NavBar/index.module.css +96 -176
  123. package/Containers/NavBar/index.stories.tsx +45 -0
  124. package/Containers/NavBar/index.tsx +94 -0
  125. package/Containers/Sidebar/ProgressionIcon/index.tsx +16 -0
  126. package/Containers/Sidebar/SidebarGroup/index.module.css +52 -180
  127. package/Containers/Sidebar/SidebarGroup/index.stories.tsx +36 -0
  128. package/Containers/Sidebar/SidebarGroup/index.tsx +49 -0
  129. package/Containers/Sidebar/SidebarItem/index.module.css +38 -49
  130. package/Containers/Sidebar/SidebarItem/index.stories.tsx +15 -0
  131. package/Containers/Sidebar/SidebarItem/index.tsx +43 -0
  132. package/Containers/Sidebar/index.module.css +24 -42
  133. package/Containers/Sidebar/index.stories.tsx +88 -0
  134. package/Containers/Sidebar/index.tsx +67 -0
  135. package/Icons/HexagonGrid.stories.tsx +10 -0
  136. package/Icons/HexagonGrid.tsx +1434 -0
  137. package/Icons/InstallationMethod/Choco.tsx +78 -0
  138. package/Icons/InstallationMethod/Devbox.tsx +21 -0
  139. package/Icons/InstallationMethod/Docker.tsx +20 -0
  140. package/Icons/InstallationMethod/FNM.tsx +132 -0
  141. package/Icons/InstallationMethod/Homebrew.tsx +69 -0
  142. package/Icons/InstallationMethod/N.tsx +32 -0
  143. package/Icons/InstallationMethod/NVM.tsx +63 -0
  144. package/Icons/InstallationMethod/Volta.tsx +34 -0
  145. package/Icons/InstallationMethod/{index.js → index.ts} +1 -0
  146. package/Icons/Logos/JsGreen.tsx +24 -0
  147. package/Icons/Logos/JsWhite.tsx +37 -0
  148. package/Icons/Logos/Nodejs.tsx +188 -0
  149. package/Icons/Logos/NodejsStackedBlack.tsx +98 -0
  150. package/Icons/Logos/NodejsStackedDark.tsx +124 -0
  151. package/Icons/Logos/NodejsStackedLight.tsx +123 -0
  152. package/Icons/Logos/NodejsStackedWhite.tsx +98 -0
  153. package/Icons/Logos/{index.js → index.ts} +10 -1
  154. package/Icons/OperatingSystem/AIX.tsx +46 -0
  155. package/Icons/OperatingSystem/Apple.tsx +23 -0
  156. package/Icons/OperatingSystem/Linux.tsx +969 -0
  157. package/Icons/OperatingSystem/Microsoft.tsx +19 -0
  158. package/Icons/OperatingSystem/{index.js → index.ts} +1 -0
  159. package/Icons/PackageManager/Npm.tsx +21 -0
  160. package/Icons/PackageManager/Pnpm.tsx +22 -0
  161. package/Icons/PackageManager/Yarn.tsx +22 -0
  162. package/Icons/PackageManager/{index.js → index.ts} +1 -0
  163. package/Icons/Social/Bluesky.tsx +19 -0
  164. package/Icons/Social/Discord.tsx +20 -0
  165. package/Icons/Social/GitHub.tsx +16 -0
  166. package/Icons/Social/LinkedIn.tsx +16 -0
  167. package/Icons/Social/Mastodon.tsx +36 -0
  168. package/Icons/Social/Slack.tsx +31 -0
  169. package/Icons/Social/X.tsx +16 -0
  170. package/Icons/Social/{index.js → index.ts} +1 -0
  171. package/MDX/CodeTabs.tsx +47 -0
  172. package/package.json +54 -6
  173. package/stylelint/__tests__/index.test.mjs +80 -0
  174. package/stylelint/one-utility-class-per-line.mjs +50 -34
  175. package/stylelint/utils.mjs +25 -19
  176. package/styles/animations.css +47 -0
  177. package/styles/base.css +17 -0
  178. package/styles/effects.css +12 -0
  179. package/styles/index.css +26 -1127
  180. package/styles/markdown.css +173 -0
  181. package/styles/theme.css +175 -0
  182. package/types.ts +25 -0
  183. package/Common/AlertBox/index.js +0 -5
  184. package/Common/AvatarGroup/Avatar/index.js +0 -11
  185. package/Common/AvatarGroup/Overlay/index.js +0 -6
  186. package/Common/AvatarGroup/index.js +0 -21
  187. package/Common/Badge/index.js +0 -7
  188. package/Common/BadgeGroup/index.js +0 -6
  189. package/Common/Banner/index.js +0 -4
  190. package/Common/BaseActiveLink/index.js +0 -14
  191. package/Common/BaseButton/index.js +0 -10
  192. package/Common/BaseCodeBox/index.js +0 -50
  193. package/Common/BaseCrossLink/index.js +0 -12
  194. package/Common/BaseLinkTabs/index.js +0 -5
  195. package/Common/BasePagination/Ellipsis/index.js +0 -4
  196. package/Common/BasePagination/PaginationListItem/index.js +0 -6
  197. package/Common/BasePagination/PrevNextArrow.js +0 -7
  198. package/Common/BasePagination/index.js +0 -10
  199. package/Common/BasePagination/useGetPageElements.js +0 -77
  200. package/Common/Blockquote/index.js +0 -4
  201. package/Common/Breadcrumbs/BreadcrumbHomeLink/index.js +0 -9
  202. package/Common/Breadcrumbs/BreadcrumbItem/index.js +0 -6
  203. package/Common/Breadcrumbs/BreadcrumbLink/index.js +0 -5
  204. package/Common/Breadcrumbs/BreadcrumbRoot/index.js +0 -4
  205. package/Common/Breadcrumbs/BreadcrumbTruncatedItem/index.js +0 -4
  206. package/Common/Breadcrumbs/index.js +0 -22
  207. package/Common/ChangeHistory/index.js +0 -9
  208. package/Common/ChangeHistory/index.module.css +0 -198
  209. package/Common/CodeTabs/index.js +0 -5
  210. package/Common/DataTag/index.js +0 -18
  211. package/Common/GlowingBackdrop/index.js +0 -5
  212. package/Common/LanguageDropDown/index.js +0 -11
  213. package/Common/Modal/index.js +0 -10
  214. package/Common/NodejsLogo/index.js +0 -7
  215. package/Common/Notification/index.js +0 -6
  216. package/Common/Preview/index.js +0 -7
  217. package/Common/Select/index.js +0 -46
  218. package/Common/Separator/index.js +0 -7
  219. package/Common/Skeleton/index.js +0 -18
  220. package/Common/Tabs/index.js +0 -6
  221. package/Common/ThemeToggle/index.js +0 -7
  222. package/Common/Tooltip/index.js +0 -8
  223. package/Containers/Article/index.js +0 -4
  224. package/Containers/DocSideBar/index.js +0 -1
  225. package/Containers/Footer/index.js +0 -22
  226. package/Containers/MetaBar/index.js +0 -12
  227. package/Containers/NavBar/NavItem/index.js +0 -7
  228. package/Containers/NavBar/index.js +0 -18
  229. package/Containers/Sidebar/ProgressionIcon/index.js +0 -3
  230. package/Containers/Sidebar/SidebarGroup/index.js +0 -9
  231. package/Containers/Sidebar/SidebarItem/index.js +0 -11
  232. package/Containers/Sidebar/index.js +0 -15
  233. package/Icons/HexagonGrid.js +0 -3
  234. package/Icons/InstallationMethod/Choco.js +0 -3
  235. package/Icons/InstallationMethod/Devbox.js +0 -3
  236. package/Icons/InstallationMethod/Docker.js +0 -3
  237. package/Icons/InstallationMethod/FNM.js +0 -3
  238. package/Icons/InstallationMethod/Homebrew.js +0 -3
  239. package/Icons/InstallationMethod/N.js +0 -5
  240. package/Icons/InstallationMethod/NVM.js +0 -3
  241. package/Icons/InstallationMethod/Volta.js +0 -3
  242. package/Icons/Logos/JsGreen.js +0 -3
  243. package/Icons/Logos/JsWhite.js +0 -3
  244. package/Icons/Logos/Nodejs.js +0 -6
  245. package/Icons/Logos/NodejsStackedBlack.js +0 -3
  246. package/Icons/Logos/NodejsStackedDark.js +0 -3
  247. package/Icons/Logos/NodejsStackedLight.js +0 -3
  248. package/Icons/Logos/NodejsStackedWhite.js +0 -3
  249. package/Icons/OperatingSystem/AIX.js +0 -3
  250. package/Icons/OperatingSystem/Apple.js +0 -3
  251. package/Icons/OperatingSystem/Linux.js +0 -3
  252. package/Icons/OperatingSystem/Microsoft.js +0 -3
  253. package/Icons/PackageManager/Npm.js +0 -3
  254. package/Icons/PackageManager/Pnpm.js +0 -3
  255. package/Icons/PackageManager/Yarn.js +0 -3
  256. package/Icons/Social/Bluesky.js +0 -3
  257. package/Icons/Social/Discord.js +0 -3
  258. package/Icons/Social/GitHub.js +0 -3
  259. package/Icons/Social/LinkedIn.js +0 -3
  260. package/Icons/Social/Mastodon.js +0 -3
  261. package/Icons/Social/Slack.js +0 -3
  262. package/Icons/Social/X.js +0 -3
  263. package/MDX/CodeTabs.js +0 -16
  264. package/types.js +0 -1
@@ -0,0 +1,83 @@
1
+ 'use client';
2
+
3
+ import classNames from 'classnames';
4
+ import type { FC } from 'react';
5
+ import { useState, useMemo } from 'react';
6
+
7
+ import type { AvatarProps } from '#ui/Common/AvatarGroup/Avatar';
8
+ import Avatar from '#ui/Common/AvatarGroup/Avatar';
9
+ import avatarstyles from '#ui/Common/AvatarGroup/Avatar/index.module.css';
10
+ import AvatarOverlay from '#ui/Common/AvatarGroup/Overlay';
11
+ import Tooltip from '#ui/Common/Tooltip';
12
+ import type { LinkLike } from '#ui/types';
13
+
14
+ import styles from './index.module.css';
15
+
16
+ type AvatarGroupProps = {
17
+ avatars: Array<AvatarProps>;
18
+ limit?: number;
19
+ isExpandable?: boolean;
20
+ size?: AvatarProps['size'];
21
+ container?: HTMLElement;
22
+ as?: LinkLike;
23
+ };
24
+
25
+ const AvatarGroup: FC<AvatarGroupProps> = ({
26
+ avatars,
27
+ limit = 10,
28
+ isExpandable = true,
29
+ size = 'small',
30
+ container,
31
+ as,
32
+ }) => {
33
+ const [showMore, setShowMore] = useState(false);
34
+
35
+ const renderAvatars = useMemo(
36
+ () => avatars.slice(0, showMore ? avatars.length : limit),
37
+ [avatars, limit, showMore]
38
+ );
39
+
40
+ const handleShowMoreClick = isExpandable
41
+ ? () => setShowMore(prev => !prev)
42
+ : undefined;
43
+
44
+ return (
45
+ <div className={classNames(styles.avatarGroup, styles[size])}>
46
+ {renderAvatars.map(avatar => (
47
+ <Tooltip
48
+ key={avatar.nickname}
49
+ asChild
50
+ container={container}
51
+ content={<AvatarOverlay {...avatar} as={as} />}
52
+ >
53
+ <Avatar
54
+ {...avatar}
55
+ size={size}
56
+ className={classNames({
57
+ 'cursor-pointer': avatar.url,
58
+ 'pointer-events-none': !avatar.url,
59
+ })}
60
+ as={as}
61
+ />
62
+ </Tooltip>
63
+ ))}
64
+
65
+ {avatars.length > limit && (
66
+ <span
67
+ onClick={handleShowMoreClick}
68
+ className={classNames(
69
+ avatarstyles.avatar,
70
+ avatarstyles[size],
71
+ 'cursor-pointer'
72
+ )}
73
+ >
74
+ <span className={avatarstyles.item}>
75
+ {`${showMore ? '-' : '+'}${avatars.length - limit}`}
76
+ </span>
77
+ </span>
78
+ )}
79
+ </div>
80
+ );
81
+ };
82
+
83
+ export default AvatarGroup;
@@ -1,46 +1,38 @@
1
- /*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */
1
+ @reference "../../styles/index.css";
2
+
2
3
  .badge {
3
- border-radius: calc(infinity*1px);
4
- border-style: var(--tw-border-style);
5
- border-width: 1px;
6
- text-align: center;
7
- color: var(--color-white, #fff);
4
+ @apply rounded-full
5
+ border
6
+ text-center
7
+ text-white;
8
+
8
9
  &.small {
9
- padding-inline: calc(var(--spacing, 0.25rem)*1.5);
10
- padding-block: calc(var(--spacing, 0.25rem)*0.5);
11
- font-size: var(--text-xs, 0.75rem);
12
- line-height: var(--tw-leading, var(--text-xs--line-height, 1.33333));
10
+ @apply px-1.5
11
+ py-0.5
12
+ text-xs;
13
13
  }
14
+
14
15
  &.medium {
15
- padding-inline: calc(var(--spacing, 0.25rem)*2.5);
16
- padding-block: calc(var(--spacing, 0.25rem)*0.5);
17
- font-size: var(--text-base, 1rem);
18
- line-height: var(--tw-leading, var(--text-base--line-height, 1.5));
16
+ @apply px-2.5
17
+ py-0.5
18
+ text-base;
19
19
  }
20
+
20
21
  &.default {
21
- border-color: var(--color-green-200, #c5e5b4);
22
- background-color: var(--color-green-600, #417e38);
23
- &:where([data-theme=dark], [data-theme=dark] *) {
24
- border-color: var(--color-green-800, #2c682c);
25
- }
22
+ @apply border-green-200
23
+ bg-green-600
24
+ dark:border-green-800;
26
25
  }
26
+
27
27
  &.error {
28
- border-color: var(--color-danger-200, #fad3d4);
29
- background-color: var(--color-danger-600, #de1a1b);
30
- &:where([data-theme=dark], [data-theme=dark] *) {
31
- border-color: var(--color-danger-800, #900e0e);
32
- }
28
+ @apply border-danger-200
29
+ bg-danger-600
30
+ dark:border-danger-800;
33
31
  }
32
+
34
33
  &.warning {
35
- border-color: var(--color-warning-200, #fad9b0);
36
- background-color: var(--color-warning-600, #ae5f00);
37
- &:where([data-theme=dark], [data-theme=dark] *) {
38
- border-color: var(--color-warning-600, #ae5f00);
39
- }
34
+ @apply border-warning-200
35
+ bg-warning-600
36
+ dark:border-warning-600;
40
37
  }
41
38
  }
42
- @property --tw-border-style {
43
- syntax: "*";
44
- inherits: false;
45
- initial-value: solid;
46
- }
@@ -0,0 +1,38 @@
1
+ import type { Meta as MetaObj, StoryObj } from '@storybook/react';
2
+
3
+ import Badge from '#ui/Common/Badge';
4
+
5
+ type Story = StoryObj<typeof Badge>;
6
+ type Meta = MetaObj<typeof Badge>;
7
+
8
+ export const Default: Story = {
9
+ args: {
10
+ kind: 'default',
11
+ },
12
+ };
13
+
14
+ export const Error: Story = {
15
+ args: {
16
+ kind: 'error',
17
+ },
18
+ };
19
+
20
+ export const Warning: Story = {
21
+ args: {
22
+ kind: 'warning',
23
+ },
24
+ };
25
+
26
+ export const Small: Story = {
27
+ args: {
28
+ size: 'small',
29
+ },
30
+ };
31
+
32
+ export const Medium: Story = {
33
+ args: {
34
+ size: 'medium',
35
+ },
36
+ };
37
+
38
+ export default { component: Badge, args: { children: 'Badge' } } as Meta;
@@ -0,0 +1,35 @@
1
+ import classNames from 'classnames';
2
+ import type { FC, HTMLAttributes, PropsWithChildren } from 'react';
3
+
4
+ import styles from './index.module.css';
5
+
6
+ type BadgeKind = 'default' | 'warning' | 'error';
7
+
8
+ type BadgeProps = HTMLAttributes<HTMLSpanElement> & {
9
+ size?: 'small' | 'medium';
10
+ kind?: BadgeKind;
11
+ };
12
+
13
+ const Badge: FC<PropsWithChildren<BadgeProps>> = ({
14
+ kind = 'default',
15
+ size = 'medium',
16
+ className,
17
+ children,
18
+ ...props
19
+ }) => {
20
+ return (
21
+ <span
22
+ className={classNames(
23
+ styles.badge,
24
+ styles[kind],
25
+ styles[size],
26
+ className
27
+ )}
28
+ {...props}
29
+ >
30
+ {children}
31
+ </span>
32
+ );
33
+ };
34
+
35
+ export default Badge;
@@ -1,101 +1,77 @@
1
- /*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */
1
+ @reference "../../styles/index.css";
2
+
2
3
  .wrapper {
3
- display: flex;
4
- width: fit-content;
5
- align-items: center;
6
- border-radius: calc(infinity*1px);
7
- border-style: var(--tw-border-style);
8
- border-width: 1px;
9
- padding-block: calc(var(--spacing, 0.25rem)*1);
10
- padding-right: calc(var(--spacing, 0.25rem)*2.5);
11
- padding-left: calc(var(--spacing, 0.25rem)*1);
12
- font-size: var(--text-sm, 0.875rem);
13
- line-height: var(--tw-leading, var(--text-sm--line-height, 1.42857));
14
- --tw-font-weight: var(--font-weight-medium, 500);
15
- font-weight: var(--font-weight-medium, 500);
4
+ @apply flex
5
+ w-fit
6
+ items-center
7
+ rounded-full
8
+ border
9
+ py-1
10
+ pl-1
11
+ pr-2.5
12
+ text-sm
13
+ font-medium;
14
+
16
15
  .icon {
17
- width: calc(var(--spacing, 0.25rem)*4);
18
- height: calc(var(--spacing, 0.25rem)*4);
16
+ @apply size-4;
19
17
  }
18
+
20
19
  .badge {
21
- margin-right: calc(var(--spacing, 0.25rem)*2);
20
+ @apply mr-2;
22
21
  }
22
+
23
23
  .message {
24
- margin-right: calc(var(--spacing, 0.25rem)*1);
24
+ @apply mr-1;
25
25
  }
26
+
26
27
  &.default {
27
- border-color: var(--color-green-200, #c5e5b4);
28
- background-color: var(--color-green-100, #edf2eb);
29
- &:where([data-theme=dark], [data-theme=dark] *) {
30
- border-color: var(--color-green-700, #2c682c);
31
- }
32
- &:where([data-theme=dark], [data-theme=dark] *) {
33
- background-color: var(--color-neutral-900, #2c3437);
34
- }
28
+ @apply border-green-200
29
+ bg-green-100
30
+ dark:border-green-700
31
+ dark:bg-neutral-900;
32
+
35
33
  .icon {
36
- color: var(--color-green-500, #5fa04e);
37
- &:where([data-theme=dark], [data-theme=dark] *) {
38
- color: var(--color-green-300, #99cc7d);
39
- }
34
+ @apply text-green-500
35
+ dark:text-green-300;
40
36
  }
37
+
41
38
  .message {
42
- color: var(--color-green-700, #2c682c);
43
- &:where([data-theme=dark], [data-theme=dark] *) {
44
- color: var(--color-green-300, #99cc7d);
45
- }
39
+ @apply text-green-700
40
+ dark:text-green-300;
46
41
  }
47
42
  }
43
+
48
44
  &.error {
49
- border-color: var(--color-danger-200, #fad3d4);
50
- background-color: var(--color-danger-100, #fbf1f0);
51
- &:where([data-theme=dark], [data-theme=dark] *) {
52
- border-color: var(--color-danger-700, #b80c0c);
53
- }
54
- &:where([data-theme=dark], [data-theme=dark] *) {
55
- background-color: var(--color-neutral-900, #2c3437);
56
- }
45
+ @apply border-danger-200
46
+ bg-danger-100
47
+ dark:border-danger-700
48
+ dark:bg-neutral-900;
49
+
57
50
  .icon {
58
- color: var(--color-danger-500, #f65354);
59
- &:where([data-theme=dark], [data-theme=dark] *) {
60
- color: var(--color-danger-300, #fab6b7);
61
- }
51
+ @apply text-danger-500
52
+ dark:text-danger-300;
62
53
  }
54
+
63
55
  .message {
64
- color: var(--color-danger-700, #b80c0c);
65
- &:where([data-theme=dark], [data-theme=dark] *) {
66
- color: var(--color-danger-300, #fab6b7);
67
- }
56
+ @apply text-danger-700
57
+ dark:text-danger-300;
68
58
  }
69
59
  }
60
+
70
61
  &.warning {
71
- border-color: var(--color-warning-200, #fad9b0);
72
- background-color: var(--color-warning-100, #fdf3e7);
73
- &:where([data-theme=dark], [data-theme=dark] *) {
74
- border-color: var(--color-warning-700, #8b4d04);
75
- }
76
- &:where([data-theme=dark], [data-theme=dark] *) {
77
- background-color: var(--color-neutral-900, #2c3437);
78
- }
62
+ @apply border-warning-200
63
+ bg-warning-100
64
+ dark:border-warning-700
65
+ dark:bg-neutral-900;
66
+
79
67
  .icon {
80
- color: var(--color-warning-500, #d07912);
81
- &:where([data-theme=dark], [data-theme=dark] *) {
82
- color: var(--color-warning-300, #f5bc75);
83
- }
68
+ @apply text-warning-500
69
+ dark:text-warning-300;
84
70
  }
71
+
85
72
  .message {
86
- color: var(--color-warning-700, #8b4d04);
87
- &:where([data-theme=dark], [data-theme=dark] *) {
88
- color: var(--color-warning-300, #f5bc75);
89
- }
73
+ @apply text-warning-700
74
+ dark:text-warning-300;
90
75
  }
91
76
  }
92
77
  }
93
- @property --tw-border-style {
94
- syntax: "*";
95
- inherits: false;
96
- initial-value: solid;
97
- }
98
- @property --tw-font-weight {
99
- syntax: "*";
100
- inherits: false;
101
- }
@@ -0,0 +1,35 @@
1
+ import type { Meta as MetaObj, StoryObj } from '@storybook/react';
2
+
3
+ import BadgeGroup from '#ui/Common/BadgeGroup';
4
+
5
+ type Story = StoryObj<typeof BadgeGroup>;
6
+ type Meta = MetaObj<typeof BadgeGroup>;
7
+
8
+ export const Default: Story = {
9
+ args: {
10
+ href: '/',
11
+ children: 'OpenJS Foundation Certification 2023',
12
+ kind: 'default',
13
+ badgeText: 'New',
14
+ },
15
+ };
16
+
17
+ export const Error: Story = {
18
+ args: {
19
+ href: '/',
20
+ children: 'OpenJS Foundation Certification 2023',
21
+ kind: 'error',
22
+ badgeText: 'New',
23
+ },
24
+ };
25
+
26
+ export const Warning: Story = {
27
+ args: {
28
+ href: '/',
29
+ children: 'OpenJS Foundation Certification 2023',
30
+ kind: 'warning',
31
+ badgeText: 'New',
32
+ },
33
+ };
34
+
35
+ export default { component: BadgeGroup } as Meta;
@@ -0,0 +1,35 @@
1
+ import ArrowRightIcon from '@heroicons/react/24/solid/ArrowRightIcon';
2
+ import type { ComponentProps, FC, PropsWithChildren } from 'react';
3
+
4
+ import Badge from '#ui/Common/Badge';
5
+ import type { LinkLike } from '#ui/types';
6
+
7
+ import styles from './index.module.css';
8
+
9
+ type BadgeGroupKind = 'default' | 'warning' | 'error';
10
+
11
+ type BadgeGroupProps = {
12
+ kind?: BadgeGroupKind;
13
+ badgeText?: string;
14
+ as: LinkLike;
15
+ } & ComponentProps<LinkLike>;
16
+
17
+ const BadgeGroup: FC<PropsWithChildren<BadgeGroupProps>> = ({
18
+ kind = 'default',
19
+ badgeText,
20
+ children,
21
+ as: Component = 'a',
22
+ ...args
23
+ }) => (
24
+ <Component className={`${styles.wrapper} ${styles[kind]}`} {...args}>
25
+ {badgeText && (
26
+ <Badge kind={kind} className={styles.badge}>
27
+ {badgeText}
28
+ </Badge>
29
+ )}
30
+ <span className={styles.message}>{children}</span>
31
+ {args.href && <ArrowRightIcon className={styles.icon} />}
32
+ </Component>
33
+ );
34
+
35
+ export default BadgeGroup;
@@ -1,45 +1,42 @@
1
- /*! tailwindcss v4.1.11 | MIT License | https://tailwindcss.com */
1
+ @reference "../../styles/index.css";
2
+
2
3
  .banner {
3
- display: flex;
4
- width: 100%;
5
- flex-direction: row;
6
- align-items: center;
7
- justify-content: center;
8
- gap: calc(var(--spacing, 0.25rem)*2);
9
- padding-inline: calc(var(--spacing, 0.25rem)*8);
10
- padding-block: calc(var(--spacing, 0.25rem)*3);
11
- font-size: var(--text-sm, 0.875rem);
12
- line-height: var(--tw-leading, var(--text-sm--line-height, 1.42857));
4
+ @apply flex
5
+ w-full
6
+ flex-row
7
+ items-center
8
+ justify-center
9
+ gap-2
10
+ px-8
11
+ py-3
12
+ text-sm;
13
+
13
14
  &,
14
15
  a {
15
- color: var(--color-white, #fff);
16
- &:where([data-theme=dark], [data-theme=dark] *) {
17
- color: var(--color-white, #fff);
18
- }
16
+ @apply text-white
17
+ dark:text-white;
19
18
  }
19
+
20
20
  a {
21
- width: fit-content;
22
- text-decoration-line: underline;
23
- text-decoration-color: color-mix(in srgb, #fff 50%, transparent);
24
- @supports (color: color-mix(in lab, red, red)) {
25
- text-decoration-color: color-mix(in oklab, var(--color-white, #fff) 50%, transparent);
26
- }
21
+ @apply w-fit
22
+ underline
23
+ decoration-white/50;
27
24
  }
25
+
28
26
  svg {
29
- width: calc(var(--spacing, 0.25rem)*4);
30
- height: calc(var(--spacing, 0.25rem)*4);
31
- color: color-mix(in srgb, #fff 50%, transparent);
32
- @supports (color: color-mix(in lab, red, red)) {
33
- color: color-mix(in oklab, var(--color-white, #fff) 50%, transparent);
34
- }
27
+ @apply size-4
28
+ text-white/50;
35
29
  }
36
30
  }
31
+
37
32
  .default {
38
- background-color: var(--color-green-600, #417e38);
33
+ @apply bg-green-600;
39
34
  }
35
+
40
36
  .error {
41
- background-color: var(--color-danger-600, #de1a1b);
37
+ @apply bg-danger-600;
42
38
  }
39
+
43
40
  .warning {
44
- background-color: var(--color-warning-600, #ae5f00);
41
+ @apply bg-warning-600;
45
42
  }
@@ -0,0 +1,29 @@
1
+ import type { Meta as MetaObj, StoryObj } from '@storybook/react';
2
+
3
+ import Banner from '#ui/Common/Banner';
4
+
5
+ type Story = StoryObj<typeof Banner>;
6
+ type Meta = MetaObj<typeof Banner>;
7
+
8
+ export const Default: Story = {
9
+ args: {
10
+ children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
11
+ type: 'default',
12
+ },
13
+ };
14
+
15
+ export const Error: Story = {
16
+ args: {
17
+ children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
18
+ type: 'error',
19
+ },
20
+ };
21
+
22
+ export const Warning: Story = {
23
+ args: {
24
+ children: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
25
+ type: 'warning',
26
+ },
27
+ };
28
+
29
+ export default { component: Banner } as Meta;
@@ -0,0 +1,18 @@
1
+ import type { FC, PropsWithChildren } from 'react';
2
+
3
+ import styles from './index.module.css';
4
+
5
+ export type BannerProps = {
6
+ type?: 'default' | 'warning' | 'error';
7
+ };
8
+
9
+ const Banner: FC<PropsWithChildren<BannerProps>> = ({
10
+ type = 'default',
11
+ children,
12
+ }) => (
13
+ <div className={`${styles.banner} ${styles[type] || styles.default}`}>
14
+ {children}
15
+ </div>
16
+ );
17
+
18
+ export default Banner;
@@ -0,0 +1,52 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+
4
+ import { render, screen } from '@testing-library/react';
5
+
6
+ import ActiveLink from '..';
7
+
8
+ describe('ActiveLink', () => {
9
+ it('renders as localized link', async () => {
10
+ render(
11
+ <ActiveLink className="link" activeClassName="active" href="/link">
12
+ Link
13
+ </ActiveLink>
14
+ );
15
+
16
+ assert.equal(
17
+ (await screen.findByText('Link')).getAttribute('href'),
18
+ '/link'
19
+ );
20
+ });
21
+
22
+ it('ignores active class when href not matches location.href', async () => {
23
+ render(
24
+ <ActiveLink className="link" activeClassName="active" href="/not-link">
25
+ Link
26
+ </ActiveLink>
27
+ );
28
+
29
+ assert.equal(
30
+ (await screen.findByText('Link')).getAttribute('class'),
31
+ 'link'
32
+ );
33
+ });
34
+
35
+ it('sets active class when href matches location.href', async () => {
36
+ render(
37
+ <ActiveLink
38
+ className="link"
39
+ activeClassName="active"
40
+ href="/link"
41
+ pathname="/link"
42
+ >
43
+ Link
44
+ </ActiveLink>
45
+ );
46
+
47
+ assert.equal(
48
+ (await screen.findByText('Link')).getAttribute('class'),
49
+ 'link active'
50
+ );
51
+ });
52
+ });
@@ -0,0 +1,34 @@
1
+ import classNames from 'classnames';
2
+ import type { ComponentProps, FC } from 'react';
3
+
4
+ import type { LinkLike } from '#ui/types';
5
+
6
+ export type ActiveLocalizedLinkProps = ComponentProps<LinkLike> & {
7
+ activeClassName?: string;
8
+ allowSubPath?: boolean;
9
+ pathname?: string;
10
+ as?: LinkLike;
11
+ };
12
+
13
+ const BaseActiveLink: FC<ActiveLocalizedLinkProps> = ({
14
+ activeClassName = 'active',
15
+ allowSubPath = false,
16
+ className,
17
+ href = '',
18
+ pathname = '/',
19
+ as: Component = 'a',
20
+ ...props
21
+ }) => {
22
+ const finalClassName = classNames(className, {
23
+ [activeClassName]: allowSubPath
24
+ ? // When using allowSubPath we want only to check if
25
+ // the current pathname starts with the utmost upper level
26
+ // of an href (e.g. /docs/...)
27
+ pathname.startsWith(`/${href.toString().split('/')[1]}`)
28
+ : href.toString() === pathname,
29
+ });
30
+
31
+ return <Component className={finalClassName} href={href} {...props} />;
32
+ };
33
+
34
+ export default BaseActiveLink;