@node-core/ui-components 1.0.1-345c7d19144bec7138956e6ae7f5b20cfa2e2450 → 1.0.1-7186d72cbe98d60c61b8f90ba2f738b0efed36ef
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.
- package/Common/AvatarGroup/index.module.css +4 -8
- package/Common/AvatarGroup/index.tsx +1 -5
- package/Common/DataTag/index.module.css +56 -0
- package/Common/DataTag/index.stories.tsx +40 -0
- package/Common/DataTag/index.tsx +39 -0
- package/Containers/DocSideBar/index.tsx +0 -0
- package/{Common/ProgressionSidebar/ProgressionSidebarIcon → Containers/Sidebar/ProgressionIcon}/index.tsx +2 -2
- package/Containers/Sidebar/SidebarGroup/index.module.css +54 -16
- package/Containers/Sidebar/SidebarGroup/index.tsx +21 -2
- package/Containers/Sidebar/SidebarItem/index.module.css +39 -18
- package/Containers/Sidebar/SidebarItem/index.tsx +25 -8
- package/Containers/Sidebar/index.module.css +5 -6
- package/Containers/Sidebar/index.stories.tsx +78 -74
- package/Containers/Sidebar/index.tsx +14 -5
- package/package.json +19 -22
- package/Common/ProgressionSidebar/ProgressionSidebarGroup/index.module.css +0 -47
- package/Common/ProgressionSidebar/ProgressionSidebarGroup/index.tsx +0 -35
- package/Common/ProgressionSidebar/ProgressionSidebarItem/index.module.css +0 -39
- package/Common/ProgressionSidebar/ProgressionSidebarItem/index.tsx +0 -32
- package/Common/ProgressionSidebar/index.module.css +0 -30
- package/Common/ProgressionSidebar/index.stories.tsx +0 -79
- package/Common/ProgressionSidebar/index.tsx +0 -59
|
@@ -4,22 +4,18 @@
|
|
|
4
4
|
@apply flex
|
|
5
5
|
flex-wrap
|
|
6
6
|
items-center;
|
|
7
|
-
|
|
8
|
-
&:not(.expandable) {
|
|
9
|
-
> span {
|
|
10
|
-
@apply ml-0;
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
7
|
}
|
|
14
8
|
|
|
15
9
|
.small {
|
|
16
10
|
> span {
|
|
17
|
-
@apply -ml-2
|
|
11
|
+
@apply -ml-2
|
|
12
|
+
first:ml-0;
|
|
18
13
|
}
|
|
19
14
|
}
|
|
20
15
|
|
|
21
16
|
.medium {
|
|
22
17
|
> span {
|
|
23
|
-
@apply -ml-2.5
|
|
18
|
+
@apply -ml-2.5
|
|
19
|
+
first:ml-0;
|
|
24
20
|
}
|
|
25
21
|
}
|
|
@@ -42,11 +42,7 @@ const AvatarGroup: FC<AvatarGroupProps> = ({
|
|
|
42
42
|
: undefined;
|
|
43
43
|
|
|
44
44
|
return (
|
|
45
|
-
<div
|
|
46
|
-
className={classNames(styles.avatarGroup, styles[size], {
|
|
47
|
-
[styles.expandable]: avatars.length > limit,
|
|
48
|
-
})}
|
|
49
|
-
>
|
|
45
|
+
<div className={classNames(styles.avatarGroup, styles[size])}>
|
|
50
46
|
{renderAvatars.map(avatar => (
|
|
51
47
|
<Tooltip
|
|
52
48
|
key={avatar.nickname}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
@reference "../../styles/index.css";
|
|
2
|
+
|
|
3
|
+
.dataTag {
|
|
4
|
+
@apply flex
|
|
5
|
+
items-center
|
|
6
|
+
justify-center
|
|
7
|
+
rounded-full
|
|
8
|
+
font-semibold
|
|
9
|
+
text-white;
|
|
10
|
+
|
|
11
|
+
&.lg {
|
|
12
|
+
@apply size-12
|
|
13
|
+
text-2xl;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.md {
|
|
17
|
+
@apply size-10
|
|
18
|
+
text-xl;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&.sm {
|
|
22
|
+
@apply size-8;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
&.event {
|
|
26
|
+
@apply bg-accent1-600;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
&.method {
|
|
30
|
+
@apply bg-info-600;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&.property {
|
|
34
|
+
@apply bg-green-600;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
&.class {
|
|
38
|
+
@apply bg-warning-600;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
&.module {
|
|
42
|
+
@apply bg-red-600;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
&.classMethod {
|
|
46
|
+
@apply bg-blue-600;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
&.ctor {
|
|
50
|
+
@apply bg-accent2-600;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&.global {
|
|
54
|
+
@apply bg-amber-600;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import DataTag, { type DataTagProps } from '#ui/Common/DataTag';
|
|
4
|
+
|
|
5
|
+
type Story = StoryObj<typeof DataTag>;
|
|
6
|
+
type Meta = MetaObj<typeof DataTag>;
|
|
7
|
+
|
|
8
|
+
export const DataTags: Story = {
|
|
9
|
+
render: () => (
|
|
10
|
+
<div className="grid grid-cols-3 gap-6 p-6">
|
|
11
|
+
{[
|
|
12
|
+
'event',
|
|
13
|
+
'method',
|
|
14
|
+
'property',
|
|
15
|
+
'class',
|
|
16
|
+
'module',
|
|
17
|
+
'classMethod',
|
|
18
|
+
'ctor',
|
|
19
|
+
'global',
|
|
20
|
+
]
|
|
21
|
+
.map(kind =>
|
|
22
|
+
['sm', 'md', 'lg'].map(size => (
|
|
23
|
+
<div
|
|
24
|
+
key={`${kind}-${size}`}
|
|
25
|
+
className="flex justify-center"
|
|
26
|
+
title={kind}
|
|
27
|
+
>
|
|
28
|
+
<DataTag
|
|
29
|
+
kind={kind as DataTagProps['kind']}
|
|
30
|
+
size={size as DataTagProps['size']}
|
|
31
|
+
/>
|
|
32
|
+
</div>
|
|
33
|
+
))
|
|
34
|
+
)
|
|
35
|
+
.flat()}
|
|
36
|
+
</div>
|
|
37
|
+
),
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export default { component: DataTag } as Meta;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import type { FC } from 'react';
|
|
3
|
+
|
|
4
|
+
import styles from './index.module.css';
|
|
5
|
+
|
|
6
|
+
export type DataTagProps = {
|
|
7
|
+
kind:
|
|
8
|
+
| 'event'
|
|
9
|
+
| 'method'
|
|
10
|
+
| 'property'
|
|
11
|
+
| 'class'
|
|
12
|
+
| 'module'
|
|
13
|
+
| 'classMethod'
|
|
14
|
+
| 'global'
|
|
15
|
+
| 'ctor';
|
|
16
|
+
size?: 'lg' | 'md' | 'sm';
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// These symbols match up with the types used in
|
|
20
|
+
// node core, and the ones defined at
|
|
21
|
+
// https://github.com/nodejs/api-docs-tooling/blob/main/src/types.d.ts#L22 (`HeadingMetadataEntry['type']`)
|
|
22
|
+
const symbolMap = {
|
|
23
|
+
event: 'E',
|
|
24
|
+
method: 'M',
|
|
25
|
+
property: 'P',
|
|
26
|
+
class: 'C',
|
|
27
|
+
module: 'M',
|
|
28
|
+
classMethod: 'S',
|
|
29
|
+
global: 'G',
|
|
30
|
+
ctor: 'C',
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
const DataTag: FC<DataTagProps> = ({ kind, size = 'md' }) => (
|
|
34
|
+
<div className={classNames(styles.dataTag, styles[size], styles[kind])}>
|
|
35
|
+
<span>{symbolMap[kind]}</span>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
export default DataTag;
|
|
File without changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { FC, SVGAttributes } from 'react';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const ProgressionIcon: FC<SVGAttributes<SVGSVGElement>> = props => (
|
|
4
4
|
<svg
|
|
5
5
|
xmlns="http://www.w3.org/2000/svg"
|
|
6
6
|
width="16"
|
|
@@ -13,4 +13,4 @@ const ProgressionSidebarIcon: FC<SVGAttributes<SVGSVGElement>> = props => (
|
|
|
13
13
|
</svg>
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
-
export default
|
|
16
|
+
export default ProgressionIcon;
|
|
@@ -5,22 +5,60 @@
|
|
|
5
5
|
w-full
|
|
6
6
|
flex-col
|
|
7
7
|
gap-2;
|
|
8
|
-
}
|
|
9
8
|
|
|
10
|
-
.
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
&:not(.progression) {
|
|
10
|
+
.groupName {
|
|
11
|
+
@apply px-2
|
|
12
|
+
py-1
|
|
13
|
+
text-xs
|
|
14
|
+
font-semibold
|
|
15
|
+
text-neutral-800
|
|
16
|
+
dark:text-neutral-600;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
&.progression {
|
|
21
|
+
@apply flex
|
|
22
|
+
flex-col
|
|
23
|
+
gap-4
|
|
24
|
+
text-sm
|
|
25
|
+
font-medium
|
|
26
|
+
text-neutral-800
|
|
27
|
+
dark:text-neutral-200;
|
|
28
|
+
|
|
29
|
+
.itemList {
|
|
30
|
+
@apply relative
|
|
31
|
+
-left-1
|
|
32
|
+
flex
|
|
33
|
+
flex-col
|
|
34
|
+
after:absolute
|
|
35
|
+
after:left-[0.45rem]
|
|
36
|
+
after:top-0
|
|
37
|
+
after:z-10
|
|
38
|
+
after:h-full
|
|
39
|
+
after:w-px
|
|
40
|
+
after:bg-neutral-200
|
|
41
|
+
after:content-['']
|
|
42
|
+
dark:after:bg-neutral-800;
|
|
43
|
+
|
|
44
|
+
a {
|
|
45
|
+
@apply first:before:absolute
|
|
46
|
+
first:before:bottom-[calc(50%+0.25rem)]
|
|
47
|
+
first:before:left-0
|
|
48
|
+
first:before:h-20
|
|
49
|
+
first:before:w-4
|
|
50
|
+
first:before:bg-white
|
|
51
|
+
first:before:content-['']
|
|
52
|
+
last:after:absolute
|
|
53
|
+
last:after:left-0
|
|
54
|
+
last:after:top-[calc(50%+0.25rem)]
|
|
55
|
+
last:after:h-20
|
|
56
|
+
last:after:w-4
|
|
57
|
+
last:after:bg-white
|
|
58
|
+
last:after:content-['']
|
|
59
|
+
first:dark:before:bg-neutral-950
|
|
60
|
+
last:dark:after:bg-neutral-950;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
26
64
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
1
2
|
import type { ComponentProps, FC } from 'react';
|
|
2
3
|
|
|
3
4
|
import SidebarItem from '#ui/Containers/Sidebar/SidebarItem';
|
|
@@ -10,18 +11,36 @@ type SidebarGroupProps = {
|
|
|
10
11
|
items: Array<Omit<ComponentProps<typeof SidebarItem>, 'as' | 'pathname'>>;
|
|
11
12
|
as?: LinkLike;
|
|
12
13
|
pathname?: string;
|
|
14
|
+
className: string;
|
|
15
|
+
showProgressionIcons?: boolean;
|
|
13
16
|
};
|
|
14
17
|
|
|
15
18
|
const SidebarGroup: FC<SidebarGroupProps> = ({
|
|
16
19
|
groupName,
|
|
17
20
|
items,
|
|
21
|
+
showProgressionIcons,
|
|
22
|
+
className,
|
|
18
23
|
...props
|
|
19
24
|
}) => (
|
|
20
|
-
<section
|
|
25
|
+
<section
|
|
26
|
+
className={classNames(
|
|
27
|
+
{
|
|
28
|
+
[styles.group]: true,
|
|
29
|
+
[styles.progression]: showProgressionIcons,
|
|
30
|
+
},
|
|
31
|
+
className
|
|
32
|
+
)}
|
|
33
|
+
>
|
|
21
34
|
<label className={styles.groupName}>{groupName}</label>
|
|
22
35
|
<ul className={styles.itemList}>
|
|
23
36
|
{items.map(({ label, link }) => (
|
|
24
|
-
<SidebarItem
|
|
37
|
+
<SidebarItem
|
|
38
|
+
key={link}
|
|
39
|
+
label={label}
|
|
40
|
+
link={link}
|
|
41
|
+
showProgressionIcons={showProgressionIcons}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
25
44
|
))}
|
|
26
45
|
</ul>
|
|
27
46
|
</section>
|
|
@@ -1,35 +1,56 @@
|
|
|
1
|
-
@reference
|
|
1
|
+
@reference '../../../styles/index.css';
|
|
2
2
|
|
|
3
|
-
.
|
|
4
|
-
@apply
|
|
3
|
+
.item {
|
|
4
|
+
@apply font-regular
|
|
5
|
+
relative
|
|
6
|
+
z-20
|
|
7
|
+
flex
|
|
5
8
|
w-full
|
|
6
|
-
|
|
9
|
+
items-center
|
|
10
|
+
overflow-hidden
|
|
11
|
+
text-sm
|
|
7
12
|
text-neutral-800
|
|
8
13
|
dark:text-neutral-200;
|
|
9
14
|
|
|
10
|
-
a {
|
|
11
|
-
@apply inline-flex
|
|
12
|
-
items-center
|
|
13
|
-
gap-2
|
|
14
|
-
p-2;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
15
|
.label {
|
|
18
16
|
@apply font-regular
|
|
19
|
-
|
|
17
|
+
p-2
|
|
20
18
|
text-sm;
|
|
21
19
|
}
|
|
22
20
|
|
|
21
|
+
.progressionIcon {
|
|
22
|
+
@apply shrink-0
|
|
23
|
+
fill-neutral-200
|
|
24
|
+
stroke-white
|
|
25
|
+
stroke-[4]
|
|
26
|
+
dark:fill-neutral-800
|
|
27
|
+
dark:stroke-neutral-950;
|
|
28
|
+
}
|
|
29
|
+
|
|
23
30
|
.icon {
|
|
24
31
|
@apply size-3
|
|
25
32
|
text-neutral-500
|
|
26
33
|
dark:text-neutral-200;
|
|
27
34
|
}
|
|
28
|
-
}
|
|
29
35
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
&.progression {
|
|
37
|
+
.label {
|
|
38
|
+
@apply p-1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&.active {
|
|
43
|
+
@apply text-neutral-900
|
|
44
|
+
dark:text-white;
|
|
45
|
+
|
|
46
|
+
.progressionIcon {
|
|
47
|
+
@apply fill-green-500;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&:not(.progression) .label {
|
|
51
|
+
@apply rounded-sm
|
|
52
|
+
bg-green-600
|
|
53
|
+
text-white;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
35
56
|
}
|
|
@@ -1,26 +1,43 @@
|
|
|
1
1
|
import { ArrowUpRightIcon } from '@heroicons/react/24/solid';
|
|
2
|
+
import classNames from 'classnames';
|
|
2
3
|
import type { FC } from 'react';
|
|
3
4
|
|
|
4
|
-
import
|
|
5
|
+
import BaseActiveLink from '#ui/Common/BaseActiveLink';
|
|
5
6
|
import type { FormattedMessage, LinkLike } from '#ui/types';
|
|
6
7
|
|
|
7
8
|
import styles from './index.module.css';
|
|
9
|
+
import ProgressionIcon from '../ProgressionIcon';
|
|
8
10
|
|
|
9
11
|
type SidebarItemProps = {
|
|
10
12
|
label: FormattedMessage;
|
|
11
13
|
link: string;
|
|
12
14
|
as?: LinkLike;
|
|
13
15
|
pathname?: string;
|
|
16
|
+
showProgressionIcons?: boolean;
|
|
14
17
|
};
|
|
15
18
|
|
|
16
|
-
const SidebarItem: FC<SidebarItemProps> = ({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
const SidebarItem: FC<SidebarItemProps> = ({
|
|
20
|
+
label,
|
|
21
|
+
link,
|
|
22
|
+
showProgressionIcons = false,
|
|
23
|
+
...props
|
|
24
|
+
}) => (
|
|
25
|
+
<BaseActiveLink
|
|
26
|
+
className={classNames({
|
|
27
|
+
[styles.item]: true,
|
|
28
|
+
[styles.progression]: showProgressionIcons,
|
|
29
|
+
})}
|
|
30
|
+
href={link}
|
|
31
|
+
activeClassName={styles.active}
|
|
32
|
+
{...props}
|
|
33
|
+
>
|
|
34
|
+
{showProgressionIcons && (
|
|
35
|
+
<ProgressionIcon className={styles.progressionIcon} />
|
|
36
|
+
)}
|
|
37
|
+
<span className={styles.label}>{label}</span>
|
|
20
38
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
</li>
|
|
39
|
+
{link.startsWith('http') && <ArrowUpRightIcon className={styles.icon} />}
|
|
40
|
+
</BaseActiveLink>
|
|
24
41
|
);
|
|
25
42
|
|
|
26
43
|
export default SidebarItem;
|
|
@@ -4,26 +4,25 @@
|
|
|
4
4
|
@apply flex
|
|
5
5
|
w-full
|
|
6
6
|
flex-col
|
|
7
|
-
items-start
|
|
8
7
|
gap-8
|
|
9
8
|
overflow-auto
|
|
10
|
-
|
|
11
|
-
border-
|
|
9
|
+
border-r-0
|
|
10
|
+
border-neutral-200
|
|
12
11
|
bg-white
|
|
13
12
|
px-4
|
|
14
13
|
py-6
|
|
15
14
|
sm:border-r
|
|
16
15
|
md:max-w-xs
|
|
17
16
|
lg:px-6
|
|
18
|
-
dark:border-
|
|
17
|
+
dark:border-neutral-900
|
|
19
18
|
dark:bg-neutral-950;
|
|
20
19
|
|
|
21
|
-
|
|
20
|
+
.navigation {
|
|
22
21
|
@apply hidden
|
|
23
22
|
sm:flex;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
.mobileSelect {
|
|
27
26
|
@apply flex
|
|
28
27
|
w-full
|
|
29
28
|
sm:hidden;
|
|
@@ -5,80 +5,84 @@ import Sidebar from '#ui/Containers/Sidebar';
|
|
|
5
5
|
type Story = StoryObj<typeof Sidebar>;
|
|
6
6
|
type Meta = MetaObj<typeof Sidebar>;
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
8
|
+
const args = {
|
|
9
|
+
groups: [
|
|
10
|
+
{
|
|
11
|
+
groupName: 'About Node.js',
|
|
12
|
+
items: [
|
|
13
|
+
{
|
|
14
|
+
link: '/item1',
|
|
15
|
+
label: 'About Node.js',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
link: '/item2',
|
|
19
|
+
label: 'Project Governance',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
link: '/item3',
|
|
23
|
+
label: 'Releases',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
link: '/item4',
|
|
27
|
+
label: 'Branding',
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
link: '/item5',
|
|
31
|
+
label: 'Privacy Policy',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
link: '/item6',
|
|
35
|
+
label: 'Security Reporting',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
groupName: 'Get Involved',
|
|
41
|
+
items: [
|
|
42
|
+
{
|
|
43
|
+
link: '/item7',
|
|
44
|
+
label: 'Get Involved',
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
link: '/item8',
|
|
48
|
+
label: 'Collab Summit',
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
link: '/item9',
|
|
52
|
+
label: 'Contribute',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
link: '/item10',
|
|
56
|
+
label: 'Code of Conduct',
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
groupName: 'Download',
|
|
62
|
+
items: [
|
|
63
|
+
{
|
|
64
|
+
link: '/item11',
|
|
65
|
+
label: 'Download',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
link: '/item12',
|
|
69
|
+
label: 'Package Manager',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
link: '/item13',
|
|
73
|
+
label: 'Node.js Releases',
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
title: 'Sidebar',
|
|
79
|
+
onSelect: console.log,
|
|
80
|
+
pathname: '/item1',
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const Default: Story = { args };
|
|
84
|
+
export const Progression: Story = {
|
|
85
|
+
args: { ...args, showProgressionIcons: true },
|
|
82
86
|
};
|
|
83
87
|
|
|
84
88
|
export default { component: Sidebar } as Meta;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentProps, FC } from 'react';
|
|
1
|
+
import type { ComponentProps, FC, PropsWithChildren } from 'react';
|
|
2
2
|
|
|
3
3
|
import Select from '#ui/Common/Select';
|
|
4
4
|
import SidebarGroup from '#ui/Containers/Sidebar/SidebarGroup';
|
|
@@ -7,19 +7,24 @@ import type { LinkLike } from '#ui/types';
|
|
|
7
7
|
import styles from './index.module.css';
|
|
8
8
|
|
|
9
9
|
type SidebarProps = {
|
|
10
|
-
groups: Array<
|
|
10
|
+
groups: Array<
|
|
11
|
+
Pick<ComponentProps<typeof SidebarGroup>, 'items' | 'groupName'>
|
|
12
|
+
>;
|
|
11
13
|
pathname?: string;
|
|
12
14
|
title: string;
|
|
13
15
|
onSelect: (value: string) => void;
|
|
14
16
|
as?: LinkLike;
|
|
17
|
+
showProgressionIcons?: boolean;
|
|
15
18
|
};
|
|
16
19
|
|
|
17
|
-
const SideBar: FC<SidebarProps
|
|
20
|
+
const SideBar: FC<PropsWithChildren<SidebarProps>> = ({
|
|
18
21
|
groups,
|
|
19
22
|
pathname,
|
|
20
23
|
title,
|
|
21
24
|
onSelect,
|
|
22
25
|
as,
|
|
26
|
+
showProgressionIcons = false,
|
|
27
|
+
children,
|
|
23
28
|
}) => {
|
|
24
29
|
const selectItems = groups.map(({ items, groupName }) => ({
|
|
25
30
|
label: groupName,
|
|
@@ -27,18 +32,20 @@ const SideBar: FC<SidebarProps> = ({
|
|
|
27
32
|
}));
|
|
28
33
|
|
|
29
34
|
const currentItem = selectItems
|
|
30
|
-
.
|
|
31
|
-
.flat()
|
|
35
|
+
.flatMap(item => item.items)
|
|
32
36
|
.find(item => pathname === item.value);
|
|
33
37
|
|
|
34
38
|
return (
|
|
35
39
|
<aside className={styles.wrapper}>
|
|
40
|
+
{children}
|
|
41
|
+
|
|
36
42
|
{selectItems.length > 0 && (
|
|
37
43
|
<Select
|
|
38
44
|
label={title}
|
|
39
45
|
values={selectItems}
|
|
40
46
|
defaultValue={currentItem?.value}
|
|
41
47
|
onChange={onSelect}
|
|
48
|
+
className={styles.mobileSelect}
|
|
42
49
|
/>
|
|
43
50
|
)}
|
|
44
51
|
|
|
@@ -49,6 +56,8 @@ const SideBar: FC<SidebarProps> = ({
|
|
|
49
56
|
items={items}
|
|
50
57
|
pathname={pathname}
|
|
51
58
|
as={as}
|
|
59
|
+
showProgressionIcons={showProgressionIcons}
|
|
60
|
+
className={styles.navigation}
|
|
52
61
|
/>
|
|
53
62
|
))}
|
|
54
63
|
</aside>
|
package/package.json
CHANGED
|
@@ -21,49 +21,46 @@
|
|
|
21
21
|
],
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@heroicons/react": "^2.2.0",
|
|
24
|
-
"@radix-ui/react-avatar": "^1.1.
|
|
25
|
-
"@radix-ui/react-dialog": "^1.1.
|
|
26
|
-
"@radix-ui/react-dropdown-menu": "~2.1.
|
|
27
|
-
"@radix-ui/react-label": "~2.1.
|
|
28
|
-
"@radix-ui/react-select": "~2.2.
|
|
29
|
-
"@radix-ui/react-separator": "~1.1.
|
|
30
|
-
"@radix-ui/react-tabs": "~1.1.
|
|
31
|
-
"@radix-ui/react-toast": "~1.2.
|
|
32
|
-
"@radix-ui/react-tooltip": "~1.2.
|
|
33
|
-
"@tailwindcss/postcss": "~4.1.
|
|
24
|
+
"@radix-ui/react-avatar": "^1.1.10",
|
|
25
|
+
"@radix-ui/react-dialog": "^1.1.14",
|
|
26
|
+
"@radix-ui/react-dropdown-menu": "~2.1.15",
|
|
27
|
+
"@radix-ui/react-label": "~2.1.7",
|
|
28
|
+
"@radix-ui/react-select": "~2.2.5",
|
|
29
|
+
"@radix-ui/react-separator": "~1.1.7",
|
|
30
|
+
"@radix-ui/react-tabs": "~1.1.12",
|
|
31
|
+
"@radix-ui/react-toast": "~1.2.14",
|
|
32
|
+
"@radix-ui/react-tooltip": "~1.2.7",
|
|
33
|
+
"@tailwindcss/postcss": "~4.1.8",
|
|
34
34
|
"@vcarl/remark-headings": "~0.1.0",
|
|
35
35
|
"classnames": "~2.5.1",
|
|
36
36
|
"postcss-calc": "^10.1.1",
|
|
37
37
|
"tailwindcss": "~4.0.17"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@storybook/addon-
|
|
41
|
-
"@storybook/addon-interactions": "^8.6.12",
|
|
40
|
+
"@storybook/addon-themes": "^9.0.3",
|
|
42
41
|
"@storybook/addon-styling-webpack": "^1.0.1",
|
|
43
|
-
"@storybook/addon-themes": "^8.6.12",
|
|
44
|
-
"@storybook/addon-viewport": "^8.6.12",
|
|
45
42
|
"@storybook/addon-webpack5-compiler-swc": "^3.0.0",
|
|
46
|
-
"@storybook/react": "^
|
|
47
|
-
"@storybook/react-webpack5": "^
|
|
43
|
+
"@storybook/react": "^9.0.3",
|
|
44
|
+
"@storybook/react-webpack5": "^9.0.3",
|
|
48
45
|
"@testing-library/user-event": "~14.6.1",
|
|
49
46
|
"@types/node": "22.15.3",
|
|
50
|
-
"@types/react": "^19.1.
|
|
47
|
+
"@types/react": "^19.1.6",
|
|
51
48
|
"cross-env": "^7.0.3",
|
|
52
49
|
"css-loader": "~7.1.2",
|
|
53
50
|
"eslint-plugin-react": "~7.37.4",
|
|
54
|
-
"eslint-plugin-storybook": "~0.
|
|
51
|
+
"eslint-plugin-storybook": "~9.0.3",
|
|
55
52
|
"global-jsdom": "^26.0.0",
|
|
56
53
|
"postcss-loader": "~8.1.1",
|
|
57
54
|
"react": "^19.1.0",
|
|
58
|
-
"storybook": "^
|
|
55
|
+
"storybook": "^9.0.3",
|
|
59
56
|
"style-loader": "~4.0.0",
|
|
60
|
-
"stylelint": "^16.
|
|
57
|
+
"stylelint": "^16.20.0",
|
|
61
58
|
"stylelint-config-standard": "^38.0.0",
|
|
62
59
|
"stylelint-order": "7.0.0",
|
|
63
60
|
"stylelint-selector-bem-pattern": "4.0.1",
|
|
64
61
|
"tsx": "^4.19.3",
|
|
65
62
|
"typescript": "~5.8.2",
|
|
66
|
-
"typescript-eslint": "~8.
|
|
63
|
+
"typescript-eslint": "~8.33.1"
|
|
67
64
|
},
|
|
68
65
|
"imports": {
|
|
69
66
|
"#ui/*": [
|
|
@@ -77,7 +74,7 @@
|
|
|
77
74
|
"engines": {
|
|
78
75
|
"node": ">=20"
|
|
79
76
|
},
|
|
80
|
-
"version": "1.0.1-
|
|
77
|
+
"version": "1.0.1-7186d72cbe98d60c61b8f90ba2f738b0efed36ef",
|
|
81
78
|
"scripts": {
|
|
82
79
|
"check-types": "tsc --noEmit",
|
|
83
80
|
"lint": "turbo run lint:js lint:css",
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
@reference "../../../styles/index.css";
|
|
2
|
-
|
|
3
|
-
.group {
|
|
4
|
-
@apply flex
|
|
5
|
-
flex-col
|
|
6
|
-
gap-4
|
|
7
|
-
text-sm
|
|
8
|
-
font-medium
|
|
9
|
-
text-neutral-800
|
|
10
|
-
dark:text-neutral-200;
|
|
11
|
-
|
|
12
|
-
.items {
|
|
13
|
-
@apply relative
|
|
14
|
-
-left-1
|
|
15
|
-
flex
|
|
16
|
-
flex-col
|
|
17
|
-
gap-2
|
|
18
|
-
after:absolute
|
|
19
|
-
after:left-[0.45rem]
|
|
20
|
-
after:top-0
|
|
21
|
-
after:z-10
|
|
22
|
-
after:h-full
|
|
23
|
-
after:w-px
|
|
24
|
-
after:bg-neutral-200
|
|
25
|
-
after:content-['']
|
|
26
|
-
dark:after:bg-neutral-800;
|
|
27
|
-
|
|
28
|
-
a {
|
|
29
|
-
@apply first:before:absolute
|
|
30
|
-
first:before:bottom-[calc(50%+0.25rem)]
|
|
31
|
-
first:before:left-0
|
|
32
|
-
first:before:h-20
|
|
33
|
-
first:before:w-4
|
|
34
|
-
first:before:bg-white
|
|
35
|
-
first:before:content-['']
|
|
36
|
-
last:after:absolute
|
|
37
|
-
last:after:left-0
|
|
38
|
-
last:after:top-[calc(50%+0.25rem)]
|
|
39
|
-
last:after:h-20
|
|
40
|
-
last:after:w-4
|
|
41
|
-
last:after:bg-white
|
|
42
|
-
last:after:content-['']
|
|
43
|
-
first:dark:before:bg-neutral-950
|
|
44
|
-
last:dark:after:bg-neutral-950;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { ComponentProps, FC } from 'react';
|
|
2
|
-
|
|
3
|
-
import ProgressionSidebarItem from '#ui/Common/ProgressionSidebar/ProgressionSidebarItem';
|
|
4
|
-
import type { FormattedMessage, LinkLike } from '#ui/types';
|
|
5
|
-
|
|
6
|
-
import styles from './index.module.css';
|
|
7
|
-
|
|
8
|
-
type ProgressionSidebarGroupProps = {
|
|
9
|
-
groupName: FormattedMessage;
|
|
10
|
-
items: Array<ComponentProps<typeof ProgressionSidebarItem>>;
|
|
11
|
-
pathname?: string;
|
|
12
|
-
as?: LinkLike;
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
const ProgressionSidebarGroup: FC<ProgressionSidebarGroupProps> = ({
|
|
16
|
-
groupName,
|
|
17
|
-
items,
|
|
18
|
-
...props
|
|
19
|
-
}) => (
|
|
20
|
-
<section className={styles.group}>
|
|
21
|
-
{groupName}
|
|
22
|
-
<div className={styles.items}>
|
|
23
|
-
{items.map(({ label, link }) => (
|
|
24
|
-
<ProgressionSidebarItem
|
|
25
|
-
key={link}
|
|
26
|
-
label={label}
|
|
27
|
-
link={link}
|
|
28
|
-
{...props}
|
|
29
|
-
/>
|
|
30
|
-
))}
|
|
31
|
-
</div>
|
|
32
|
-
</section>
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
export default ProgressionSidebarGroup;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
@reference "../../../styles/index.css";
|
|
2
|
-
|
|
3
|
-
a.item {
|
|
4
|
-
@apply font-regular
|
|
5
|
-
relative
|
|
6
|
-
z-20
|
|
7
|
-
flex
|
|
8
|
-
w-full
|
|
9
|
-
items-center
|
|
10
|
-
gap-1
|
|
11
|
-
overflow-hidden
|
|
12
|
-
text-sm
|
|
13
|
-
text-neutral-800
|
|
14
|
-
dark:text-neutral-200;
|
|
15
|
-
|
|
16
|
-
&:hover {
|
|
17
|
-
@apply text-neutral-900
|
|
18
|
-
motion-safe:transition-colors
|
|
19
|
-
dark:text-white;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
svg {
|
|
23
|
-
@apply shrink-0
|
|
24
|
-
fill-neutral-200
|
|
25
|
-
stroke-white
|
|
26
|
-
stroke-[4]
|
|
27
|
-
dark:fill-neutral-800
|
|
28
|
-
dark:stroke-neutral-950;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
&.active {
|
|
32
|
-
@apply text-neutral-900
|
|
33
|
-
dark:text-white;
|
|
34
|
-
|
|
35
|
-
svg {
|
|
36
|
-
@apply fill-green-500;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { FC } from 'react';
|
|
2
|
-
|
|
3
|
-
import BaseActiveLink from '#ui/Common/BaseActiveLink';
|
|
4
|
-
import ProgressionSidebarIcon from '#ui/Common/ProgressionSidebar/ProgressionSidebarIcon';
|
|
5
|
-
import type { FormattedMessage, LinkLike } from '#ui/types';
|
|
6
|
-
|
|
7
|
-
import styles from './index.module.css';
|
|
8
|
-
|
|
9
|
-
type ProgressionSidebarItemProps = {
|
|
10
|
-
label: FormattedMessage;
|
|
11
|
-
link: string;
|
|
12
|
-
as?: LinkLike;
|
|
13
|
-
pathname?: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const ProgressionSidebarItem: FC<ProgressionSidebarItemProps> = ({
|
|
17
|
-
label,
|
|
18
|
-
link,
|
|
19
|
-
...props
|
|
20
|
-
}) => (
|
|
21
|
-
<BaseActiveLink
|
|
22
|
-
className={styles.item}
|
|
23
|
-
activeClassName={styles.active}
|
|
24
|
-
href={link}
|
|
25
|
-
{...props}
|
|
26
|
-
>
|
|
27
|
-
<ProgressionSidebarIcon />
|
|
28
|
-
{label}
|
|
29
|
-
</BaseActiveLink>
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
export default ProgressionSidebarItem;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
@reference "../../styles/index.css";
|
|
2
|
-
|
|
3
|
-
.wrapper {
|
|
4
|
-
@apply flex
|
|
5
|
-
w-full
|
|
6
|
-
flex-col
|
|
7
|
-
gap-8
|
|
8
|
-
overflow-auto
|
|
9
|
-
border-r-0
|
|
10
|
-
border-neutral-200
|
|
11
|
-
bg-white
|
|
12
|
-
px-4
|
|
13
|
-
py-6
|
|
14
|
-
sm:border-r
|
|
15
|
-
md:max-w-xs
|
|
16
|
-
lg:px-6
|
|
17
|
-
dark:border-neutral-900
|
|
18
|
-
dark:bg-neutral-950;
|
|
19
|
-
|
|
20
|
-
> section {
|
|
21
|
-
@apply hidden
|
|
22
|
-
sm:flex;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
> span {
|
|
26
|
-
@apply flex
|
|
27
|
-
w-full
|
|
28
|
-
sm:hidden;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
|
|
2
|
-
|
|
3
|
-
import ProgressionSidebar from '#ui/Common/ProgressionSidebar';
|
|
4
|
-
|
|
5
|
-
type Story = StoryObj<typeof ProgressionSidebar>;
|
|
6
|
-
type Meta = MetaObj<typeof ProgressionSidebar>;
|
|
7
|
-
|
|
8
|
-
export const Default: Story = {
|
|
9
|
-
args: {
|
|
10
|
-
groups: [
|
|
11
|
-
{
|
|
12
|
-
groupName: 'Getting Started',
|
|
13
|
-
items: [
|
|
14
|
-
{
|
|
15
|
-
label: 'Introduction to Node.js',
|
|
16
|
-
link: '/',
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
label: 'How to install Node.js',
|
|
20
|
-
link: '/how-to-install-nodejs',
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
label: 'How much JavaScript do you need to know to use Node.js?',
|
|
24
|
-
link: '/how-much-javascript-do-you-need-to-know-to-use-nodejs',
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
label: 'Differences between Node.js and the Browser',
|
|
28
|
-
link: '/differences-between-nodejs-and-the-browser',
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
label: 'The V8 JavaScript Engine',
|
|
32
|
-
link: '/the-v8-javascript-engine',
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
label: 'An introduction to the npm package manager',
|
|
36
|
-
link: '/an-introduction-to-the-npm-package-manager',
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
groupName: 'Asynchronous Work',
|
|
42
|
-
items: [
|
|
43
|
-
{
|
|
44
|
-
label: 'Asynchronous flow control',
|
|
45
|
-
link: '/asynchronous-flow-control',
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
label: 'Overview of Blocking vs Non-Blocking',
|
|
49
|
-
link: '/overview-of-blocking-vs-non-blocking',
|
|
50
|
-
},
|
|
51
|
-
],
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
groupName: 'Manipulating Files',
|
|
55
|
-
items: [
|
|
56
|
-
{
|
|
57
|
-
label: 'Node.js file stats',
|
|
58
|
-
link: '/nodejs-file-stats',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
label: 'Node.js File Paths',
|
|
62
|
-
link: '/nodejs-file-paths',
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
groupName: 'Single item',
|
|
68
|
-
items: [
|
|
69
|
-
{
|
|
70
|
-
label: 'Item',
|
|
71
|
-
link: '/item',
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
},
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
export default { component: ProgressionSidebar } as Meta;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { useRef, type ComponentProps, type FC } from 'react';
|
|
4
|
-
|
|
5
|
-
import ProgressionSidebarGroup from '#ui/Common/ProgressionSidebar/ProgressionSidebarGroup';
|
|
6
|
-
import Select from '#ui/Common/Select';
|
|
7
|
-
import type { LinkLike } from '#ui/types';
|
|
8
|
-
|
|
9
|
-
import styles from './index.module.css';
|
|
10
|
-
|
|
11
|
-
type ProgressionSidebarProps = {
|
|
12
|
-
groups: Array<ComponentProps<typeof ProgressionSidebarGroup>>;
|
|
13
|
-
pathname?: string;
|
|
14
|
-
title: string;
|
|
15
|
-
onSelect: (value: string) => void;
|
|
16
|
-
as?: LinkLike;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const ProgressionSidebar: FC<ProgressionSidebarProps> = ({
|
|
20
|
-
groups,
|
|
21
|
-
pathname,
|
|
22
|
-
title,
|
|
23
|
-
onSelect,
|
|
24
|
-
as,
|
|
25
|
-
}) => {
|
|
26
|
-
const ref = useRef<HTMLElement>(null);
|
|
27
|
-
const selectItems = groups.map(({ items, groupName }) => ({
|
|
28
|
-
label: groupName,
|
|
29
|
-
items: items.map(({ label, link }) => ({ value: link, label })),
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
const currentItem = selectItems
|
|
33
|
-
.map(item => item.items)
|
|
34
|
-
.flat()
|
|
35
|
-
.find(item => pathname === item.value);
|
|
36
|
-
|
|
37
|
-
return (
|
|
38
|
-
<nav className={styles.wrapper} ref={ref}>
|
|
39
|
-
<Select
|
|
40
|
-
label={title}
|
|
41
|
-
onChange={onSelect}
|
|
42
|
-
values={selectItems}
|
|
43
|
-
defaultValue={currentItem?.value}
|
|
44
|
-
/>
|
|
45
|
-
|
|
46
|
-
{groups.map(({ groupName, items }) => (
|
|
47
|
-
<ProgressionSidebarGroup
|
|
48
|
-
key={groupName.toString()}
|
|
49
|
-
groupName={groupName}
|
|
50
|
-
items={items}
|
|
51
|
-
as={as}
|
|
52
|
-
pathname={pathname}
|
|
53
|
-
/>
|
|
54
|
-
))}
|
|
55
|
-
</nav>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default ProgressionSidebar;
|