React tabs UI component providing comprehensive, accessible, and customizable tabbed interfaces
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Animation system with configurable ink bar and tab pane transitions for smooth user experiences. RC Tabs integrates with rc-motion to provide fluid animations and visual feedback during tab interactions.
Comprehensive animation settings for different parts of the tabs interface.
/**
* Animation configuration object controlling various transition effects
*/
interface AnimatedConfig {
/** Enable/disable ink bar animation (the moving underline indicator) */
inkBar?: boolean;
/** Enable/disable tab pane content transitions */
tabPane?: boolean;
/** Custom motion configuration for tab pane transitions */
tabPaneMotion?: CSSMotionProps;
}
/**
* Simple boolean animation control
* - true: Enables both ink bar and tab pane animations with defaults
* - false: Disables all animations
*/
type AnimatedSimple = boolean;
/**
* Combined animation prop type
*/
type AnimatedProp = boolean | AnimatedConfig;Usage Examples:
import Tabs from "rc-tabs";
// Disable all animations
function NoAnimationTabs() {
return (
<Tabs
animated={false}
items={tabItems}
/>
);
}
// Enable all animations with defaults
function AnimatedTabs() {
return (
<Tabs
animated={true} // Both ink bar and tab pane animations
items={tabItems}
/>
);
}
// Custom animation configuration
function CustomAnimatedTabs() {
return (
<Tabs
animated={{
inkBar: true, // Enable ink bar animation
tabPane: false, // Disable tab pane animation
}}
items={tabItems}
/>
);
}The ink bar is the visual indicator that shows which tab is currently active, typically appearing as an underline or highlight.
/**
* Ink bar animation configuration
* Controls the animated indicator that follows the active tab
*/
interface InkBarConfig {
/** Whether to animate the ink bar movement between tabs */
inkBar?: boolean;
}Ink Bar Behavior:
// Tabs with animated ink bar only
function InkBarOnlyTabs() {
return (
<Tabs
animated={{
inkBar: true, // Smooth ink bar transitions
tabPane: false, // No content animation
}}
tabPosition="top"
items={[
{ key: '1', label: 'Short', children: <div>Content 1</div> },
{ key: '2', label: 'Much Longer Tab', children: <div>Content 2</div> },
{ key: '3', label: 'Medium', children: <div>Content 3</div> },
]}
/>
);
}Content area animations that occur when switching between tabs.
/**
* Tab pane animation configuration
* Controls transitions for tab content areas
*/
interface TabPaneConfig {
/** Whether to animate tab pane content changes */
tabPane?: boolean;
/** Custom motion configuration for advanced transitions */
tabPaneMotion?: CSSMotionProps;
}
/**
* CSS Motion properties from rc-motion library
* Provides advanced animation control for tab pane transitions
*/
interface CSSMotionProps {
/** CSS transition or animation name */
motionName?: string;
/** Animation appear behavior when component first mounts */
motionAppear?: boolean;
/** Animation enter behavior when becoming visible */
motionEnter?: boolean;
/** Animation leave behavior when becoming hidden */
motionLeave?: boolean;
/** Duration for appear animation */
motionAppearDuration?: number;
/** Duration for enter animation */
motionEnterDuration?: number;
/** Duration for leave animation */
motionLeaveDuration?: number;
/** Custom motion event handlers */
onAppearStart?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onEnterStart?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onLeaveStart?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onAppearActive?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onEnterActive?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onLeaveActive?: (node: HTMLElement, done: () => void) => CSSMotionEvent;
onAppearEnd?: (node: HTMLElement, done: () => void) => boolean | void;
onEnterEnd?: (node: HTMLElement, done: () => void) => boolean | void;
onLeaveEnd?: (node: HTMLElement, done: () => void) => boolean | void;
}
/**
* CSS Motion event object
*/
interface CSSMotionEvent {
deadline?: boolean;
target?: HTMLElement;
}Usage Examples:
// Default tab pane animations
function DefaultPaneAnimation() {
return (
<Tabs
animated={{
inkBar: true,
tabPane: true, // Uses default fade transition
}}
items={tabItems}
/>
);
}
// Custom tab pane motion
function CustomPaneMotion() {
return (
<Tabs
animated={{
inkBar: true,
tabPane: true,
tabPaneMotion: {
motionName: 'slide', // Custom CSS class prefix
motionAppear: false,
motionEnter: true,
motionLeave: false,
},
}}
items={tabItems}
/>
);
}
// No content animation, only ink bar
function InkBarOnly() {
return (
<Tabs
animated={{
inkBar: true,
tabPane: false, // Instant content switching
}}
items={tabItems}
/>
);
}Different animation behaviors based on tab positioning.
/**
* Animation behavior varies by tab position
* - top/bottom: Horizontal ink bar movement, vertical content transitions
* - left/right: Vertical ink bar movement, horizontal content transitions
*/
type PositionAnimationBehavior = {
'top': 'horizontal-ink-bar',
'bottom': 'horizontal-ink-bar',
'left': 'vertical-ink-bar',
'right': 'vertical-ink-bar',
};// Vertical tabs with appropriate animations
function VerticalAnimatedTabs() {
return (
<Tabs
tabPosition="left"
animated={true} // Ink bar moves vertically
items={[
{ key: '1', label: 'First', children: <div>First content</div> },
{ key: '2', label: 'Second', children: <div>Second content</div> },
{ key: '3', label: 'Third', children: <div>Third content</div> },
]}
/>
);
}
// Bottom positioned tabs
function BottomAnimatedTabs() {
return (
<Tabs
tabPosition="bottom"
animated={{
inkBar: true, // Horizontal movement above content
tabPane: true,
}}
items={tabItems}
/>
);
}Animation settings that affect performance and user experience.
/**
* Performance optimization strategies for animations
*/
interface AnimationPerformance {
/** Disable animations on low-end devices */
respectMotionPreferences?: boolean;
/** Reduce animation complexity for many tabs */
optimizeForTabCount?: boolean;
/** CSS-only animations vs JavaScript-driven */
useCSSSTransitions?: boolean;
}Performance Best Practices:
// Optimized for performance
function PerformantAnimatedTabs() {
const [isLowEndDevice, setIsLowEndDevice] = useState(false);
useEffect(() => {
// Detect low-end devices or user preferences
setIsLowEndDevice(
navigator.hardwareConcurrency < 4 ||
window.matchMedia('(prefers-reduced-motion: reduce)').matches
);
}, []);
return (
<Tabs
animated={isLowEndDevice ? false : true}
items={tabItems}
/>
);
}
// Selective animation for large tab sets
function ManyTabsAnimation({ tabCount }: { tabCount: number }) {
return (
<Tabs
animated={{
inkBar: true, // Keep ink bar for visual feedback
tabPane: tabCount < 10, // Disable content animation for many tabs
}}
items={generateManyTabs(tabCount)}
/>
);
}RC Tabs generates CSS classes that can be styled for custom animations.
/**
* Generated CSS classes for animation styling
* Prefix customizable via prefixCls prop (default: 'rc-tabs')
*/
interface AnimationClasses {
/** Ink bar animation classes */
inkBar: '.rc-tabs-ink-bar';
/** Tab pane motion classes */
tabPane: '.rc-tabs-content-animated';
/** Individual tab transitions */
tab: '.rc-tabs-tab';
}Custom CSS Animation Example:
/* Custom ink bar animation */
.custom-tabs .rc-tabs-ink-bar {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
background: linear-gradient(90deg, #1890ff, #722ed1);
height: 3px;
}
/* Custom tab pane transitions */
.custom-tabs .rc-tabs-content-animated .rc-tabs-tabpane {
transition: opacity 0.2s ease-in-out;
}
.custom-tabs .rc-tabs-content-animated .rc-tabs-tabpane-inactive {
opacity: 0;
pointer-events: none;
}
.custom-tabs .rc-tabs-content-animated .rc-tabs-tabpane-active {
opacity: 1;
}// Using custom animation styles
function CustomStyledTabs() {
return (
<Tabs
className="custom-tabs"
animated={true}
items={tabItems}
/>
);
}Install with Tessl CLI
npx tessl i tessl/npm-rc-tabs