Skip to content

Commit

Permalink
feat: trigger 와 content 에 ref 추가, style className 에 대해 DefaultPRops 로 변경
Browse files Browse the repository at this point in the history
  • Loading branch information
SeieunYoo committed Sep 11, 2024
1 parent ec4ab33 commit 3d056fa
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 18 deletions.
15 changes: 13 additions & 2 deletions packages/wow-ui/src/components/Tabs/TabsContent.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
"use client";

import { forwardRef, type PropsWithChildren } from "react";
import type { PropsWithChildren } from "react";
import { forwardRef } from "react";

import type { DefaultProps } from "@/types/DefaultProps";

import { useTabContext } from "./contexts/TabContext";

interface TabsContentProps extends PropsWithChildren {
/**
* @description TabsContent 컴포넌트는 각 Tab에 해당하는 콘텐츠입니다.
* @param {string} value - TabTrigger의 value와 일치하는 값입니다.
* @param {string} [className] - TabsContent에 전달할 커스텀 클래스.
* @param {CSSProperties} [style] - TabsContent에 전달할 커스텀 스타일.
* @param {ComponentPropsWithoutRef<T>} rest 렌더링된 요소 또는 컴포넌트에 전달할 추가 props.
* @param {ComponentPropsWithRef<T>["ref"]} ref 렌더링된 요소 또는 컴포넌트에 연결할 ref.
*/
interface TabsContentProps extends PropsWithChildren, DefaultProps {
value: string;
}

Expand Down
12 changes: 12 additions & 0 deletions packages/wow-ui/src/components/Tabs/TabsList.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"use client";

import { css } from "@styled-system/css";
import { Flex } from "@styled-system/jsx";
import { type KeyboardEvent, type PropsWithChildren, useCallback } from "react";

import { useCollectionContext } from "./contexts/CollectionContext";
import { useTabContext } from "./contexts/TabContext";

/**
* @description TabsList 컴포넌트는 TabTrigger 컴포넌트를 관리합니다.
*/
export const TabsList = ({ children }: PropsWithChildren) => {
const { label, setSelectedValue, value: selectedValue } = useTabContext();

Expand Down Expand Up @@ -40,10 +44,18 @@ export const TabsList = ({ children }: PropsWithChildren) => {
<Flex
aria-label={`${label}-tab-list`}
aria-orientation="horizontal"
className={tabsListStyle}
role="tablist"
onKeyDown={handleKeyDown}
>
{children}
</Flex>
);
};

const tabsListStyle = css({
lg: {
overflowX: "scroll",
scrollBehavior: "smooth",
},
});
34 changes: 29 additions & 5 deletions packages/wow-ui/src/components/Tabs/TabsTrigger.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
"use client";

import { cva } from "@styled-system/css";
import { forwardRef, type PropsWithChildren, useEffect, useRef } from "react";
import { clsx } from "clsx";
import type { ButtonHTMLAttributes, PropsWithChildren } from "react";
import { forwardRef, useEffect, useRef } from "react";

import { useMergeRefs } from "@/hooks/useMergeRefs";
import type { DefaultProps } from "@/types/DefaultProps";

import { useCollectionContext } from "./contexts/CollectionContext";
import { useTabContext } from "./contexts/TabContext";

interface TapTriggerProps extends PropsWithChildren {
/**
* @description TabsTrigger 컴포넌트는 각 Tab 컴포넌트입니다.
* @param {string} value - TabsContent의 value와 일치하는 값입니다.
* @param {string} [className] - TabsTrigger에 전달할 커스텀 클래스.
* @param {CSSProperties} [style] - TabsTrigger에 전달할 커스텀 스타일.
* @param {ComponentPropsWithoutRef<T>} rest 렌더링된 요소 또는 컴포넌트에 전달할 추가 props.
* @param {ComponentPropsWithRef<T>["ref"]} ref 렌더링된 요소 또는 컴포넌트에 연결할 ref.
*/
interface TabsTriggerProps
extends PropsWithChildren,
DefaultProps,
ButtonHTMLAttributes<HTMLButtonElement> {
value: string;
}

export const TabsTrigger = forwardRef<HTMLButtonElement, TapTriggerProps>(
({ value, children }: TapTriggerProps, ref) => {
export const TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(
({ value, children, className, ...rest }: TabsTriggerProps, ref) => {
const { value: selectedValue, setSelectedValue, label } = useTabContext();
const selected = selectedValue === value;

Expand All @@ -39,12 +53,16 @@ export const TabsTrigger = forwardRef<HTMLButtonElement, TapTriggerProps>(
<button
aria-controls={`${label}-tab-content-${value}`}
aria-selected={selected}
className={tabTriggerStyle({ type: selected ? "selected" : "default" })}
id={`${label}-tab-trigger-${value}`}
ref={buttonRef}
role="tab"
tabIndex={selected ? 0 : -1}
className={clsx(
tabTriggerStyle({ type: selected ? "selected" : "default" }),
className
)}
onClick={handleClickTabTrigger}
{...rest}
>
{children}
</button>
Expand All @@ -64,6 +82,12 @@ const tabTriggerStyle = cva({
color: "sub",
outline: "none",
cursor: "pointer",
xsToSm: {
display: "flex",
flexGrow: 1,
justifyContent: "center",
alignItems: "center",
},
},
variants: {
type: {
Expand Down
43 changes: 32 additions & 11 deletions packages/wow-ui/src/components/Tabs/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
"use client";

import { type PropsWithChildren, useEffect, useState } from "react";
import { css } from "@styled-system/css";
import { clsx } from "clsx";
import type { PropsWithChildren } from "react";
import { useEffect, useState } from "react";

import { CollectionProvider } from "@/components/Tabs/contexts/CollectionContext";
import { TabContext } from "@/components/Tabs/contexts/TabContext";
import type { DefaultProps } from "@/types/DefaultProps";

interface TabsProps extends PropsWithChildren {
/**
* @description Tabs 컴포넌트는 탭을 통해 콘텐츠를 선택할 수 있는 컴포넌트입니다.
* @param {string} [defaultValue] - 탭의 기본값입니다.
* @param {string} [value] - 현재 선택된 탭의 값입니다.
* @param {string} [label] - 각 탭을 구분할 수 있는 레이블입니다.
* @param {(value: string) => void} [onChange] - 탭이 변경될 때 호출되는 함수입니다.
* @param {CSSProperties} [style] - 탭 컴포넌트의 커스텀 스타일.
* @param {string} [className] - 탭 컴포넌트에 전달할 커스텀 클래스.
*/
export interface TabsProps extends PropsWithChildren, DefaultProps {
defaultValue?: string;
value?: string;
label?: string;
Expand All @@ -17,6 +30,8 @@ export const Tabs = ({
label = "default-tab",
children,
onChange,
className,
style,
}: TabsProps) => {
const [selectedValue, setSelectedValue] = useState(
defaultValue ?? value ?? ""
Expand All @@ -36,14 +51,20 @@ export const Tabs = ({
};

return (
<TabContext.Provider
value={{
value: selectedValue,
setSelectedValue: handleSelect,
label,
}}
>
<CollectionProvider>{children}</CollectionProvider>
</TabContext.Provider>
<div className={clsx(tabsContainerStyle, className)} style={style}>
<TabContext.Provider
value={{
value: selectedValue,
setSelectedValue: handleSelect,
label,
}}
>
<CollectionProvider>{children}</CollectionProvider>
</TabContext.Provider>
</div>
);
};

const tabsContainerStyle = css({
width: "100%",
});
11 changes: 11 additions & 0 deletions packages/wow-ui/src/types/DefaultProps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { CSSProperties } from "react";

/**
* @description 컴포넌트에 전달한 기본적으로 전달한 props 입니다.
* @property {string} className - 컴포넌트에 전달할 커스텀 클래스명입니다.
* @property {CSSProperties} style - 컴포넌트에 전달할 커스텀 스타일입니다.
*/
export interface DefaultProps {
className?: string;
style?: CSSProperties;
}

0 comments on commit 3d056fa

Please sign in to comment.