Skip to content

Commit

Permalink
feat(segmented): animated strong segmented
Browse files Browse the repository at this point in the history
  • Loading branch information
nolimits4web committed Aug 31, 2021
1 parent f4c9c94 commit ecf6f71
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 5 deletions.
5 changes: 1 addition & 4 deletions src/react/components/Button.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,7 @@ const Button = forwardRef((props, ref) => {
'dark:active:bg-white dark:active:bg-opacity-5 dark:touch-ripple-white'
)
),
segmentedStrongActive: cls(
`bg-white shadow`,
dark('dark:bg-opacity-15 dark:touch-ripple-white')
),
segmentedStrongActive: 'duration-0',
},
size: {
small: {
Expand Down
49 changes: 48 additions & 1 deletion src/react/components/Segmented.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const Segmented = forwardRef((props, ref) => {
// Children
children,

activeButtonIndex = undefined,
childButtonsLength = undefined,

// Rest
...rest
} = props;
Expand Down Expand Up @@ -58,11 +61,46 @@ const Segmented = forwardRef((props, ref) => {
outline: `border-2 ${colors.border}`,
outlineInner: `-m-0.5 flex w-full justify-center items-center divide-x-2 ${colors.divide}`,
strong: cls(
'p-1 bg-black bg-opacity-5 space-x-1',
'p-0.5 bg-black bg-opacity-5 space-x-1 relative',
dark('dark:bg-white dark:bg-opacity-10')
),
strongHighlight: cls(
'bg-red-500 absolute left-0.5 top-0.5 bottom-0.5 !ml-0 pointer-events-none duration-200',
rounded ? 'rounded-full' : 'rounded',
`bg-white shadow`,
dark('dark:bg-opacity-15 dark:touch-ripple-white')
),
});

let highlightWidth;
let highlightTranslate;

if (strong) {
let buttonsLength = childButtonsLength;
let activeIndex = activeButtonIndex;
if (
typeof activeIndex === 'undefined' &&
children &&
(children.length || children.type === React.Fragment)
) {
const elements =
children.type === React.Fragment ? children.props.children : children;
if (typeof buttonsLength === 'undefined') {
buttonsLength = elements.length || 0;
}
const activeButton = elements.filter(
(child) =>
child.props && (child.props.active || child.props.segmentedActive)
)[0];
activeIndex = elements.indexOf(activeButton);
}

const between = '4px';
const padding = '2px';
highlightWidth = `calc((100% - ${padding} * 2 - ${between} * (${buttonsLength} - 1)) / ${buttonsLength})`;
highlightTranslate = `calc(${activeIndex} * 100% + ${activeIndex} * ${between})`;
}

const classes = cls(
// base
rounded ? c.base.rounded : c.base.square,
Expand All @@ -76,6 +114,15 @@ const Segmented = forwardRef((props, ref) => {
return (
<Component ref={elRef} className={classes} {...attrs}>
{outline ? <span className={c.outlineInner}>{children}</span> : children}
{strong && (
<span
className={c.strongHighlight}
style={{
width: highlightWidth,
transform: `translateX(${highlightTranslate})`,
}}
/>
)}
</Component>
);
});
Expand Down
13 changes: 13 additions & 0 deletions src/types/Segmented.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,17 @@ interface Props {
* @default false
*/
rounded?: boolean;

/**
* Only for `strong` segmented. Active index of the currently active button. If not specified it will look in child components for button with `active` or `segmenterActive` prop.
*
* @default undefined
*/
activeButtonIndex?: number;
/**
* Only for `strong` segmented. Amount of segmented buttons. If not specified it will look on the amount of child components.
*
* @default undefined
*/
childButtonsLength?: number;
}

0 comments on commit ecf6f71

Please sign in to comment.