Skip to content

Commit

Permalink
fix: tab rounded variant
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <tukon479@gmail.com>
  • Loading branch information
Innei committed Oct 20, 2024
1 parent 0a98f37 commit 847c317
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 111 deletions.
99 changes: 52 additions & 47 deletions apps/renderer/src/components/ui/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ const tabsTriggerVariants = cva("", {
variant: {
default:
"py-1.5 border-b-2 border-transparent data-[state=active]:text-accent dark:data-[state=active]:text-theme-accent-500",
rounded:
"py-1 rounded-sm data-[state=active]:bg-theme-accent-300 dark:data-[state=active]:bg-theme-accent-800 data-[state=active]:shadow-sm",
rounded: "!py-1 !px-3 bg-transparent",
},
},
defaultVariants: {
Expand All @@ -68,58 +67,64 @@ const tabsTriggerVariants = cva("", {
export interface TabsTriggerProps
extends React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>,
VariantProps<typeof tabsTriggerVariants> {}
const TabsTrigger = React.forwardRef<
React.ElementRef<typeof TabsPrimitive.Trigger>,
TabsTriggerProps
>(({ className, variant, children, ...props }, ref) => {
const triggerRef = React.useRef(null)
React.useImperativeHandle(ref, () => triggerRef.current!, [ref])
const TabsTrigger = React.forwardRef<HTMLDivElement, TabsTriggerProps>(
({ className, variant, children, ...props }, ref) => {
const triggerRef = React.useRef<HTMLDivElement>(null)
React.useImperativeHandle(ref, () => triggerRef.current!, [])

const [isSelect, setIsSelect] = React.useState(false)
const id = React.useContext(TabsIdContext)
const layoutId = `tab-selected-underline-${id}`
React.useLayoutEffect(() => {
if (!triggerRef.current) return
const [isSelect, setIsSelect] = React.useState(false)
const id = React.useContext(TabsIdContext)
const layoutId = `tab-selected-underline-${id}`
React.useLayoutEffect(() => {
if (!triggerRef.current) return

const trigger = triggerRef.current as HTMLElement
const trigger = triggerRef.current as HTMLElement

const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
const ob = new MutationObserver(() => {
const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
})
ob.observe(trigger, {
attributes: true,
attributeFilter: ["data-state"],
})
const ob = new MutationObserver(() => {
const isSelect = trigger.dataset.state === "active"
setIsSelect(isSelect)
})
ob.observe(trigger, {
attributes: true,
attributeFilter: ["data-state"],
})

return () => {
ob.disconnect()
}
}, [])
return () => {
ob.disconnect()
}
}, [])

return (
<TabsPrimitive.Trigger
ref={triggerRef}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap px-3 text-sm font-medium ring-offset-background transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-theme-foreground",
"relative",
tabsTriggerVariants({ variant }),
className,
)}
{...props}
>
{children}
{isSelect && (
<m.span
layoutId={layoutId}
className="absolute -bottom-1 h-0.5 w-[calc(100%-16px)] rounded bg-accent"
/>
)}
</TabsPrimitive.Trigger>
)
})
return (
<TabsPrimitive.Trigger
ref={triggerRef as any}
className={cn(
"inline-flex items-center justify-center whitespace-nowrap px-3 text-sm font-medium ring-offset-background transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:text-theme-foreground",
"group relative z-[1]",
tabsTriggerVariants({ variant }),
// !isSelect &&
// "hover:before:bg-theme-item-hover before:content-[''] before:pointer-events-none before:absolute before:inset-y-0 before:inset-x-1 before:duration-200 before:opacity-60 before:rounded-lg",
// className,
)}
{...props}
>
{children}
{isSelect && (
<m.span
layoutId={layoutId}
className={cn(
"absolute",
variant === "rounded"
? "inset-0 z-[-1] rounded-lg bg-muted duration-200 group-hover:bg-theme-item-hover"
: "-bottom-1 h-0.5 w-[calc(100%-16px)] rounded bg-accent",
)}
/>
)}
</TabsPrimitive.Trigger>
)
},
)
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName

const TabsContent = React.forwardRef<
Expand Down
66 changes: 2 additions & 64 deletions apps/renderer/src/modules/entry-column/layouts/EntryListHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,21 @@ import { ImpressionView } from "~/components/common/ImpressionTracker"
import { ActionButton } from "~/components/ui/button"
import { DividerVertical } from "~/components/ui/divider"
import { RotatingRefreshIcon } from "~/components/ui/loading"
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs"
import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography"
import { FEED_COLLECTION_LIST, ROUTE_ENTRY_PENDING, views } from "~/constants"
import { shortcuts } from "~/constants/shortcuts"
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
import { useRouteParams } from "~/hooks/biz/useRouteParams"
import { useIsOnline } from "~/hooks/common"
import { stopPropagation } from "~/lib/dom"
import { FeedViewType } from "~/lib/enum"
import { cn, getOS, isBizId } from "~/lib/utils"
import { useAIDailyReportModal } from "~/modules/ai/ai-daily/hooks"
import { EntryHeader } from "~/modules/entry-content/header"
import { InboxItem, ListItem } from "~/modules/feed-column/item"
import { useRefreshFeedMutation } from "~/queries/feed"
import { useFeedById, useFeedHeaderTitle } from "~/store/feed"
import { useSubscriptionStore } from "~/store/subscription"

import { MarkAllReadWithOverlay } from "../components/mark-all-button"
import { TimelineTabs } from "./TimelineTabs"

export const EntryListHeader: FC<{
totalCount: number
Expand Down Expand Up @@ -76,7 +73,7 @@ export const EntryListHeader: FC<{
return (
<div
ref={containerRef}
className="mb-2 flex w-full flex-col pl-6 pr-4 pt-2.5 transition-[padding] duration-300 ease-in-out"
className="flex w-full flex-col pl-6 pr-4 pt-2.5 transition-[padding] duration-300 ease-in-out"
>
<div className={cn("flex w-full", titleAtBottom ? "justify-end" : "justify-between")}>
{!titleAtBottom && titleInfo}
Expand Down Expand Up @@ -276,62 +273,3 @@ const AppendTaildingDivider = ({ children }: { children: React.ReactNode }) => (
)}
</>
)

const TimelineTabs = () => {
const routerParams = useRouteParams()
const { view, listId, inboxId } = routerParams

const listsData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "listId" in s),
)
const inboxData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "inboxId" in s),
)
const hasData = listsData.length > 0 || inboxData.length > 0

const timeline = listId || inboxId || ""

const navigate = useNavigateEntry()
if (!hasData) return null
return (
<Tabs
className="-mr-4 mt-1 overflow-x-auto scrollbar-none"
value={timeline}
onValueChange={(val) => {
if (!val) {
navigate({
feedId: null,
entryId: null,
view,
})
}
}}
>
<TabsList className="h-10 space-x-3 border-b-0">
<TabsTrigger className="p-0" value="">
Yours
</TabsTrigger>
{listsData.map((s) => (
<TabsTrigger className="p-0" key={s.listId} value={s.listId!}>
<ListItem
listId={s.listId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
{inboxData.map((s) => (
<TabsTrigger key={s.inboxId} value={s.inboxId!}>
<InboxItem
inboxId={s.inboxId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
</TabsList>
</Tabs>
)
}
64 changes: 64 additions & 0 deletions apps/renderer/src/modules/entry-column/layouts/TimelineTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Tabs, TabsList, TabsTrigger } from "~/components/ui/tabs"
import { useNavigateEntry } from "~/hooks/biz/useNavigateEntry"
import { useRouteParams } from "~/hooks/biz/useRouteParams"
import { InboxItem, ListItem } from "~/modules/feed-column/item"
import { useSubscriptionStore } from "~/store/subscription"

export const TimelineTabs = () => {
const routerParams = useRouteParams()
const { view, listId, inboxId } = routerParams

const listsData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "listId" in s),
)
const inboxData = useSubscriptionStore((state) =>
state.feedIdByView[view].map((id) => state.data[id]).filter((s) => "inboxId" in s),
)
const hasData = listsData.length > 0 || inboxData.length > 0

const timeline = listId || inboxId || ""

const navigate = useNavigateEntry()
if (!hasData) return null
return (
<Tabs
className="-ml-3 -mr-4 mt-1 overflow-x-auto scrollbar-none"
value={timeline}
onValueChange={(val) => {
if (!val) {
navigate({
feedId: null,
entryId: null,
view,
})
}
}}
>
<TabsList className="h-10 border-b-0">
<TabsTrigger variant={"rounded"} className="p-0" value="">
Yours
</TabsTrigger>
{listsData.map((s) => (
<TabsTrigger variant={"rounded"} className="p-0" key={s.listId} value={s.listId!}>
<ListItem
listId={s.listId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
{inboxData.map((s) => (
<TabsTrigger variant={"rounded"} key={s.inboxId} value={s.inboxId!}>
<InboxItem
inboxId={s.inboxId!}
view={view}
iconSize={16}
className="h-5 !bg-transparent p-0 leading-none"
/>
</TabsTrigger>
))}
</TabsList>
</Tabs>
)
}

0 comments on commit 847c317

Please sign in to comment.