From 171ca392d76bfe9fa06f7baed4507b452969d301 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Fri, 28 Mar 2025 21:51:18 +0800 Subject: [PATCH 1/4] New dir --- docs/src/app/(private)/experiments/{ => tabs}/tabs.module.css | 0 docs/src/app/(private)/experiments/{ => tabs}/tabs.tsx | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) rename docs/src/app/(private)/experiments/{ => tabs}/tabs.module.css (100%) rename docs/src/app/(private)/experiments/{ => tabs}/tabs.tsx (96%) diff --git a/docs/src/app/(private)/experiments/tabs.module.css b/docs/src/app/(private)/experiments/tabs/tabs.module.css similarity index 100% rename from docs/src/app/(private)/experiments/tabs.module.css rename to docs/src/app/(private)/experiments/tabs/tabs.module.css diff --git a/docs/src/app/(private)/experiments/tabs.tsx b/docs/src/app/(private)/experiments/tabs/tabs.tsx similarity index 96% rename from docs/src/app/(private)/experiments/tabs.tsx rename to docs/src/app/(private)/experiments/tabs/tabs.tsx index de114b8cde..1abc0ca55d 100644 --- a/docs/src/app/(private)/experiments/tabs.tsx +++ b/docs/src/app/(private)/experiments/tabs/tabs.tsx @@ -5,8 +5,8 @@ import { Tabs } from '@base-ui-components/react/tabs'; import { SettingsMetadata, useExperimentSettings, -} from '../../../components/Experiments/SettingsPanel'; -import '../../../demo-theme.css'; +} from '../../../../components/Experiments/SettingsPanel'; +import '../../../../demo-theme.css'; import classes from './tabs.module.css'; export default function TabsExperiment() { From aa892e5099f4d6a58ef2b5b8eb1e4cade29917a3 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Sat, 29 Mar 2025 00:03:26 +0800 Subject: [PATCH 2/4] Tabs motion examples --- .../app/(private)/experiments/tabs/_icons.tsx | 30 ++++++ .../app/(private)/experiments/tabs/motion.tsx | 96 +++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 docs/src/app/(private)/experiments/tabs/_icons.tsx create mode 100644 docs/src/app/(private)/experiments/tabs/motion.tsx diff --git a/docs/src/app/(private)/experiments/tabs/_icons.tsx b/docs/src/app/(private)/experiments/tabs/_icons.tsx new file mode 100644 index 0000000000..0aa7450059 --- /dev/null +++ b/docs/src/app/(private)/experiments/tabs/_icons.tsx @@ -0,0 +1,30 @@ +'use client'; +import * as React from 'react'; + +export default function Nothing() { + return
This is just a dummy file to hold icons
; +} + +export function OverviewIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} + +export function ProjectIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} + +export function PersonIcon(props: React.ComponentProps<'svg'>) { + return ( + + + + ); +} diff --git a/docs/src/app/(private)/experiments/tabs/motion.tsx b/docs/src/app/(private)/experiments/tabs/motion.tsx new file mode 100644 index 0000000000..75a9c8d3aa --- /dev/null +++ b/docs/src/app/(private)/experiments/tabs/motion.tsx @@ -0,0 +1,96 @@ +'use client'; +import * as React from 'react'; +import { Tabs } from '@base-ui-components/react/tabs'; +import { AnimatePresence, motion } from 'motion/react'; +import styles from '../../../(public)/(content)/react/components/tabs/demos/hero/css-modules/index.module.css'; +import { OverviewIcon, ProjectIcon, PersonIcon } from './_icons'; + +const DURATION = 0.6; // seconds + +const MotionTabPanel = React.forwardRef(function MotionTabPanel( + props: Tabs.Panel.Props, + forwardedRef: React.ForwardedRef, +) { + const { children, value, ...otherProps } = props; + return ( + + ); +}); + +export default function ExampleTabs() { + const [value, setValue] = React.useState('overview'); + return ( + + + + Overview + + + Projects + + + Account + + + + + + {value === 'overview' && ( + + + + )} + + {value === 'projects' && ( + + + + )} + + {value === 'account' && ( + + + + )} + + + ); +} From 93c3de32b1426839b8f45179f125a3fbaceb8544 Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Sat, 29 Mar 2025 03:05:08 +0800 Subject: [PATCH 3/4] TS --- docs/src/app/(private)/experiments/tabs/motion.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/app/(private)/experiments/tabs/motion.tsx b/docs/src/app/(private)/experiments/tabs/motion.tsx index 75a9c8d3aa..43685a3d67 100644 --- a/docs/src/app/(private)/experiments/tabs/motion.tsx +++ b/docs/src/app/(private)/experiments/tabs/motion.tsx @@ -1,7 +1,7 @@ 'use client'; import * as React from 'react'; import { Tabs } from '@base-ui-components/react/tabs'; -import { AnimatePresence, motion } from 'motion/react'; +import { AnimatePresence, motion, type HTMLMotionProps } from 'motion/react'; import styles from '../../../(public)/(content)/react/components/tabs/demos/hero/css-modules/index.module.css'; import { OverviewIcon, ProjectIcon, PersonIcon } from './_icons'; @@ -26,7 +26,7 @@ const MotionTabPanel = React.forwardRef(function MotionTabPanel( const direction = state.tabActivationDirection === 'right' ? -1 : 1; return ( )} initial={{ opacity: 0, x: -100 * direction, From 6692c292c2585175c14080a0c62afe562c1c22bb Mon Sep 17 00:00:00 2001 From: Albert Yu Date: Tue, 1 Apr 2025 18:02:53 +0800 Subject: [PATCH 4/4] TabIndicator --- .../experiments/tabs/motion.module.css | 7 +++ .../app/(private)/experiments/tabs/motion.tsx | 57 +++++++++++++++---- 2 files changed, 53 insertions(+), 11 deletions(-) create mode 100644 docs/src/app/(private)/experiments/tabs/motion.module.css diff --git a/docs/src/app/(private)/experiments/tabs/motion.module.css b/docs/src/app/(private)/experiments/tabs/motion.module.css new file mode 100644 index 0000000000..27cd646b50 --- /dev/null +++ b/docs/src/app/(private)/experiments/tabs/motion.module.css @@ -0,0 +1,7 @@ +.Indicator { + position: absolute; + z-index: -1; + inset: 4px 0 5px 0; + border-radius: 0.25rem; + background-color: var(--color-gray-100); +} diff --git a/docs/src/app/(private)/experiments/tabs/motion.tsx b/docs/src/app/(private)/experiments/tabs/motion.tsx index 43685a3d67..b2ba3ec5fd 100644 --- a/docs/src/app/(private)/experiments/tabs/motion.tsx +++ b/docs/src/app/(private)/experiments/tabs/motion.tsx @@ -4,8 +4,9 @@ import { Tabs } from '@base-ui-components/react/tabs'; import { AnimatePresence, motion, type HTMLMotionProps } from 'motion/react'; import styles from '../../../(public)/(content)/react/components/tabs/demos/hero/css-modules/index.module.css'; import { OverviewIcon, ProjectIcon, PersonIcon } from './_icons'; +import motionStyles from './motion.module.css'; -const DURATION = 0.6; // seconds +const DURATION = 1; // seconds const MotionTabPanel = React.forwardRef(function MotionTabPanel( props: Tabs.Panel.Props, @@ -52,24 +53,58 @@ const MotionTabPanel = React.forwardRef(function MotionTabPanel( ); }); +const MotionTab = React.forwardRef(function MotionTab( + props: Tabs.Tab.Props & { + selectedValue: Tabs.Tab.Props['value']; + }, + forwardedRef: React.ForwardedRef, +) { + const { value, selectedValue, style, children, ...otherProps } = props; + return ( + + {children} + {value === selectedValue ? ( + + } + /> + ) : null} + + ); +}); + export default function ExampleTabs() { const [value, setValue] = React.useState('overview'); return ( - + Overview - - + + Projects - - + + Account - - +