Number Spinner

A numeric input with increment and decrement controls

Basic Usage

Simple number spinner with min/max constraints.

Simple Number Spinner

Current value: 0

With Constraints

Quantity: 1


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner, Badge } from "@kareyes/aether";
4
5	let basicValue = $state(0);
6	let quantityValue = $state(1);
7</script>
8
9<div class="grid gap-8 md:grid-cols-2">
10	<div class="space-y-2">
11		<h3 class="text-lg font-medium">Simple Number Spinner</h3>
12		<NumberSpinner bind:value={basicValue} min={0} max={100} />
13		<p class="text-sm text-muted-foreground">
14			Current value: <Badge variant="secondary">{basicValue}</Badge>
15		</p>
16	</div>
17	<div class="space-y-2">
18		<h3 class="text-lg font-medium">With Constraints</h3>
19		<NumberSpinner bind:value={quantityValue} min={1} max={99} />
20		<p class="text-sm text-muted-foreground">
21			Quantity: <Badge variant="outline">{quantityValue}</Badge>
22		</p>
23	</div>
24</div>

Variants

Available visual styles for the number spinner.

Default

Outline

Filled

Ghost


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4</script>
5
6<div class="grid gap-8 md:grid-cols-2 lg:grid-cols-4">
7	<NumberSpinner variant="default" value={10} />
8	<NumberSpinner variant="outline" value={10} />
9	<NumberSpinner variant="filled" value={10} />
10	<NumberSpinner variant="ghost" value={10} />
11</div>

Sizes

Different size options for the number spinner.

Small

Default

Large


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4</script>
5
6<div class="grid gap-8 md:grid-cols-3">
7	<NumberSpinner size="sm" value={5} min={0} max={10} />
8	<NumberSpinner size="default" value={5} min={0} max={10} />
9	<NumberSpinner size="lg" value={5} min={0} max={10} />
10</div>

Orientations

Vertical and horizontal button placement options.

Vertical (Default)

Buttons are positioned vertically on the right

Horizontal

Buttons are positioned on both sides


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4</script>
5
6<div class="grid gap-8 md:grid-cols-2">
7	<div class="space-y-2">
8		<h3 class="text-lg font-medium">Vertical (Default)</h3>
9		<NumberSpinner orientation="vertical" value={10} min={0} max={20} />
10	</div>
11	<div class="space-y-2">
12		<h3 class="text-lg font-medium">Horizontal</h3>
13		<NumberSpinner orientation="horizontal" value={10} min={0} max={20} />
14	</div>
15</div>

Advanced Features

Decimal precision, step control, and custom configurations.

Price Input (Decimal Precision)

Price: $9.99

Temperature (Step Control)

Temperature: 20.5°C

Large Step Size

Increments by 10

Integer Only

No decimal values allowed


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner, Badge } from "@kareyes/aether";
4
5	let priceValue = $state(9.99);
6	let temperatureValue = $state(20.5);
7</script>
8
9<div class="grid gap-8 md:grid-cols-2">
10	<!-- Price Input (Decimal Precision) -->
11	<NumberSpinner
12		bind:value={priceValue}
13		min={0} max={9999.99}
14		step={0.01} precision={2}
15		placeholder="0.00" variant="outline"
16	/>
17
18	<!-- Temperature (Step Control) -->
19	<NumberSpinner
20		bind:value={temperatureValue}
21		min={-50} max={50}
22		step={0.5} precision={1}
23		orientation="horizontal" size="lg"
24	/>
25
26	<!-- Large Step Size -->
27	<NumberSpinner value={50} min={0} max={1000} step={10} />
28
29	<!-- Integer Only -->
30	<NumberSpinner value={25} min={0} max={100} step={1} />
31</div>

Practical Examples

Real-world usage patterns like shopping carts.

Shopping Cart

Product A - $19.99
Product B - $29.99
Product C - $9.99

Total Items: 4


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner, Badge } from "@kareyes/aether";
4
5	let cartQuantity1 = $state(1);
6	let cartQuantity2 = $state(2);
7	let cartQuantity3 = $state(1);
8	const totalCartItems = $derived((cartQuantity1 ?? 0) + (cartQuantity2 ?? 0) + (cartQuantity3 ?? 0));
9</script>
10
11<div class="space-y-3 rounded-lg border p-4">
12	<div class="flex items-center justify-between">
13		<span class="text-sm">Product A - $19.99</span>
14		<NumberSpinner bind:value={cartQuantity1} min={1} max={99} size="sm" orientation="horizontal" />
15	</div>
16	<div class="flex items-center justify-between">
17		<span class="text-sm">Product B - $29.99</span>
18		<NumberSpinner bind:value={cartQuantity2} min={1} max={99} size="sm" orientation="horizontal" />
19	</div>
20	<div class="flex items-center justify-between">
21		<span class="text-sm">Product C - $9.99</span>
22		<NumberSpinner bind:value={cartQuantity3} min={1} max={99} size="sm" orientation="horizontal" />
23	</div>
24	<div class="border-t pt-3">
25		<p class="text-sm font-medium">
26			Total Items: <Badge variant="secondary">{totalCartItems}</Badge>
27		</p>
28	</div>
29</div>

Error States

Validation error display with the number spinner.

With Error

Age is required

Valid State

No errors


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4
5	let ageValue = $state(null);
6</script>
7
8<div class="grid gap-8 md:grid-cols-2">
9	<div class="space-y-2">
10		<NumberSpinner bind:value={ageValue} error={!ageValue} required min={1} max={150} />
11		{#if !ageValue}
12			<p class="text-sm text-destructive">Age is required</p>
13		{/if}
14	</div>
15	<div class="space-y-2">
16		<NumberSpinner value={25} error={false} />
17		<p class="text-sm text-muted-foreground">No errors</p>
18	</div>
19</div>

With Field Component

Using the Field component for labels, descriptions, and error handling.

Number of items to order

Enter the price in USD (up to $9,999.99)

Set your preferred temperature (-10°C to 40°C)


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner, Field } from "@kareyes/aether";
4
5	let ageValue = $state(null);
6</script>
7
8<div class="max-w-2xl space-y-6">
9	<Field label="Age" description="Enter your age (1-150)" error={!ageValue ? "Age is required" : undefined} required>
10		<NumberSpinner bind:value={ageValue} error={!ageValue} min={1} max={150} />
11	</Field>
12
13	<Field label="Quantity" description="Number of items to order" required>
14		<NumberSpinner value={1} min={1} max={100} orientation="horizontal" />
15	</Field>
16
17	<Field label="Product Price" description="Enter the price in USD (up to $9,999.99)" required>
18		<NumberSpinner value={0} min={0} max={9999.99} step={0.01} precision={2} variant="filled" placeholder="0.00" />
19	</Field>
20
21	<Field label="Room Temperature" description="Set your preferred temperature (-10°C to 40°C)">
22		<NumberSpinner value={22} min={-10} max={40} step={0.5} precision={1} orientation="horizontal" size="lg" />
23	</Field>
24</div>

Form Integration

Complete form example with validation and submission.

Order Form

Number of items

Total: $0.00


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner, Field, Badge } from "@kareyes/aether";
4
5	let formQuantity = $state(1);
6	let formPrice = $state(0);
7	let formAge = $state(null);
8	const formValid = $derived(formQuantity > 0 && formPrice > 0 && formAge !== null && formAge > 0);
9</script>
10
11<form class="max-w-2xl space-y-6 rounded-lg border p-6" onsubmit={(e) => { e.preventDefault(); }}>
12	<Field label="Quantity" error={formQuantity < 1 ? "Quantity must be at least 1" : undefined} required>
13		<NumberSpinner bind:value={formQuantity} error={formQuantity < 1} min={1} max={100} />
14	</Field>
15
16	<Field label="Unit Price" error={formPrice <= 0 ? "Price must be greater than 0" : undefined} required>
17		<NumberSpinner bind:value={formPrice} error={formPrice <= 0} min={0} max={9999.99} step={0.01} precision={2} variant="outline" />
18	</Field>
19
20	<Field label="Customer Age" error={!formAge || formAge < 18 ? "Must be 18 or older" : undefined} required>
21		<NumberSpinner bind:value={formAge} error={!formAge || formAge < 18} min={18} max={150} />
22	</Field>
23
24	<div class="flex items-center justify-between pt-4">
25		<p class="text-sm text-muted-foreground">
26			Total: <Badge variant="secondary">${((formPrice ?? 0) * (formQuantity ?? 0)).toFixed(2)}</Badge>
27		</p>
28		<button type="submit" class="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground" disabled={!formValid}>
29			Submit Order
30		</button>
31	</div>
32</form>

Disabled State

Number spinner in disabled state for both orientations.

Vertical Disabled

Horizontal Disabled


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4</script>
5
6<div class="grid gap-8 md:grid-cols-2">
7	<NumberSpinner value={10} disabled={true} />
8	<NumberSpinner value={10} disabled={true} orientation="horizontal" />
9</div>

All Variants & Sizes

Complete matrix of all variant and size combinations.

Vertical Orientation

Horizontal Orientation


Code Svelte
1
2<script lang="ts">
3	import { NumberSpinner } from "@kareyes/aether";
4</script>
5
6<div class="grid gap-8 lg:grid-cols-2">
7	<!-- Vertical -->
8	<div class="space-y-4">
9		<h3 class="font-semibold">Vertical Orientation</h3>
10		{#each ["default", "outline", "filled", "ghost"] as variant}
11			<div class="grid grid-cols-3 gap-4">
12				<NumberSpinner variant={variant} value={10} size="sm" />
13				<NumberSpinner variant={variant} value={10} size="default" />
14				<NumberSpinner variant={variant} value={10} size="lg" />
15			</div>
16		{/each}
17	</div>
18
19	<!-- Horizontal -->
20	<div class="space-y-4">
21		<h3 class="font-semibold">Horizontal Orientation</h3>
22		{#each ["default", "outline", "filled", "ghost"] as variant}
23			<div class="grid grid-cols-3 gap-4">
24				<NumberSpinner variant={variant} value={10} size="sm" orientation="horizontal" />
25				<NumberSpinner variant={variant} value={10} size="default" orientation="horizontal" />
26				<NumberSpinner variant={variant} value={10} size="lg" orientation="horizontal" />
27			</div>
28		{/each}
29	</div>
30</div>