Skip to content

Commit

Permalink
feat(range): adds tick markers
Browse files Browse the repository at this point in the history
  • Loading branch information
dvcol committed Feb 12, 2025
1 parent 942f6a3 commit 516cf1f
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
37 changes: 37 additions & 0 deletions demo/components/DemoInputs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -1143,6 +1143,43 @@
</div>
</div>

<!-- Range inputs -->
<div class="row">
<div class="column content">
<span class="label">Tick Range</span>
{@render validationState(rangeSteppedState, true)}
<SphereBackdrop glass={options.glass}>
<NeoRange
label="Tick Stepped"
step={10}
ticks
bind:touched={rangeSteppedState.touched}
bind:dirty={rangeSteppedState.dirty}
bind:valid={rangeSteppedState.valid}
bind:value={rangeSteppedState.value}
{...options}
/>
</SphereBackdrop>
</div>

<div class="column content">
<span class="label">Tick Interval</span>
{@render validationState(rangeArrayState, true)}
<SphereBackdrop glass={options.glass}>
<NeoRange
label="Tick Interval"
step={10}
ticks
bind:touched={rangeArrayState.touched}
bind:dirty={rangeArrayState.dirty}
bind:valid={rangeArrayState.valid}
bind:value={rangeArrayState.value}
{...options}
/>
</SphereBackdrop>
</div>
</div>

{#snippet beforeRange()}
<NeoButton
rounded
Expand Down
56 changes: 52 additions & 4 deletions src/lib/inputs/NeoRange.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
error,
before,
after,
mark,
// State
id = label ? `neo-range-${getUUID()}` : undefined,
Expand All @@ -43,6 +44,7 @@
min = 0,
max = 100,
step,
ticks,
// Styles
start,
Expand Down Expand Up @@ -87,7 +89,15 @@
// TODO - vertical
const lowerProgress = $derived(((lower - min) / (max - min)) * 100);
const upperProgress = $derived(upper ? ((upper - min) / (max - min)) * 100 : undefined);
const upperProgress = $derived(upper ? ((upper - min) / (max - min)) * 100 : lowerProgress);
const steps = $derived(ticks ? Math.round((max - min) / (step ?? 1)) : 0);
const isFilled = (tick: number) => {
const tickProgress = (tick / steps) * 100;
if (isArray) return tickProgress >= lowerProgress && tickProgress <= upperProgress;
return tickProgress <= lowerProgress;
};
const boxShadow = $derived(computeShadowElevation(-Math.abs(elevation), { glass, pressed: elevation > 0 }, DefaultShallowMinMaxElevation));
Expand Down Expand Up @@ -275,6 +285,7 @@
disabled,
readonly,
initial,
loading,
min,
max,
Expand All @@ -286,9 +297,12 @@
valid,
// Styles
ticks,
color,
tooltips,
rounded,
glass,
tinted,
start,
skeleton,
elevation,
Expand Down Expand Up @@ -384,7 +398,7 @@
style={toStyle(lowerTooltip.floatingStyles, floatingProps?.style)}
>
{#if tooltip}
{@render tooltip({ lower: true, upper: false, value: lower, context })}
{@render tooltip({ lower: true, upper: false, value: lower }, context)}
{:else}
{lower}
{/if}
Expand All @@ -400,7 +414,7 @@
style={toStyle(upperTooltip.floatingStyles, floatingProps?.style)}
>
{#if tooltip}
{@render tooltip({ lower: false, upper: true, value: upper, context })}
{@render tooltip({ lower: false, upper: true, value: upper }, context)}
{:else}
{upper}
{/if}
Expand All @@ -425,6 +439,7 @@
class:neo-flat={!elevation}
class:neo-valid={validation && valid}
class:neo-invalid={validation && !valid}
style:--neo-range-tick-count={steps}
style:--neo-range-color={getColorVariable(color)}
style:--neo-range-box-shadow={boxShadow}
style:--neo-range-progress="{lowerProgress}%"
Expand Down Expand Up @@ -455,6 +470,20 @@
<span class="neo-range-handle-after">
<!-- handle after -->
</span>
{#if steps > 1}
{#each { length: (steps ?? 0) + 1 } as _, i}
{@const filled = isFilled(i)}
<div class="neo-range-tick" style:--neo-range-tick-index={i}>
{#if mark}
{@render mark({ index: i, filled }, context)}
{:else}
<span class="neo-range-tick-mark" class:neo-filled={filled}>
<!-- tick content -->
</span>
{/if}
</div>
{/each}
{/if}
</span>
</span>
{#if loading !== undefined || after !== undefined}
Expand Down Expand Up @@ -494,6 +523,7 @@
}
&-rail {
position: relative;
display: inline-flex;
align-items: center;
box-sizing: border-box;
Expand All @@ -506,6 +536,24 @@
transition: background-color 0.3s ease;
}
&-tick {
position: absolute;
translate: -50%;
left: calc((var(--neo-range-tick-index) * 100% / var(--neo-range-tick-count)));
&-mark {
display: block;
width: 0.25rem;
height: 0.25rem;
background-color: var(--neo-range-mark-background, color-mix(in srgb, transparent, currentcolor 15%));
border-radius: 50%;
&.neo-filled {
background-color: var(--neo-range-mark-background, currentcolor);
}
}
}
&-handle {
z-index: calc(var(--neo-z-index-in-front, 1) + var(--neo-range-handler-z-index, 0));
display: inline-flex;
Expand Down Expand Up @@ -700,7 +748,7 @@
}
&.neo-tinted {
background-color: var(--neo-input-bg-color, var(--neo-background-color-tinted));
background-color: var(--neo-range-bg-color, var(--neo-background-color-tinted));
}
&.neo-skeleton {
Expand Down
18 changes: 16 additions & 2 deletions src/lib/inputs/neo-range.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export type NeoRangeStates = {
};

export type NeoRangeStyles = {
/**
* If true, the input will show step markers.
*
* @see step
*/
ticks?: boolean;
/**
* If true, the input value will be displayed as tooltip on hover/focus.
*
Expand Down Expand Up @@ -95,7 +101,11 @@ export type NeoRangeTooltipContext = {
lower?: boolean;
upper?: boolean;
value?: number;
context: NeoRangeContext;
};

export type NeoRangeTickContext = {
index: number;
filled?: boolean;
};

export type NeoRangeProps = Pick<NeoInputValidationProps, 'valid' | 'validation' | 'error' | 'context' | 'message' | 'messageProps'> &
Expand All @@ -108,7 +118,11 @@ export type NeoRangeProps = Pick<NeoInputValidationProps, 'valid' | 'validation'
/**
* A snippet to display as value labels.
*/
tooltip?: Snippet<[NeoRangeTooltipContext]>;
tooltip?: Snippet<[NeoRangeTooltipContext, NeoValidationFieldContext]>;
/**
* A snippet to display as a tick mark.
*/
mark?: Snippet<[NeoRangeTickContext, NeoValidationFieldContext]>;
/**
* A snippet to display as the input prefix.
*/
Expand Down

0 comments on commit 516cf1f

Please sign in to comment.