Skip to content

Commit f91283b

Browse files
authored
V2 Slider Update (#308)
* Enhance Slider component with new features and styles * refactor Slider component to remove isRange state and enhance value handling * fix: use constant instead of signal read * refactor Slider component to simplify value handling and update hidden input rendering * refactor Slider component to improve rendering logic and streamline input handling * refactor Slider component tests to remove unused styles and streamline code * refactor Slider component to standardize value handling and improve context usage * refactor SliderLabel component to replace Label with Render for improved rendering flexibility * chore: remove unused dependency '@oxc-parser/binding-darwin-arm64' from package.json and pnpm-lock.yaml
1 parent d04b115 commit f91283b

File tree

15 files changed

+530
-130
lines changed

15 files changed

+530
-130
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { Slider } from "@qds.dev/ui";
2+
import { component$, useSignal, useStyles$ } from "@qwik.dev/core";
3+
import styles from "./slider-custom.css?inline";
4+
5+
export default component$(() => {
6+
useStyles$(styles);
7+
8+
const formData = useSignal<Record<string, FormDataEntryValue>>();
9+
10+
return (
11+
<form
12+
preventdefault:submit
13+
onSubmit$={(e) => {
14+
const form = e.target as HTMLFormElement;
15+
formData.value = Object.fromEntries(new FormData(form));
16+
}}
17+
class="flex flex-col gap-4"
18+
>
19+
<VolumeSlider />
20+
<button
21+
type="submit"
22+
class="px-4 py-2 cursor-pointer bg-blue-500 text-white rounded hover:bg-blue-600"
23+
>
24+
Submit
25+
</button>
26+
{formData.value && (
27+
<div class="p-2 bg-gray-100 rounded">
28+
Submitted: {JSON.stringify(formData.value, null, 2)}
29+
</div>
30+
)}
31+
</form>
32+
);
33+
});
34+
35+
export const VolumeSlider = component$(() => {
36+
return (
37+
<Slider.Root name="volume" value={50} class="slider-root">
38+
<Slider.Label>Volume</Slider.Label>
39+
<Slider.Track class="slider-track">
40+
<Slider.Range class="slider-range" />
41+
<Slider.Thumb class="slider-thumb" />
42+
</Slider.Track>
43+
<Slider.HiddenInput />
44+
</Slider.Root>
45+
);
46+
});

libs/components/src/slider/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ export { SliderRange as Range } from "./slider-range";
55
export { SliderThumb as Thumb } from "./slider-thumb";
66
export { SliderMarkerGroup as MarkerGroup } from "./slider-marker-group";
77
export { SliderMarker as Marker } from "./slider-marker";
8+
export { SliderHiddenInput as HiddenInput } from "./slider-hidden-input";
89
// export { SliderTooltip as Tooltip } from "./slider-tooltip";

libs/components/src/slider/slider-context.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ export type ThumbType = "start" | "end";
44
export type SliderValue = number | [number, number];
55

66
export interface SliderContext {
7-
isRange: Signal<boolean>;
8-
value: Signal<SliderValue>;
7+
sliderValue: Signal<SliderValue>;
98
startValue: Signal<number>;
109
endValue: Signal<number>;
1110
min: Signal<number>;
@@ -16,9 +15,9 @@ export interface SliderContext {
1615
setValue: QRL<(newValue: number, type?: ThumbType) => void>;
1716
calculateValue: QRL<(clientX: number, rect: DOMRect) => number>;
1817
thumbType: Signal<ThumbType | undefined>;
19-
onChange$?: (value: SliderValue) => void;
20-
onChangeEnd$?: (value: SliderValue) => void;
2118
localId: string;
19+
name?: string;
20+
required?: boolean;
2221
}
2322

2423
export const sliderContextId = createContextId<SliderContext>("slider-context");
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { type PropsOf, component$, useComputed$, useContext } from "@qwik.dev/core";
2+
import { VisuallyHidden } from "../visually-hidden/visually-hidden";
3+
import { sliderContextId } from "./slider-context";
4+
5+
type PublicSliderHiddenNativeInputProps = Omit<
6+
PropsOf<"input">,
7+
"type" | "value" | "min" | "max" | "step"
8+
>;
9+
10+
export const SliderHiddenInput = component$(
11+
(props: PublicSliderHiddenNativeInputProps) => {
12+
const context = useContext(sliderContextId);
13+
14+
const stringValue = useComputed$(() => {
15+
const value = context.sliderValue.value;
16+
return Array.isArray(value) ? value.join(",") : String(value);
17+
});
18+
19+
return (
20+
<VisuallyHidden>
21+
<input
22+
{...props}
23+
type="hidden"
24+
tabIndex={-1}
25+
data-qds-slider-hidden-input
26+
name={context.name ?? props.name ?? undefined}
27+
required={context.required ?? props.required ?? undefined}
28+
value={stringValue.value}
29+
/>
30+
</VisuallyHidden>
31+
);
32+
}
33+
);

libs/components/src/slider/slider-label.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const SliderLabel = component$((props: PublicLabelProps) => {
1010
const labelId = `${context.localId}-label`;
1111

1212
return (
13-
<Render {...props} id={labelId} data-qds-slider-label fallback="span">
13+
<Render {...props} fallback="span" id={labelId} data-qds-slider-label>
1414
<Slot />
1515
</Render>
1616
);
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { type PropsOf, Slot, component$ } from "@qwik.dev/core";
2+
import { Render } from "../render/render";
23

34
/** A container component for slider markers */
45
export const SliderMarkerGroup = component$((props: PropsOf<"div">) => {
56
return (
67
// Container element for grouping slider markers
7-
<div {...props} data-qds-slider-marker-group>
8+
<Render {...props} fallback="div" data-qds-slider-marker-group>
89
<Slot />
9-
</div>
10+
</Render>
1011
);
1112
});

libs/components/src/slider/slider-marker.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type PropsOf, Slot, component$, useComputed$, useContext } from "@qwik.dev/core";
2+
import { Render } from "../render/render";
23
import { sliderContextId } from "./slider-context";
34
interface PublicMarkerProps extends PropsOf<"div"> {
45
/** The value at which to place the marker on the slider track */
@@ -14,13 +15,14 @@ export const SliderMarker = component$((props: PublicMarkerProps) => {
1415
});
1516

1617
return (
17-
<div
18+
<Render
1819
{...rest}
20+
fallback="div"
1921
// Individual marker element representing a specific value on the slider
2022
data-qds-slider-marker
2123
style={{ left: `${markerPosition.value}%` }}
2224
>
2325
<Slot />
24-
</div>
26+
</Render>
2527
);
2628
});

libs/components/src/slider/slider-range.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { type PropsOf, component$, useComputed$, useContext } from "@qwik.dev/core";
2+
import { Render } from "../render/render";
23
import { sliderContextId } from "./slider-context";
34

45
/** Component that displays the filled range between min value and current value */
@@ -9,9 +10,10 @@ export const SliderRange = component$((props: PropsOf<"div">) => {
910
const range = context.max.value - context.min.value;
1011
if (range === 0) return { left: "0%", width: "0%" };
1112

12-
if (!context.isRange.value) {
13+
// Check if this is a range slider by checking if value is an array
14+
if (!Array.isArray(context.sliderValue.value)) {
1315
const percentage =
14-
(((context.value.value as number) - context.min.value) / range) * 100;
16+
(((context.sliderValue.value as number) - context.min.value) / range) * 100;
1517
return {
1618
left: "0%",
1719
width: `${Math.min(100, Math.max(0, percentage))}%`
@@ -29,8 +31,9 @@ export const SliderRange = component$((props: PropsOf<"div">) => {
2931
});
3032

3133
return (
32-
<div
34+
<Render
3335
{...props}
36+
fallback="div"
3437
// Visual indicator showing the selected range between minimum and maximum values
3538
data-qds-slider-range
3639
style={styles.value}

0 commit comments

Comments
 (0)