diff --git a/src/components/common/Layout/Header/Header.tsx b/src/components/common/Layout/Header/Header.tsx index cdbc60e..2ca1779 100644 --- a/src/components/common/Layout/Header/Header.tsx +++ b/src/components/common/Layout/Header/Header.tsx @@ -1,4 +1,4 @@ -import type { ReactNode } from 'react' +import type { ReactNode, ForwardedRef } from 'react' import * as S from './styled' import { Typography as T } from '../../../../core/typography' @@ -6,15 +6,17 @@ type Props = { title: string subtitle?: string actions?: ReactNode + forwardedRef?: ForwardedRef } export default function BaseLayout({ title = 'Title', subtitle = '', actions, + forwardedRef, }: Props) { return ( - +
{title} {subtitle} diff --git a/src/components/common/organisms/Tabs/Tabs.tsx b/src/components/common/organisms/Tabs/Tabs.tsx index 3761e3e..ceb9e1a 100644 --- a/src/components/common/organisms/Tabs/Tabs.tsx +++ b/src/components/common/organisms/Tabs/Tabs.tsx @@ -7,9 +7,13 @@ export type TabItem = { content: React.ReactNode } -type Props = { items: TabItem[]; defaultKey?: string } +type Props = { + items: TabItem[] + defaultKey?: string + offset: number +} -export default function Tabs({ items, defaultKey }: Props) { +export default function Tabs({ items, defaultKey, offset }: Props) { const keys = items.map((i) => i.key) const [active, setActive] = useState(defaultKey ?? keys[0]) @@ -28,7 +32,12 @@ export default function Tabs({ items, defaultKey }: Props) { return ( <> - + {items.map((t) => { const isActive = t.key === active return ( diff --git a/src/components/common/organisms/Tabs/styled.ts b/src/components/common/organisms/Tabs/styled.ts index f276d26..5e47b9e 100644 --- a/src/components/common/organisms/Tabs/styled.ts +++ b/src/components/common/organisms/Tabs/styled.ts @@ -4,11 +4,16 @@ import tokens from '../../../../core/tokens' const DIVIDER_W = `${tokens.size.BASELINE / 8}px` const INDICATOR_H = '2px' -export const Bar = styled.nav` +export const Bar = styled.nav<{ offset: number }>` display: flex; gap: ${tokens.gap.LARGE}px; margin: ${tokens.spacing.BASELINE * 2}px 0 ${tokens.spacing.BASELINE}px; border-bottom: ${DIVIDER_W} solid ${({ theme }) => theme.colors.scrollBar}; + background: ${({ theme }) => theme.colors.primaryBackground}; + + position: sticky; + top: ${({ offset }) => offset}px; + z-index: 10; ` export const TabButton = styled.button<{ active: boolean }>` diff --git a/src/hooks/useElementHeight.ts b/src/hooks/useElementHeight.ts new file mode 100644 index 0000000..ed366a7 --- /dev/null +++ b/src/hooks/useElementHeight.ts @@ -0,0 +1,19 @@ +import { useLayoutEffect, useRef, useState } from 'react' + +export function useElementHeight() { + const ref = useRef(null) + const [height, setHeight] = useState(0) + + useLayoutEffect(() => { + if (!ref.current) return + + const updateHeight = () => setHeight(ref.current?.offsetHeight || 0) + + updateHeight() + + window.addEventListener('resize', updateHeight) + return () => window.removeEventListener('resize', updateHeight) + }, []) + + return { ref, height } +} diff --git a/src/pages/LiberyPage/index.tsx b/src/pages/LiberyPage/index.tsx index b8810e8..fab8afd 100644 --- a/src/pages/LiberyPage/index.tsx +++ b/src/pages/LiberyPage/index.tsx @@ -2,17 +2,21 @@ import Tabs from '../../components/common/organisms/Tabs' import { PaddedContainer } from '../../components/common/styled' import { LIBRARY_TABS } from './tabs.config' import Header from '../../components/common/Layout/Header' +import { useElementHeight } from '../../hooks/useElementHeight' export default function LibraryPage() { + const { ref, height } = useElementHeight() + return ( <>
- + )