tangled
alpha
login
or
join now
whey.party
/
red-dwarf
82
fork
atom
an independent Bluesky client using Constellation, PDS Queries, and other services
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
client
app
82
fork
atom
overview
issues
25
pulls
pipelines
better settings styles
rimar1337
4 months ago
65f60fa0
fc6b4da8
+146
-24
2 changed files
expand all
collapse all
unified
split
src
routes
settings.tsx
styles
app.css
+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
4
-
import { useEffect,useState } from "react";
4
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
43
+
44
44
+
<SettingHeading title="Personalization" top />
45
45
+
<Hue />
46
46
+
47
47
+
<SettingHeading title="Network Configuration" />
48
48
+
<div className="flex flex-col px-4 pb-2">
49
49
+
<span className="text-md">Service Endpoints</span>
50
50
+
<span className="text-sm text-gray-500 dark:text-gray-400">
51
51
+
Customize the servers to be used by the app
52
52
+
</span>
53
53
+
</div>
43
54
<TextInputSetting
44
55
atom={constellationURLAtom}
45
56
title={"Constellation"}
···
69
80
init={defaultVideoCDN}
70
81
/>
71
82
72
72
-
<Hue />
83
83
+
<SettingHeading title="Experimental" />
73
84
<SwitchSetting
74
85
atom={enableBitesAtom}
75
86
title={"Bites"}
76
76
-
description={"Enable Wafrn Bites"}
87
87
+
description={"Enable Wafrn Bites to bite other people"}
77
88
//init={false}
78
78
-
/>
79
79
-
<p className="text-gray-500 dark:text-gray-400 py-4 px-6 text-sm">
80
80
-
please restart/refresh the app if changes arent applying correctly
89
89
+
/>
90
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
91
+
Notice: Please restart/refresh the app if changes arent applying
92
92
+
correctly
81
93
</p>
82
94
</>
83
95
);
84
96
}
85
97
98
98
+
export function SettingHeading({
99
99
+
title,
100
100
+
top,
101
101
+
}: {
102
102
+
title: string;
103
103
+
top?: boolean;
104
104
+
}) {
105
105
+
return (
106
106
+
<div
107
107
+
className="px-4"
108
108
+
style={{ marginTop: top ? 0 : 18, paddingBottom: 12 }}
109
109
+
>
110
110
+
<span className=" text-sm font-medium text-gray-500 dark:text-gray-400">
111
111
+
{title}
112
112
+
</span>
113
113
+
</div>
114
114
+
);
115
115
+
}
116
116
+
86
117
export function SwitchSetting({
87
118
atom,
88
119
title,
···
105
136
}
106
137
107
138
return (
108
108
-
<div className="flex items-center gap-4 px-4 py-2">
139
139
+
<div className="flex items-center gap-4 px-4 ">
109
140
<div className="flex flex-col">
110
110
-
<label htmlFor="switch-demo" className="text-lg">
141
141
+
<label htmlFor="switch-demo" className="text-md">
111
142
{title}
112
143
</label>
113
113
-
<span className="text-sm">{description}</span>
144
144
+
<span className="text-sm text-gray-500 dark:text-gray-400">
145
145
+
{description}
146
146
+
</span>
114
147
</div>
148
148
+
149
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
120
-
className="w-10 h-6 bg-gray-300 rounded-full relative data-[state=checked]:bg-blue-500 transition-colors"
155
155
+
className="m3switch root"
121
156
>
122
122
-
<Switch.Thumb
123
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
124
-
/>
157
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
133
-
<div className="flex flex-col px-4 mt-4 ">
134
134
-
<span className="z-10">Hue</span>
135
135
-
<div className="flex flex-row items-center gap-4">
136
136
-
<SliderComponent
137
137
-
atom={hueAtom}
138
138
-
max={360}
139
139
-
/>
166
166
+
<div className="flex flex-col px-4">
167
167
+
<span className="z-[2] text-md">Hue</span>
168
168
+
<span className="z-[2] text-sm text-gray-500 dark:text-gray-400">
169
169
+
Change the colors of the app
170
170
+
</span>
171
171
+
<div className="z-[1] flex flex-row items-center gap-4">
172
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
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
224
-
225
225
-
const [value, setValue] = useAtom(atom)
256
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
242
-
};
273
273
+
};
+91
src/styles/app.css
···
277
277
}
278
278
}
279
279
}
280
280
+
}
281
281
+
282
282
+
:root{
283
283
+
--thumb-size: 2rem;
284
284
+
--root-size: 3.25rem;
285
285
+
286
286
+
--switch-off-border: var(--color-gray-400);
287
287
+
--switch-off-bg: var(--color-gray-200);
288
288
+
--switch-off-thumb: var(--color-gray-400);
289
289
+
290
290
+
291
291
+
--switch-on-bg: var(--color-gray-500);
292
292
+
--switch-on-thumb: var(--color-gray-50);
293
293
+
294
294
+
}
295
295
+
@media (prefers-color-scheme: dark) {
296
296
+
:root {
297
297
+
--switch-off-border: var(--color-gray-500);
298
298
+
--switch-off-bg: var(--color-gray-800);
299
299
+
--switch-off-thumb: var(--color-gray-500);
300
300
+
301
301
+
302
302
+
--switch-on-bg: var(--color-gray-400);
303
303
+
--switch-on-thumb: var(--color-gray-700);
304
304
+
}
305
305
+
}
306
306
+
307
307
+
.m3switch.root{
308
308
+
/*w-10 h-6 bg-gray-300 rounded-full relative data-[state=checked]:bg-gray-500 transition-colors*/
309
309
+
/*width: 40px;
310
310
+
height: 24px;*/
311
311
+
312
312
+
inline-size: var(--root-size);
313
313
+
block-size: 2rem;
314
314
+
border-radius: 99999px;
315
315
+
316
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
317
+
transition-timing-function: var(--default-transition-timing-function); /* cubic-bezier(0.4, 0, 0.2, 1) */
318
318
+
transition-duration: var(--default-transition-duration); /* 150ms */
319
319
+
320
320
+
.m3switch.thumb{
321
321
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
322
322
+
323
323
+
height: var(--thumb-size);
324
324
+
width: var(--thumb-size);
325
325
+
display: inline-block;
326
326
+
border-radius: 9999px;
327
327
+
328
328
+
transform-origin: center;
329
329
+
330
330
+
transition-property: transform, translate, scale, rotate;
331
331
+
transition-timing-function: var(--default-transition-timing-function); /* cubic-bezier(0.4, 0, 0.2, 1) */
332
332
+
transition-duration: var(--default-transition-duration); /* 150ms */
333
333
+
334
334
+
}
335
335
+
336
336
+
&[aria-checked="true"] {
337
337
+
box-shadow: inset 0px 0px 0px 1.8px transparent;
338
338
+
background-color: var(--switch-on-bg);
339
339
+
340
340
+
.m3switch.thumb{
341
341
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
342
342
+
343
343
+
background-color: var(--switch-on-thumb);
344
344
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.72);
345
345
+
&:active {
346
346
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.88);
347
347
+
}
348
348
+
349
349
+
}
350
350
+
&:active .m3switch.thumb{
351
351
+
transform: translate(calc((var(--root-size) / 2) - 50%),0) scale(0.88);
352
352
+
}
353
353
+
}
354
354
+
355
355
+
&[aria-checked="false"] {
356
356
+
box-shadow: inset 0px 0px 0px 1.8px var(--switch-off-border);
357
357
+
background-color: var(--switch-off-bg);
358
358
+
.m3switch.thumb{
359
359
+
/*block w-5 h-5 bg-white rounded-full shadow-sm transition-transform translate-x-[2px] data-[state=checked]:translate-x-[20px]*/
360
360
+
361
361
+
background-color: var(--switch-off-thumb);
362
362
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.5);
363
363
+
&:active {
364
364
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.88);
365
365
+
}
366
366
+
}
367
367
+
&:active .m3switch.thumb{
368
368
+
transform: translate(calc(-1 * (var(--root-size) / 2) + 50%),0) scale(0.88);
369
369
+
}
370
370
+
}
280
371
}