CHANGES: Added unoptimized progress bar inside <Slider> component
FIXED: Some styles
This commit is contained in:
parent
f736f73a1f
commit
ead00b5ae9
23
app/page.tsx
23
app/page.tsx
|
@ -61,7 +61,7 @@ export default function Page() {
|
||||||
<Button icon={'add'} iconPlace={'right'}>
|
<Button icon={'add'} iconPlace={'right'}>
|
||||||
Label 2
|
Label 2
|
||||||
</Button>
|
</Button>
|
||||||
<SegmentedButtons>
|
<SegmentedButtons toggled={true}>
|
||||||
<SegmentButton
|
<SegmentButton
|
||||||
fillIcon={1}
|
fillIcon={1}
|
||||||
icon={'change_history'}
|
icon={'change_history'}
|
||||||
|
@ -80,7 +80,26 @@ export default function Page() {
|
||||||
</SegmentButton>
|
</SegmentButton>
|
||||||
</SegmentedButtons>
|
</SegmentedButtons>
|
||||||
<Checkbox />
|
<Checkbox />
|
||||||
<Slider />
|
<Slider
|
||||||
|
defaultValue={0}
|
||||||
|
max={100}
|
||||||
|
min={0}
|
||||||
|
options={[0, 10, 20, 100]}
|
||||||
|
/>
|
||||||
|
<Slider defaultValue={0} max={100} min={0} />
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
list={'lol'}
|
||||||
|
max={100}
|
||||||
|
min={0}
|
||||||
|
type={'range'}
|
||||||
|
/>
|
||||||
|
<datalist id={'lol'}>
|
||||||
|
<option value={0} />
|
||||||
|
<option value={50} />
|
||||||
|
<option value={100} />
|
||||||
|
</datalist>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -6,7 +6,3 @@ export interface InputLayoutProps
|
||||||
typeInput?: string;
|
typeInput?: string;
|
||||||
type?: string;
|
type?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LabelPlacement {
|
|
||||||
labelPlacement?: 'left' | 'right';
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +1,46 @@
|
||||||
import React, { forwardRef, HTMLAttributes } from 'react';
|
'use client';
|
||||||
import { InputLayout } from '../input-layout/input-layout';
|
|
||||||
|
import { InputLayout } from '../input-layout/input-layout';
|
||||||
|
import React, { forwardRef, InputHTMLAttributes, useId, useState } from 'react';
|
||||||
|
|
||||||
|
interface SliderProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||||
|
options?: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Slider = forwardRef<HTMLInputElement, SliderProps>(
|
||||||
|
({ options, ...props }, ref) => {
|
||||||
|
const sliderId = useId();
|
||||||
|
const [progress, setProgress] = useState<number>(0);
|
||||||
|
|
||||||
export const Slider = forwardRef<
|
|
||||||
HTMLInputElement,
|
|
||||||
HTMLAttributes<HTMLInputElement>
|
|
||||||
>((props, ref) => {
|
|
||||||
return (
|
return (
|
||||||
<div className={'m3 m3-slider-container'}>
|
<div className={'m3 m3-slider-container'}>
|
||||||
<InputLayout
|
<InputLayout
|
||||||
|
{...props}
|
||||||
className={props.className}
|
className={props.className}
|
||||||
|
list={sliderId}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setProgress(
|
||||||
|
(parseInt(event.target.value) /
|
||||||
|
parseInt(event.target.max)) *
|
||||||
|
100,
|
||||||
|
);
|
||||||
|
}}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
style={{
|
||||||
|
...props.style,
|
||||||
|
background: `linear-gradient(to right, var(--md-sys-color-primary) ${progress}%, var(--md-sys-color-surface-container-highest) ${progress}%)`,
|
||||||
|
}}
|
||||||
type={'range'}
|
type={'range'}
|
||||||
typeInput={'slider'}
|
typeInput={'slider'}
|
||||||
/>
|
/>
|
||||||
|
{options && (
|
||||||
|
<datalist id={sliderId}>
|
||||||
|
{options.map((option, index) => (
|
||||||
|
<option key={index} value={option} />
|
||||||
|
))}
|
||||||
|
</datalist>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
|
@ -4,17 +4,14 @@ import { bool } from 'prop-types';
|
||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef } from 'react';
|
||||||
import { SwitchMainProps } from './switch.types';
|
import { SwitchMainProps } from './switch.types';
|
||||||
import { InputLayout } from '../input-layout/input-layout';
|
import { InputLayout } from '../input-layout/input-layout';
|
||||||
import { LabelPlacement } from '../input-layout/input-layout.types';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switch component
|
* Switch component
|
||||||
** description
|
** description
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const Switch = forwardRef<
|
export const Switch = forwardRef<HTMLInputElement, SwitchMainProps>(
|
||||||
HTMLInputElement,
|
({ icon, selected = false, ...props }, ref) => (
|
||||||
SwitchMainProps & LabelPlacement
|
|
||||||
>(({ icon, selected = false, ...props }, ref) => (
|
|
||||||
<>
|
<>
|
||||||
<div className={'m3 m3-switch'}>
|
<div className={'m3 m3-switch'}>
|
||||||
<InputLayout
|
<InputLayout
|
||||||
|
@ -29,7 +26,9 @@ export const Switch = forwardRef<
|
||||||
<circle className={'m3 m3-switch-handler-state-layer'} />
|
<circle className={'m3 m3-switch-handler-state-layer'} />
|
||||||
<g>
|
<g>
|
||||||
{icon && !selected && (
|
{icon && !selected && (
|
||||||
<text className={'m3 m3-icon-unchecked'}>close</text>
|
<text className={'m3 m3-icon-unchecked'}>
|
||||||
|
close
|
||||||
|
</text>
|
||||||
)}
|
)}
|
||||||
{icon && (
|
{icon && (
|
||||||
<text className={'m3 m3-icon-checked'}>check</text>
|
<text className={'m3 m3-icon-checked'}>check</text>
|
||||||
|
@ -38,7 +37,8 @@ export const Switch = forwardRef<
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
));
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Switch.propTypes = {
|
Switch.propTypes = {
|
||||||
icon: bool,
|
icon: bool,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { createElement, forwardRef } from 'react';
|
import { createElement, forwardRef } from 'react';
|
||||||
import { getTypographyRole } from './get-typography-role';
|
import { getTypographyRole } from './utils/get-typography-role';
|
||||||
import {
|
import {
|
||||||
TypographyProps,
|
TypographyProps,
|
||||||
Typography as TypographyTargetRef,
|
Typography as TypographyTargetRef,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { TypographyRole, TypographySize } from './typography.types';
|
import { TypographyRole, TypographySize } from '../typography.types';
|
||||||
|
|
||||||
export function getTypographyRole(role: TypographyRole, size: TypographySize) {
|
export function getTypographyRole(role: TypographyRole, size: TypographySize) {
|
||||||
switch (role) {
|
switch (role) {
|
|
@ -881,36 +881,39 @@ div.m3.m3-slider-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
div.m3.m3-slider-container > datalist {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
input[type=range].m3.m3-slider {
|
input[type=range].m3.m3-slider {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 4px;
|
|
||||||
appearance: none;
|
appearance: none;
|
||||||
overflow: visible;
|
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
margin-inline: 10px;
|
margin-inline: 8px;
|
||||||
background-color: var(--md-sys-color-surface-container-highest);
|
background: linear-gradient(to right, var(--md-sys-color-primary) 0%, var(--md-sys-color-surface-container-highest) 0%);
|
||||||
}
|
}
|
||||||
input[type=range].m3.m3-slider::-webkit-slider-container {
|
input[type=range].m3.m3-slider::-webkit-slider-container {
|
||||||
margin-inline: -8px;
|
appearance: none;
|
||||||
|
box-shadow: none;
|
||||||
|
border-radius: 2px;
|
||||||
|
min-block-size: 4px;
|
||||||
|
height: 4px !important;
|
||||||
|
}
|
||||||
|
input[type=range].m3.m3-slider::-webkit-slider-runnable-track {
|
||||||
|
height: 4px;
|
||||||
}
|
}
|
||||||
input[type=range].m3.m3-slider::-webkit-slider-thumb {
|
input[type=range].m3.m3-slider::-webkit-slider-thumb {
|
||||||
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.15), 0 1px 2px 0 rgba(0, 0, 0, 0.3);
|
box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.15), 0 1px 2px 0 rgba(0, 0, 0, 0.3);
|
||||||
width: 20px;
|
width: 20px;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
overflow: visible;
|
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
|
margin-top: -8px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
outline: 10px solid transparent;
|
outline: 10px solid transparent;
|
||||||
background: var(--md-sys-color-primary);
|
background: var(--md-sys-color-primary);
|
||||||
transition: 0.2s cubic-bezier(0.2, 0, 0, 1);
|
transition: 0.2s cubic-bezier(0.2, 0, 0, 1);
|
||||||
}
|
}
|
||||||
input[type=range].m3.m3-slider::-webkit-slider-thumb::after {
|
|
||||||
width: 40px;
|
|
||||||
aspect-ratio: 1;
|
|
||||||
background-color: transparent;
|
|
||||||
}
|
|
||||||
input[type=range].m3.m3-slider::-webkit-slider-thumb:hover {
|
input[type=range].m3.m3-slider::-webkit-slider-thumb:hover {
|
||||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent);
|
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent);
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -3,26 +3,30 @@ div.m3.m3-slider-container
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
|
|
||||||
|
& > datalist
|
||||||
|
display: none
|
||||||
|
|
||||||
|
|
||||||
input[type="range"].m3.m3-slider
|
input[type="range"].m3.m3-slider
|
||||||
margin: 0
|
margin: 0
|
||||||
height: 4px
|
|
||||||
appearance: none
|
appearance: none
|
||||||
overflow: visible
|
|
||||||
border-radius: 2px
|
border-radius: 2px
|
||||||
margin-inline: 10px
|
margin-inline: 8px
|
||||||
background-color: var(--md-sys-color-surface-container-highest)
|
background: linear-gradient(to right, var(--md-sys-color-primary) 0%, var(--md-sys-color-surface-container-highest) 0%)
|
||||||
|
|
||||||
&::-webkit-slider-container
|
&::-webkit-slider-container
|
||||||
margin-inline: -8px
|
appearance: none
|
||||||
|
box-shadow: none
|
||||||
|
border-radius: 2px
|
||||||
|
min-block-size: 4px
|
||||||
|
height: 4px !important
|
||||||
|
|
||||||
|
&::-webkit-slider-runnable-track
|
||||||
|
height: 4px
|
||||||
|
|
||||||
&::-webkit-slider-thumb
|
&::-webkit-slider-thumb
|
||||||
@include elevation-1(false)
|
@include elevation-1(false)
|
||||||
|
|
||||||
&::after
|
|
||||||
width: 40px
|
|
||||||
aspect-ratio: 1
|
|
||||||
background-color: transparent
|
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent)
|
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent)
|
||||||
|
|
||||||
|
@ -32,8 +36,8 @@ input[type="range"].m3.m3-slider
|
||||||
width: 20px
|
width: 20px
|
||||||
aspect-ratio: 1
|
aspect-ratio: 1
|
||||||
appearance: none
|
appearance: none
|
||||||
overflow: visible
|
|
||||||
border-radius: 50%
|
border-radius: 50%
|
||||||
|
margin-top: -8px
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
outline: 10px solid transparent
|
outline: 10px solid transparent
|
||||||
background: var(--md-sys-color-primary)
|
background: var(--md-sys-color-primary)
|
||||||
|
|
Loading…
Reference in New Issue