mirror of
https://github.com/linsa-io/linsa.git
synced 2026-01-12 12:20:23 +01:00
active path sidebar
This commit is contained in:
@@ -3,11 +3,10 @@ import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { useAccount } from "@/lib/providers/jazz-provider"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { LaIcon } from "@/components/custom/la-icon"
|
||||
import { PersonalLinkLists } from "@/lib/schema/personal-link"
|
||||
|
||||
export const LinkSection: React.FC = () => {
|
||||
export const LinkSection: React.FC<{ pathname: string }> = ({ pathname }) => {
|
||||
const { me } = useAccount({
|
||||
root: {
|
||||
personalLinks: []
|
||||
@@ -15,12 +14,13 @@ export const LinkSection: React.FC = () => {
|
||||
})
|
||||
|
||||
const linkCount = me?.root.personalLinks?.length || 0
|
||||
const isActive = pathname === "/"
|
||||
|
||||
if (!me) return null
|
||||
|
||||
return (
|
||||
<div className="group/pages flex flex-col gap-px py-2">
|
||||
<LinkSectionHeader linkCount={linkCount} />
|
||||
<LinkSectionHeader linkCount={linkCount} isActive={isActive} />
|
||||
<List personalLinks={me.root.personalLinks} />
|
||||
</div>
|
||||
)
|
||||
@@ -28,18 +28,22 @@ export const LinkSection: React.FC = () => {
|
||||
|
||||
interface LinkSectionHeaderProps {
|
||||
linkCount: number
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
const LinkSectionHeader: React.FC<LinkSectionHeaderProps> = ({ linkCount }) => (
|
||||
const LinkSectionHeader: React.FC<LinkSectionHeaderProps> = ({ linkCount, isActive }) => (
|
||||
<div
|
||||
className={cn("flex min-h-[30px] items-center gap-px rounded-md", "hover:bg-accent hover:text-accent-foreground")}
|
||||
className={cn(
|
||||
"flex min-h-[30px] items-center gap-px rounded-md",
|
||||
isActive ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground"
|
||||
)}
|
||||
>
|
||||
<Link
|
||||
href="/"
|
||||
className={cn(
|
||||
"size-6 flex-1 items-center justify-start rounded-md px-2 py-1",
|
||||
"focus-visible:outline-none focus-visible:ring-0",
|
||||
"hover:bg-accent hover:text-accent-foreground"
|
||||
isActive ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground"
|
||||
)}
|
||||
>
|
||||
<p className="flex items-center text-xs font-medium">
|
||||
@@ -83,7 +87,6 @@ const ListItem: React.FC<ListItemProps> = ({ label, href, count, isActive }) =>
|
||||
)}
|
||||
>
|
||||
<div className="flex max-w-full flex-1 items-center gap-1.5 truncate text-sm">
|
||||
<LaIcon name="Link" className="flex-shrink-0 opacity-60" />
|
||||
<p className={cn("truncate opacity-95 group-hover/topic-link:opacity-100")}>{label}</p>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
@@ -46,20 +46,32 @@ const SHOWS: Option<ShowOption>[] = [
|
||||
const pageSortAtom = atomWithStorage<SortOption>("pageSort", "title")
|
||||
const pageShowAtom = atomWithStorage<ShowOption>("pageShow", 5)
|
||||
|
||||
export const PageSection: React.FC = () => {
|
||||
const { me } = useAccount({ root: { personalPages: [] } })
|
||||
export const PageSection: React.FC<{ pathname?: string }> = ({ pathname }) => {
|
||||
const { me } = useAccount({
|
||||
root: {
|
||||
personalPages: []
|
||||
}
|
||||
})
|
||||
|
||||
const [sort, setSort] = useAtom(pageSortAtom)
|
||||
const [show, setShow] = useAtom(pageShowAtom)
|
||||
|
||||
const pageCount = me?.root.personalPages?.length || 0
|
||||
const isActive = pathname ? pathname.startsWith("/pages") : false
|
||||
|
||||
if (!me) return null
|
||||
|
||||
return (
|
||||
<div className="group/pages flex flex-col gap-px py-2">
|
||||
<PageSectionHeader pageCount={pageCount} />
|
||||
{me?.root.personalPages && <PageList personalPages={me.root.personalPages} />}
|
||||
<PageSectionHeader pageCount={pageCount} isActive={isActive} />
|
||||
<PageList personalPages={me.root.personalPages} sort={sort} show={show} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface PageSectionHeaderProps {
|
||||
pageCount: number
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
const PageSectionHeader: React.FC<PageSectionHeaderProps> = ({ pageCount }) => (
|
||||
@@ -121,6 +133,8 @@ const NewPageButton: React.FC = () => {
|
||||
|
||||
interface PageListProps {
|
||||
personalPages: PersonalPageLists
|
||||
sort: SortOption
|
||||
show: ShowOption
|
||||
}
|
||||
|
||||
const PageList: React.FC<PageListProps> = ({ personalPages }) => {
|
||||
@@ -250,4 +264,4 @@ const ShowAllForm: React.FC = () => {
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { LaIcon } from "@/components/custom/la-icon"
|
||||
import { ListOfTopics } from "@/lib/schema"
|
||||
import { LEARNING_STATES, LearningStateValue } from "@/lib/constants"
|
||||
|
||||
export const TopicSection: React.FC = () => {
|
||||
export const TopicSection: React.FC<{ pathname: string }> = ({ pathname }) => {
|
||||
const { me } = useAccount({
|
||||
root: {
|
||||
topicsWantToLearn: [],
|
||||
@@ -22,11 +22,13 @@ export const TopicSection: React.FC = () => {
|
||||
(me?.root.topicsLearning?.length || 0) +
|
||||
(me?.root.topicsLearned?.length || 0)
|
||||
|
||||
const isActive = pathname.startsWith("/topics")
|
||||
|
||||
if (!me) return null
|
||||
|
||||
return (
|
||||
<div className="group/pages flex flex-col gap-px py-2">
|
||||
<TopicSectionHeader topicCount={topicCount} />
|
||||
<TopicSectionHeader topicCount={topicCount} isActive={isActive} />
|
||||
<List
|
||||
topicsWantToLearn={me.root.topicsWantToLearn}
|
||||
topicsLearning={me.root.topicsLearning}
|
||||
@@ -38,11 +40,15 @@ export const TopicSection: React.FC = () => {
|
||||
|
||||
interface TopicSectionHeaderProps {
|
||||
topicCount: number
|
||||
isActive: boolean
|
||||
}
|
||||
|
||||
const TopicSectionHeader: React.FC<TopicSectionHeaderProps> = ({ topicCount }) => (
|
||||
const TopicSectionHeader: React.FC<TopicSectionHeaderProps> = ({ topicCount, isActive }) => (
|
||||
<div
|
||||
className={cn("flex min-h-[30px] items-center gap-px rounded-md", "hover:bg-accent hover:text-accent-foreground")}
|
||||
className={cn(
|
||||
"flex min-h-[30px] items-center gap-px rounded-md",
|
||||
isActive ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground"
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
variant="ghost"
|
||||
@@ -131,4 +137,4 @@ const ListItem: React.FC<ListItemProps> = ({ label, value, href, count, isActive
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,6 +109,7 @@ const LogoAndSearch: React.FC = React.memo(() => {
|
||||
LogoAndSearch.displayName = "LogoAndSearch"
|
||||
|
||||
const SidebarContent: React.FC = React.memo(() => {
|
||||
const pathname = usePathname()
|
||||
return (
|
||||
<>
|
||||
<nav className="bg-background relative flex h-full w-full shrink-0 flex-col">
|
||||
@@ -117,9 +118,9 @@ const SidebarContent: React.FC = React.memo(() => {
|
||||
</div>
|
||||
<div tabIndex={-1} className="relative mb-0.5 mt-1.5 flex grow flex-col overflow-y-auto rounded-md px-3">
|
||||
<div className="h-2 shrink-0" />
|
||||
<LinkSection />
|
||||
<PageSection />
|
||||
<TopicSection />
|
||||
<LinkSection pathname={pathname} />
|
||||
<PageSection pathname={pathname} />
|
||||
<TopicSection pathname={pathname} />
|
||||
</div>
|
||||
</nav>
|
||||
<ProfileSection />
|
||||
|
||||
Reference in New Issue
Block a user