Skip to main content

Slider

Die Slider-Komponente ermöglicht es Benutzern, einen Wert innerhalb eines bestimmten Bereichs auszuwählen, indem sie einen Schieberegler entlang einer Leiste bewegen.

Import

import { Slider } from '@smolitux/core';

Verwendung

Einfacher Slider

<Slider defaultValue={50} />

Slider mit Min/Max-Werten

<Slider min={0} max={100} defaultValue={30} />

Slider mit Schrittgröße

<Slider min={0} max={100} step={10} defaultValue={30} />

Slider mit Label

<Slider label="Lautstärke" defaultValue={70} />

Slider mit verschiedenen Größen

<Slider size="xs" defaultValue={20} className="mb-4" />
<Slider size="sm" defaultValue={30} className="mb-4" />
<Slider size="md" defaultValue={40} className="mb-4" />
<Slider size="lg" defaultValue={50} className="mb-4" />
<Slider size="xl" defaultValue={60} />

Slider mit verschiedenen Varianten

<Slider variant="solid" defaultValue={20} className="mb-4" />
<Slider variant="outline" defaultValue={30} className="mb-4" />
<Slider variant="filled" defaultValue={40} className="mb-4" />
<Slider variant="minimal" defaultValue={50} />

Slider mit verschiedenen Farbschemata

<Slider colorScheme="primary" defaultValue={20} className="mb-4" />
<Slider colorScheme="secondary" defaultValue={30} className="mb-4" />
<Slider colorScheme="success" defaultValue={40} className="mb-4" />
<Slider colorScheme="danger" defaultValue={50} className="mb-4" />
<Slider colorScheme="warning" defaultValue={60} className="mb-4" />
<Slider colorScheme="info" defaultValue={70} className="mb-4" />
<Slider colorScheme="neutral" defaultValue={80} />

Vertikaler Slider

<div style={{ height: '200px' }}>
<Slider orientation="vertical" defaultValue={50} />
</div>

Slider mit Markierungen

const marks = [
{ value: 0, label: '0°C' },
{ value: 25, label: '25°C' },
{ value: 50, label: '50°C' },
{ value: 75, label: '75°C' },
{ value: 100, label: '100°C' }
];

<Slider
defaultValue={50}
min={0}
max={100}
marks={marks}
/>

Slider mit benutzerdefinierten Markierungspositionen

<Slider 
defaultValue={50}
min={0}
max={100}
marks={marks}
markPosition="below"
/>

Slider mit Wertanzeige

<Slider 
defaultValue={50}
showValue
valuePosition="above"
/>

Slider mit Tooltip-Wertanzeige

<Slider 
defaultValue={50}
showValue
valuePosition="tooltip"
/>

Slider mit benutzerdefinierten Thumb-Formen

<Slider 
defaultValue={50}
thumbShape="square"
className="mb-4"
/>

<Slider
defaultValue={50}
thumbShape="rectangle"
className="mb-4"
/>

<Slider
defaultValue={50}
thumbShape="diamond"
/>

Slider mit benutzerdefinierten Track-Formen

<Slider 
defaultValue={50}
trackShape="square"
/>

Slider mit Hilfetext

<Slider 
label="Bildqualität"
defaultValue={70}
helperText="Höhere Werte bedeuten bessere Qualität, aber größere Dateien."
/>

Slider mit Fehlermeldung

<Slider 
label="Temperatur"
defaultValue={90}
error="Die Temperatur ist zu hoch!"
/>

Slider mit Erfolgsmeldung

<Slider 
label="Energieverbrauch"
defaultValue={30}
successMessage="Niedriger Energieverbrauch!"
/>

Kontrollierter Slider

function ControlledSliderExample() {
const [value, setValue] = useState(50);

const handleChange = (newValue) => {
setValue(newValue);
};

return (
<div>
<Slider
label="Kontrollierter Slider"
value={value}
onChange={handleChange}
/>
<p className="mt-2">
Aktueller Wert: {value}
</p>
</div>
);
}

Slider mit benutzerdefinierten Ereignissen

function EventSliderExample() {
const [status, setStatus] = useState('Bereit');

const handleChangeStart = (value) => {
setStatus(`Ziehen gestartet bei ${value}`);
};

const handleChange = (value) => {
setStatus(`Aktueller Wert: ${value}`);
};

const handleChangeEnd = (value) => {
setStatus(`Ziehen beendet bei ${value}`);
};

return (
<div>
<Slider
defaultValue={50}
onChangeStart={handleChangeStart}
onChange={handleChange}
onChangeEnd={handleChangeEnd}
/>
<p className="mt-2">
Status: {status}
</p>
</div>
);
}

Slider mit benutzerdefiniertem Wertformat

<Slider 
defaultValue={50}
showValue
valueFormat={(value) => `${value}%`}
/>

Slider mit benutzerdefiniertem Thumb

<Slider 
defaultValue={50}
thumbShape="custom"
customThumb={
<div className="w-6 h-6 bg-primary-500 rounded-full flex items-center justify-center text-white text-xs">
↔️
</div>
}
/>

Props

PropTypStandardBeschreibung
valuenumber-Aktueller Wert des Sliders
defaultValuenumber0Standardwert des Sliders
minnumber0Minimaler Wert des Sliders
maxnumber100Maximaler Wert des Sliders
stepnumber1Schrittgröße des Sliders
onChange(value: number) => void-Callback bei Änderung des Werts
onChangeStart(value: number) => void-Callback bei Start des Ziehens
onChangeEnd(value: number) => void-Callback bei Ende des Ziehens
labelReactNode-Text-Label
helperTextReactNode-Hilfetext
errorReactNode-Fehlermeldung
successMessageReactNode-Erfolgsmeldung
size'xs' | 'sm' | 'md' | 'lg' | 'xl''md'Größe des Sliders
variant'solid' | 'outline' | 'filled' | 'minimal''solid'Visuelle Variante
colorScheme'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'neutral''primary'Farbe des Sliders
orientation'horizontal' | 'vertical''horizontal'Ausrichtung des Sliders
thumbShape'circle' | 'square' | 'rectangle' | 'diamond' | 'custom''circle'Form des Schiebereglers
trackShape'rounded' | 'square' | 'custom''rounded'Form der Leiste
marksSliderMark[]-Markierungen auf der Leiste
markPosition'above' | 'below' | 'left' | 'right''above'Position der Markierungen
showValuebooleanfalseWert anzeigen
valuePosition'above' | 'below' | 'left' | 'right' | 'tooltip''above'Position der Wertanzeige
valueFormat(value: number) => string-Formatierung des angezeigten Werts
customThumbReactNode-Benutzerdefinierter Schieberegler
customTrackReactNode-Benutzerdefinierte Leiste
isDisabledboolean-Ob der Slider deaktiviert ist
isReadOnlyboolean-Ob der Slider schreibgeschützt ist
isRequiredboolean-Ob der Slider erforderlich ist
classNamestring-Zusätzliche CSS-Klassen

SliderMark Interface

EigenschaftTypBeschreibung
valuenumberWert der Markierung
labelReactNodeLabel der Markierung
styleCSSPropertiesBenutzerdefinierte Styles für die Markierung
classNamestringZusätzliche CSS-Klassen für die Markierung

Barrierefreiheit

Die Slider-Komponente ist für Barrierefreiheit optimiert:

  • Verwendet native <input type="range"> Elemente für korrekte Semantik
  • Unterstützt Tastaturnavigation (Pfeiltasten, Home, End)
  • Korrekte ARIA-Attribute (aria-valuemin, aria-valuemax, aria-valuenow, aria-orientation)
  • Ausreichender Kontrast zwischen Vorder- und Hintergrund

Beispiele

Farbwähler mit RGB-Slidern

function RGBColorPickerExample() {
const [color, setColor] = useState({ r: 100, g: 100, b: 100 });

const handleChange = (channel) => (value) => {
setColor(prev => ({
...prev,
[channel]: value
}));
};

const rgbColor = `rgb(${color.r}, ${color.g}, ${color.b})`;

return (
<div className="max-w-md">
<h2 className="text-xl font-bold mb-4">RGB-Farbwähler</h2>

<div className="mb-6 h-24 rounded-lg" style={{ backgroundColor: rgbColor }}></div>

<div className="space-y-4">
<Slider
label="R (Rot)"
min={0}
max={255}
value={color.r}
onChange={handleChange('r')}
colorScheme="danger"
showValue
valuePosition="tooltip"
/>

<Slider
label="G (Grün)"
min={0}
max={255}
value={color.g}
onChange={handleChange('g')}
colorScheme="success"
showValue
valuePosition="tooltip"
/>

<Slider
label="B (Blau)"
min={0}
max={255}
value={color.b}
onChange={handleChange('b')}
colorScheme="info"
showValue
valuePosition="tooltip"
/>
</div>

<div className="mt-4 p-2 bg-gray-100 rounded font-mono text-sm">
{rgbColor}
</div>
</div>
);
}

Preis-Range-Slider

function PriceRangeSliderExample() {
const [priceRange, setPriceRange] = useState([200, 800]);

const handleMinChange = (value) => {
setPriceRange([Math.min(value, priceRange[1] - 50), priceRange[1]]);
};

const handleMaxChange = (value) => {
setPriceRange([priceRange[0], Math.max(value, priceRange[0] + 50)]);
};

return (
<div className="max-w-md">
<h2 className="text-xl font-bold mb-4">Preisbereich</h2>

<div className="flex justify-between mb-6">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Mindestpreis
</label>
<div className="relative">
<span className="absolute inset-y-0 left-0 pl-3 flex items-center text-gray-500">

</span>
<input
type="number"
className="pl-8 pr-4 py-2 border border-gray-300 rounded-md w-32"
value={priceRange[0]}
onChange={(e) => handleMinChange(parseInt(e.target.value) || 0)}
min={0}
max={priceRange[1] - 50}
/>
</div>
</div>

<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Höchstpreis
</label>
<div className="relative">
<span className="absolute inset-y-0 left-0 pl-3 flex items-center text-gray-500">

</span>
<input
type="number"
className="pl-8 pr-4 py-2 border border-gray-300 rounded-md w-32"
value={priceRange[1]}
onChange={(e) => handleMaxChange(parseInt(e.target.value) || 0)}
min={priceRange[0] + 50}
max={1000}
/>
</div>
</div>
</div>

<div className="space-y-6">
<Slider
min={0}
max={1000}
value={priceRange[0]}
onChange={handleMinChange}
marks={[
{ value: 0, label: '0 €' },
{ value: 250, label: '250 €' },
{ value: 500, label: '500 €' },
{ value: 750, label: '750 €' },
{ value: 1000, label: '1000 €' }
]}
markPosition="below"
helperText="Mindestpreis"
/>

<Slider
min={0}
max={1000}
value={priceRange[1]}
onChange={handleMaxChange}
helperText="Höchstpreis"
/>
</div>

<div className="mt-6">
<button className="px-4 py-2 bg-primary-500 text-white rounded-md">
Filter anwenden
</button>
</div>
</div>
);
}

Audio-Player mit Slider

function AudioPlayerExample() {
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const [duration, setDuration] = useState(180); // 3 Minuten in Sekunden
const [volume, setVolume] = useState(80);

const togglePlay = () => {
setIsPlaying(!isPlaying);
};

const formatTime = (seconds) => {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
};

// Simuliere Fortschritt, wenn abgespielt wird
useEffect(() => {
let interval;
if (isPlaying && currentTime < duration) {
interval = setInterval(() => {
setCurrentTime(prev => Math.min(prev + 1, duration));
}, 1000);
}
return () => clearInterval(interval);
}, [isPlaying, currentTime, duration]);

return (
<div className="max-w-md p-4 border rounded-lg bg-gray-50">
<h3 className="font-medium mb-2">Beispiel-Titel</h3>
<p className="text-sm text-gray-500 mb-4">Künstler - Album</p>

<div className="mb-4">
<Slider
value={currentTime}
min={0}
max={duration}
onChange={setCurrentTime}
variant="minimal"
size="sm"
/>
<div className="flex justify-between text-xs text-gray-500 mt-1">
<span>{formatTime(currentTime)}</span>
<span>{formatTime(duration)}</span>
</div>
</div>

<div className="flex items-center justify-between">
<div className="flex items-center space-x-4">
<button className="p-2 rounded-full hover:bg-gray-200">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
</svg>
</button>

<button
className="p-3 bg-primary-500 text-white rounded-full hover:bg-primary-600"
onClick={togglePlay}
>
{isPlaying ? (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 9v6m4-6v6" />
</svg>
) : (
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
)}
</button>

<button className="p-2 rounded-full hover:bg-gray-200">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
</div>

<div className="flex items-center w-32">
<svg className="w-5 h-5 text-gray-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15.536a5 5 0 010-7.072m12.728 0l-3.536 3.536m-10.607 0l3.536-3.536" />
</svg>
<Slider
value={volume}
onChange={setVolume}
size="xs"
variant="minimal"
/>
</div>
</div>
</div>
);
}