ADDED: slider label but it's not done
This commit is contained in:
parent
1410861afb
commit
33bd4f57a6
99
app/page.tsx
99
app/page.tsx
|
@ -1,109 +1,14 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Card } from '../src/primitive-components/card/card';
|
import { Card } from '../src/primitive-components/card/card';
|
||||||
import {
|
|
||||||
Button,
|
|
||||||
FAB,
|
|
||||||
IconButton,
|
|
||||||
} from '../src/primitive-components/components';
|
|
||||||
import { CardFooter } from '../src/primitive-components/card/card-footer';
|
import { CardFooter } from '../src/primitive-components/card/card-footer';
|
||||||
import { SegmentButton } from '../src/primitive-components/button-components/segmented-buttons/segment-button';
|
import { Slider } from '../src/primitive-components/input-components/slider/slider';
|
||||||
import { SegmentedButtons } from '../src/primitive-components/button-components/segmented-buttons/segmented-buttons';
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
return (
|
return (
|
||||||
<main>
|
<main>
|
||||||
<Card variant={'outlined'}>
|
<Card variant={'outlined'}>
|
||||||
<CardFooter>
|
<CardFooter>
|
||||||
<Button> Default Button </Button>
|
<Slider />
|
||||||
<Button ripple={false}> Default Button </Button>
|
|
||||||
<FAB icon={'edit'} variant={'secondary'} />
|
|
||||||
<FAB icon={'edit'} ripple={false} variant={'secondary'} />
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
variant={'filled'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
variant={'default'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
variant={'tonal'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
variant={'outlined'}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
toggled={{
|
|
||||||
selected: 'settings',
|
|
||||||
unselected: 'settings',
|
|
||||||
}}
|
|
||||||
variant={'filled'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
toggled={{
|
|
||||||
selected: 'settings',
|
|
||||||
unselected: 'settings',
|
|
||||||
}}
|
|
||||||
variant={'default'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
toggled={{
|
|
||||||
selected: 'settings',
|
|
||||||
unselected: 'settings',
|
|
||||||
}}
|
|
||||||
variant={'tonal'}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
icon={'settings'}
|
|
||||||
ripple={false}
|
|
||||||
toggled={{
|
|
||||||
selected: 'settings',
|
|
||||||
unselected: 'settings',
|
|
||||||
}}
|
|
||||||
variant={'outlined'}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SegmentedButtons density={-2} selectable={true}>
|
|
||||||
<SegmentButton
|
|
||||||
fillIcon={1}
|
|
||||||
icon={'change_history'}
|
|
||||||
ripple={false}
|
|
||||||
>
|
|
||||||
Label 1
|
|
||||||
</SegmentButton>
|
|
||||||
<SegmentButton
|
|
||||||
fillIcon={1}
|
|
||||||
icon={'change_history'}
|
|
||||||
iconPlace={'right'}
|
|
||||||
ripple={false}
|
|
||||||
selectable={false}
|
|
||||||
>
|
|
||||||
Not selectable
|
|
||||||
</SegmentButton>
|
|
||||||
<SegmentButton
|
|
||||||
fillIcon={1}
|
|
||||||
icon={'change_history'}
|
|
||||||
iconPlace={'right'}
|
|
||||||
ripple={false}
|
|
||||||
>
|
|
||||||
Label 3
|
|
||||||
</SegmentButton>
|
|
||||||
<SegmentButton disabled>Label 4</SegmentButton>
|
|
||||||
</SegmentedButtons>
|
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</Card>
|
||||||
</main>
|
</main>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { Typography } from '../../typography/typography';
|
||||||
import { InputLayout } from '../input-layout/input-layout';
|
import { InputLayout } from '../input-layout/input-layout';
|
||||||
import React, {
|
import React, {
|
||||||
ChangeEvent,
|
ChangeEvent,
|
||||||
|
@ -14,33 +15,71 @@ interface SliderProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||||
options?: number[];
|
options?: number[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function fractionCalc(current: number | string, max: number | string): number {
|
||||||
|
const _current = isNaN(parseInt(current as string))
|
||||||
|
? 50
|
||||||
|
: parseInt(current as string);
|
||||||
|
const _max = isNaN(parseInt(max as string)) ? 100 : parseInt(max as string);
|
||||||
|
|
||||||
|
return (_current / _max) * 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
function gradientStyle(value: number): string {
|
||||||
|
return `linear-gradient( to right, var(--md-sys-color-primary) ${value}%, var(--md-sys-color-surface-container-highest) ${value}%)`;
|
||||||
|
}
|
||||||
|
|
||||||
export const Slider = forwardRef<HTMLInputElement, SliderProps>(
|
export const Slider = forwardRef<HTMLInputElement, SliderProps>(
|
||||||
({ options, ...props }, ref) => {
|
({ options, ...props }, ref) => {
|
||||||
const sliderId = useId();
|
const sliderId = useId();
|
||||||
const [isChrome, setIsChrome] = useState<boolean>(false);
|
const [isChrome, setIsChrome] = useState<boolean>(false);
|
||||||
|
const [value, setValue] = useState(props.defaultValue ?? 50);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setIsChrome(navigator.userAgent.indexOf('AppleWebKit') != -1);
|
setIsChrome(navigator.userAgent.indexOf('AppleWebKit') != -1);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
if (isChrome) {
|
||||||
|
const initialFraction = fractionCalc(
|
||||||
|
(props.value as string) ?? (props.defaultValue as string),
|
||||||
|
props.max as string,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (props.style === undefined) {
|
||||||
|
props.style = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
props.style.background = gradientStyle(initialFraction);
|
||||||
|
}
|
||||||
|
|
||||||
|
const webkitProgress = (event: ChangeEvent<HTMLInputElement>) => {
|
||||||
|
if (isChrome) {
|
||||||
|
const fraction = fractionCalc(
|
||||||
|
(event.target.value as string) ??
|
||||||
|
(event.target.defaultValue as string),
|
||||||
|
event.target.max,
|
||||||
|
);
|
||||||
|
|
||||||
|
event.target.style.background = gradientStyle(fraction);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'m3 m3-slider-container'}>
|
<div className={'m3 m3-slider-container'}>
|
||||||
|
<div className={'m3 m3-slider-label'}>
|
||||||
|
<Typography role={'label'} size={'small'}>
|
||||||
|
{value}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
<InputLayout
|
<InputLayout
|
||||||
{...props}
|
{...props}
|
||||||
className={props.className}
|
className={props.className}
|
||||||
list={sliderId}
|
list={sliderId}
|
||||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||||
props.onChange?.apply(this, props?.onChange?.prototype);
|
props.onChange?.apply(this, props?.onChange?.prototype);
|
||||||
|
setValue(event.target.value);
|
||||||
|
|
||||||
if (isChrome) {
|
if (isChrome) {
|
||||||
const fraction =
|
webkitProgress(event);
|
||||||
(parseInt(event.target.value) /
|
|
||||||
parseInt(event.target.max)) *
|
|
||||||
100;
|
|
||||||
event.target.style.background = `linear-gradient(\
|
|
||||||
to right, var(--md-sys-color-primary) ${fraction}%, \
|
|
||||||
var(--md-sys-color-surface-container-highest) ${fraction}%\
|
|
||||||
)`;
|
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
|
|
@ -925,6 +925,29 @@ div.m3.m3-slider-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
div.m3.m3-slider-container div.m3.m3-slider-label {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
div.m3.m3-slider-container div.m3.m3-slider-label::before {
|
||||||
|
content: "";
|
||||||
|
width: 28px;
|
||||||
|
rotate: 45deg;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 14px 14px 0 14px;
|
||||||
|
background-color: var(--md-sys-color-primary);
|
||||||
|
}
|
||||||
|
div.m3.m3-slider-container div.m3.m3-slider-label > label.m3.m3-typography {
|
||||||
|
display: inline;
|
||||||
|
font-weight: 500;
|
||||||
|
position: absolute;
|
||||||
|
font-size: 12px !important;
|
||||||
|
color: var(--md-sys-color-on-primary);
|
||||||
|
}
|
||||||
div.m3.m3-slider-container > datalist {
|
div.m3.m3-slider-container > datalist {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -19,13 +19,32 @@
|
||||||
background: var(--md-sys-color-primary)
|
background: var(--md-sys-color-primary)
|
||||||
transition: .2s cubic-bezier(0.2, 0, 0, 1)
|
transition: .2s cubic-bezier(0.2, 0, 0, 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
div.m3.m3-slider-container
|
div.m3.m3-slider-container
|
||||||
height: 20px
|
height: 20px
|
||||||
display: flex
|
display: flex
|
||||||
align-items: center
|
align-items: center
|
||||||
|
|
||||||
|
div.m3.m3-slider-label
|
||||||
|
@include center(inline-flex)
|
||||||
|
position: absolute
|
||||||
|
pointer-events: none
|
||||||
|
|
||||||
|
&::before
|
||||||
|
content: ""
|
||||||
|
width: 28px
|
||||||
|
rotate: 45deg
|
||||||
|
aspect-ratio: 1
|
||||||
|
position: absolute
|
||||||
|
border-radius: 14px 14px 0 14px
|
||||||
|
background-color: var(--md-sys-color-primary)
|
||||||
|
|
||||||
|
& > label.m3.m3-typography
|
||||||
|
display: inline
|
||||||
|
font-weight: 500
|
||||||
|
position: absolute
|
||||||
|
font-size: 12px !important
|
||||||
|
color: var(--md-sys-color-on-primary)
|
||||||
|
|
||||||
& > datalist
|
& > datalist
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue