SettingsModal.svelte 13.5 KB
Newer Older
Timothy J. Baek's avatar
Timothy J. Baek committed
1
<script lang="ts">
2
	import { getContext } from 'svelte';
Jannik Streidl's avatar
Jannik Streidl committed
3
	import { toast } from 'svelte-sonner';
Timothy J. Baek's avatar
Timothy J. Baek committed
4
	import { models, settings, user } from '$lib/stores';
5

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
6
	import { getModels as _getModels } from '$lib/apis';
Timothy J. Baek's avatar
Timothy J. Baek committed
7
8

	import Modal from '../common/Modal.svelte';
9
	import Account from './Settings/Account.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
10
11
12
13
	import About from './Settings/About.svelte';
	import Models from './Settings/Models.svelte';
	import General from './Settings/General.svelte';
	import Interface from './Settings/Interface.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
14
	import Audio from './Settings/Audio.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
15
	import Chats from './Settings/Chats.svelte';
16
	import Connections from './Settings/Connections.svelte';
Timothy J. Baek's avatar
Timothy J. Baek committed
17
	import Images from './Settings/Images.svelte';
18
19
	import User from '../icons/User.svelte';
	import Personalization from './Settings/Personalization.svelte';
20
	import { updateUserSettings } from '$lib/apis/users';
21

22
23
	const i18n = getContext('i18n');

Timothy J. Baek's avatar
Timothy J. Baek committed
24
	export let show = false;
25
26
27
28

	const saveSettings = async (updated) => {
		console.log(updated);
		await settings.set({ ...$settings, ...updated });
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
29
		await models.set(await getModels());
30
		await updateUserSettings(localStorage.token, { ui: $settings });
31
	};
32

Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
33
34
	const getModels = async () => {
		return await _getModels(localStorage.token);
35
36
	};

37
	let selectedTab = 'general';
Timothy J. Baek's avatar
Timothy J. Baek committed
38
39
40
</script>

<Modal bind:show>
Timothy J. Baek's avatar
Timothy J. Baek committed
41
	<div class="text-gray-700 dark:text-gray-100">
Timothy J. Baek's avatar
Timothy J. Baek committed
42
		<div class=" flex justify-between dark:text-gray-300 px-5 pt-4 pb-1">
43
			<div class=" text-lg font-medium self-center">{$i18n.t('Settings')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
			<button
				class="self-center"
				on:click={() => {
					show = false;
				}}
			>
				<svg
					xmlns="http://www.w3.org/2000/svg"
					viewBox="0 0 20 20"
					fill="currentColor"
					class="w-5 h-5"
				>
					<path
						d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
					/>
				</svg>
			</button>
		</div>

Timothy J. Baek's avatar
Timothy J. Baek committed
63
64
		<div class="flex flex-col md:flex-row w-full p-4 md:space-x-4">
			<div
Timothy J. Baek's avatar
Timothy J. Baek committed
65
				class="tabs flex flex-row overflow-x-auto space-x-1 md:space-x-0 md:space-y-1 md:flex-col flex-1 md:flex-none md:w-40 dark:text-gray-200 text-xs text-left mb-3 md:mb-0"
Timothy J. Baek's avatar
Timothy J. Baek committed
66
67
			>
				<button
68
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
Timothy J. Baek's avatar
Timothy J. Baek committed
69
					'general'
Timothy J. Baek's avatar
Timothy J. Baek committed
70
71
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
Timothy J. Baek's avatar
Timothy J. Baek committed
72
					on:click={() => {
73
						selectedTab = 'general';
Timothy J. Baek's avatar
Timothy J. Baek committed
74
					}}
Timothy J. Baek's avatar
Timothy J. Baek committed
75
				>
Timothy J. Baek's avatar
Timothy J. Baek committed
76
77
78
79
80
81
82
83
84
85
86
87
88
89
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 20 20"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								fill-rule="evenodd"
								d="M8.34 1.804A1 1 0 019.32 1h1.36a1 1 0 01.98.804l.295 1.473c.497.144.971.342 1.416.587l1.25-.834a1 1 0 011.262.125l.962.962a1 1 0 01.125 1.262l-.834 1.25c.245.445.443.919.587 1.416l1.473.294a1 1 0 01.804.98v1.361a1 1 0 01-.804.98l-1.473.295a6.95 6.95 0 01-.587 1.416l.834 1.25a1 1 0 01-.125 1.262l-.962.962a1 1 0 01-1.262.125l-1.25-.834a6.953 6.953 0 01-1.416.587l-.294 1.473a1 1 0 01-.98.804H9.32a1 1 0 01-.98-.804l-.295-1.473a6.957 6.957 0 01-1.416-.587l-1.25.834a1 1 0 01-1.262-.125l-.962-.962a1 1 0 01-.125-1.262l.834-1.25a6.957 6.957 0 01-.587-1.416l-1.473-.294A1 1 0 011 10.68V9.32a1 1 0 01.804-.98l1.473-.295c.144-.497.342-.971.587-1.416l-.834-1.25a1 1 0 01.125-1.262l.962-.962A1 1 0 015.38 3.03l1.25.834a6.957 6.957 0 011.416-.587l.294-1.473zM13 10a3 3 0 11-6 0 3 3 0 016 0z"
								clip-rule="evenodd"
							/>
						</svg>
					</div>
90
					<div class=" self-center">{$i18n.t('General')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
91
92
				</button>

93
94
95
				{#if $user?.role === 'admin'}
					<button
						class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
96
						'connections'
97
98
99
							? 'bg-gray-200 dark:bg-gray-700'
							: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
						on:click={() => {
100
							selectedTab = 'connections';
101
102
103
104
105
						}}
					>
						<div class=" self-center mr-2">
							<svg
								xmlns="http://www.w3.org/2000/svg"
Timothy J. Baek's avatar
Timothy J. Baek committed
106
								viewBox="0 0 16 16"
107
108
109
110
								fill="currentColor"
								class="w-4 h-4"
							>
								<path
Timothy J. Baek's avatar
Timothy J. Baek committed
111
									d="M1 9.5A3.5 3.5 0 0 0 4.5 13H12a3 3 0 0 0 .917-5.857 2.503 2.503 0 0 0-3.198-3.019 3.5 3.5 0 0 0-6.628 2.171A3.5 3.5 0 0 0 1 9.5Z"
112
113
114
								/>
							</svg>
						</div>
115
						<div class=" self-center">{$i18n.t('Connections')}</div>
116
					</button>
117

118
119
					<button
						class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
Timothy J. Baek's avatar
Timothy J. Baek committed
120
						'models'
121
122
123
							? 'bg-gray-200 dark:bg-gray-700'
							: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
						on:click={() => {
Timothy J. Baek's avatar
Timothy J. Baek committed
124
							selectedTab = 'models';
125
126
127
128
129
						}}
					>
						<div class=" self-center mr-2">
							<svg
								xmlns="http://www.w3.org/2000/svg"
Timothy J. Baek's avatar
Timothy J. Baek committed
130
								viewBox="0 0 20 20"
131
132
133
134
								fill="currentColor"
								class="w-4 h-4"
							>
								<path
Timothy J. Baek's avatar
Timothy J. Baek committed
135
136
137
									fill-rule="evenodd"
									d="M10 1c3.866 0 7 1.79 7 4s-3.134 4-7 4-7-1.79-7-4 3.134-4 7-4zm5.694 8.13c.464-.264.91-.583 1.306-.952V10c0 2.21-3.134 4-7 4s-7-1.79-7-4V8.178c.396.37.842.688 1.306.953C5.838 10.006 7.854 10.5 10 10.5s4.162-.494 5.694-1.37zM3 13.179V15c0 2.21 3.134 4 7 4s7-1.79 7-4v-1.822c-.396.37-.842.688-1.306.953-1.532.875-3.548 1.369-5.694 1.369s-4.162-.494-5.694-1.37A7.009 7.009 0 013 13.179z"
									clip-rule="evenodd"
138
139
140
								/>
							</svg>
						</div>
141
						<div class=" self-center">{$i18n.t('Models')}</div>
142
143
					</button>
				{/if}
144

145
				<button
146
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
Timothy J. Baek's avatar
Timothy J. Baek committed
147
					'interface'
Timothy J. Baek's avatar
Timothy J. Baek committed
148
149
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
150
					on:click={() => {
Timothy J. Baek's avatar
Timothy J. Baek committed
151
						selectedTab = 'interface';
152
153
154
155
156
					}}
				>
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
Timothy J. Baek's avatar
Timothy J. Baek committed
157
							viewBox="0 0 16 16"
158
159
160
161
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
Timothy J. Baek's avatar
Timothy J. Baek committed
162
								fill-rule="evenodd"
Timothy J. Baek's avatar
Timothy J. Baek committed
163
								d="M2 4.25A2.25 2.25 0 0 1 4.25 2h7.5A2.25 2.25 0 0 1 14 4.25v5.5A2.25 2.25 0 0 1 11.75 12h-1.312c.1.128.21.248.328.36a.75.75 0 0 1 .234.545v.345a.75.75 0 0 1-.75.75h-4.5a.75.75 0 0 1-.75-.75v-.345a.75.75 0 0 1 .234-.545c.118-.111.228-.232.328-.36H4.25A2.25 2.25 0 0 1 2 9.75v-5.5Zm2.25-.75a.75.75 0 0 0-.75.75v4.5c0 .414.336.75.75.75h7.5a.75.75 0 0 0 .75-.75v-4.5a.75.75 0 0 0-.75-.75h-7.5Z"
Timothy J. Baek's avatar
Timothy J. Baek committed
164
165
166
167
								clip-rule="evenodd"
							/>
						</svg>
					</div>
168
					<div class=" self-center">{$i18n.t('Interface')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
169
170
				</button>

Timothy J. Baek's avatar
Timothy J. Baek committed
171
172
				<button
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
173
					'personalization'
Timothy J. Baek's avatar
Timothy J. Baek committed
174
175
176
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
					on:click={() => {
177
						selectedTab = 'personalization';
Timothy J. Baek's avatar
Timothy J. Baek committed
178
179
180
					}}
				>
					<div class=" self-center mr-2">
181
						<User />
Timothy J. Baek's avatar
Timothy J. Baek committed
182
					</div>
183
					<div class=" self-center">{$i18n.t('Personalization')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
184
185
				</button>

Timothy J. Baek's avatar
Timothy J. Baek committed
186
187
				<button
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
Timothy J. Baek's avatar
Timothy J. Baek committed
188
					'audio'
Timothy J. Baek's avatar
Timothy J. Baek committed
189
190
191
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
					on:click={() => {
Timothy J. Baek's avatar
Timothy J. Baek committed
192
						selectedTab = 'audio';
Timothy J. Baek's avatar
Timothy J. Baek committed
193
194
195
196
197
198
199
200
201
202
203
204
205
206
					}}
				>
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 16 16"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								d="M7.557 2.066A.75.75 0 0 1 8 2.75v10.5a.75.75 0 0 1-1.248.56L3.59 11H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h1.59l3.162-2.81a.75.75 0 0 1 .805-.124ZM12.95 3.05a.75.75 0 1 0-1.06 1.06 5.5 5.5 0 0 1 0 7.78.75.75 0 1 0 1.06 1.06 7 7 0 0 0 0-9.9Z"
							/>
							<path
								d="M10.828 5.172a.75.75 0 1 0-1.06 1.06 2.5 2.5 0 0 1 0 3.536.75.75 0 1 0 1.06 1.06 4 4 0 0 0 0-5.656Z"
207
208
209
							/>
						</svg>
					</div>
210
					<div class=" self-center">{$i18n.t('Audio')}</div>
211
				</button>
Timothy J. Baek's avatar
Timothy J. Baek committed
212

Timothy J. Baek's avatar
Timothy J. Baek committed
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
				{#if $user.role === 'admin'}
					<button
						class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
						'images'
							? 'bg-gray-200 dark:bg-gray-700'
							: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
						on:click={() => {
							selectedTab = 'images';
						}}
					>
						<div class=" self-center mr-2">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								viewBox="0 0 16 16"
								fill="currentColor"
								class="w-4 h-4"
							>
								<path
									fill-rule="evenodd"
									d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V4Zm10.5 5.707a.5.5 0 0 0-.146-.353l-1-1a.5.5 0 0 0-.708 0L9.354 9.646a.5.5 0 0 1-.708 0L6.354 7.354a.5.5 0 0 0-.708 0l-2 2a.5.5 0 0 0-.146.353V12a.5.5 0 0 0 .5.5h8a.5.5 0 0 0 .5-.5V9.707ZM12 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"
									clip-rule="evenodd"
								/>
							</svg>
						</div>
237
						<div class=" self-center">{$i18n.t('Images')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
238
239
					</button>
				{/if}
Timothy J. Baek's avatar
Timothy J. Baek committed
240

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
				<button
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
					'chats'
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
					on:click={() => {
						selectedTab = 'chats';
					}}
				>
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 16 16"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								fill-rule="evenodd"
								d="M8 2C4.262 2 1 4.57 1 8c0 1.86.98 3.486 2.455 4.566a3.472 3.472 0 0 1-.469 1.26.75.75 0 0 0 .713 1.14 6.961 6.961 0 0 0 3.06-1.06c.403.062.818.094 1.241.094 3.738 0 7-2.57 7-6s-3.262-6-7-6ZM5 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Zm7-1a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM8 9a1 1 0 1 0 0-2 1 1 0 0 0 0 2Z"
								clip-rule="evenodd"
							/>
						</svg>
					</div>
264
					<div class=" self-center">{$i18n.t('Chats')}</div>
265
266
				</button>

Timothy J. Baek's avatar
Timothy J. Baek committed
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
				<button
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
					'account'
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
					on:click={() => {
						selectedTab = 'account';
					}}
				>
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 16 16"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								fill-rule="evenodd"
								d="M15 8A7 7 0 1 1 1 8a7 7 0 0 1 14 0Zm-5-2a2 2 0 1 1-4 0 2 2 0 0 1 4 0ZM8 9c-1.825 0-3.422.977-4.295 2.437A5.49 5.49 0 0 0 8 13.5a5.49 5.49 0 0 0 4.294-2.063A4.997 4.997 0 0 0 8 9Z"
								clip-rule="evenodd"
							/>
						</svg>
					</div>
290
					<div class=" self-center">{$i18n.t('Account')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
291
292
				</button>

Timothy J. Baek's avatar
Timothy J. Baek committed
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
				<button
					class="px-2.5 py-2.5 min-w-fit rounded-lg flex-1 md:flex-none flex text-right transition {selectedTab ===
					'about'
						? 'bg-gray-200 dark:bg-gray-700'
						: ' hover:bg-gray-300 dark:hover:bg-gray-800'}"
					on:click={() => {
						selectedTab = 'about';
					}}
				>
					<div class=" self-center mr-2">
						<svg
							xmlns="http://www.w3.org/2000/svg"
							viewBox="0 0 20 20"
							fill="currentColor"
							class="w-4 h-4"
						>
							<path
								fill-rule="evenodd"
								d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
								clip-rule="evenodd"
							/>
						</svg>
					</div>
316
					<div class=" self-center">{$i18n.t('About')}</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
317
				</button>
Timothy J. Baek's avatar
Timothy J. Baek committed
318
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
319
			<div class="flex-1 md:min-h-[28rem]">
320
				{#if selectedTab === 'general'}
Timothy J. Baek's avatar
Timothy J. Baek committed
321
					<General
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
322
						{getModels}
Timothy J. Baek's avatar
Timothy J. Baek committed
323
324
						{saveSettings}
						on:save={() => {
325
							toast.success($i18n.t('Settings saved successfully!'));
Timothy J. Baek's avatar
Timothy J. Baek committed
326
327
						}}
					/>
Timothy J. Baek's avatar
Timothy J. Baek committed
328
				{:else if selectedTab === 'models'}
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
329
					<Models {getModels} />
330
331
				{:else if selectedTab === 'connections'}
					<Connections
Timothy J. Baek's avatar
refac  
Timothy J. Baek committed
332
						{getModels}
Timothy J. Baek's avatar
Timothy J. Baek committed
333
						on:save={() => {
334
							toast.success($i18n.t('Settings saved successfully!'));
335
						}}
Timothy J. Baek's avatar
Timothy J. Baek committed
336
					/>
337
				{:else if selectedTab === 'interface'}
Timothy J. Baek's avatar
Timothy J. Baek committed
338
					<Interface
Timothy J. Baek's avatar
Timothy J. Baek committed
339
						{saveSettings}
Timothy J. Baek's avatar
Timothy J. Baek committed
340
						on:save={() => {
341
							toast.success($i18n.t('Settings saved successfully!'));
342
						}}
Timothy J. Baek's avatar
Timothy J. Baek committed
343
					/>
344
345
346
347
348
349
350
				{:else if selectedTab === 'personalization'}
					<Personalization
						{saveSettings}
						on:save={() => {
							toast.success($i18n.t('Settings saved successfully!'));
						}}
					/>
Timothy J. Baek's avatar
Timothy J. Baek committed
351
352
				{:else if selectedTab === 'audio'}
					<Audio
Timothy J. Baek's avatar
Timothy J. Baek committed
353
354
						{saveSettings}
						on:save={() => {
355
							toast.success($i18n.t('Settings saved successfully!'));
Timothy J. Baek's avatar
Timothy J. Baek committed
356
						}}
Timothy J. Baek's avatar
Timothy J. Baek committed
357
					/>
Timothy J. Baek's avatar
Timothy J. Baek committed
358
359
360
361
				{:else if selectedTab === 'images'}
					<Images
						{saveSettings}
						on:save={() => {
362
							toast.success($i18n.t('Settings saved successfully!'));
Timothy J. Baek's avatar
Timothy J. Baek committed
363
364
						}}
					/>
365
				{:else if selectedTab === 'chats'}
Timothy J. Baek's avatar
Timothy J. Baek committed
366
					<Chats {saveSettings} />
367
				{:else if selectedTab === 'account'}
368
369
					<Account
						saveHandler={() => {
370
							toast.success($i18n.t('Settings saved successfully!'));
371
						}}
372
					/>
Timothy J. Baek's avatar
Timothy J. Baek committed
373
				{:else if selectedTab === 'about'}
Timothy J. Baek's avatar
Timothy J. Baek committed
374
					<About />
Timothy J. Baek's avatar
Timothy J. Baek committed
375
376
				{/if}
			</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
377
		</div>
Timothy J. Baek's avatar
Timothy J. Baek committed
378
379
	</div>
</Modal>
380
381
382
383
384
385
386
387
388

<style>
	input::-webkit-outer-spin-button,
	input::-webkit-inner-spin-button {
		/* display: none; <- Crashes Chrome on hover */
		-webkit-appearance: none;
		margin: 0; /* <-- Apparently some margin are still there even though it's hidden */
	}

389
390
391
392
393
394
395
396
397
	.tabs::-webkit-scrollbar {
		display: none; /* for Chrome, Safari and Opera */
	}

	.tabs {
		-ms-overflow-style: none; /* IE and Edge */
		scrollbar-width: none; /* Firefox */
	}

398
399
400
401
	input[type='number'] {
		-moz-appearance: textfield; /* Firefox */
	}
</style>