Skip to content

Commit b6c6b8f

Browse files
committed
Merge remote-tracking branch 'origin' into kien/cnct-1917-docs
2 parents 9bdda90 + 98c5fd0 commit b6c6b8f

File tree

253 files changed

+6082
-5284
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

253 files changed

+6082
-5284
lines changed

.changeset/sixty-seals-tell.md

Lines changed: 0 additions & 57 deletions
This file was deleted.

apps/dashboard/.eslintrc.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = {
6161
"useToast",
6262
"useClipboard",
6363
"Badge",
64+
"Stack",
6465
// also the types
6566
"ButtonProps",
6667
"BadgeProps",
@@ -73,6 +74,7 @@ module.exports = {
7374
"MenuItemProps",
7475
"AspectRatioProps",
7576
"BadgeProps",
77+
"StackProps",
7678
],
7779
message:
7880
'Use the equivalent component from "tw-components" instead.',

apps/dashboard/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@
110110
"@next/eslint-plugin-next": "14.2.13",
111111
"@playwright/test": "1.47.2",
112112
"@storybook/addon-essentials": "8.3.2",
113-
"@storybook/addon-interactions": "8.3.2",
113+
"@storybook/addon-interactions": "8.3.4",
114114
"@storybook/addon-links": "8.3.2",
115115
"@storybook/addon-onboarding": "8.3.2",
116116
"@storybook/addon-viewport": "8.3.2",
117-
"@storybook/blocks": "8.3.2",
117+
"@storybook/blocks": "8.3.4",
118118
"@storybook/nextjs": "8.3.2",
119-
"@storybook/react": "8.3.2",
119+
"@storybook/react": "8.3.4",
120120
"@storybook/test": "8.3.2",
121121
"@types/color": "^3.0.6",
122122
"@types/node": "20.14.9",
@@ -135,7 +135,7 @@
135135
"eslint": "8.57.0",
136136
"eslint-config-biome": "1.8.4",
137137
"eslint-plugin-react-compiler": "0.0.0-experimental-ca16900-20240916",
138-
"eslint-plugin-storybook": "^0.8.0",
138+
"eslint-plugin-storybook": "^0.9.0",
139139
"knip": "^5.30.5",
140140
"next-sitemap": "^4.2.3",
141141
"postcss": "8.4.47",

apps/dashboard/src/@/components/blocks/MobileSidebar.tsx

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,45 @@ import { Button } from "@/components/ui/button";
44
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog";
55
import { ChevronDownIcon } from "lucide-react";
66
import { usePathname } from "next/navigation";
7-
import { useState } from "react";
7+
import { useMemo, useState } from "react";
88
import { cn } from "../../lib/utils";
9-
import { NavLink } from "../ui/NavLink";
10-
import type { SidebarLink } from "./Sidebar";
9+
import {
10+
RenderSidebarLinks,
11+
type SidebarBaseLink,
12+
type SidebarLink,
13+
} from "./Sidebar";
1114

1215
export function MobileSidebar(props: {
13-
links?: SidebarLink[];
16+
links: SidebarLink[];
1417
footer?: React.ReactNode;
1518
trigger?: React.ReactNode;
1619
triggerClassName?: string;
1720
}) {
1821
const [isOpen, setIsOpen] = useState(false);
1922
const pathname = usePathname();
20-
const activeLink = props.links?.find((link) => {
21-
if (link.exactMatch) {
22-
return link.href === pathname;
23+
24+
const activeLink = useMemo(() => {
25+
function isActive(link: SidebarBaseLink) {
26+
if (link.exactMatch) {
27+
return link.href === pathname;
28+
}
29+
return pathname?.startsWith(link.href);
30+
}
31+
32+
for (const link of props.links) {
33+
if ("group" in link) {
34+
for (const subLink of link.links) {
35+
if (isActive(subLink)) {
36+
return subLink;
37+
}
38+
}
39+
} else {
40+
if (isActive(link)) {
41+
return link;
42+
}
43+
}
2344
}
24-
return pathname?.startsWith(link.href);
25-
});
45+
}, [props.links, pathname]);
2646

2747
const defaultTrigger = (
2848
<Button
@@ -41,31 +61,15 @@ export function MobileSidebar(props: {
4161
<Dialog open={isOpen} onOpenChange={setIsOpen}>
4262
<DialogTrigger asChild>{props.trigger || defaultTrigger}</DialogTrigger>
4363
<DialogContent
44-
className="rounded-t-xl rounded-b-none p-4"
64+
className="no-scrollbar max-h-[80vh] overflow-auto rounded-t-xl rounded-b-none p-4"
4565
dialogCloseClassName="hidden"
4666
onClick={(e) => {
4767
if (e.target instanceof HTMLAnchorElement) {
4868
setIsOpen(false);
4969
}
5070
}}
5171
>
52-
<div className="flex flex-col gap-2">
53-
{props.links?.map((link) => {
54-
return (
55-
<Button size="sm" variant="ghost" asChild key={link.href}>
56-
<NavLink
57-
href={link.href}
58-
className="!text-left flex h-auto justify-start gap-2 py-3"
59-
activeClassName="bg-accent"
60-
exactMatch={link.exactMatch}
61-
tracking={link.tracking}
62-
>
63-
{link.label}
64-
</NavLink>
65-
</Button>
66-
);
67-
})}
68-
</div>
72+
<RenderSidebarLinks links={props.links} />
6973
{props.footer}
7074
</DialogContent>
7175
</Dialog>

apps/dashboard/src/@/components/blocks/Sidebar.tsx

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type React from "react";
33
import { cn } from "../../lib/utils";
44
import { NavLink } from "../ui/NavLink";
55

6-
export type SidebarLink = {
6+
export type SidebarBaseLink = {
77
href: string;
88
label: React.ReactNode;
99
exactMatch?: boolean;
@@ -14,6 +14,13 @@ export type SidebarLink = {
1414
};
1515
};
1616

17+
export type SidebarLink =
18+
| SidebarBaseLink
19+
| {
20+
group: string;
21+
links: SidebarBaseLink[];
22+
};
23+
1724
type SidebarContentProps = {
1825
header?: React.ReactNode;
1926
links: SidebarLink[];
@@ -31,23 +38,42 @@ export function Sidebar(props: SidebarContentProps) {
3138
<div className="pt-7">
3239
{props.header}
3340
<div className="flex flex-col gap-1">
34-
{props.links?.map((link) => {
35-
const isExternal = link.href.startsWith("http");
36-
return (
37-
<NavLink
38-
key={link.href}
39-
href={link.href}
40-
className="flex items-center gap-2 rounded-md px-3 py-2 text-muted-foreground text-sm hover:bg-muted"
41-
activeClassName="text-foreground"
42-
exactMatch={link.exactMatch}
43-
>
44-
{link.label}
45-
{isExternal && <ExternalLinkIcon className="size-3" />}
46-
</NavLink>
47-
);
48-
})}
41+
<RenderSidebarLinks links={props.links} />
4942
</div>
5043
</div>
5144
</aside>
5245
);
5346
}
47+
48+
export function RenderSidebarLinks(props: { links: SidebarLink[] }) {
49+
return (
50+
<div className="flex flex-col gap-1">
51+
{props.links.map((link, i) => {
52+
if ("group" in link) {
53+
return (
54+
<div className={cn({ "mt-6": i !== 0 })}>
55+
<p className={cn("px-3 py-2 font-medium text-foreground")}>
56+
{link.group}
57+
</p>
58+
<RenderSidebarLinks links={link.links} />
59+
</div>
60+
);
61+
}
62+
63+
const isExternal = link.href.startsWith("http");
64+
return (
65+
<NavLink
66+
key={link.href}
67+
href={link.href}
68+
className="flex items-center gap-2 rounded-md px-3 py-2 text-muted-foreground text-sm hover:bg-muted"
69+
activeClassName="text-foreground"
70+
exactMatch={link.exactMatch}
71+
>
72+
{link.label}
73+
{isExternal && <ExternalLinkIcon className="size-3" />}
74+
</NavLink>
75+
);
76+
})}
77+
</div>
78+
);
79+
}

0 commit comments

Comments
 (0)