Skip to content

Commit ca99e79

Browse files
feat: redesign settings screen (#1193)
1 parent ec80d28 commit ca99e79

File tree

7 files changed

+223
-188
lines changed

7 files changed

+223
-188
lines changed

src/css/browserAction.css

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,31 @@
11
:root {
2+
font-size: 16px;
3+
24
--window-padding: 1.75rem;
5+
--container-outside-text-padding-left: 0.25rem;
36

4-
--theme-background-color: #fff;
7+
--theme-background-color: #f2f3f6;
8+
--theme-secondary-background-color: white;
9+
--theme-secondary-background-color-variant: #fafafc;
510
--theme-font-color: rgb(51, 51, 51);
611
--theme-secondary-font-color: rgb(51, 51, 51, 0.7);
712

8-
--md-sys-color-primary: rgb(29, 155, 240);
13+
--md-sys-color-primary: rgb(73, 113, 214);
14+
--md-sys-color-on-primary: var(--theme-secondary-background-color);
915
--md-sys-color-on-surface-variant: #888;
1016
--md-sys-color-on-surface: #aaa;
1117
}
1218

1319
@media (prefers-color-scheme: dark) {
1420
:root {
15-
--theme-background-color: #121212;
16-
--theme-font-color: rgb(255, 255, 255);
17-
--theme-secondary-font-color: rgb(255, 255, 255, 0.7);
18-
19-
--md-sys-color-primary: rgb(29, 155, 240);
21+
--theme-background-color: #0d0e14;
22+
--theme-secondary-background-color: #1f2029;
23+
--theme-secondary-background-color-variant: #2a2b37;
24+
--theme-font-color: #ebedf2;
25+
--theme-secondary-font-color: #a8b2c7;
26+
27+
--md-sys-color-primary: rgb(98, 125, 194);
28+
--md-sys-color-on-primary: var(--theme-secondary-background-color);
2029
--md-sys-color-on-surface-variant: #aaa;
2130
--md-sys-color-on-surface: #888;
2231
}
@@ -29,16 +38,6 @@
2938
font-family: sans-serif;
3039
}
3140

32-
html {
33-
font-size: 16px;
34-
}
35-
36-
html,
37-
body {
38-
max-width: 100%;
39-
max-height: 100%;
40-
}
41-
4241
body {
4342
padding: var(--window-padding);
4443
width: max-content;
@@ -62,24 +61,39 @@ h1 {
6261
margin-left: 0.5rem;
6362
color: inherit;
6463
text-decoration: none;
64+
color: var(--theme-secondary-font-color);
6565
}
6666

6767
fieldset {
68-
margin: 1rem 0;
68+
margin: 1.5rem 0;
6969
border: none;
7070
}
7171

72-
settings-separator:not(:first-of-type) {
73-
margin-top: 1rem;
72+
settings-item {
73+
margin: 0.15rem 0;
74+
}
75+
76+
*:not(settings-item) + settings-item {
77+
border-radius: 1rem 1rem 0.25rem 0.25rem;
78+
}
79+
80+
settings-group-title {
81+
padding-left: var(--container-outside-text-padding-left);
82+
}
83+
84+
settings-group-title:not(:first-child) {
85+
margin: 1.5rem 0 0.5rem 0;
7486
}
7587

7688
settings-description {
77-
margin: 1rem 0;
89+
margin: 0.25rem 0 0.5rem 0;
90+
padding-left: var(--container-outside-text-padding-left);
7891
}
7992

8093
small {
8194
font-size: 0.8em;
8295
color: var(--theme-secondary-font-color);
96+
padding-left: var(--container-outside-text-padding-left);
8397
}
8498

8599
#footer-links {

src/ts/browserAction/loadSettings.ts

Lines changed: 50 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3,51 +3,65 @@ import "../components/settingsItem";
33
// eslint-disable-next-line import-x/no-unassigned-import
44
import "../components/settingsDescription";
55
// eslint-disable-next-line import-x/no-unassigned-import
6-
import "../components/settingsSeparator";
6+
import "../components/settingsGroupTitle";
7+
import { SETTINGS_ITEMS, type SettingsData, type SettingsItemData } from "./settingsItems";
78
import { i18n, runtime } from "webextension-polyfill";
89
import { loadSettingsFromStorage, writeSettingsToStorage } from "../common/settings";
9-
import { SETTINGS_ITEMS } from "./settingsItems";
1010
import type { Settings } from "../../types/common/settings";
1111
// eslint-disable-next-line no-duplicate-imports
1212
import type { SettingsDescription } from "../components/settingsDescription";
1313
// eslint-disable-next-line no-duplicate-imports
14-
import type { SettingsItem } from "../components/settingsItem";
14+
import type { SettingsGroupTitle } from "../components/settingsGroupTitle";
1515
// eslint-disable-next-line no-duplicate-imports
16-
import type { SettingsSeparator } from "../components/settingsSeparator";
16+
import type { SettingsItem } from "../components/settingsItem";
1717
import { TRANSLATION_ATTRIBUTE } from "../common/constants";
1818
import { Translator } from "../common/translator";
1919

2020
/**
21-
* Create new settings separator element.
21+
* Create new settings group title element.
2222
* @param translationKey translation key
2323
* @returns created settings separator
2424
*/
25-
const createSettingsSeparator = (translationKey: string): SettingsSeparator => {
26-
const separator = document.createElement("settings-separator");
25+
const createGroupTitle = (translationKey: string): SettingsGroupTitle => {
26+
const separator = document.createElement("settings-group-title");
2727
separator.setAttribute(TRANSLATION_ATTRIBUTE, translationKey);
2828

2929
return separator;
3030
};
3131

32-
const createSettingsDescription = (translationKey: string): SettingsDescription => {
32+
/**
33+
* Create new settings description element.
34+
* @param translationKey translation key
35+
* @returns created settings description
36+
*/
37+
const createGroupDescription = (translationKey: string): SettingsDescription => {
3338
const description = document.createElement("settings-description");
3439
description.setAttribute(TRANSLATION_ATTRIBUTE, translationKey);
3540

3641
return description;
3742
};
3843

3944
/**
40-
* Create new settings item element.
41-
* @param settingsName settings name
42-
* @param translationKey translation key
43-
* @param checked settings status
44-
* @returns created settings item
45+
* Create a new settings item element.
46+
* @param settingsItemData Settings item data
47+
* @param checked Settings status
48+
* @param isFirstItem Whether this is the first item
49+
* @param isLastItem Whether this is the last item
50+
* @returns The created settings item
4551
*/
46-
const createSettingsItem = (settingsName: string, translationKey: string, checked: boolean): SettingsItem => {
52+
const createSettingsItem = (
53+
settingsItemData: SettingsItemData,
54+
checked: boolean,
55+
isFirstItem: boolean,
56+
isLastItem: boolean
57+
// eslint-disable-next-line max-params
58+
): SettingsItem => {
4759
const item = document.createElement("settings-item");
48-
item.settingsName = settingsName;
49-
item.setAttribute(TRANSLATION_ATTRIBUTE, translationKey);
60+
item.settingsName = settingsItemData.settingsName;
61+
item.setAttribute(TRANSLATION_ATTRIBUTE, settingsItemData.translationKey);
5062
item.checked = checked;
63+
item.isFirstItem = isFirstItem;
64+
item.isLastItem = isLastItem;
5165
item.addEventListener("change", () => {
5266
void writeSettingsToStorage({ [item.settingsName]: item.checked });
5367
});
@@ -64,28 +78,28 @@ const runTranslation = (): void => {
6478
};
6579

6680
/**
67-
* Create settings item or separator element from data.
81+
* Create settings items from group.
6882
* @param settings settings
69-
* @param data settings item data
70-
* @returns created element
83+
* @param group settings item group
84+
* @returns created elements
7185
*/
72-
const createItemsFromData = (
73-
settings: Settings,
74-
data: (typeof SETTINGS_ITEMS)[number]
75-
): SettingsSeparator | SettingsDescription | SettingsItem => {
76-
switch (data.type) {
77-
case "separator":
78-
return createSettingsSeparator(data.translationKey);
79-
80-
case "description":
81-
return createSettingsDescription(data.translationKey);
82-
83-
case "checkbox":
84-
return createSettingsItem(data.settingsName, data.translationKey, settings[data.settingsName]);
86+
const createItemsFromGroup = (settings: Settings, group: SettingsData[number]): DocumentFragment => {
87+
const fragment = document.createDocumentFragment();
88+
fragment.appendChild(createGroupTitle(group.groupName));
89+
if (group.description) {
90+
fragment.appendChild(createGroupDescription(group.description));
91+
}
8592

86-
default:
87-
throw new Error("Invalid type");
93+
for (const [index, item] of group.items.entries()) {
94+
// eslint-disable-next-line no-magic-numbers
95+
const isFirstItem = index === 0;
96+
// eslint-disable-next-line no-magic-numbers
97+
const isLastItem = index === group.items.length - 1;
98+
const settingsItem = createSettingsItem(item, settings[item.settingsName], isFirstItem, isLastItem);
99+
fragment.appendChild(settingsItem);
88100
}
101+
102+
return fragment;
89103
};
90104

91105
/**
@@ -98,8 +112,8 @@ const loadSettings = async (): Promise<void> => {
98112
if (!fieldset) throw new Error("Failed to get fieldset");
99113
const fragment = document.createDocumentFragment();
100114

101-
for (const data of SETTINGS_ITEMS) {
102-
const element = createItemsFromData(settings, data);
115+
for (const settingsGroup of SETTINGS_ITEMS) {
116+
const element = createItemsFromGroup(settings, settingsGroup);
103117
fragment.appendChild(element);
104118
}
105119

Lines changed: 68 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,85 @@
11
import type { Settings } from "../../types/common/settings";
22
import type { TranslationKey } from "../../types/common/translator";
33

4-
interface SettingsItem {
4+
interface SettingsItemData {
55
settingsName: keyof Settings;
66
translationKey: TranslationKey;
77
type: "checkbox";
88
}
99

10-
interface SettingsSeparator {
11-
translationKey: TranslationKey;
12-
type: "separator";
13-
}
14-
15-
interface SettingsDescription {
16-
translationKey: TranslationKey;
17-
type: "description";
10+
interface SettingsGroup {
11+
groupName: TranslationKey;
12+
type: "group";
13+
description?: TranslationKey;
14+
items: SettingsItemData[];
1815
}
1916

20-
type SettingsItems = Array<SettingsItem | SettingsSeparator | SettingsDescription>;
17+
type SettingsData = SettingsGroup[];
2118

2219
const SETTINGS_ITEMS = [
2320
{
24-
translationKey: "settingsWhereToDisplayCheckResults",
25-
type: "separator"
26-
},
27-
{
28-
translationKey: "settingsAlwaysShowMessagesIfYourAccountShadowbanned",
29-
type: "description"
30-
},
31-
{
32-
settingsName: "showMessagesInUnproblematicTweets",
33-
translationKey: "settingsShowMessagesInUnproblematicTweets",
34-
type: "checkbox"
35-
},
36-
{
37-
settingsName: "showMessagesInUnproblematicProfiles",
38-
translationKey: "settingsShowMessagesInUnproblematicProfiles",
39-
type: "checkbox"
40-
},
41-
{
42-
settingsName: "enableForOtherUsersTweets",
43-
translationKey: "settingsEnableForOtherUsersTweets",
44-
type: "checkbox"
45-
},
46-
{
47-
settingsName: "enableForOtherUsersProfiles",
48-
translationKey: "settingsEnableForOtherUsersProfiles",
49-
type: "checkbox"
50-
},
51-
{
52-
translationKey: "settingsOtherSettings",
53-
type: "separator"
54-
},
55-
{
56-
settingsName: "enableCompactMode",
57-
translationKey: "settingsEnableCompactMode",
58-
type: "checkbox"
59-
},
60-
{
61-
settingsName: "alwaysDetailedView",
62-
translationKey: "settingsAlwaysDetailedView",
63-
type: "checkbox"
64-
},
65-
{
66-
settingsName: "showNotesInMessages",
67-
translationKey: "settingsShowNotesInMessages",
68-
type: "checkbox"
69-
},
70-
{
71-
settingsName: "showTweetButton",
72-
translationKey: "settingsShowTweetButton",
73-
type: "checkbox"
74-
},
75-
{
76-
settingsName: "enableOnXPro",
77-
translationKey: "settingsEnableOnXPro",
78-
type: "checkbox"
21+
description: "settingsAlwaysShowMessagesIfYourAccountShadowbanned",
22+
groupName: "settingsWhereToDisplayCheckResults",
23+
items: [
24+
{
25+
settingsName: "showMessagesInUnproblematicTweets",
26+
translationKey: "settingsShowMessagesInUnproblematicTweets",
27+
type: "checkbox"
28+
},
29+
{
30+
settingsName: "showMessagesInUnproblematicProfiles",
31+
translationKey: "settingsShowMessagesInUnproblematicProfiles",
32+
type: "checkbox"
33+
},
34+
{
35+
settingsName: "enableForOtherUsersTweets",
36+
translationKey: "settingsEnableForOtherUsersTweets",
37+
type: "checkbox"
38+
},
39+
{
40+
settingsName: "enableForOtherUsersProfiles",
41+
translationKey: "settingsEnableForOtherUsersProfiles",
42+
type: "checkbox"
43+
}
44+
],
45+
type: "group"
7946
},
8047
{
81-
settingsName: "showReleaseNotes",
82-
translationKey: "settingsShowReleaseNotes",
83-
type: "checkbox"
48+
groupName: "settingsOtherSettings",
49+
items: [
50+
{
51+
settingsName: "enableCompactMode",
52+
translationKey: "settingsEnableCompactMode",
53+
type: "checkbox"
54+
},
55+
{
56+
settingsName: "alwaysDetailedView",
57+
translationKey: "settingsAlwaysDetailedView",
58+
type: "checkbox"
59+
},
60+
{
61+
settingsName: "showNotesInMessages",
62+
translationKey: "settingsShowNotesInMessages",
63+
type: "checkbox"
64+
},
65+
{
66+
settingsName: "showTweetButton",
67+
translationKey: "settingsShowTweetButton",
68+
type: "checkbox"
69+
},
70+
{
71+
settingsName: "enableOnXPro",
72+
translationKey: "settingsEnableOnXPro",
73+
type: "checkbox"
74+
},
75+
{
76+
settingsName: "showReleaseNotes",
77+
translationKey: "settingsShowReleaseNotes",
78+
type: "checkbox"
79+
}
80+
],
81+
type: "group"
8482
}
85-
] as const satisfies SettingsItems;
83+
] as const satisfies SettingsData;
8684

87-
export { SETTINGS_ITEMS };
85+
export { type SettingsData, type SettingsItemData, SETTINGS_ITEMS };

0 commit comments

Comments
 (0)