+55
-24
src/routes/settings.tsx
+55
-24
src/routes/settings.tsx
···
1
1
import { createFileRoute } from "@tanstack/react-router";
2
2
import { useAtom, useAtomValue, useSetAtom } from "jotai";
3
3
import { Slider, Switch } from "radix-ui";
4
-
import { useEffect,useState } from "react";
4
+
import { useEffect, useState } from "react";
5
5
6
6
import { Header } from "~/components/Header";
7
7
import Login from "~/components/Login";
···
40
40
<Login />
41
41
</div>
42
42
<div className="h-4" />
43
+
44
+
<SettingHeading title="Personalization" top />
45
+
<Hue />
46
+
47
+
<SettingHeading title="Network Configuration" />
48
+
<div className="flex flex-col px-4 pb-2">
49
+
<span className="text-md">Service Endpoints</span>
50
+
<span className="text-sm text-gray-500 dark:text-gray-400">
51
+
Customize the servers to be used by the app
52
+
</span>
53
+
</div>
43
54
<TextInputSetting
44
55
atom={constellationURLAtom}
45
56
title={"Constellation"}
···
69
80
init={defaultVideoCDN}
70
81
/>
71
82
72
-
<Hue />
83
+
<SettingHeading title="Experimental" />
73
84
<SwitchSetting
74
85
atom={enableBitesAtom}
75
86
title={"Bites"}
76
-
description={"Enable Wafrn Bites"}
87
+
description={"Enable Wafrn Bites to bite other people"}
77
88
//init={false}
78
-
/>
79
-
<p className="text-gray-500 dark:text-gray-400 py-4 px-6 text-sm">
80
-
please restart/refresh the app if changes arent applying correctly
89
+
/>
90
+
<p className="text-gray-500 dark:text-gray-400 py-4 px-4 text-sm border rounded-xl mx-4 mt-8 mb-4">
91
+
Notice: Please restart/refresh the app if changes arent applying
92
+
correctly
81
93
</p>
82
94
</>
83
95
);
84
96
}
85
97
98
+
export function SettingHeading({
99
+
title,
100
+
top,
101
+
}: {
102
+
title: string;
103
+
top?: boolean;
104
+
}) {
105
+
return (
106
+
<div
107
+
className="px-4"
108
+
style={{ marginTop: top ? 0 : 18, paddingBottom: 12 }}
109
+
>
110
+
<span className=" text-sm font-medium text-gray-500 dark:text-gray-400">
111
+
{title}
112
+
</span>
113
+
</div>
114
+
);
115
+
}
116
+
86
117
export function SwitchSetting({
87
118
atom,
88
119
title,
···
105
136
}
106
137
107
138
return (
108
-
<div className="flex items-center gap-4 px-4 py-2">
139
+
<div className="flex items-center gap-4 px-4 ">
109
140
<div className="flex flex-col">
110
-
<label htmlFor="switch-demo" className="text-lg">
141
+
<label htmlFor="switch-demo" className="text-md">
111
142
{title}
112
143
</label>
113
-
<span className="text-sm">{description}</span>
144
+
<span className="text-sm text-gray-500 dark:text-gray-400">
145
+
{description}
146
+
</span>
114
147
</div>
148
+
149
+
<div className="flex-1" />
115
150
116
151
<Switch.Root
117
152
id="switch-demo"
118
153
checked={value}
119
154
onCheckedChange={(v) => setValue(v)}
120
-
className="w-10 h-6 bg-gray-300 rounded-full relative data-[state=checked]:bg-blue-500 transition-colors"
155
+
className="m3switch root"
121
156
>
122
-
<Switch.Thumb
123
-
className="block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]"
124
-
/>
157
+
<Switch.Thumb className="m3switch thumb " />
125
158
</Switch.Root>
126
159
</div>
127
160
);
···
130
163
function Hue() {
131
164
const [hue, setHue] = useAtom(hueAtom);
132
165
return (
133
-
<div className="flex flex-col px-4 mt-4 ">
134
-
<span className="z-10">Hue</span>
135
-
<div className="flex flex-row items-center gap-4">
136
-
<SliderComponent
137
-
atom={hueAtom}
138
-
max={360}
139
-
/>
166
+
<div className="flex flex-col px-4">
167
+
<span className="z-[2] text-md">Hue</span>
168
+
<span className="z-[2] text-sm text-gray-500 dark:text-gray-400">
169
+
Change the colors of the app
170
+
</span>
171
+
<div className="z-[1] flex flex-row items-center gap-4">
172
+
<SliderComponent atom={hueAtom} max={360} />
140
173
<button
141
174
onClick={() => setHue(defaulthue ?? 28)}
142
175
className="px-6 py-2 h-12 rounded-full bg-gray-100 dark:bg-gray-800
···
207
240
);
208
241
}
209
242
210
-
211
243
interface SliderProps {
212
244
atom: typeof hueAtom;
213
245
min?: number;
···
221
253
max = 100,
222
254
step = 1,
223
255
}) => {
224
-
225
-
const [value, setValue] = useAtom(atom)
256
+
const [value, setValue] = useAtom(atom);
226
257
227
258
return (
228
259
<Slider.Root
···
239
270
<Slider.Thumb className="shadow-[0_0_0_8px_var(--color-white)] dark:shadow-[0_0_0_8px_var(--color-gray-950)] block w-[3px] h-12 bg-gray-500 dark:bg-gray-400 rounded-md focus:outline-none" />
240
271
</Slider.Root>
241
272
);
242
-
};
273
+
};
+91
src/styles/app.css
+91
src/styles/app.css
···
277
277
}
278
278
}
279
279
}
280
+
}
281
+
282
+
:root{
283
+
--thumb-size: 2rem;
284
+
--root-size: 3.25rem;
285
+
286
+
--switch-off-border: var(--color-gray-400);
287
+
--switch-off-bg: var(--color-gray-200);
288
+
--switch-off-thumb: var(--color-gray-400);
289
+
290
+
291
+
--switch-on-bg: var(--color-gray-500);
292
+
--switch-on-thumb: var(--color-gray-50);
293
+
294
+
}
295
+
@media (prefers-color-scheme: dark) {
296
+
:root {
297
+
--switch-off-border: var(--color-gray-500);
298
+
--switch-off-bg: var(--color-gray-800);
299
+
--switch-off-thumb: var(--color-gray-500);
300
+
301
+
302
+
--switch-on-bg: var(--color-gray-400);
303
+
--switch-on-thumb: var(--color-gray-700);
304
+
}
305
+
}
306
+
307
+
.m3switch.root{
308
+
/*w-10 h-6 bg-gray-300 rounded-full relative data-[state=checked]:bg-gray-500 transition-colors*/
309
+
/*width: 40px;
310
+
height: 24px;*/
311
+
312
+
inline-size: var(--root-size);
313
+
block-size: 2rem;
314
+
border-radius: 99999px;
315
+
316
+
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
317
+
transition-timing-function: var(--default-transition-timing-function); /* cubic-bezier(0.4, 0, 0.2, 1) */
318
+
transition-duration: var(--default-transition-duration); /* 150ms */
319
+
320
+
.m3switch.thumb{
321
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
322
+
323
+
height: var(--thumb-size);
324
+
width: var(--thumb-size);
325
+
display: inline-block;
326
+
border-radius: 9999px;
327
+
328
+
transform-origin: center;
329
+
330
+
transition-property: transform, translate, scale, rotate;
331
+
transition-timing-function: var(--default-transition-timing-function); /* cubic-bezier(0.4, 0, 0.2, 1) */
332
+
transition-duration: var(--default-transition-duration); /* 150ms */
333
+
334
+
}
335
+
336
+
&[aria-checked="true"] {
337
+
box-shadow: inset 0px 0px 0px 1.8px transparent;
338
+
background-color: var(--switch-on-bg);
339
+
340
+
.m3switch.thumb{
341
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
342
+
343
+
background-color: var(--switch-on-thumb);
344
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.72);
345
+
&:active {
346
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.88);
347
+
}
348
+
349
+
}
350
+
&:active .m3switch.thumb{
351
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.88);
352
+
}
353
+
}
354
+
355
+
&[aria-checked="false"] {
356
+
box-shadow: inset 0px 0px 0px 1.8px var(--switch-off-border);
357
+
background-color: var(--switch-off-bg);
358
+
.m3switch.thumb{
359
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
360
+
361
+
background-color: var(--switch-off-thumb);
362
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.5);
363
+
&:active {
364
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.88);
365
+
}
366
+
}
367
+
&:active .m3switch.thumb{
368
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.88);
369
+
}
370
+
}
280
371
}