segmented.tsx
Overview
The segmented.tsx file defines a reusable React functional component named Segmented. This component renders a segmented control UI element, which allows users to select one option from a set of choices displayed as adjacent segments (similar to a tab or toggle group). Each segment represents an option, which may be a simple string/number or an object with additional metadata such as labels, disabled state, and custom CSS classes.
This component manages internal selection state and supports controlled and uncontrolled modes via props. It also provides styling hooks to customize the active segment appearance.
Detailed Explanation
Types and Interfaces
SegmentedValue
export declare type SegmentedValue = string | number;
Represents the value type of an option, which can be either a string or a number.
SegmentedRawOption
export declare type SegmentedRawOption = SegmentedValue;
A raw option is just a value without any additional metadata.
SegmentedLabeledOption
export interface SegmentedLabeledOption {
className?: string;
disabled?: boolean;
label: React.ReactNode;
value: SegmentedRawOption;
title?: string;
}
Describes an option object with additional properties:
className(optional): Custom CSS class for the segment.disabled(optional): If true, disables the segment (not handled explicitly in current code but reserved for future use).label: Content displayed inside the segment (can be any React node).value: The value representing this option.title(optional): HTMLtitleattribute for tooltip.
SegmentedOptions
type SegmentedOptions = (SegmentedRawOption | SegmentedLabeledOption)[];
The options prop can be an array of either raw values or labeled option objects.
SegmentedProps
export interface SegmentedProps extends Omit<React.HTMLProps<HTMLDivElement>, 'onChange'> {
options: SegmentedOptions;
defaultValue?: SegmentedValue;
value?: SegmentedValue;
onChange?: (value: SegmentedValue) => void;
disabled?: boolean;
prefixCls?: string;
direction?: 'ltr' | 'rtl';
motionName?: string;
activeClassName?: string;
}
Props accepted by the
Segmentedcomponent:options: The array of selectable options.defaultValue: Initial selected value (uncontrolled mode).value: Controlled selected value.onChange: Callback fired when selected value changes.disabled: (Not explicitly handled in current code) Disable the whole control.prefixCls: Optional CSS prefix (not used internally).direction: Text direction (left-to-right or right-to-left) (not used internally).motionName: Animation class (not used internally).activeClassName: Additional CSS class applied to the active segment.
Segmented React Component
export function Segmented({
options,
value,
onChange,
className,
activeClassName,
}: SegmentedProps) {
const [selectedValue, setSelectedValue] = React.useState<
SegmentedValue | undefined
>(value);
const handleOnChange = (e: SegmentedValue) => {
if (onChange) {
onChange(e);
}
setSelectedValue(e);
};
return (
<div
className={cn(
'flex items-center rounded-3xl p-1 gap-2 bg-bg-card px-5 py-2.5',
className,
)}
>
{options.map((option) => {
const isObject = typeof option === 'object';
const actualValue = isObject ? option.value : option;
return (
<div
key={actualValue}
className={cn(
'inline-flex items-center px-6 py-2 text-base font-normal rounded-3xl cursor-pointer',
{
'text-bg-base bg-metallic-gradient border-b-[#00BEB4] border-b-2':
selectedValue === actualValue,
},
activeClassName && selectedValue === actualValue
? activeClassName
: '',
)}
onClick={() => handleOnChange(actualValue)}
>
{isObject ? option.label : option}
</div>
);
})}
</div>
);
}
Parameters
options(SegmentedOptions): Array of options displayed as segments.value(SegmentedValue | undefined): Controlled selected value.onChange((value: SegmentedValue) => void | undefined): Callback when selection changes.className(string | undefined): Additional CSS classes for the root container.activeClassName(string | undefined): Additional CSS classes for the active segment.
Returns
JSX element rendering the segmented control.
Behavior and Implementation Details
The component maintains internal state
selectedValueinitialized with the controlledvalueprop.Clicking on a segment triggers
handleOnChange, updating internal state and invoking theonChangecallback if provided.Each option renders as a
<div>styled as a segment. If the option is an object, it usesoption.labelandoption.value; otherwise, the option itself is used as both label and value.The active segment receives a special styling class (default and optionally
activeClassName).Utilizes a utility function
cn(assumed to be a classnames utility) to conditionally join CSS classes.Does not currently handle disabled options or other props like
direction,motionName, orprefixClsinternally.
Usage Example
import { Segmented } from './segmented';
const options = [
{ label: 'Option 1', value: 'opt1' },
'Option 2',
{ label: <b>Option 3</b>, value: 'opt3', className: 'custom-class' },
];
function App() {
const [selected, setSelected] = React.useState('opt1');
return (
<Segmented
options={options}
value={selected}
onChange={setSelected}
className="my-segmented"
activeClassName="active-segment"
/>
);
}
Important Implementation Details
Controlled vs Uncontrolled State: The component accepts a
valueprop for controlled usage but internally callssetSelectedValueto update local state. However, the current implementation initializes state only from thevalueprop once and never syncs back on prop changes, which means it behaves as uncontrolled ifvaluechanges externally after mount.Styling: The component applies a base style for layout and active segment indication using Tailwind CSS utility classes and supports additional class injection via props.
Options Flexibility: Options can be simple strings/numbers or rich objects with labels and metadata, enhancing flexibility.
No Disabled Handling: Although the
SegmentedLabeledOptioninterface defines adisabledproperty, this is not currently implemented in the component behavior or styling.No Keyboard Accessibility: The segments are simple
<div>elements with click handlers but lack keyboard navigability and ARIA roles for accessibility.
Interaction with Other Parts of the System
Utility Function
cn: The component importscnfrom'@/lib/utils', presumably a classnames helper function that conditionally concatenates CSS class names.React Library: Uses React for state management and JSX rendering.
Styling System: The component relies heavily on Tailwind CSS utility classes for styling.
Parent Components: This component can be used anywhere in the React app where a segmented control UI is needed, and it communicates selection changes upwards via the
onChangecallback.
Mermaid Diagram: Component Structure and Workflow
componentDiagram
Segmented <|-- React.Component
Segmented : +props: SegmentedProps
Segmented : +state: selectedValue
Segmented : +handleOnChange(value: SegmentedValue)
Segmented : +render()
Segmented --> "Segment[]" : options prop
note right of Segmented
- Renders segmented control UI
- Manages selection state
- Calls onChange callback on selection
end note
Summary
The segmented.tsx file provides a versatile, styled segmented control component in React, supporting flexible options and selection management. While simple and clean in design, it currently lacks some accessibility features and complete prop handling for disabled state and controlled mode updates. It fits into a UI library or component set where segmented selection is required, leveraging Tailwind CSS and a utility for class name management.
If you need additional details such as how to extend this component with accessibility or animations, or integration examples within a larger app, please ask!