Skip to content

Commit 04f989a

Browse files
committed
fix: add Tabs support
Signed-off-by: Innei <[email protected]>
1 parent 59a8f61 commit 04f989a

File tree

5 files changed

+89
-4
lines changed

5 files changed

+89
-4
lines changed

src/components/ui/code-highlighter/shiki/Shiki.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,10 @@ export const ShikiHighLighter: FC<Props> = (props) => {
140140
<MotionButtonBase
141141
onClick={handleCopy}
142142
className={clsx(
143-
'absolute right-2 top-[calc(1rem-3px)] z-[1] flex rounded border border-current p-2 text-xs center',
144-
'rounded-md border border-black/5 bg-accent/80 p-1.5 text-white backdrop-blur duration-200 dark:border-white/10',
143+
'absolute right-2 top-2 z-[1] flex rounded border border-current p-2 text-xs center',
144+
'rounded-md border border-accent/5 bg-accent/80 p-1.5 text-white backdrop-blur duration-200',
145145
'opacity-0 group-hover:opacity-100',
146+
filename && 'top-12',
146147
)}
147148
>
148149
<i className="icon-[mingcute--copy-2-fill] h-4 w-4" />

src/components/ui/markdown/Markdown.tsx

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import { MDetails } from './renderers/collapse'
3838
import { MFootNote } from './renderers/footnotes'
3939
import { MHeader } from './renderers/heading'
4040
import { MarkdownImage } from './renderers/image'
41+
import { Tab, Tabs } from './renderers/Tabs'
4142
import { MTag } from './renderers/tag'
4243
import { getFootNoteDomId, getFootNoteRefDomId } from './utils/get-id'
4344
import { redHighlight } from './utils/redHighlight'
@@ -81,6 +82,7 @@ export const Markdown: FC<MdProps & MarkdownToJSX.Options & PropsWithChildren> =
8182
as: As = 'div',
8283
allowsScript = false,
8384
removeWrapper = false,
85+
8486
...rest
8587
} = props
8688

@@ -109,6 +111,9 @@ export const Markdown: FC<MdProps & MarkdownToJSX.Options & PropsWithChildren> =
109111
img: MarkdownImage,
110112
tag: MTag,
111113

114+
Tabs,
115+
Tab,
116+
112117
// for custom react component
113118
// Tag: MTag,
114119

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import * as RadixTabs from '@radix-ui/react-tabs'
2+
import {
3+
createContext,
4+
useCallback,
5+
useContext,
6+
useEffect,
7+
useId,
8+
useState,
9+
} from 'react'
10+
import { m } from 'framer-motion'
11+
import type { FC, PropsWithChildren } from 'react'
12+
13+
import { clsxm } from '~/lib/helper'
14+
15+
const TabActionContext = createContext<{
16+
addTab: (label: string) => void
17+
}>(null!)
18+
export const Tabs: FC<PropsWithChildren> = ({ children }) => {
19+
const [tabs, setTabs] = useState<string[]>([])
20+
const [activeTab, setActiveTab] = useState<string | null>(null)
21+
const id = useId()
22+
return (
23+
<TabActionContext.Provider
24+
value={{
25+
addTab: useCallback(
26+
(label) => {
27+
setTabs((tabs) => [...tabs, label])
28+
29+
if (!activeTab) setActiveTab(label)
30+
return () => {
31+
setTabs((tabs) => tabs.filter((tab) => tab !== label))
32+
}
33+
},
34+
[activeTab],
35+
),
36+
}}
37+
>
38+
<RadixTabs.Root value={activeTab || ''} onValueChange={setActiveTab}>
39+
<RadixTabs.List className="flex gap-2">
40+
{tabs.map((tab) => {
41+
return (
42+
<RadixTabs.Trigger
43+
className={clsxm(
44+
'relative flex px-2 py-1 text-sm font-bold focus:outline-none',
45+
'text-gray-600 transition-colors duration-300 dark:text-gray-300',
46+
)}
47+
key={tab}
48+
value={tab}
49+
>
50+
{tab}
51+
52+
{activeTab === tab && (
53+
<m.div
54+
layoutId={`tab${id}`}
55+
layout
56+
className="absolute -bottom-1 left-2 right-2 h-[2px] rounded-md bg-accent"
57+
/>
58+
)}
59+
</RadixTabs.Trigger>
60+
)
61+
})}
62+
</RadixTabs.List>
63+
64+
{children}
65+
</RadixTabs.Root>
66+
</TabActionContext.Provider>
67+
)
68+
}
69+
70+
export const Tab: FC<{
71+
label: string
72+
children: React.ReactNode
73+
}> = ({ label, children }) => {
74+
const { addTab } = useContext(TabActionContext)
75+
useEffect(() => {
76+
return addTab(label)
77+
}, [])
78+
79+
return <RadixTabs.Content value={label}>{children}</RadixTabs.Content>
80+
}

src/components/ui/tabs/Tabs.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Root.displayName = 'Tabs.Root'
2222
export const List = React.forwardRef<
2323
React.ElementRef<typeof TabsPrimitive.List>,
2424
React.ComponentPropsWithoutRef<typeof TabsPrimitive.List> & {
25-
id: string
25+
id?: string
2626
}
2727
>(({ id, className, children, ...rest }, forwardedRef) => (
2828
<TabsPrimitive.List

src/hooks/shared/use-mask-scrollarea.ts

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export const useMaskScrollArea = <T extends HTMLElement = HTMLElement>({
1717
size?: 'base' | 'lg'
1818
selector?: string
1919
} = {}) => {
20-
console.log('useMaskScrollArea', element)
2120
const containerRef = useRef<T>(null)
2221
const [isScrollToBottom, setIsScrollToBottom] = useState(false)
2322
const [isScrollToTop, setIsScrollToTop] = useState(false)

0 commit comments

Comments
 (0)