Skip to content

Conversation

@ZeroChoi2781
Copy link
Contributor

Related Issues

N/A

Description of Changes

Component Changes (packages/core)

1. Component Renaming: Tabs.TriggerTabs.Button

  • Renamed component to better reflect its semantic role as a button element
  • Updated all internal references and type definitions

2. New Primitive Components

  • Tabs.ListPrimitive: Low-level tab list container without built-in indicator
  • Tabs.IndicatorPrimitive: Direct access to the active tab indicator element
  • Enables complex layouts by allowing custom composition with other UI elements

3. Enhanced Tabs.List

  • Added indicatorElement prop for custom indicator support
  • Internally composes Tabs.ListPrimitive + Tabs.IndicatorPrimitive
  • Updated description to clarify it includes indicator by default

4. Utility Type Exports

  • Exported utility prop types for better TypeScript support:
    • TabsRootProps, TabsListProps, TabsListPrimitiveProps
    • TabsButtonProps, TabsIndicatorPrimitiveProps, TabsPanelProps

Documentation Changes (apps/website)

New Documentation

  • Props specs: Added documentation for Tabs.ListPrimitive and Tabs.IndicatorPrimitive
  • Undocumented props: Added specs for existing activateOnFocus, loop, and indicatorElement props

New Examples

  • Custom Indicator: Demonstrates gradient indicator using indicatorElement prop
  • List Primitive: Shows advanced composition patterns (complex layouts, multiple indicators, flexible spacing)

Updates

  • Renamed Tabs.TriggerTabs.Button across all examples and documentation
  • Improved descriptions for Size, Variant, States, and Keyboard Navigation sections
  • Fixed typo in Tabs.Root description

Codemod Changes (packages/codemod)

  • Updated codemod to handle Tabs.TriggerTabs.Button renaming
  • Existing plainfill variant migration already supported

Breaking Changes

// Before
<Tabs.Trigger value="tab1">Tab 1</Tabs.Trigger>

// After
<Tabs.Button value="tab1">Tab 1</Tabs.Button>

Migration: Use the provided codemod or manually rename all instances.

Screenshots

Checklist

Before submitting the PR, please make sure you have checked all of the following items.

  • The PR title follows the Conventional Commits convention. (e.g., feat, fix, docs, style, refactor, test, chore)
  • I have added tests for my changes.
  • I have updated the Storybook or relevant documentation.
  • I have added a changeset for this change. (e.g., for any changes that affect users, such as component prop changes or new features).
  • I have performed a self-code review.
  • I have followed the project's coding conventions and component patterns.

@changeset-bot
Copy link

changeset-bot bot commented Dec 19, 2025

⚠️ No Changeset found

Latest commit: 9803762

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Dec 19, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
vapor-ui Error Error Dec 19, 2025 1:19am

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ZeroChoi2781, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 Pull Request는 Tabs 컴포넌트의 구조를 개선하고 유연성을 높이는 데 중점을 둡니다. Tabs.TriggerTabs.Button으로 의미론적으로 더 적절하게 변경하고, Tabs.ListPrimitiveTabs.IndicatorPrimitive와 같은 저수준 Primitive 컴포넌트를 도입하여 개발자가 탭 컴포넌트를 더욱 세밀하게 제어하고 커스터마이징할 수 있도록 합니다. 이 변경은 Tabs.List 컴포넌트의 기능도 확장하여 커스텀 인디케이터를 쉽게 통합할 수 있게 하며, 전반적인 코드베이스의 유지보수성과 확장성을 향상시킵니다.

Highlights

  • 컴포넌트 이름 변경: Tabs.Trigger 컴포넌트가 Tabs.Button으로 이름이 변경되어, 버튼 요소로서의 의미론적 역할을 더 잘 반영합니다. 모든 내부 참조 및 타입 정의가 업데이트되었습니다.
  • 새로운 Primitive 컴포넌트 추가: 새로운 저수준 Primitive 컴포넌트인 Tabs.ListPrimitiveTabs.IndicatorPrimitive가 추가되었습니다. 이를 통해 복잡한 레이아웃과 커스텀 구성이 가능해졌습니다.
  • Tabs.List 기능 강화: Tabs.ListindicatorElement prop이 추가되어 커스텀 인디케이터를 지원합니다. 이제 Tabs.List는 내부적으로 Tabs.ListPrimitiveTabs.IndicatorPrimitive를 조합하여 사용합니다.
  • 유틸리티 타입 내보내기: 더 나은 TypeScript 지원을 위해 TabsRootProps, TabsListProps, TabsListPrimitiveProps, TabsButtonProps, TabsIndicatorPrimitiveProps, TabsPanelProps와 같은 유틸리티 prop 타입들이 내보내졌습니다.
  • 문서 및 예제 업데이트: 새로운 Primitive 컴포넌트에 대한 Props 사양이 추가되었고, activateOnFocus, loop, indicatorElement와 같은 기존의 문서화되지 않은 prop에 대한 사양도 추가되었습니다. 커스텀 인디케이터 및 List Primitive를 활용한 새로운 예제들이 추가되었으며, Tabs.Trigger에서 Tabs.Button으로의 이름 변경이 모든 문서와 예제에 반영되었습니다.
  • Codemod 업데이트: Tabs.Trigger에서 Tabs.Button으로의 이름 변경을 처리하기 위해 Codemod가 업데이트되었습니다.
  • 호환성 파괴 변경: Tabs.TriggerTabs.Button으로 변경되었습니다. 기존 코드는 제공된 Codemod를 사용하거나 수동으로 모든 인스턴스를 변경해야 합니다.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Tabs component, renaming Tabs.Trigger to Tabs.Button and introducing new primitive components: Tabs.ListPrimitive and Tabs.IndicatorPrimitive. The Tabs.List component now internally includes Tabs.IndicatorPrimitive but allows for custom indicators via an indicatorElement prop. These changes are reflected across documentation, generated prop JSON files, and all example usages. Review comments indicate that TabsListPrimitive needs to be updated to correctly prioritize its own props (like variant, orientation, loop, activateOnFocus) over context values, and an unused TabsIndicator type definition namespace should be removed for clarity.

Comment on lines +65 to +81
export const TabsListPrimitive = forwardRef<HTMLDivElement, TabsListPrimitive.Props>(
(props, ref) => {
const { className, ...componentProps } = resolveStyles(props);
const { activateOnFocus, loop, variant, orientation } = useTabsContext();

return (
<BaseTabs.List
ref={ref}
loop={loop}
activateOnFocus={activateOnFocus}
className={clsx(styles.list({ variant, orientation }), className)}
{...componentProps}
/>
);
},
);
TabsListPrimitive.displayName = 'Tabs.ListPrimitive';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

TabsListPrimitive 컴포넌트가 자체적으로 받는 variant, orientation, loop, activateOnFocus 등의 props를 스타일링 및 동작에 반영하지 않고 컨텍스트(useTabsContext)의 값만 사용하고 있습니다. 이로 인해 <Tabs.ListPrimitive variant="fill" /> 와 같이 props를 전달해도 의도대로 스타일이나 동작이 적용되지 않는 문제가 발생합니다. 컴포넌트에 직접 전달된 props가 컨텍스트 값보다 우선 적용되도록 수정해야 합니다.

export const TabsListPrimitive = forwardRef<HTMLDivElement, TabsListPrimitive.Props>(
    (props, ref) => {
        const { className, ...allProps } = resolveStyles(props);
        const context = useTabsContext();

        const {
            variant: variantProp,
            orientation: orientationProp,
            loop: loopProp,
            activateOnFocus: activateOnFocusProp,
            ...otherProps
        } = allProps;

        const variant = variantProp ?? context.variant;
        const orientation = orientationProp ?? context.orientation;
        const loop = loopProp ?? context.loop;
        const activateOnFocus = activateOnFocusProp ?? context.activateOnFocus;

        return (
            <BaseTabs.List
                ref={ref}
                loop={loop}
                activateOnFocus={activateOnFocus}
                className={clsx(styles.list({ variant, orientation }), className)}
                {...otherProps}
            />
        );
    },
);
TabsListPrimitive.displayName = 'Tabs.ListPrimitive';

Comment on lines 182 to 184
export namespace TabsIndicator {
export interface Props extends ComponentPropsWithoutRef<typeof BaseTabs.Indicator> {}
export interface Props extends VComponentProps<typeof BaseTabs.Indicator> {}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

TabsIndicator 컴포넌트가 TabsIndicatorPrimitive로 대체되면서 해당 컴포넌트는 삭제되었지만, 타입 정의를 위한 TabsIndicator 네임스페이스는 남아있습니다. 이 네임스페이스는 현재 사용되지 않으며, index.parts.ts를 통해 외부로 노출되지도 않아 코드에 혼란을 줄 수 있습니다. 사용되지 않는 코드를 제거하여 명확성을 높이는 것이 좋습니다.

@vapor-ui
Copy link
Collaborator

All tests passed!

Tests Passed Failed Duration Report
136 136 0 m 0s Open report ↗︎

Click here if you need to update snapshots.

@ZeroChoi2781 ZeroChoi2781 removed their assignment Dec 19, 2025
const { activateOnFocus, loop, variant, orientation } = useTabsContext();
const { children, indicatorElement, ...componentProps } = resolveStyles(props);

const IndicatorElement = createSlot(indicatorElement || <TabsIndicatorPrimitive />);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#389

It would be good to modify this part as well to match the PR content!

Comment on lines +18 to +22
type RootControlledProps = {
activateOnFocus?: boolean;
loop?: boolean;
disabled?: boolean;
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using a Pick utility type for this part? If the subcomponent's spec changes, it seems like we won't be able to catch the error at compile time.

Base automatically changed from add-tabs-variants to main December 24, 2025 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants