Skip to content

Commit

Permalink
feat: segmented support classnames and styles (#296)
Browse files Browse the repository at this point in the history
* feat: segmented support classnames and styles

* fix
  • Loading branch information
thinkasany authored Jan 16, 2025
1 parent 8afca79 commit 7f2e8f5
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 2 deletions.
25 changes: 23 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react';

import MotionThumb from './MotionThumb';

export type SemanticName = 'item' | 'label';
export type SegmentedValue = string | number;

export type SegmentedRawOption = SegmentedValue;
Expand Down Expand Up @@ -41,6 +42,8 @@ export interface SegmentedProps<ValueType = SegmentedValue>
motionName?: string;
vertical?: boolean;
name?: string;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
}

function getValidTitle(option: SegmentedLabeledOption) {
Expand Down Expand Up @@ -74,6 +77,9 @@ function normalizeOptions(options: SegmentedOptions): SegmentedLabeledOption[] {
const InternalSegmentedOption: React.FC<{
prefixCls: string;
className?: string;
style?: React.CSSProperties;
classNames?: Partial<Record<SemanticName, string>>;
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
disabled?: boolean;
checked: boolean;
label: React.ReactNode;
Expand All @@ -92,6 +98,9 @@ const InternalSegmentedOption: React.FC<{
}> = ({
prefixCls,
className,
style,
styles,
classNames: segmentedClassNames,
disabled,
checked,
label,
Expand All @@ -117,6 +126,7 @@ const InternalSegmentedOption: React.FC<{
className={classNames(className, {
[`${prefixCls}-item-disabled`]: disabled,
})}
style={style}
onMouseDown={onMouseDown}
>
<input
Expand All @@ -132,9 +142,13 @@ const InternalSegmentedOption: React.FC<{
onKeyUp={onKeyUp}
/>
<div
className={`${prefixCls}-item-label`}
className={classNames(
`${prefixCls}-item-label`,
segmentedClassNames?.label,
)}
title={title}
aria-selected={checked}
style={styles?.label}
>
{label}
</div>
Expand All @@ -155,6 +169,9 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
name,
onChange,
className = '',
style,
styles,
classNames: segmentedClassNames,
motionName = 'thumb-motion',
...restProps
} = props;
Expand Down Expand Up @@ -240,12 +257,12 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
break;
}
};

return (
<div
role="radiogroup"
aria-label="segmented control"
tabIndex={disabled ? undefined : 0}
style={style}
{...divProps}
className={classNames(
prefixCls,
Expand Down Expand Up @@ -285,6 +302,7 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
className={classNames(
segmentedOption.className,
`${prefixCls}-item`,
segmentedClassNames?.item,
{
[`${prefixCls}-item-selected`]:
segmentedOption.value === rawValue && !thumbShow,
Expand All @@ -294,6 +312,9 @@ const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>(
segmentedOption.value === rawValue,
},
)}
style={styles?.item}
classNames={segmentedClassNames}
styles={styles}
checked={segmentedOption.value === rawValue}
onChange={handleChange}
onFocus={handleFocus}
Expand Down
34 changes: 34 additions & 0 deletions tests/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -765,4 +765,38 @@ describe('Segmented keyboard navigation', () => {
'rc-segmented-item-input-focused',
);
});
it('should apply custom styles to Segmented', () => {
const customClassNames = {
item: 'custom-item',
label: 'custom-label',
};

const customStyles = {
item: { color: 'yellow' },
label: { backgroundColor: 'black' },
};

const { container } = render(
<Segmented
options={['iOS', 'Android', 'Web']}
classNames={customClassNames}
styles={customStyles}
/>,
);

const itemElement = container.querySelector(
'.rc-segmented-item',
) as HTMLElement;
const labelElement = container.querySelector(
'.rc-segmented-item-label',
) as HTMLElement;

// check classNames
expect(itemElement.classList).toContain('custom-item');
expect(labelElement.classList).toContain('custom-label');

// check styles
expect(itemElement.style.color).toBe('yellow');
expect(labelElement.style.backgroundColor).toBe('black');
});
});

0 comments on commit 7f2e8f5

Please sign in to comment.