Files
components/slider.tsx
1'use client'
2
3import * as React from 'react'
4import { toast } from 'sonner'
5
6import { Badge } from '@/components/ui/badge'
7import { Button } from '@/components/ui/button'
8import {
9    Card,
10    CardContent,
11    CardDescription,
12    CardFooter,
13    CardHeader,
14    CardTitle,
15} from '@/components/ui/card'
16import { Checkbox } from '@/components/ui/checkbox'
17import { Label } from '@/components/ui/label'
18import { Separator } from '@/components/ui/separator'
19import { Slider } from '@/components/ui/slider'
20
21export function Slider01() {
22    const [price, setPrice] = React.useState<[number, number]>([120, 350])
23
24    const onSubmit = () => {
25        toast.success(`Price selected : Min $${price[0]} - Max $${price[1]}`)
26    }
27
28    return (
29        <Card className="max-w-md rounded-2xl border border-gray-200 bg-white shadow-sm">
30            <CardHeader>
31                <CardTitle>Hotel Filter</CardTitle>
32                <CardDescription>Get your preferred hotel</CardDescription>
33            </CardHeader>
34            <CardContent>
35                <div className="mb-3 flex items-center justify-between">
36                    <div className="text-md font-medium text-black">
37                        Amenities
38                    </div>
39                    <Button variant="link">View All</Button>
40                </div>
41                <div className="space-y-2">
42                    <div className="flex items-center gap-2">
43                        <Checkbox id="wifi" defaultChecked />
44                        <Label
45                            htmlFor="wifi"
46                            className="flex items-center gap-2 text-sm font-normal"
47                        >
48                            Free Wi-Fi
49                            <Badge
50                                variant="secondary"
51                                className="bg-success text-[10px] text-white"
52                            >
53                                Top Rated
54                            </Badge>
55                        </Label>
56                    </div>
57                    <div className="flex items-center gap-2">
58                        <Checkbox id="pool" />
59                        <Label htmlFor="pool" className="text-sm font-normal">
60                            Swimming Pool
61                        </Label>
62                    </div>
63                    <div className="flex items-center gap-2">
64                        <Checkbox id="parking" />
65                        <Label
66                            htmlFor="parking"
67                            className="text-sm font-normal"
68                        >
69                            Free Parking
70                        </Label>
71                    </div>
72                    <div className="flex items-center gap-2">
73                        <Checkbox id="spa" />
74                        <Label htmlFor="spa" className="text-sm font-normal">
75                            Spa & Wellness
76                        </Label>
77                    </div>
78                </div>
79                <Separator className="my-4" />
80                <div>
81                    <div className="text-md text-black">Price per night</div>
82                    <div className="flex items-center justify-between space-y-3">
83                        <span className="rounded bg-black px-2 py-1 text-xs text-white">
84                            $ {price[0]}
85                        </span>
86                        <span className="rounded bg-black px-2 py-1 text-xs text-white">
87                            $ {price[1]}
88                        </span>
89                    </div>
90                    <Slider
91                        value={price}
92                        min={50}
93                        max={700}
94                        step={10}
95                        onValueChange={(v) => setPrice(v as [number, number])}
96                    />
97                </div>
98                <Separator className="my-4" />
99                <div>
100                    <h3 className="mb-2 text-sm font-medium text-black">
101                        Cancellation Policy
102                    </h3>
103                    <div className="space-y-2">
104                        <div className="flex items-center gap-2">
105                            <Checkbox id="free-cancel" defaultChecked />
106                            <Label
107                                htmlFor="free-cancel"
108                                className="text-sm font-normal"
109                            >
110                                Free Cancellation
111                            </Label>
112                        </div>
113                        <div className="flex items-center gap-2">
114                            <Checkbox id="partial" />
115                            <Label
116                                htmlFor="partial"
117                                className="text-sm font-normal"
118                            >
119                                Partial Refund
120                            </Label>
121                        </div>
122                        <div className="flex items-center gap-2">
123                            <Checkbox id="non-refundable" />
124                            <Label
125                                htmlFor="non-refundable"
126                                className="text-sm font-normal"
127                            >
128                                Non-Refundable
129                            </Label>
130                        </div>
131                    </div>
132                </div>
133            </CardContent>
134            <CardFooter className="flex justify-end gap-3 border-t pt-4">
135                <Button onClick={onSubmit}>Submit</Button>
136            </CardFooter>
137        </Card>
138    )
139}
140
Slider for hotel filter
slider-01
Files
components/slider.tsx
1'use client'
2
3import * as React from 'react'
4import Image from 'next/image'
5import { RotateCw, ZoomIn, ZoomOut } from 'lucide-react'
6
7import { Button } from '@/components/ui/button'
8import {
9    Card,
10    CardContent,
11    CardHeader,
12    CardTitle,
13} from '@/components/ui/card'
14import { Slider } from '@/components/ui/slider'
15
16export function ImageZoomSlider() {
17    const [zoom, setZoom] = React.useState<number>(1)
18    const [rotation, setRotation] = React.useState<number>(0)
19
20    const handleZoomIn = () => setZoom((prev) => Math.min(prev + 0.1, 2))
21    const handleZoomOut = () => setZoom((prev) => Math.max(prev - 0.1, 0.5))
22    const handleRotate = () => setRotation((prev) => (prev + 90) % 360)
23
24    const handleClear = () => {
25        setZoom(1)
26        setRotation(0)
27    }
28
29    return (
30        <Card className="max-w-lg rounded-2xl border border-gray-200 bg-white shadow-sm">
31            <CardHeader className="flex flex-row items-center justify-between">
32                <CardTitle className="text-gray text-base font-semibold">
33                    Image Zoom Example
34                </CardTitle>
35                <Button variant="ghost" size="sm" onClick={handleClear}>
36                    Clear
37                </Button>
38            </CardHeader>
39
40            <CardContent className="flex w-full flex-col items-center gap-4">
41                <div className="relative w-full overflow-hidden rounded-lg bg-gray-100">
42                    <div
43                        className="flex items-center justify-center transition-transform duration-200"
44                        style={{
45                            transform: `scale(${zoom}) rotate(${rotation}deg)`,
46                        }}
47                    >
48                        <Image
49                            src="/images/random-image/random-6.jpg"
50                            alt="Uploaded"
51                            width={400}
52                            height={400}
53                            className="rounded-md object-contain"
54                        />
55                    </div>
56                </div>
57
58                <div className="w-full">
59                    <div className="text-gray mb-2 flex items-center justify-between text-sm">
60                        <Button
61                            variant="ghost"
62                            size="icon"
63                            onClick={handleZoomOut}
64                        >
65                            <ZoomOut className="h-4 w-4" />
66                        </Button>
67                        <span>Zoom</span>
68                        <Button
69                            variant="ghost"
70                            size="icon"
71                            onClick={handleZoomIn}
72                        >
73                            <ZoomIn className="h-4 w-4" />
74                        </Button>
75                    </div>
76                    <Slider
77                        value={[zoom]}
78                        min={0.5}
79                        max={2}
80                        step={0.1}
81                        onValueChange={(v) => setZoom(v[0])}
82                    />
83                </div>
84                <div className="flex items-center justify-center gap-3">
85                    <Button
86                        variant="outline"
87                        size="icon"
88                        onClick={handleRotate}
89                    >
90                        <RotateCw className="h-4 w-4" />
91                    </Button>
92                </div>
93            </CardContent>
94        </Card>
95    )
96}
97
Slider for image zoom in and zoom out.
slider-02
Files
components/slider.tsx
1'use client'
2
3import React, { useState } from 'react'
4import { AlertCircle, CheckCircle, CrownIcon, Shield, Zap } from 'lucide-react'
5
6import { Button } from '@/components/ui/button'
7import {
8    Card,
9    CardContent,
10    CardDescription,
11    CardHeader,
12    CardTitle,
13} from '@/components/ui/card'
14import { Checkbox } from '@/components/ui/checkbox'
15import { Label } from '@/components/ui/label'
16import {
17    Select,
18    SelectContent,
19    SelectItem,
20    SelectTrigger,
21    SelectValue,
22} from '@/components/ui/select'
23import { Separator } from '@/components/ui/separator'
24import { Slider } from '@/components/ui/slider'
25
26export function Slider03() {
27    const [billingCycle, setBillingCycle] = useState('yearly')
28    const [teamMembers, setTeamMembers] = useState(1)
29    const [apiCalls, setApiCalls] = useState(50)
30    const [prioritySupport, setPrioritySupport] = useState(true)
31
32    const memberPrice = billingCycle === 'yearly' ? 45 : 55
33    const discount = billingCycle === 'yearly' ? 0.2 : 0
34    const premiumPlanPrice = memberPrice * 12 * (1 - discount)
35    const teamLicensePrice = teamMembers * 199.99
36    const apiPrice = (apiCalls / 50) * 399.0
37    const supportPrice = prioritySupport ? 149.99 : 0
38
39    const subtotal =
40        premiumPlanPrice + teamLicensePrice + apiPrice + supportPrice
41    const taxAmount = subtotal * 0.08
42    const totalAtRenewal = subtotal + taxAmount
43    const dueNow = totalAtRenewal
44
45    return (
46        <>
47            <Card>
48                <CardHeader>
49                    <div className="text-gray hidden h-9 w-9 items-center justify-center rounded-full border md:flex">
50                        <CrownIcon className="text-gray h-4 w-4" />
51                    </div>
52                    <div className="flex flex-col space-y-2">
53                        <CardTitle>Upgrade to Premium Pro</CardTitle>
54                        <CardDescription>
55                            Manage team size, billing, and integrations
56                        </CardDescription>
57                    </div>
58                </CardHeader>
59                <CardContent className="flex flex-col gap-7 md:flex-row">
60                    <div className="space-y-2">
61                        <div className="space-y-2">
62                            <Label>Billing cycle</Label>
63                            <Select
64                                value={billingCycle}
65                                onValueChange={(value) =>
66                                    setBillingCycle(value)
67                                }
68                            >
69                                <SelectTrigger className="w-full">
70                                    <SelectValue placeholder="Select billing cycle" />
71                                </SelectTrigger>
72                                <SelectContent>
73                                    <SelectItem value="yearly">
74                                        Yearly - $118.00 / user / month
75                                    </SelectItem>
76                                    <SelectItem value="monthly">
77                                        Monthly - $55.00 / user / month
78                                    </SelectItem>
79                                    <SelectItem value="quarterly">
80                                        Quarterly - $49.00 / user / month
81                                    </SelectItem>
82                                </SelectContent>
83                            </Select>
84                        </div>
85                        <div className="space-y-2">
86                            <Label>Team members</Label>
87                            <div className="border-border rounded-lg border p-5">
88                                <div className="mb-3 flex items-center justify-between">
89                                    <span className="text-gray font-semibold">
90                                        Number of team members
91                                    </span>
92                                    <div className="flex items-center gap-3">
93                                        <Button
94                                            variant="outline"
95                                            size="sm"
96                                            onClick={() =>
97                                                setTeamMembers(
98                                                    Math.max(
99                                                        1,
100                                                        teamMembers - 1,
101                                                    ),
102                                                )
103                                            }
104                                        >
105
106                                        </Button>
107                                        <span className="w-8 text-center font-semibold">
108                                            {teamMembers}
109                                        </span>
110                                        <Button
111                                            variant="outline"
112                                            size="sm"
113                                            onClick={() =>
114                                                setTeamMembers(teamMembers + 1)
115                                            }
116                                        >
117                                            +
118                                        </Button>
119                                    </div>
120                                </div>
121                                <p className="text-gray mb-3 text-sm">
122                                    Add team members to collaborate on projects
123                                </p>
124                                <div className="border-border flex items-start gap-2 rounded-lg border p-3">
125                                    <AlertCircle className="text-gray mt-0.5 h-5 w-5 flex-shrink-0" />
126                                    <p className="text-gray text-sm">
127                                        Each team member gets full access to
128                                        premium features
129                                    </p>
130                                </div>
131                            </div>
132                        </div>
133                        <div className="space-y-2">
134                            <Label className="">API call limit</Label>
135                            <div className="rounded-lg border border-gray-200 bg-white p-6">
136                                <div className="mb-4 flex items-center justify-between">
137                                    <div>
138                                        <h3 className="text-gray flex items-center gap-2 font-semibold">
139                                            <Zap className="h-5 w-5" />
140                                            API Credits
141                                        </h3>
142                                        <p className="text-gray text-sm">
143                                            10K included + additional capacity
144                                        </p>
145                                    </div>
146                                    <div className="text-right">
147                                        <span className="text-gray text-2xl font-bold">
148                                            {apiCalls}K
149                                        </span>
150                                        <span className="text-gray block text-sm">
151                                            requests/month
152                                        </span>
153                                    </div>
154                                </div>
155
156                                <div>
157                                    <div className="text-gray mb-2 flex items-center justify-between text-sm">
158                                        <span>10K</span>
159                                        <span>500K</span>
160                                    </div>
161                                    <Slider
162                                        value={[apiCalls]}
163                                        min={10}
164                                        max={500}
165                                        step={10}
166                                        onValueChange={(v) => setApiCalls(v[0])}
167                                        className="cursor-pointer"
168                                    />
169                                </div>
170                            </div>
171                        </div>
172                        <div className="space-y-2">
173                            <Label> Additional services</Label>
174                            <div
175                                onClick={() =>
176                                    setPrioritySupport(!prioritySupport)
177                                }
178                                className={`cursor-pointer rounded-lg border-2 bg-white p-5 transition-all ${
179                                    prioritySupport
180                                        ? 'bg-border border-black'
181                                        : 'hover:border-gray border-border'
182                                }`}
183                            >
184                                <div className="flex items-start justify-between">
185                                    <div className="flex items-start gap-3">
186                                        <Checkbox
187                                            id="priority-support"
188                                            checked={prioritySupport}
189                                            onCheckedChange={(checked) =>
190                                                setPrioritySupport(!!checked)
191                                            }
192                                        />
193                                        <div>
194                                            <Label className="flex items-center gap-2 font-semibold">
195                                                <Shield className="h-5 w-5" />
196                                                Priority Support
197                                            </Label>
198                                            <p className="text-gray mt-1 text-sm">
199                                                24/7 dedicated support with
200                                                2-hour response time
201                                            </p>
202                                        </div>
203                                    </div>
204                                    <span className="text-gray text-lg font-bold">
205                                        $149.99
206                                    </span>
207                                </div>
208                            </div>
209                        </div>
210                    </div>
211                    <div>
212                        <div className="sticky top-8 rounded-2xl bg-white p-6 shadow-lg">
213                            <h2 className="mb-6 text-xl font-bold text-black">
214                                Order Summary
215                            </h2>
216
217                            <div className="mb-6 space-y-4">
218                                <div className="flex justify-between text-sm">
219                                    <span>Premium Pro Plan</span>
220                                    <span className="font-semibold">
221                                        ${premiumPlanPrice.toFixed(2)}
222                                    </span>
223                                </div>
224                                <div className="flex justify-between text-sm">
225                                    <span>{teamMembers}× Team License(s)</span>
226                                    <span className="font-semibold">
227                                        ${teamLicensePrice.toFixed(2)}
228                                    </span>
229                                </div>
230                                <div className="flex justify-between text-sm">
231                                    <span>API Credits ({apiCalls}K)</span>
232                                    <span className="font-semibold">
233                                        ${apiPrice.toFixed(2)}
234                                    </span>
235                                </div>
236                                {prioritySupport && (
237                                    <div className="flex justify-between text-sm">
238                                        <span>Priority Support</span>
239                                        <span className="font-semibold">
240                                            ${supportPrice.toFixed(2)}
241                                        </span>
242                                    </div>
243                                )}
244                            </div>
245                            <Separator />
246                            <div className="mb-6 space-y-3 border-gray-200 pt-4">
247                                <div className="flex justify-between">
248                                    <span className="text-black">Subtotal</span>
249                                    <span className="font-bold text-black">
250                                        ${subtotal.toFixed(2)}
251                                    </span>
252                                </div>
253                                <div className="flex justify-between text-sm">
254                                    <span>Tax (8%)</span>
255                                    <span>${taxAmount.toFixed(2)}</span>
256                                </div>
257                                <div className="flex justify-between">
258                                    <span>Total at renewal</span>
259                                    <span className="font-bold">
260                                        ${totalAtRenewal.toFixed(2)}
261                                    </span>
262                                </div>
263                                <Separator />
264                                <div className="flex justify-between pt-2 text-lg">
265                                    <span className="font-semibold text-black">
266                                        Due today
267                                    </span>
268                                    <span className="font-bold text-black">
269                                        ${dueNow.toFixed(2)}
270                                    </span>
271                                </div>
272                            </div>
273
274                            <Button className="shadow-gray mb-4 w-full rounded-lg px-4 py-3 font-semibold text-white shadow-lg transition-all">
275                                Complete Upgrade
276                            </Button>
277
278                            <p className="text-gray flex items-center justify-center gap-1 text-center text-xs">
279                                <CheckCircle className="size-4" />
280                                Instant activation after payment
281                            </p>
282                        </div>
283                    </div>
284                </CardContent>
285            </Card>
286        </>
287    )
288}
289
Slider for upgrade plan.
slider-03
Files
components/slider.tsx
1'use client'
2
3import React, { useState } from 'react'
4import { Bell, X } from 'lucide-react'
5import { toast } from 'sonner'
6
7import { Button } from '@/components/ui/button'
8import {
9    Card,
10    CardContent,
11    CardDescription,
12    CardFooter,
13    CardHeader,
14    CardTitle,
15} from '@/components/ui/card'
16import { Slider } from '@/components/ui/slider'
17
18export function NotificationPreference() {
19    const [emailFrequency, setEmailFrequency] = useState(15)
20
21    const calculateCost = (frequency: number) => {
22        const baseCost = 5.99
23        const additionalCost = (frequency / 30) * 14.01
24        return (baseCost + additionalCost).toFixed(2)
25    }
26
27    const onSubmit = () => {
28        toast.success(
29            `Preferences saved! You'll receive ${emailFrequency} emails per month.`,
30        )
31    }
32
33    return (
34        <Card>
35            <CardHeader className="flex flex-wrap items-center justify-between gap-3 sm:gap-4">
36                <div className="flex items-center gap-3 sm:gap-4">
37                    <div className="text-gray hidden h-9 w-9 items-center justify-center rounded-full border md:flex">
38                        <Bell className="text-gray h-5 w-5" />
39                    </div>
40                    <div className="flex flex-col space-y-2">
41                        <CardTitle>Email Digest Preferences</CardTitle>
42                        <CardDescription>
43                            Customize how often you receive update emails.
44                        </CardDescription>
45                    </div>
46                </div>
47                <Button variant="ghost" size="icon">
48                    <X className="h-5 w-5" />
49                </Button>
50            </CardHeader>
51
52            <CardContent>
53                <div className="p-6">
54                    <div className="mb-6 text-center">
55                        <p className="mb-2 text-xs font-semibold text-black uppercase">
56                            Monthly Email Frequency
57                        </p>
58                        <div className="mb-1 text-5xl font-bold text-black">
59                            {emailFrequency}
60                        </div>
61                        <p className="text-sm text-black">emails per month</p>
62                    </div>
63
64                    <div className="mb-6">
65                        <div className="relative mb-3">
66                            <Slider
67                                value={[emailFrequency]}
68                                min={0}
69                                max={30}
70                                step={1}
71                                onValueChange={(v) => setEmailFrequency(v[0])}
72                                className="w-full"
73                            />
74
75                            <div
76                                className="pointer-events-none absolute top-0 h-4 w-4 -translate-y-[6px] rounded-full shadow-lg transition-all"
77                                style={{
78                                    left: `calc(${(emailFrequency / 30) * 100}% - 8px)`,
79                                }}
80                            />
81                        </div>
82
83                        <div className="text-gray flex justify-between px-1 text-xs">
84                            {[0, 5, 10, 15, 20, 25, 30].map((mark) => (
85                                <span key={mark}>{mark}</span>
86                            ))}
87                        </div>
88                    </div>
89
90                    <div className="rounded-lg p-4">
91                        <div className="text-gray flex items-center gap-2 text-sm">
92                            <span>
93                                You will be charged{' '}
94                                <span className="text-gray font-bold">
95                                    ${calculateCost(emailFrequency)}
96                                </span>{' '}
97                                to receive {emailFrequency} monthly digest
98                                emails.
99                            </span>
100                        </div>
101                    </div>
102
103                    {emailFrequency >= 20 && (
104                        <div className="border-secondary rounded-lg border p-3">
105                            <p className="text-secondary text-xs">
106                                <span className="font-semibold">💡 Tip:</span>{' '}
107                                Consider reducing frequency to save costs while
108                                staying informed.
109                            </p>
110                        </div>
111                    )}
112
113                    {emailFrequency === 0 && (
114                        <div className="border-warning rounded-lg border p-3">
115                            <p className="text-warning text-xs">
116                                <span className="font-semibold">
117                                    ⚠️ Warning:
118                                </span>{' '}
119                                You won&apos;t receive any email updates.
120                                Important notifications may be missed.
121                            </p>
122                        </div>
123                    )}
124                </div>
125            </CardContent>
126
127            <CardFooter className="gap-2">
128                <Button variant="outline" className="w-1/2">
129                    Cancel
130                </Button>
131                <Button onClick={onSubmit} className="w-1/2">
132                    Continue
133                </Button>
134            </CardFooter>
135        </Card>
136    )
137}
138
Slider for email frequency and see pricing update.
slider-04