Skip to content

Commit 03c75ba

Browse files
authored
feat(settings): make settings menu more beautiful (#4321)
1 parent a1ee2f4 commit 03c75ba

32 files changed

Lines changed: 2400 additions & 2344 deletions

js/app/packages/app/component/EmailAuth.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ function EmailLinkCallback(props: Pick<EmailAuthParams, 'successPath'>) {
119119
navigateToSuccess();
120120
return;
121121
}
122-
setActiveTabId('Email');
122+
setActiveTabId('Connected');
123123
navigate('/component/mail/component/settings', { replace: true });
124124
};
125125

js/app/packages/app/component/next-soup/soup-view/filters-bar/inbox-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export function InboxSelector() {
5959
icon: () => <PlusIcon class="size-4" />,
6060
onSelect: () =>
6161
guardAddInbox(() => {
62-
openSettings('Email');
62+
openSettings('Connected');
6363
openAddInboxDialog();
6464
}),
6565
}

js/app/packages/app/component/settings/Account.tsx

Lines changed: 85 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { staticFileIdEndpoint } from '@core/constant/servers';
77
import { createStaticFile } from '@core/util/create';
88
import { openFilePicker } from '@core/util/upload';
99
import { Dialog, Button, Panel, Tooltip, ToggleSwitch, Dropdown } from '@ui';
10+
import { SettingsCard, SettingsPage, SettingsSection } from './primitives';
1011
import {
1112
blockNameToFileExtensions,
1213
blockNameToMimeTypes,
@@ -338,88 +339,84 @@ export function Account() {
338339
};
339340

340341
return (
341-
<div class="h-full overflow-hidden flex justify-center p-2">
342-
<div class="max-w-200 size-full">
343-
<Panel depth={2} class="h-full overflow-hidden text-ink">
344-
<Panel.Header class="px-6">
345-
<div class="flex items-center gap-2">
346-
<div class="text-sm font-semibold">Account</div>
347-
</div>
348-
</Panel.Header>
349-
350-
<Panel.Body scroll class="text-ink">
351-
<div class="grid settings-row-dividers">
352-
<Show when={ENABLE_PROFILE_PICTURES}>
353-
<Show when={userId()} keyed>
354-
{(id) => <ProfilePictureRow userId={id} />}
355-
</Show>
356-
</Show>
357-
358-
<Row label="Email">
359-
<span class="ph-no-capture text-sm text-ink-muted">
360-
{email() ?? ''}
361-
</span>
362-
</Row>
363-
364-
<Row label="First Name">
365-
<NameInput
366-
value={firstName()}
367-
onSave={(newValue) =>
368-
saveUserName(
369-
newValue,
370-
'first_name',
371-
updatedFirstName(),
372-
setUpdatedFirstName
373-
)
374-
}
375-
placeholder="Enter First Name"
376-
/>
377-
</Row>
378-
379-
<Row label="Last Name">
380-
<NameInput
381-
value={lastName()}
382-
onSave={(newValue) =>
383-
saveUserName(
384-
newValue,
385-
'last_name',
386-
updatedLastName(),
387-
setUpdatedLastName
388-
)
389-
}
390-
placeholder="Enter Last Name"
391-
/>
392-
</Row>
393-
394-
<Show when={autoUpdateUIEnabled()}>
395-
<BundleVersionRow />
396-
<BundleUpdateRow />
397-
</Show>
398-
399-
<NotificationToggle />
400-
</div>
401-
402-
<Show when={isMobile()}>
403-
<div class="flex items-center justify-center px-6 py-6">
404-
<Button
405-
variant="base"
406-
size="md"
407-
depth={3}
408-
class="px-4"
409-
onClick={() => logout()}
410-
>
411-
<SignOutIcon class="size-4" />
412-
Log out
413-
</Button>
414-
</div>
342+
<SettingsPage title="Account">
343+
<SettingsSection>
344+
<SettingsCard>
345+
<Show when={ENABLE_PROFILE_PICTURES}>
346+
<Show when={userId()} keyed>
347+
{(id) => <ProfilePictureRow userId={id} />}
415348
</Show>
349+
</Show>
416350

417-
<Show when={isNativeMobilePlatform()}>
418-
<div class="border-t border-edge pt-4">
419-
<Button variant="danger" depth={3} onClick={() => setShowDeleteModal(true)}>
420-
Delete Account
421-
</Button>
422-
<Dialog
351+
<Row label="Email">
352+
<span class="ph-no-capture text-sm text-ink-muted">
353+
{email() ?? ''}
354+
</span>
355+
</Row>
356+
357+
<Row label="First Name">
358+
<NameInput
359+
value={firstName()}
360+
onSave={(newValue) =>
361+
saveUserName(
362+
newValue,
363+
'first_name',
364+
updatedFirstName(),
365+
setUpdatedFirstName
366+
)
367+
}
368+
placeholder="Enter First Name"
369+
/>
370+
</Row>
371+
372+
<Row label="Last Name">
373+
<NameInput
374+
value={lastName()}
375+
onSave={(newValue) =>
376+
saveUserName(
377+
newValue,
378+
'last_name',
379+
updatedLastName(),
380+
setUpdatedLastName
381+
)
382+
}
383+
placeholder="Enter Last Name"
384+
/>
385+
</Row>
386+
387+
<Show when={autoUpdateUIEnabled()}>
388+
<BundleVersionRow />
389+
<BundleUpdateRow />
390+
</Show>
391+
392+
<NotificationToggle />
393+
</SettingsCard>
394+
</SettingsSection>
395+
396+
<Show when={isMobile()}>
397+
<SettingsSection>
398+
<div class="flex items-center justify-center">
399+
<Button
400+
variant="base"
401+
size="md"
402+
depth={3}
403+
class="px-4"
404+
onClick={() => logout()}
405+
>
406+
<SignOutIcon class="size-4" />
407+
Log out
408+
</Button>
409+
</div>
410+
</SettingsSection>
411+
</Show>
412+
413+
<Show when={isNativeMobilePlatform()}>
414+
<SettingsSection title="Danger zone">
415+
<div>
416+
<Button variant="danger" depth={3} onClick={() => setShowDeleteModal(true)}>
417+
Delete Account
418+
</Button>
419+
<Dialog
423420
open={showDeleteModal()}
424421
onOpenChange={setShowDeleteModal}
425422
position="center"
@@ -478,18 +475,16 @@ export function Account() {
478475
</Panel.Body>
479476
</Panel>
480477
</Dialog>
481-
</div>
482-
</Show>
483-
</Panel.Body>
484-
</Panel>
485-
</div>
486-
</div>
478+
</div>
479+
</SettingsSection>
480+
</Show>
481+
</SettingsPage>
487482
);
488483
}
489484

490485
function Row(props: { label: string; children?: any }) {
491486
return (
492-
<div class="bg-surface flex items-center justify-between h-15.25 px-6">
487+
<div class="bg-surface flex items-center justify-between gap-4 min-h-15.25 px-6 py-3">
493488
<div class="text-sm">{props.label}</div>
494489
<div class="text-right">{props.children}</div>
495490
</div>
@@ -548,10 +543,10 @@ function NameInput(props: {
548543
};
549544

550545
return (
551-
<div class="ph-no-capture group relative flex items-center gap-1.5 rounded-lg h-7 mobile:h-9 px-2 border text-xs bg-transparent text-ink-muted border-edge-muted hover:text-ink focus-within:text-ink focus-within:border-accent">
546+
<div class="ph-no-capture group relative flex items-center gap-1.5 rounded-lg h-9 px-3 border text-sm bg-transparent text-ink-muted border-edge-muted hover:text-ink focus-within:text-ink focus-within:border-accent">
552547
<input
553548
type="text"
554-
class="flex-1 min-w-0 bg-transparent outline-none border-0 p-0 text-xs placeholder:text-ink-extra-muted"
549+
class="flex-1 min-w-0 bg-transparent outline-none border-0 p-0 text-sm placeholder:text-ink-extra-muted"
555550
value={inputValue()}
556551
onInput={(e) => setInputValue(e.currentTarget.value)}
557552
onFocus={() => {
@@ -623,6 +618,7 @@ function NotificationSettings(props: {
623618
return (
624619
<Row label="Notifications">
625620
<ToggleSwitch
621+
size="md"
626622
checked={props.settings.isEnabled()}
627623
onChange={handleToggle}
628624
/>
Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { For } from 'solid-js';
2-
import { Button, Panel, ToggleSwitch } from '@ui';
2+
import { Button, ToggleSwitch } from '@ui';
33
import {
44
type DebugSettingDef,
55
DEBUG_SETTINGS,
@@ -8,61 +8,46 @@ import {
88
getDebugSetting,
99
setDebugSetting,
1010
} from '@app/lib/debugSettings';
11+
import { SettingsCard, SettingsPage, SettingsRow } from './primitives';
1112

1213
function DebugSettingRow(props: { setting: DebugSettingDef }) {
1314
const checked = () => getDebugSetting(props.setting.key);
1415

1516
return (
16-
<div class="flex items-center justify-between gap-4 py-2 px-6">
17-
<div class="min-w-0">
18-
<div class="text-sm">{props.setting.label}</div>
19-
<div class="text-xs text-ink-extra-muted">
20-
{props.setting.description}
21-
</div>
22-
</div>
17+
<SettingsRow label={props.setting.label} description={props.setting.description}>
2318
<ToggleSwitch
19+
size="md"
2420
checked={checked()}
2521
onChange={(value) => setDebugSetting(props.setting.key, value)}
2622
/>
27-
</div>
23+
</SettingsRow>
2824
);
2925
}
3026

3127
export function Admin() {
3228
const hasActiveSettings = () => Object.keys(debugSettings()).length > 0;
3329

3430
return (
35-
<div class="h-full overflow-hidden flex justify-center p-2">
36-
<div class="max-w-200 size-full">
37-
<Panel depth={2}>
38-
<Panel.Header>
39-
<div class="flex items-center justify-between gap-4 w-full px-2 py-2">
40-
<div>
41-
<div class="text-sm font-medium">Debug settings</div>
42-
<div class="text-xs text-ink-extra-muted">
43-
Local toggles for debugging — only visible to Macro staff.
44-
</div>
45-
</div>
46-
<Button
47-
variant="base"
48-
size="sm"
49-
disabled={!hasActiveSettings()}
50-
onClick={clearAllDebugSettings}
51-
>
52-
Reset all
53-
</Button>
54-
</div>
55-
</Panel.Header>
56-
57-
<Panel.Body scroll>
58-
<div class="flex flex-col py-2">
59-
<For each={DEBUG_SETTINGS}>
60-
{(setting) => <DebugSettingRow setting={setting} />}
61-
</For>
62-
</div>
63-
</Panel.Body>
64-
</Panel>
65-
</div>
66-
</div>
31+
<SettingsPage
32+
title="Debug"
33+
description="Local toggles for debugging — only visible to Macro staff."
34+
actions={
35+
<Button
36+
variant="base"
37+
size="sm"
38+
depth={3}
39+
disabled={!hasActiveSettings()}
40+
onClick={clearAllDebugSettings}
41+
>
42+
Reset all
43+
</Button>
44+
}
45+
>
46+
<SettingsCard>
47+
<For each={DEBUG_SETTINGS}>
48+
{(setting) => <DebugSettingRow setting={setting} />}
49+
</For>
50+
</SettingsCard>
51+
</SettingsPage>
6752
);
6853
}

0 commit comments

Comments
 (0)