Skip to content

Commit 39f9bf8

Browse files
committed
✨ Add Slider component
1 parent 633d4f7 commit 39f9bf8

File tree

14 files changed

+348
-10
lines changed

14 files changed

+348
-10
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ import { Accordion } from 'webcoreui/react'
200200
- [Progress](https://github.com/Frontendland/webcoreui/tree/main/src/components/Progress)
201201
- [Radio](https://github.com/Frontendland/webcoreui/tree/main/src/components/Radio)
202202
- [Rating](https://github.com/Frontendland/webcoreui/tree/main/src/components/Rating)
203+
- [Slider](https://github.com/Frontendland/webcoreui/tree/main/src/components/Slider)
203204
- [Spinner](https://github.com/Frontendland/webcoreui/tree/main/src/components/Spinner)
204205
- [Switch](https://github.com/Frontendland/webcoreui/tree/main/src/components/Switch)
205206
- [Table](https://github.com/Frontendland/webcoreui/tree/main/src/components/Table)

scripts/buildTypes.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ const buildTypes = type => {
2727
'Checkbox',
2828
'Input',
2929
'Radio',
30-
'Switch'
30+
'Switch',
31+
'Slider'
3132
]
3233

3334
return componentsWithSvelteSpecificTypes.includes(component)

src/components/Slider/Slider.astro

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
import type { SliderProps } from './slider'
3+
4+
import styles from './slider.module.scss'
5+
import { classNames } from '../../utils/classNames'
6+
7+
interface Props extends SliderProps {}
8+
9+
const {
10+
min,
11+
max,
12+
value,
13+
step,
14+
color,
15+
background,
16+
thumb,
17+
id,
18+
className
19+
} = Astro.props
20+
21+
const classes = [
22+
styles.slider,
23+
className
24+
]
25+
26+
const styleVariables = classNames([
27+
color && `--w-slider-color: ${color};`,
28+
background && `--w-slider-background: ${background};`,
29+
thumb && `--w-slider-thumb: ${thumb};`
30+
])
31+
---
32+
33+
<input
34+
type="range"
35+
min={min}
36+
max={max}
37+
value={value || min}
38+
step={step}
39+
class:list={classes}
40+
id={id}
41+
style={styleVariables}
42+
/>

src/components/Slider/Slider.svelte

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<script lang="ts">
2+
import type { SvelteSliderProps } from './slider'
3+
4+
import styles from './slider.module.scss'
5+
import { classNames } from '../../utils/classNames'
6+
7+
export let min: SvelteSliderProps['min'] = 0
8+
export let max: SvelteSliderProps['max'] = 100
9+
export let value: SvelteSliderProps['value'] = 0
10+
export let step: SvelteSliderProps['step'] = 1
11+
export let color: SvelteSliderProps['color'] = ''
12+
export let background: SvelteSliderProps['background'] = ''
13+
export let thumb: SvelteSliderProps['thumb'] = ''
14+
export let id: SvelteSliderProps['id'] = ''
15+
export let className: SvelteSliderProps['className'] = ''
16+
export let onChange: SvelteSliderProps['onChange'] = () => {}
17+
18+
const classes = classNames([
19+
styles.slider,
20+
className
21+
])
22+
23+
const styleVariables = classNames([
24+
color && `--w-slider-color: ${color};`,
25+
background && `--w-slider-background: ${background};`,
26+
thumb && `--w-slider-thumb: ${thumb};`
27+
])
28+
</script>
29+
30+
<input
31+
type="range"
32+
min={min}
33+
max={max}
34+
value={value || min}
35+
step={step}
36+
class={classes}
37+
id={id}
38+
style={styleVariables}
39+
on:change={onChange}
40+
/>

src/components/Slider/Slider.tsx

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react'
2+
import type { ReactSliderProps } from './slider'
3+
4+
import styles from './slider.module.scss'
5+
import { classNames } from '../../utils/classNames'
6+
7+
const Slider = ({
8+
min,
9+
max,
10+
value,
11+
step,
12+
color,
13+
background,
14+
thumb,
15+
id,
16+
className,
17+
onChange
18+
}: ReactSliderProps) => {
19+
const classes = classNames([
20+
styles.slider,
21+
className
22+
])
23+
24+
const styleVariables = {
25+
...(color && { '--w-slider-color': color }),
26+
...(background && { '--w-slider-background': background }),
27+
...(thumb && { '--w-slider-thumb': thumb })
28+
} as React.CSSProperties
29+
30+
return (
31+
<input
32+
type="range"
33+
min={min}
34+
max={max}
35+
defaultValue={value || min}
36+
step={step}
37+
className={classes}
38+
id={id}
39+
style={styleVariables}
40+
onChange={onChange}
41+
/>
42+
43+
)
44+
}
45+
46+
export default Slider
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
@import '../../scss/config.scss';
2+
3+
body {
4+
--w-slider-background: var(--w-color-primary-50);
5+
--w-slider-color: var(--w-color-primary);
6+
--w-slider-thumb: var(--w-color-primary-50);
7+
}
8+
9+
.slider {
10+
@include border-radius(xl);
11+
@include size('w100%');
12+
@include visibility(hidden);
13+
@include size(h10px);
14+
@include spacing(m0);
15+
16+
-webkit-appearance: none;
17+
appearance: none;
18+
cursor: pointer;
19+
}
20+
21+
.slider::-webkit-slider-runnable-track {
22+
@include background(var(--w-slider-background));
23+
}
24+
25+
.slider::-moz-range-track {
26+
@include background(var(--w-slider-background));
27+
@include size(h10px);
28+
}
29+
30+
.slider::-webkit-slider-thumb {
31+
@include background(var(--w-slider-thumb));
32+
@include size(10px);
33+
@include border-radius(max);
34+
@include border(var(--w-slider-color));
35+
36+
-webkit-appearance: none;
37+
appearance: none;
38+
box-shadow: -405px 0 0 400px var(--w-slider-color);
39+
}
40+
41+
.slider::-moz-range-thumb {
42+
@include background(var(--w-slider-thumb));
43+
@include size(9px);
44+
@include border-radius(max);
45+
@include border(var(--w-slider-color));
46+
47+
box-shadow: -405px 0 0 400px var(--w-slider-color);
48+
}

src/components/Slider/slider.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
export type SliderProps = {
2+
min: number
3+
max: number
4+
value?: number
5+
step?: number
6+
id?: string
7+
color?: string
8+
background?: string
9+
thumb?: string
10+
className?: string
11+
}
12+
13+
export type SvelteSliderProps = {
14+
onChange?: (e: any) => any
15+
} & SliderProps
16+
17+
export type ReactSliderProps = {
18+
onChange?: (e: any) => any
19+
} & SliderProps

src/pages/index.astro

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Menu from '@components/Menu/Menu.astro'
1515
import Progress from '@components/Progress/Progress.astro'
1616
import Radio from '@components/Radio/Radio.astro'
1717
import Rating from '@components/Rating/Rating.astro'
18+
import Slider from '@components/Slider/Slider.astro'
1819
import Spinner from '@components/Spinner/Spinner.astro'
1920
import Switch from '@components/Switch/Switch.astro'
2021
import Table from '@components/Table/Table.astro'
@@ -152,6 +153,9 @@ const tabItems = [{
152153
<CardWrapper title="Rating" href="/rating">
153154
<Rating score={4} />
154155
</CardWrapper>
156+
<CardWrapper title="Slider" href="/slider">
157+
<Slider min={0} max={100} value={50} />
158+
</CardWrapper>
155159
<CardWrapper title="Spinner" href="/spinner">
156160
<Spinner />
157161
</CardWrapper>

src/pages/slider.astro

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
---
2+
import Layout from '@static/Layout.astro'
3+
import ComponentWrapper from '@static/ComponentWrapper.astro'
4+
5+
import AstroSlider from '@components/Slider/Slider.astro'
6+
import SvelteSlider from '@components/Slider/Slider.svelte'
7+
import ReactSlider from '@components/Slider/Slider.tsx'
8+
9+
import { getSections } from '@helpers'
10+
11+
const sections = getSections({
12+
title: 'sliders',
13+
components: [AstroSlider, SvelteSlider, ReactSlider],
14+
showSubTitle: true
15+
})
16+
---
17+
18+
<Layout>
19+
<h1>Slider</h1>
20+
<div class="grid md-2 lg-3">
21+
<ComponentWrapper type="Astro">
22+
<AstroSlider min={0} max={100} value={50} />
23+
</ComponentWrapper>
24+
25+
<ComponentWrapper type="Svelte">
26+
<SvelteSlider min={0} max={100} value={50} />
27+
</ComponentWrapper>
28+
29+
<ComponentWrapper type="React">
30+
<ReactSlider min={0} max={100} value={50} />
31+
</ComponentWrapper>
32+
</div>
33+
34+
{sections.map(section => (
35+
<h1>{section.title}</h1>
36+
<Fragment>
37+
{section.subTitle && <h2 set:html={section.subTitle} />}
38+
</Fragment>
39+
<div class="grid md-2 lg-3">
40+
<ComponentWrapper title="Default with no value">
41+
<section.component min={0} max={100} />
42+
</ComponentWrapper>
43+
44+
<ComponentWrapper title="With default value">
45+
<section.component min={0} max={100} value={33} />
46+
</ComponentWrapper>
47+
48+
<ComponentWrapper title="With steps">
49+
<section.component
50+
min={0}
51+
max={100}
52+
step={20}
53+
value={20}
54+
/>
55+
</ComponentWrapper>
56+
57+
<ComponentWrapper title="With custom colors">
58+
<section.component
59+
min={0}
60+
max={100}
61+
value={50}
62+
color="var(--w-color-success)"
63+
background="var(--w-color-primary-60)"
64+
thumb="var(--w-color-primary)"
65+
/>
66+
</ComponentWrapper>
67+
68+
<ComponentWrapper title="With label">
69+
<div class="flex items-center xs">
70+
<section.component
71+
min={0}
72+
max={100}
73+
value={20}
74+
className="labelled"
75+
/>
76+
<span class="muted">20</span>
77+
</div>
78+
</ComponentWrapper>
79+
80+
<ComponentWrapper title="With label on top">
81+
<span class="muted">40</span>
82+
<section.component
83+
min={0}
84+
max={100}
85+
value={40}
86+
className="labelled1"
87+
/>
88+
</ComponentWrapper>
89+
</div>
90+
))}
91+
</Layout>
92+
93+
<script>
94+
const slider1 = document.querySelector('.labelled')
95+
const slider2 = document.querySelector('.labelled1');
96+
97+
slider1?.addEventListener('change', (e: any) => {
98+
e.target.nextElementSibling.innerText = e.target.value
99+
})
100+
101+
slider2?.addEventListener('change', (e: any) => {
102+
e.target.previousElementSibling.innerText = e.target.value
103+
})
104+
105+
</script>

src/pages/themes.astro

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Examples from '@static/Examples.astro'
44
import ThemeSwitcher from '@components/ThemeSwitcher/ThemeSwitcher.astro'
55
import Button from '@components/Button/Button.astro'
66
import Toast from '@components/Toast/Toast.astro'
7+
import Slider from '@components/Slider/Slider.astro'
78
89
import { themes } from '@data'
910
---
@@ -15,9 +16,8 @@ import { themes } from '@data'
1516

1617
<div class="flex sm justify-center my column">
1718
<label class="flex column none">
18-
<span class="muted">Radius</span>
19-
<input
20-
type="range"
19+
<div class="muted">Radius</div>
20+
<Slider
2121
min={0}
2222
max={100}
2323
value={50}
@@ -85,8 +85,10 @@ import { themes } from '@data'
8585
</script>
8686

8787
<style lang="scss">
88-
input {
89-
margin: 0;
88+
@import '../scss/config.scss';
89+
90+
.muted {
91+
@include spacing(mb-xs);
9092
}
9193

9294
.flex {

0 commit comments

Comments
 (0)