Skip to content

Commit 92c5227

Browse files
committed
feat: improve preferences layout to get more space
1 parent 9e47172 commit 92c5227

6 files changed

Lines changed: 177 additions & 57 deletions

File tree

src/service/PreferencesService.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ class PreferencesService {
3636
const win = new BrowserWindow({
3737
icon: undefined,
3838
title: AppState.strings.preferences.title,
39-
width: 620,
40-
height: 620,
39+
width: 720,
40+
height: 530,
4141
show: false,
4242
frame: false,
4343
alwaysOnTop: true,
@@ -49,8 +49,9 @@ class PreferencesService {
4949
});
5050

5151
AppState.preferences = win;
52+
5253
const fps = Storage.getSettings(Settings.DRAG_REFRESH_RATE) as number || null;
53-
Draggable.from(win, { region: { height: 86 }, exclude: '.exit-btn, li', fps });
54+
Draggable.from(win, { fps, selector: '.sidebar-header, .main-header' });
5455

5556
win.setVisibleOnAllWorkspaces(true, { visibleOnFullScreen: true });
5657
this.buildContextMenu();

web/assets/styles/app.css

Lines changed: 126 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,37 +28,113 @@ body {
2828

2929
/* TABS =============================== */
3030

31-
.inline-tabs {
31+
.tab-content {
32+
flex: 1;
33+
overflow: auto;
34+
padding: 0 20px 20px 20px;
35+
}
36+
37+
.tab-pane {
38+
display: none;
39+
}
40+
41+
.tab-pane.active {
42+
display: block;
43+
}
44+
45+
/* SIDEBAR ============================ */
46+
47+
.sidebar {
48+
width: 180px;
49+
min-width: 180px;
3250
display: flex;
33-
padding-left: 0;
34-
border-bottom: 1px solid var(--divider-border-color);
35-
margin-bottom: 0;
36-
list-style: none;
51+
flex-direction: column;
52+
border-right: 1px solid var(--divider-border-color);
53+
background-color: var(--sidebar-background);
54+
user-select: none;
3755
}
3856

39-
.inline-tabs .tab {
40-
background-color: transparent;
41-
color: var(--color);
57+
.sidebar-header {
58+
padding: 20px 16px 12px;
59+
}
60+
61+
.sidebar-title {
4262
font-size: .8rem;
43-
font-weight: bold;
44-
padding: 8px 16px;
45-
border-width: 0 0 2px;
46-
border-bottom-color: transparent;
47-
margin-bottom: -1px;
48-
transition: .15s ease-in-out all;
49-
white-space: nowrap;
63+
font-weight: 700;
64+
letter-spacing: .02em;
65+
opacity: .5;
66+
text-transform: uppercase;
67+
pointer-events: none;
68+
}
69+
70+
.sidebar-menu {
71+
list-style: none;
72+
padding: 0 8px;
73+
margin: 0;
74+
display: flex;
75+
flex-direction: column;
76+
gap: 2px;
5077
}
5178

52-
.inline-tabs .tab:hover,
53-
.inline-tabs .tab:focus {
79+
.sidebar-item {
80+
display: flex;
81+
align-items: center;
82+
gap: 10px;
83+
padding: 8px 12px;
84+
border-radius: 6px;
85+
font-size: .8rem;
86+
font-weight: 500;
87+
cursor: pointer;
5488
color: var(--color);
55-
border-bottom: 2px solid var(--color);
89+
opacity: .6;
90+
transition: all .15s ease;
5691
}
5792

58-
.inline-tabs .tab.active {
59-
cursor: default;
93+
.sidebar-item:hover {
94+
opacity: .85;
95+
background-color: var(--tab-hover-background);
96+
}
97+
98+
.sidebar-item.active {
99+
opacity: 1;
100+
font-weight: 600;
101+
background-color: var(--tab-hover-background);
60102
color: var(--tab-active-color);
61-
border-bottom: 2px solid var(--tab-active-border);
103+
}
104+
105+
.sidebar-item.active .sidebar-icon {
106+
color: var(--tab-active-border);
107+
}
108+
109+
.sidebar-icon {
110+
width: 16px;
111+
height: 16px;
112+
flex-shrink: 0;
113+
}
114+
115+
/* MAIN CONTENT ======================= */
116+
117+
.main-content {
118+
flex: 1;
119+
display: flex;
120+
flex-direction: column;
121+
min-width: 0;
122+
overflow: hidden;
123+
}
124+
125+
.main-header {
126+
display: flex;
127+
justify-content: flex-end;
128+
align-items: center;
129+
padding: 6px 8px;
130+
flex-shrink: 0;
131+
box-shadow: 0 0 0 0 rgba(0, 0, 0, 0);
132+
transition: box-shadow .2s ease;
133+
z-index: 1;
134+
}
135+
136+
.main-header.scrolled {
137+
box-shadow: 0 4px 8px -2px rgba(0, 0, 0, .15);
62138
}
63139

64140
/* INPUT ======================= */
@@ -413,12 +489,9 @@ body {
413489

414490
.exit-btn {
415491
cursor: pointer !important;
416-
position: fixed;
417-
right: 16px;
418-
top: 12px;
419492
padding: 8px;
420493
line-height: 0;
421-
border-radius: 4px;
494+
border-radius: 50%;
422495
transition: .1s linear all;
423496
}
424497

@@ -758,7 +831,8 @@ body {
758831
border: 1px dashed #8b8b50;
759832
padding: 10px;
760833
border-radius: 8px;
761-
margin: 0px -36px;
834+
margin: 0;
835+
font-size: .63rem;
762836
color: var(--color);
763837
}
764838

@@ -941,6 +1015,27 @@ body {
9411015
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 1a2 2 0 0 1 2 2v4H6V3a2 2 0 0 1 2-2zm3 6V3a3 3 0 0 0-6 0v4a2 2 0 0 0-2 2v5a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2z'/%3E%3C/svg%3E");
9421016
}
9431017

1018+
/* Sidebar Icons */
1019+
.icon-pages {
1020+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M0 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2h2a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2H2a2 2 0 0 1-2-2V2zm2-1a1 1 0 0 0-1 1v8a1 1 0 0 0 1 1h2V6a2 2 0 0 1 2-2h5V2a1 1 0 0 0-1-1H2z'/%3E%3C/svg%3E");
1021+
}
1022+
1023+
.icon-shield {
1024+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M5.338 1.59a61.44 61.44 0 0 0-2.837.856.481.481 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.725 10.725 0 0 0 2.287 2.233c.346.244.652.42.893.533.12.057.218.095.293.118a.55.55 0 0 0 .101.025.615.615 0 0 0 .1-.025c.076-.023.174-.061.294-.118.24-.113.547-.29.893-.533a10.726 10.726 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.775 11.775 0 0 1-2.517 2.453 7.159 7.159 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7.158 7.158 0 0 1-1.048-.625 11.777 11.777 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 62.456 62.456 0 0 1 5.072.56z'/%3E%3Cpath d='M10.854 5.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 7.793l2.646-2.647a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E");
1025+
}
1026+
1027+
.icon-gear {
1028+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M7.068.727c.243-.97 1.62-.97 1.864 0l.071.286a.96.96 0 0 0 1.622.434l.205-.211c.695-.719 1.888-.03 1.613.931l-.08.284a.96.96 0 0 0 1.187 1.187l.283-.081c.96-.275 1.65.918.931 1.613l-.211.205a.96.96 0 0 0 .434 1.622l.286.071c.97.243.97 1.62 0 1.864l-.286.071a.96.96 0 0 0-.434 1.622l.211.205c.719.695.03 1.888-.931 1.613l-.284-.08a.96.96 0 0 0-1.187 1.187l.081.283c.275.96-.918 1.65-1.613.931l-.205-.211a.96.96 0 0 0-1.622.434l-.071.286c-.243.97-1.62.97-1.864 0l-.071-.286a.96.96 0 0 0-1.622-.434l-.205.211c-.695.719-1.888.03-1.613-.931l.08-.284a.96.96 0 0 0-1.186-1.187l-.284.081c-.96.275-1.65-.918-.931-1.613l.211-.205a.96.96 0 0 0-.434-1.622l-.286-.071c-.97-.243-.97-1.62 0-1.864l.286-.071a.96.96 0 0 0 .434-1.622l-.211-.205c-.719-.695-.03-1.888.931-1.613l.284.08a.96.96 0 0 0 1.187-1.186l-.081-.284c-.275-.96.918-1.65 1.613-.931l.205.211a.96.96 0 0 0 1.622-.434l.071-.286zM12.973 8.5H8.25l-2.834 3.779A4.998 4.998 0 0 0 12.973 8.5zm0-1a4.998 4.998 0 0 0-7.557-3.779L8.25 7.5h4.723zM5.048 3.967c-.03.021-.058.043-.087.065l.087-.065zm-.431.355A4.995 4.995 0 0 0 3.002 8c0 1.455.622 2.765 1.615 3.678L7.375 8 4.617 4.322zm.344 7.646l.087.065-.087-.065z'/%3E%3C/svg%3E");
1029+
}
1030+
1031+
.icon-sync {
1032+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z'/%3E%3Cpath d='M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z'/%3E%3C/svg%3E");
1033+
}
1034+
1035+
.icon-info {
1036+
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z'/%3E%3Cpath d='m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z'/%3E%3C/svg%3E");
1037+
}
1038+
9441039
/* GENERICS =========================== */
9451040

9461041
.btn:disabled {
@@ -986,6 +1081,11 @@ body {
9861081
height: 14px;
9871082
}
9881083

1084+
.square-12 {
1085+
width: 12px;
1086+
height: 12px;
1087+
}
1088+
9891089
.smallest {
9901090
font-size: .75em;
9911091
}

web/assets/styles/darktheme.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
--btn-secondary-color: #e0e0e0;
4747
--btn-secondary-hover: #4a4a4a;
4848

49+
/* Sidebar */
50+
--sidebar-background: #181818;
51+
4952
/* Scrollbar */
5053
--scrollbar-thumb: #676767;
5154
--scrollbar-track: #333;

web/assets/styles/lighttheme.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
--btn-secondary-color: #1a1e24;
4444
--btn-secondary-hover: #d4dae0;
4545

46+
/* Sidebar */
47+
--sidebar-background: #edf0f3;
48+
4649
/* Scrollbar */
4750
--scrollbar-thumb: #888;
4851
--scrollbar-track: #e0e0e0;

web/preferences/components/settings/Settings.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ app.component('Settings', {
22
template: /*html*/ `
33
<div id="settings-tab">
44
<template v-if="inputs" v-for="(section, i) in Object.keys(inputs)" :key="section">
5-
<div v-if="hasEnabledInputs(section)" class="h6" :class="{ 'mt-3': !i, 'mt-5': i }">{{ section }}</div>
5+
<div v-if="hasEnabledInputs(section)" class="h6" :class="{ 'mt-5': i }">{{ section }}</div>
66
<template v-for="(input) in inputs[section]" :key="input.id">
77
<template v-if="!input.disabled">
88
<hr class="input-divider">

web/preferences/main.js

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,55 +10,63 @@ window.addEventListener('load', async () => {
1010

1111
const app = Vue.createApp({
1212
template: /*html*/ `
13-
<div class="exit-btn" @click="$remote.window.close()">
14-
<svg class="square-14" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>
15-
<path d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/>
16-
</svg>
17-
</div>
18-
<div class="w-100 d-flex flex-column">
19-
<div class="mt-3 mb-2">
20-
<span class="h6 ps-4 pe-none">{{ $i18n.preferences.title }}</span>
13+
<nav class="sidebar">
14+
<div class="sidebar-header">
15+
<span class="sidebar-title">{{ $i18n.preferences.title }}</span>
2116
</div>
22-
<ul class="inline-tabs px-4">
23-
<li @click="tab = 'pages'">
24-
<button class="tab" :class="{ active: tab === 'pages' }">{{ $i18n.preferences.tabs.pages }}</button>
17+
<ul class="sidebar-menu">
18+
<li class="sidebar-item" :class="{ active: tab === 'pages' }" @click="tab = 'pages'">
19+
<span class="icon sidebar-icon icon-pages"></span>
20+
<span>{{ $i18n.preferences.tabs.pages }}</span>
2521
</li>
26-
<li @click="tab = 'permissions'">
27-
<button class="tab" :class="{ active: tab === 'permissions' }">{{ $i18n.preferences.tabs.permissions }}</button>
22+
<li class="sidebar-item" :class="{ active: tab === 'permissions' }" @click="tab = 'permissions'">
23+
<span class="icon sidebar-icon icon-shield"></span>
24+
<span>{{ $i18n.preferences.tabs.permissions }}</span>
2825
</li>
29-
<li @click="tab = 'settings'">
30-
<button class="tab" :class="{ active: tab === 'settings' }">{{ $i18n.preferences.tabs.settings }}</button>
26+
<li class="sidebar-item" :class="{ active: tab === 'settings' }" @click="tab = 'settings'">
27+
<span class="icon sidebar-icon icon-gear"></span>
28+
<span>{{ $i18n.preferences.tabs.settings }}</span>
3129
</li>
32-
<li @click="tab = 'sync'">
33-
<button class="tab" :class="{ active: tab === 'sync' }">{{ $i18n.preferences.tabs.sync }}</button>
30+
<li class="sidebar-item" :class="{ active: tab === 'sync' }" @click="tab = 'sync'">
31+
<span class="icon sidebar-icon icon-sync"></span>
32+
<span>{{ $i18n.preferences.tabs.sync }}</span>
3433
</li>
35-
<li @click="tab = 'about'">
36-
<button class="tab" :class="{ active: tab === 'about' }">{{ $i18n.preferences.tabs.about }}</button>
34+
<li class="sidebar-item" :class="{ active: tab === 'about' }" @click="tab = 'about'">
35+
<span class="icon sidebar-icon icon-info"></span>
36+
<span>{{ $i18n.preferences.tabs.about }}</span>
3737
</li>
3838
</ul>
39-
40-
<div class="tab-content p-3 overflow-auto">
41-
<div class="tab-pane container" :class="{ active: tab === 'pages' }">
39+
</nav>
40+
<div class="main-content">
41+
<div class="main-header" :class="{ scrolled: isScrolled }">
42+
<div class="exit-btn" @click="$remote.window.close()">
43+
<svg class="square-12" xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'>
44+
<path d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/>
45+
</svg>
46+
</div>
47+
</div>
48+
<div class="tab-content" @scroll="onContentScroll">
49+
<div class="tab-pane" :class="{ active: tab === 'pages' }">
4250
<pages @navigate="navigateToTab"></pages>
4351
</div>
44-
<div class="tab-pane container" :class="{ active: tab === 'permissions' }">
52+
<div class="tab-pane" :class="{ active: tab === 'permissions' }">
4553
<permissions></permissions>
4654
</div>
47-
<div class="tab-pane container" :class="{ active: tab === 'settings' }">
55+
<div class="tab-pane" :class="{ active: tab === 'settings' }">
4856
<settings></settings>
4957
</div>
50-
<div class="tab-pane container" :class="{ active: tab === 'sync' }">
58+
<div class="tab-pane" :class="{ active: tab === 'sync' }">
5159
<sync-tab></sync-tab>
5260
</div>
53-
<div class="tab-pane container" :class="{ active: tab === 'about' }">
61+
<div class="tab-pane" :class="{ active: tab === 'about' }">
5462
<about-tab v-if="tab === 'about'"></about-tab>
5563
</div>
5664
</div>
5765
</div>
5866
`,
5967

6068
inject: ['$remote', '$const', '$i18n'],
61-
data() { return { tab: 'pages', appEl: document.getElementById('app'), themeChangeListener: null } },
69+
data() { return { tab: 'pages', isScrolled: false, appEl: document.getElementById('app'), themeChangeListener: null } },
6270
beforeMount() {
6371
this.setupBootstrapTheme()
6472
this.setupLinuxSpecificStyles()
@@ -81,8 +89,13 @@ const app = Vue.createApp({
8189
this.appEl.style.setProperty('border', '1px solid var(--border-color)')
8290
},
8391

92+
onContentScroll(e) {
93+
this.isScrolled = e.target.scrollTop > 0
94+
},
95+
8496
navigateToTab(tab) {
8597
this.tab = tab
98+
this.isScrolled = false
8699
},
87100

88101
setupBootstrapTheme() {

0 commit comments

Comments
 (0)