Skip to content

Commit

Permalink
core: slider component
Browse files Browse the repository at this point in the history
Signed-off-by: Valentin Chanas <anisometropie@gmail.com>
  • Loading branch information
anisometropie committed Nov 26, 2024
1 parent 3ffe206 commit 4079f88
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 0 deletions.
57 changes: 57 additions & 0 deletions ui-core/src/components/inputs/Slider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import React, { useState } from 'react';
import type { ChangeEvent, MouseEvent, InputHTMLAttributes } from 'react';

import cx from 'classnames';

export type SliderProps = InputHTMLAttributes<HTMLInputElement> & {
onChangeCommitted?: (e: MouseEvent<HTMLInputElement>) => void;
};

// onChange returns an event or number
const Slider = ({
id,
value: initialValue,
min = 0,
max = 100,
step = 1,
onChange,
onChangeCommitted,
disabled,
...rest
}: SliderProps) => {
const [value, setValue] = useState<number>(
initialValue !== undefined ? Number(initialValue) : Number(min)
);

const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const newValue = Number(e.target.value);
setValue(newValue);
onChange?.(e);
};

const handleMouseUp = (e: MouseEvent<HTMLInputElement>) => {
if (onChangeCommitted) {
onChangeCommitted(e);
}
};

return (
<div className="range-wrapper">
<input
type="range"
className={cx('range-slider', { 'range-slider-disabled': disabled })}
id={id}
value={value}
min={min}
max={max}
step={step}
onChange={handleChange}
onMouseUp={handleMouseUp}
disabled={disabled}
{...rest}
/>
</div>
);
};

export default Slider;
59 changes: 59 additions & 0 deletions ui-core/src/stories/Slider.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useState } from 'react';

import { type Meta, type StoryObj } from '@storybook/react';

import Slider, { type SliderProps } from '../components/inputs/Slider';

import './stories.css';

const Wrapper = (props: SliderProps) => {
const [value, setValue] = useState(0);
const [committedValue, setCommittedValue] = useState(0);

return (
<div className="wrapper-container">
<div className="values-container">
<div className="value-box">Value: {value}</div>
<div className="value-box">Committed Value: {committedValue}</div>
</div>
<div className="slider-container">
<Slider
value={value}
onChange={(e) => {
setValue(Number(e.target.value));
}}
onChangeCommitted={(e) => {
setCommittedValue(Number(e.currentTarget.value));
}}
{...props}
/>
</div>
</div>
);
};

const meta: Meta<typeof Wrapper> = {
component: Wrapper,
args: {
disabled: false,
},
decorators: [
(Story) => (
<div style={{ maxWidth: 'fit-content' }}>
<Story />
</div>
),
],
title: 'Core/Slider',
tags: ['autodocs'],
};

export default meta;

type Story = StoryObj<typeof Slider>;

export const Value: Story = {
args: {
disabled: false,
},
};
28 changes: 28 additions & 0 deletions ui-core/src/stories/stories.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,31 @@
width: 300px;
}
}

.wrapper-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 50px;
text-align: center;
}

.values-container {
display: flex;
gap: 20px;
margin-bottom: 40px;
}

.value-box {
padding: 20px;
font-size: 18px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
}

.slider-container {
width: 100%;
max-width: 600px;
}
1 change: 1 addition & 0 deletions ui-core/src/styles/inputs/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
@import './tokenInput.css';
@import './tolerancePicker.css';
@import './comboBox.css';
@import './slider.css';
72 changes: 72 additions & 0 deletions ui-core/src/styles/inputs/slider.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.range-wrapper {
margin: 50px;
width: 80%;
height: 10px;

.range-slider {
-webkit-appearance: none;
appearance: none;
height: 10px;
width: 100%;

&::-webkit-slider-runnable-track {
-webkit-appearance: none;
appearance: none;
height: 4px;
border-radius: 2px;
box-shadow: 0px 0px 0px 0.5px rgba(0, 0, 0, 0.25) inset;
background-color: rgba(0, 0, 0, 0.05);
}

&::-moz-range-track {
-webkit-appearance: none;
appearance: none;
height: 4px;
border-radius: 2px;
box-shadow: 0px 0px 0px 0.5px rgba(0, 0, 0, 0.25) inset;
background-color: rgba(0, 0, 0, 0.05);
}

&::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
margin-top: -3px;
border-radius: 50%;
border: 0.5px solid rgba(73, 70, 65, 1);
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25);
opacity: 1;
background-color: rgba(255, 255, 255, 1);
}

&::-moz-range-thumb {
-webkit-appearance: none;
appearance: none;
width: 10px;
height: 10px;
margin-top: -3px;
border-radius: 50%;
border: 0.5px solid rgba(73, 70, 65, 1);
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25);
opacity: 1;
background-color: rgba(255, 255, 255, 1);
}
}

.range-slider-disabled {
&::-webkit-slider-thumb {
border: 0.5px solid rgb(182, 179, 175);
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.5);
opacity: 1;
background-color: rgba(255, 255, 255, 1);
}

&::-moz-range-thumb {
border: 0.5px solid rgb(182, 179, 175);
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.5);
opacity: 1;
background-color: rgba(255, 255, 255, 1);
}
}
}

0 comments on commit 4079f88

Please sign in to comment.