Skip to content

Commit

Permalink
feat(slider): ✨ improve tooltip interaction (#214)
Browse files Browse the repository at this point in the history
  • Loading branch information
navin-moorthy authored Dec 1, 2021
1 parent 963ecee commit fbe823b
Show file tree
Hide file tree
Showing 14 changed files with 286 additions and 29 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
]
},
"dependencies": {
"@react-aria/interactions": "^3.7.0",
"@react-aria/live-announcer": "^3.0.1",
"@renderlesskit/react": "^0.9.1",
"reakit": "^1.3.11",
Expand Down
12 changes: 11 additions & 1 deletion src/slider/SliderProps.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,15 @@ const componentMap = {

export const useSliderProps = (props: React.PropsWithChildren<SliderProps>) => {
const [state, sliderProps] = useSliderStateSplit(props);
const { range, size, knobIcon, tooltip, ...thumbState } = state;
const {
range,
size,
knobIcon,
tooltip,
isDragging,
setIsDragging,
...thumbState
} = state;
const { children, ...restProps } = sliderProps;
const { componentProps, finalChildren } = getComponentProps(
componentMap,
Expand Down Expand Up @@ -61,6 +69,8 @@ export const useSliderProps = (props: React.PropsWithChildren<SliderProps>) => {
size,
knobIcon,
tooltip,
isDragging,
setIsDragging,
sliderState: thumbState,
...componentProps.thumbProps,
};
Expand Down
51 changes: 47 additions & 4 deletions src/slider/SliderState.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as React from "react";
import {
SliderAction as RenderlesskitSliderActions,
SliderInitialState as RenderlesskitSliderInitialState,
Expand Down Expand Up @@ -34,9 +35,19 @@ export type SliderState = RenderlesskitSliderState & {
* Provide custom icons as a replacement for the default ones.
*/
knobIcon: RenderPropType<SliderThumbStateReturn>;

/**
* True, if the value start to change.
*/
isDragging: boolean;
};

export type SliderActions = RenderlesskitSliderActions & {};
export type SliderActions = RenderlesskitSliderActions & {
/**
* Action to change the draggin state
*/
setIsDragging: React.Dispatch<React.SetStateAction<boolean>>;
};

export type SliderStateReturn = SliderState & SliderActions;

Expand All @@ -47,13 +58,45 @@ export function useSliderState(props: SliderInitialState): SliderStateReturn {
const {
range = false,
size = "md",
knobIcon,
tooltip = true,
knobIcon,
onChange: onInitialOnChange,
onChangeEnd: onInitialOnChangeEnd,
...rest
} = props;
const slider = useRenderlesskitSliderState(rest);
const [isDragging, setIsDragging] = React.useState(false);

const onChange = React.useCallback(
(value: number[]) => {
onInitialOnChange?.(value);
if (!isDragging) setIsDragging(true);
},
[isDragging, onInitialOnChange],
);

return { ...slider, range, size, knobIcon, tooltip };
const onChangeEnd = React.useCallback(
(value: number[]) => {
onInitialOnChangeEnd?.(value);
setIsDragging(false);
},
[onInitialOnChangeEnd],
);

const sliderState = useRenderlesskitSliderState({
...rest,
onChange,
onChangeEnd,
});

return {
...sliderState,
range,
size,
knobIcon,
tooltip,
isDragging,
setIsDragging,
};
}

export const SliderDefaultKnobIcon: SliderProps["knobIcon"] = state => {
Expand Down
50 changes: 35 additions & 15 deletions src/slider/SliderThumb.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import * as React from "react";

import { Tooltip } from "../tooltip";
import { ArrowIcon } from "../icons";
import {
TooltipArrow,
TooltipArrowContent,
TooltipContent,
TooltipWrapper,
useTooltipState,
} from "../tooltip";
import { SliderTooltipReference } from "../tooltip/SliderTooltipReference";
import { runIfFn, withIconA11y } from "../utils";

import { SliderThumbContainer } from "./SliderThumbContainer";
Expand All @@ -21,23 +29,35 @@ export const SliderThumb = React.forwardRef<HTMLDivElement, SliderThumbProps>(
const { wrapperProps, containerProps, inputProps, state } =
useSliderThumbProps(props);

const tooltip = useTooltipState({});

return (
<SliderThumbWrapper {...wrapperProps}>
{state.tooltip && !state.sliderState.baseState.isDisabled ? (
<Tooltip
side="top"
withArrow
content={state.sliderState.baseState.getThumbValueLabel(
state.index,
)}
>
<SliderThumbContainer {...containerProps} tabIndex={-1}>
<SliderThumbInput ref={ref} {...inputProps} />
{state.knobIcon
? withIconA11y(runIfFn(state.knobIcon, state))
: null}
</SliderThumbContainer>
</Tooltip>
<>
<SliderTooltipReference
isDragging={state.isDragging}
setIsDragging={state.setIsDragging}
{...tooltip}
>
<SliderThumbContainer {...containerProps} tabIndex={-1}>
<SliderThumbInput ref={ref} {...inputProps} />
{state.knobIcon
? withIconA11y(runIfFn(state.knobIcon, state))
: null}
</SliderThumbContainer>
</SliderTooltipReference>
<TooltipWrapper ref={ref} {...tooltip}>
<TooltipContent {...tooltip}>
{state.sliderState.baseState.getThumbValueLabel(state.index)}
<TooltipArrow {...tooltip}>
<TooltipArrowContent {...tooltip}>
{withIconA11y(runIfFn(<ArrowIcon />, state))}
</TooltipArrowContent>
</TooltipArrow>
</TooltipContent>
</TooltipWrapper>
</>
) : (
<SliderThumbContainer {...containerProps} tabIndex={-1}>
<SliderThumbInput ref={ref} {...inputProps} />
Expand Down
34 changes: 30 additions & 4 deletions src/slider/SliderThumbState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,46 @@ export type SliderThumbState = RenderlesskitSliderThumbState & {
* Provide custom icons as a replacement for the default ones.
*/
knobIcon: RenderPropType<SliderThumbStateReturn>;

/**
* True, if the value start to change.
*/
isDragging: boolean;
};

export type SliderThumbActions = RenderlesskitSliderThumbActions & {};
export type SliderThumbActions = RenderlesskitSliderThumbActions & {
/**
* Action to change the draggin state
*/
setIsDragging: React.Dispatch<React.SetStateAction<boolean>>;
};

export type SliderThumbStateReturn = SliderThumbState & SliderThumbActions;

export type SliderThumbInitialState = RenderlesskitSliderThumbInitialState &
Partial<Pick<SliderThumbState, "size" | "knobIcon" | "tooltip">> & {};
Partial<Pick<SliderThumbState, "size" | "knobIcon" | "tooltip">> &
Pick<SliderThumbStateReturn, "isDragging" | "setIsDragging"> & {};

export function useSliderThumbState(
props: SliderThumbInitialState,
): SliderThumbStateReturn {
const { size = "md", knobIcon, tooltip = true, ...rest } = props;
const {
size = "md",
knobIcon,
tooltip = true,
isDragging,
setIsDragging,
...rest
} = props;
const sliderThumb = useRenderlesskitSliderThumbState(rest);

return { ...sliderThumb, knobIcon, index: props.index, size, tooltip };
return {
...sliderThumb,
knobIcon,
index: props.index,
size,
tooltip,
isDragging,
setIsDragging,
};
}
6 changes: 6 additions & 0 deletions src/slider/__keys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const SLIDER_STATE_KEYS = [
"range",
"tooltip",
"knobIcon",
"isDragging",
"setIsDragging",
] as const;
export const USE_SLIDER_STATE_KEYS = [
"orientation",
Expand Down Expand Up @@ -44,6 +46,8 @@ export const SLIDER_THUMB_STATE_KEYS = [
"index",
"tooltip",
"knobIcon",
"isDragging",
"setIsDragging",
] as const;
export const USE_SLIDER_THUMB_STATE_KEYS = [
"sliderState",
Expand All @@ -69,6 +73,8 @@ export const USE_SLIDER_THUMB_STATE_KEYS = [
"size",
"knobIcon",
"tooltip",
"isDragging",
"setIsDragging",
] as const;
export const SLIDER_FILLED_TRACK_KEYS = [
...SLIDER_STATE_KEYS,
Expand Down
2 changes: 1 addition & 1 deletion src/slider/stories/SliderRange.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentMeta, ComponentStoryObj } from "@storybook/react";

import { createControls, createPreviewTabs } from "../../../.storybook/utils";
import { SliderDefaultKnobIcon } from "..";
import { SliderDefaultKnobIcon } from "../SliderState";

import js from "./templates/SliderRangeJsx";
import ts from "./templates/SliderRangeTsx";
Expand Down
2 changes: 1 addition & 1 deletion src/switch/stories/SwitchBasic.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentMeta, ComponentStoryObj } from "@storybook/react";

import { createControls, createPreviewTabs } from "../../../.storybook/utils";
import { Switch, SwitchText } from "..";
import { Switch, SwitchText } from "../index";

import js from "./templates/SwitchBasicJsx";
import ts from "./templates/SwitchBasicTsx";
Expand Down
Loading

1 comment on commit fbe823b

@vercel
Copy link

@vercel vercel bot commented on fbe823b Dec 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.