diff --git a/packages/smarthr-ui/src/components/AppNavi/AppNaviAnchor.tsx b/packages/smarthr-ui/src/components/AppNavi/AppNaviAnchor.tsx index e76ff106c8..5e7ac422cb 100644 --- a/packages/smarthr-ui/src/components/AppNavi/AppNaviAnchor.tsx +++ b/packages/smarthr-ui/src/components/AppNavi/AppNaviAnchor.tsx @@ -1,18 +1,40 @@ -import React, { FC, PropsWithChildren, useMemo } from 'react' +import React, { + ComponentPropsWithoutRef, + ComponentType, + ElementType, + FC, + PropsWithoutRef, + ReactElement, + Ref, + forwardRef, + useMemo, +} from 'react' import { tv } from 'tailwind-variants' +import { ElementRef, ElementRefProps } from '../../types' import { ComponentProps as IconProps } from '../Icon' import { appNaviItemStyle } from './style' -export type AppNaviAnchorProps = PropsWithChildren<{ +type ElementProps = Omit< + ComponentPropsWithoutRef, + keyof AppNaviAnchorProps & ElementRefProps +> + +export type AppNaviAnchorProps = { /** アンカーの href */ - href: string + href?: string /** 表示するアイコンタイプ */ - icon?: React.ComponentType + icon?: ComponentType /** アクティブ状態であるかどうか */ current?: boolean -}> + /** next/link などのカスタムコンポーネントを指定します。指定がない場合はデフォルトで `a` タグが使用されます。 */ + elementAs?: T +} + +type AppNaviAnchorComponent = ( + props: AppNaviAnchorProps & ElementProps & ElementRefProps, +) => ReturnType const appNaviAnchor = tv({ extend: appNaviItemStyle, @@ -21,24 +43,39 @@ const appNaviAnchor = tv({ }, }) -export const AppNaviAnchor: FC = ({ - children, - href, - icon: Icon, - current = false, -}) => { - const { wrapperStyle, iconStyle } = useMemo(() => { - const { wrapper, icon } = appNaviAnchor({ active: current }) - return { - wrapperStyle: wrapper(), - iconStyle: icon(), - } - }, [current]) - - return ( - - {Icon && } - {children} - - ) -} +export const AppNaviAnchor: AppNaviAnchorComponent = forwardRef( + ( + { + children, + href, + icon: Icon, + current = false, + elementAs, + ...others + }: PropsWithoutRef> & ElementProps, + ref: Ref>, + ): ReactElement => { + const { wrapperStyle, iconStyle } = useMemo(() => { + const { wrapper, icon } = appNaviAnchor({ active: current }) + return { + wrapperStyle: wrapper(), + iconStyle: icon(), + } + }, [current]) + + const Component = elementAs || 'a' + + return ( + + {Icon && } + {children} + + ) + }, +)