feat(menu): profile deletion via confirmation popup

This commit is contained in:
dragonwocky 2023-01-19 22:34:41 +11:00
parent 23834475c0
commit 72332acc58
Signed by: dragonwocky
GPG Key ID: 7998D08F7D7BD7A8
15 changed files with 2766 additions and 130 deletions

View File

@ -693,13 +693,13 @@ const styleAccents = () => {
"rgb(211, 79, 67)", "rgb(211, 79, 67)",
"rgb(205, 73, 69)", "rgb(205, 73, 69)",
], ],
secondaryHover = cssVariable({
name: "accent-secondary_hover",
value: "rgba(235, 87, 87, 0.1)",
}),
secondaryContrast = cssVariable({ secondaryContrast = cssVariable({
name: "accent-secondary_contrast", name: "accent-secondary_contrast",
value: "white", value: "white",
}),
secondaryTransparent = cssVariable({
name: "accent-secondary_transparent",
value: "rgba(235, 87, 87, 0.1)",
}); });
overrideStyle({ overrideStyle({
property: "color", property: "color",
@ -746,7 +746,7 @@ const styleAccents = () => {
}); });
overrideStyle({ overrideStyle({
property: "background", property: "background",
variable: secondaryTransparent, variable: secondaryHover,
specificity: ["value"], specificity: ["value"],
}); });

View File

@ -12,7 +12,7 @@ import { fileURLToPath } from "node:url";
const dependencies = { const dependencies = {
"htm.min.js": "https://unpkg.com/htm@3.1.1/mini/index.js", "htm.min.js": "https://unpkg.com/htm@3.1.1/mini/index.js",
"twind.min.js": "https://unpkg.com/@twind/cdn@1.0.7/cdn.global.js", "twind.min.js": "https://unpkg.com/@twind/cdn@1.0.7/cdn.global.js",
"lucide.min.js": "https://unpkg.com/lucide@0.104.0/dist/umd/lucide.min.js", "lucide.min.js": "https://unpkg.com/lucide@0.105.0/dist/umd/lucide.min.js",
"coloris.min.js": "coloris.min.js":
"https://cdn.jsdelivr.net/gh/mdbassit/Coloris@latest/dist/coloris.min.js", "https://cdn.jsdelivr.net/gh/mdbassit/Coloris@latest/dist/coloris.min.js",
"coloris.min.css": "coloris.min.css":

View File

@ -39,38 +39,35 @@ const sendMessage = (channel, message) => {
const initDatabase = (namespace, fallbacks = {}) => { const initDatabase = (namespace, fallbacks = {}) => {
if (Array.isArray(namespace)) namespace = namespace.join("__"); if (Array.isArray(namespace)) namespace = namespace.join("__");
namespace = namespace ? namespace + "__" : ""; namespace = namespace ? namespace + "__" : "";
const namespaceify = (key) =>
key.startsWith(namespace) ? key : namespace + key;
return { return {
get: async (key) => { get: async (key) => {
const fallback = fallbacks[key]; const fallback = fallbacks[key];
key = key.startsWith(namespace) ? key : namespace + key; key = namespaceify(key);
return new Promise((res, _rej) => { return (await chrome.storage.local.get([key]))[key] ?? fallback;
chrome.storage.local.get([key], ({ [key]: value }) => {
return res(value ?? fallback);
});
});
}, },
set: async (key, value) => { set: (key, value) => {
key = key.startsWith(namespace) ? key : namespace + key; key = namespaceify(key);
return new Promise((res, _rej) => { return chrome.storage.local.set({ [key]: value });
chrome.storage.local.set({ [key]: value }, () => res(true)); },
}); remove: (keys) => {
keys = Array.isArray(keys) ? keys : [keys];
keys = keys.map(namespaceify);
return chrome.storage.local.remove(keys);
}, },
export: async () => { export: async () => {
const obj = await new Promise((res, _rej) => { const obj = await chrome.storage.local.get();
chrome.storage.local.get((value) => res(value));
});
if (!namespace) return obj; if (!namespace) return obj;
const entries = Object.entries(obj) const entries = Object.entries(obj)
.filter(([key]) => key.startsWith(namespace)) .filter(([key]) => key.startsWith(namespace))
.map(([key, value]) => [key.slice(namespace.length), value]); .map(([key, value]) => [key.slice(namespace.length), value]);
return Object.fromEntries(entries); return Object.fromEntries(entries);
}, },
import: async (obj) => { import: (obj) => {
const entries = Object.entries(obj) // const entries = Object.entries(obj) //
.map(([key, value]) => [namespace + key, value]); .map(([key, value]) => [namespace + key, value]);
return new Promise((res, _rej) => { return chrome.storage.local.set(Object.fromEntries(entries));
chrome.storage.local.set(Object.fromEntries(entries), () => res(true));
});
}, },
}; };
}; };

View File

@ -50,6 +50,8 @@ let __db;
const initDatabase = (namespace, fallbacks = {}) => { const initDatabase = (namespace, fallbacks = {}) => {
if (Array.isArray(namespace)) namespace = namespace.join("__"); if (Array.isArray(namespace)) namespace = namespace.join("__");
namespace = namespace ? namespace + "__" : ""; namespace = namespace ? namespace + "__" : "";
const namespaceify = (key) =>
key.startsWith(namespace) ? key : namespace + key;
// schema: // schema:
// - ("profileIds") = $profileId[] // - ("profileIds") = $profileId[]
@ -68,11 +70,11 @@ const initDatabase = (namespace, fallbacks = {}) => {
init.run(); init.run();
__db = db; __db = db;
// prettier-ignore
const insert = db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`), const insert = db.prepare(`INSERT INTO ${table} (key, value) VALUES (?, ?)`),
// prettier-ignore
update = db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`), update = db.prepare(`UPDATE ${table} SET value = ? WHERE key = ?`),
select = db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`), select = db.prepare(`SELECT * FROM ${table} WHERE key = ? LIMIT 1`),
remove = db.prepare(`DELETE FROM ${table} WHERE key = ?`),
removeMany = db.transaction((arr) => arr.forEach((key) => remove.run(key))),
dump = db.prepare(`SELECT * FROM ${table}`), dump = db.prepare(`SELECT * FROM ${table}`),
populate = db.transaction((obj) => { populate = db.transaction((obj) => {
for (const key in obj) { for (const key in obj) {
@ -85,7 +87,7 @@ const initDatabase = (namespace, fallbacks = {}) => {
// wrap methods in promises for consistency w/ chrome.storage // wrap methods in promises for consistency w/ chrome.storage
get: (key) => { get: (key) => {
const fallback = fallbacks[key]; const fallback = fallbacks[key];
key = key.startsWith(namespace) ? key : namespace + key; key = namespaceify(key);
try { try {
const value = JSON.parse(select.get(key)?.value); const value = JSON.parse(select.get(key)?.value);
return Promise.resolve(value ?? fallback); return Promise.resolve(value ?? fallback);
@ -93,13 +95,19 @@ const initDatabase = (namespace, fallbacks = {}) => {
return Promise.resolve(fallback); return Promise.resolve(fallback);
}, },
set: (key, value) => { set: (key, value) => {
key = key.startsWith(namespace) ? key : namespace + key; key = namespaceify(key);
value = JSON.stringify(value); value = JSON.stringify(value);
if (select.get(key) === undefined) { if (select.get(key) === undefined) {
insert.run(key, value); insert.run(key, value);
} else update.run(value, key); } else update.run(value, key);
return Promise.resolve(true); return Promise.resolve(true);
}, },
remove: (keys) => {
keys = Array.isArray(keys) ? keys : [keys];
keys = keys.map(namespaceify);
removeMany(keys);
return Promise.resolve(true);
},
export: () => { export: () => {
const entries = dump const entries = dump
.all() .all()

View File

@ -51,7 +51,16 @@ const getProfile = async () => {
enabledMods = initDatabase([await getProfile(), "enabledMods"]); enabledMods = initDatabase([await getProfile(), "enabledMods"]);
return Boolean(await enabledMods.get(id)); return Boolean(await enabledMods.get(id));
}, },
optionDefaults = async (id) => { setEnabled = async (id, enabled) => {
const { initDatabase } = globalThis.__enhancerApi;
// prettier-ignore
return await initDatabase([
await getProfile(),
"enabledMods"
]).set(id, enabled);
};
const optionDefaults = async (id) => {
const mod = (await getMods()).find((mod) => mod.id === id), const mod = (await getMods()).find((mod) => mod.id === id),
optionEntries = mod.options optionEntries = mod.options
.map((opt) => { .map((opt) => {
@ -64,6 +73,10 @@ const getProfile = async () => {
}) })
.filter((opt) => opt); .filter((opt) => opt);
return Object.fromEntries(optionEntries); return Object.fromEntries(optionEntries);
},
modDatabase = async (id) => {
const { initDatabase } = globalThis.__enhancerApi;
return initDatabase([await getProfile(), id], await optionDefaults(id));
}; };
globalThis.__enhancerApi ??= {}; globalThis.__enhancerApi ??= {};
@ -75,5 +88,7 @@ Object.assign(globalThis.__enhancerApi, {
getIntegrations, getIntegrations,
getProfile, getProfile,
isEnabled, isEnabled,
setEnabled,
optionDefaults, optionDefaults,
modDatabase,
}); });

View File

@ -9,7 +9,7 @@ import { setState, useState, getState } from "./state.mjs";
// generic // generic
function _Button( function _Button(
{ type, size, icon, primary, class: cls = "", ...props }, { type, size, variant, icon, class: cls = "", ...props },
...children ...children
) { ) {
const { html } = globalThis.__enhancerApi, const { html } = globalThis.__enhancerApi,
@ -20,10 +20,14 @@ function _Button(
return html`<${type} return html`<${type}
class="flex gap-[8px] items-center px-[12px] shrink-0 class="flex gap-[8px] items-center px-[12px] shrink-0
rounded-[4px] ${size === "sm" ? "h-[28px]" : "h-[32px]"} rounded-[4px] ${size === "sm" ? "h-[28px]" : "h-[32px]"}
transition duration-[20ms] ${primary transition duration-[20ms] ${variant === "primary"
? `text-[color:var(--theme--accent-primary\\_contrast)] ? `text-[color:var(--theme--accent-primary\\_contrast)]
font-medium bg-[color:var(--theme--accent-primary)] font-medium bg-[color:var(--theme--accent-primary)]
hover:bg-[color:var(--theme--accent-primary\\_hover)]` hover:bg-[color:var(--theme--accent-primary\\_hover)]`
: variant === "secondary"
? `text-[color:var(--theme--accent-secondary)]
border-(& [color:var(--theme--accent-secondary)])
hover:bg-[color:var(--theme--accent-secondary\\_hover)]`
: `border-(& [color:var(--theme--fg-border)]) : `border-(& [color:var(--theme--fg-border)])
hover:bg-[color:var(--theme--bg-hover)]`} ${cls}" hover:bg-[color:var(--theme--bg-hover)]`} ${cls}"
...${props} ...${props}
@ -211,6 +215,79 @@ function View({ id }, ...children) {
return $el; return $el;
} }
function Popup(
{ for: $trigger, onopen, onclose, onbeforeclose, ...props },
...children
) {
const { html } = globalThis.__enhancerApi,
$popup = html`<div
class="notion-enhancer--menu-popup
group absolute top-0 left-0 w-full h-full
flex flex-col justify-center items-end
pointer-events-none z-20"
...${props}
>
<div class="relative right-[100%]">
<div
class="bg-[color:var(--theme--bg-secondary)]
w-[250px] max-w-[calc(100vw-24px)] max-h-[70vh]
py-[6px] px-[4px] drop-shadow-xl overflow-y-auto
transition duration-[200ms] opacity-0 scale-95 rounded-[4px]
group-open:(pointer-events-auto opacity-100 scale-100)"
>
${children}
</div>
</div>
</div>`;
const { onclick, onkeydown } = $trigger,
enableTabbing = () => {
$popup
.querySelectorAll("[tabindex]")
.forEach(($el) => ($el.tabIndex = 0));
},
disableTabbing = () => {
$popup
.querySelectorAll("[tabindex]")
.forEach(($el) => ($el.tabIndex = -1));
},
openPopup = () => {
$popup.setAttribute("open", true);
enableTabbing();
onopen?.();
setState({ popupOpen: true });
},
closePopup = () => {
$popup.removeAttribute("open");
disableTabbing();
onbeforeclose?.();
setTimeout(() => {
onclose?.();
setState({ popupOpen: false });
}, 200);
};
disableTabbing();
$trigger.onclick = (event) => {
onclick?.(event);
openPopup();
};
$trigger.onkeydown = (event) => {
onkeydown?.(event);
if (event.key === "Enter") openPopup();
};
useState(["rerender"], () => {
if ($popup.hasAttribute("open")) closePopup();
});
document.addEventListener("click", (event) => {
if (!$popup.hasAttribute("open")) return;
if ($popup.contains(event.target) || $popup === event.target) return;
if ($trigger.contains(event.target) || $trigger === event.target) return;
closePopup();
});
return $popup;
}
// input // input
function Input({ function Input({
@ -443,66 +520,26 @@ function Select({ values, _get, _set, ...props }) {
></div>`, ></div>`,
$options = values.map((value) => { $options = values.map((value) => {
return html`<${SelectOption} ...${{ value, _get, _set }} />`; return html`<${SelectOption} ...${{ value, _get, _set }} />`;
}),
$popup = html`<div
class="group absolute top-0 left-0
flex flex-col justify-center items-end
pointer-events-none w-full h-full"
>
<div class="relative right-[100%]">
<div
class="bg-[color:var(--theme--bg-secondary)]
w-[250px] max-w-[calc(100vw-24px)] max-h-[70vh]
py-[6px] px-[4px] drop-shadow-xl overflow-y-auto
transition duration-[200ms] opacity-0 scale-95 rounded-[4px]
group-open:(pointer-events-auto opacity-100 scale-100)"
>
${$options}
</div>
</div>
</div>`;
const { onclick, onkeydown } = $select,
openPopup = () => {
$popup.setAttribute("open", true);
$options.forEach(($opt) => ($opt.tabIndex = 0));
setState({ popupOpen: true });
},
closePopup = (value) => {
$popup.removeAttribute("open");
$options.forEach(($opt) => ($opt.tabIndex = -1));
$select.style.width = `${$select.offsetWidth}px`;
$select.style.background = "transparent";
if (value) $select.innerText = value;
setTimeout(() => {
$select.style.width = "";
$select.style.background = "";
setState({ popupOpen: false });
}, 200);
};
$select.onclick = (event) => {
onclick?.(event);
openPopup();
};
$select.onkeydown = (event) => {
onkeydown?.(event);
if (event.key === "Enter") openPopup();
};
useState(["rerender"], () => {
_get?.().then((value) => {
if ($popup.hasAttribute("open")) {
closePopup(value);
} else $select.innerText = value;
}); });
}); useState(["rerender"], () => {
document.addEventListener("click", (event) => { _get?.().then((value) => ($select.innerText = value));
if (!$popup.hasAttribute("open")) return;
if ($popup.contains(event.target) || event.target === $select) return;
closePopup();
}); });
return html`<div class="notion-enhancer--menu-select relative"> return html`<div class="notion-enhancer--menu-select relative">
${$select}${$popup} ${$select}
<${Popup}
for=${$select}
onbeforeclose=${() => {
$select.style.width = `${$select.offsetWidth}px`;
$select.style.background = "transparent";
}}
onclose=${() => {
$select.style.width = "";
$select.style.background = "";
}}
>
${$options}
<//>
<i <i
class="i-chevron-down pointer-events-none class="i-chevron-down pointer-events-none
absolute right-[6px] top-[6px] w-[16px] h-[16px] absolute right-[6px] top-[6px] w-[16px] h-[16px]
@ -515,6 +552,7 @@ function SelectOption({ value, _get, _set, ...props }) {
const { html } = globalThis.__enhancerApi, const { html } = globalThis.__enhancerApi,
$selected = html`<i class="ml-auto i-check w-[16px] h-[16px]"></i>`, $selected = html`<i class="ml-auto i-check w-[16px] h-[16px]"></i>`,
$option = html`<div $option = html`<div
tabindex="0"
role="button" role="button"
class="select-none cursor-pointer rounded-[3px] class="select-none cursor-pointer rounded-[3px]
flex items-center w-full h-[28px] px-[12px] leading-[1.2] flex items-center w-full h-[28px] px-[12px] leading-[1.2]
@ -608,7 +646,10 @@ function Checkbox({ _get, _set, ...props }) {
return html`<label tabindex="0" class="cursor-pointer"> return html`<label tabindex="0" class="cursor-pointer">
${$input} ${$input}
<div class="flex items-center h-[16px] transition duration-[200ms]"> <div class="flex items-center h-[16px] transition duration-[200ms]">
<i class="i-check w-[14px] h-[14px]"></i> <i
class="i-check w-[14px] h-[14px]
text-[color:var(--theme--accent-primary\\_contrast)]"
></i>
</div> </div>
</label>`; </label>`;
} }
@ -778,6 +819,7 @@ function Profile({
setActive, setActive,
exportJson, exportJson,
importJson, importJson,
deleteProfile,
...props ...props
}) { }) {
const { html } = globalThis.__enhancerApi, const { html } = globalThis.__enhancerApi,
@ -812,6 +854,35 @@ function Profile({
$a.remove(); $a.remove();
}; };
const $delete = html`<${Icon} icon="x" />`,
$name = html`<mark></mark>`,
$confirmation = html`<${Popup}
for=${$delete}
onopen=${async () => ($name.innerText = await getName())}
>
<p class="text-[14px] pt-[2px] px-[8px]">
Are you sure you want to delete the profile ${$name} permanently?
</p>
<div class="flex flex-col gap-[8px] pt-[8px] pb-[6px] px-[8px]">
<${Button}
tabindex="0"
icon="trash"
class="justify-center"
variant="secondary"
onclick=${() => deleteProfile()}
>
Delete
<//>
<${Button}
tabindex="0"
class="justify-center"
onclick=${() => setState({ rerender: true })}
>
Cancel
<//>
</div>
<//>`;
return html`<li class="flex items-center my-[14px] gap-[8px]" ...${props}> return html`<li class="flex items-center my-[14px] gap-[8px]" ...${props}>
<${Checkbox} <${Checkbox}
...${{ _get: isActive, _set: setActive }} ...${{ _get: isActive, _set: setActive }}
@ -834,8 +905,8 @@ function Profile({
/> />
Import Import
<//> <//>
<${Button} size="sm" icon="upload" onclick=${downloadProfile}> Export <//> <${Button} size="sm" icon="upload" onclick=${downloadProfile}>Export<//>
<${Icon} icon="x" /> <div class="relative">${$delete}${$confirmation}</div>
</li>`; </li>`;
} }

View File

@ -94,7 +94,7 @@ body > #skeleton .row-group .shimmer {
height: 11px; height: 11px;
} }
.notion-enhancer--menu-description mark { mark {
color: inherit; color: inherit;
padding: 2px 4px; padding: 2px 4px;
border-radius: 3px; border-radius: 3px;

View File

@ -4,13 +4,7 @@
* (https://notion-enhancer.github.io/) under the MIT license * (https://notion-enhancer.github.io/) under the MIT license
*/ */
import { import { getState, setState, useState } from "./state.mjs";
getState,
setState,
useState,
setEnabled,
modDatabase,
} from "./state.mjs";
import { import {
Button, Button,
Description, Description,
@ -72,7 +66,7 @@ const renderSidebar = (items, categories) => {
return $sidebar; return $sidebar;
}, },
renderList = async (id, mods, description) => { renderList = async (id, mods, description) => {
const { html, isEnabled } = globalThis.__enhancerApi; const { html, isEnabled, setEnabled } = globalThis.__enhancerApi;
mods = mods.map(async (mod) => { mods = mods.map(async (mod) => {
const _get = () => isEnabled(mod.id), const _get = () => isEnabled(mod.id),
_set = async (enabled) => { _set = async (enabled) => {
@ -86,7 +80,7 @@ const renderSidebar = (items, categories) => {
<//>`; <//>`;
}, },
renderOptions = async (mod) => { renderOptions = async (mod) => {
const { html, platform, getProfile } = globalThis.__enhancerApi; const { html, platform, modDatabase } = globalThis.__enhancerApi;
let options = mod.options.reduce((options, opt) => { let options = mod.options.reduce((options, opt) => {
if (!opt.key && (opt.type !== "heading" || !opt.label)) return options; if (!opt.key && (opt.type !== "heading" || !opt.label)) return options;
if (opt.platforms && !opt.platforms.includes(platform)) return options; if (opt.platforms && !opt.platforms.includes(platform)) return options;
@ -116,14 +110,26 @@ const renderSidebar = (items, categories) => {
db = initDatabase(), db = initDatabase(),
$list = html`<ul></ul>`, $list = html`<ul></ul>`,
renderProfile = (id) => { renderProfile = (id) => {
const profile = initDatabase([id]); const profile = initDatabase([id]),
isActive = async () => id === (await getProfile()),
deleteProfile = async () => {
const keys = Object.keys(await profile.export());
profileIds.splice(profileIds.indexOf(id), 1);
await db.set("profileIds", profileIds);
await profile.remove(keys);
if (isActive()) {
await db.remove("activeProfile");
setState({ databaseUpdated: true });
}
setState({ rerender: true });
};
return html`<${Profile} return html`<${Profile}
id=${id} id=${id}
getName=${async () => getName=${async () =>
(await profile.get("profileName")) ?? (await profile.get("profileName")) ??
(id === "default" ? "default" : "")} (id === "default" ? "default" : "")}
setName=${(name) => profile.set("profileName", name)} setName=${(name) => profile.set("profileName", name)}
isActive=${async () => id === (await getProfile())} isActive=${isActive}
setActive=${async () => { setActive=${async () => {
await db.set("activeProfile", id); await db.set("activeProfile", id);
setState({ rerender: true, databaseUpdated: true }); setState({ rerender: true, databaseUpdated: true });
@ -133,10 +139,12 @@ const renderSidebar = (items, categories) => {
try { try {
await profile.import(JSON.parse(json)); await profile.import(JSON.parse(json));
setState({ rerender: true, databaseUpdated: true }); setState({ rerender: true, databaseUpdated: true });
// success
} catch { } catch {
// error // error
} }
}} }}
deleteProfile=${deleteProfile}
/>`; />`;
}, },
refreshProfiles = async () => { refreshProfiles = async () => {
@ -164,9 +172,6 @@ const renderSidebar = (items, categories) => {
}; };
useState(["rerender"], () => refreshProfiles()); useState(["rerender"], () => refreshProfiles());
// todo: deleting profiles inc. clearing db keys,
// throwing errors on invalid json upload
const $input = html`<${Input} const $input = html`<${Input}
size="md" size="md"
type="text" type="text"
@ -198,7 +203,7 @@ const renderSidebar = (items, categories) => {
</div>`; </div>`;
}, },
renderMods = async (mods) => { renderMods = async (mods) => {
const { html, isEnabled } = globalThis.__enhancerApi; const { html, isEnabled, setEnabled } = globalThis.__enhancerApi;
mods = mods mods = mods
.filter((mod) => { .filter((mod) => {
return mod.options?.filter((opt) => opt.type !== "heading").length; return mod.options?.filter((opt) => opt.type !== "heading").length;
@ -325,8 +330,8 @@ const render = async () => {
<//>`; <//>`;
}); });
const $reload = html`<${Button} const $reload = html`<${Button}
primary
class="ml-auto" class="ml-auto"
variant="primary"
icon="refresh-cw" icon="refresh-cw"
onclick=${() => reloadApp()} onclick=${() => reloadApp()}
style="display: none" style="display: none"

View File

@ -21,18 +21,4 @@ const _state = {},
callback(getState(keys)); callback(getState(keys));
}; };
const setEnabled = async (id, enabled) => { export { setState, useState, getState };
const { getProfile, initDatabase } = globalThis.__enhancerApi;
// prettier-ignore
return await initDatabase([
await getProfile(),
"enabledMods"
]).set(id, enabled);
},
modDatabase = async (id) => {
const { getProfile, initDatabase } = globalThis.__enhancerApi,
{ optionDefaults } = globalThis.__enhancerApi;
return initDatabase([await getProfile(), id], await optionDefaults(id));
};
export { setState, useState, getState, setEnabled, modDatabase };

File diff suppressed because one or more lines are too long

View File

@ -57,8 +57,8 @@ body.dark {
--theme--accent-primary_contrast: #fff; --theme--accent-primary_contrast: #fff;
--theme--accent-primary_transparent: rgba(35, 131, 226, 0.14); --theme--accent-primary_transparent: rgba(35, 131, 226, 0.14);
--theme--accent-secondary: #eb5757; --theme--accent-secondary: #eb5757;
--theme--accent-secondary_hover: rgba(235, 87, 87, 0.1);
--theme--accent-secondary_contrast: #fff; --theme--accent-secondary_contrast: #fff;
--theme--accent-secondary_transparent: rgba(235, 87, 87, 0.1);
--theme--scrollbar-track: rgba(202, 204, 206, 0.04); --theme--scrollbar-track: rgba(202, 204, 206, 0.04);
--theme--scrollbar-thumb: #474c50; --theme--scrollbar-thumb: #474c50;
@ -154,7 +154,7 @@ body:not(.dark) {
--theme--accent-primary_transparent: rgba(35, 131, 226, 0.14); --theme--accent-primary_transparent: rgba(35, 131, 226, 0.14);
--theme--accent-secondary: #eb5757; --theme--accent-secondary: #eb5757;
--theme--accent-secondary_contrast: #fff; --theme--accent-secondary_contrast: #fff;
--theme--accent-secondary_transparent: rgba(235, 87, 87, 0.1); --theme--accent-secondary_hover: rgba(235, 87, 87, 0.1);
--theme--scrollbar-track: #edece9; --theme--scrollbar-track: #edece9;
--theme--scrollbar-thumb: #d3d1cb; --theme--scrollbar-thumb: #d3d1cb;

View File

@ -48,8 +48,8 @@ body.dark {
--theme--accent-primary_contrast: #fff; --theme--accent-primary_contrast: #fff;
--theme--accent-primary_transparent: rgb(46, 170, 220, 0.25); --theme--accent-primary_transparent: rgb(46, 170, 220, 0.25);
--theme--accent-secondary: #eb5757; --theme--accent-secondary: #eb5757;
--theme--accent-secondary_hover: rgba(235, 87, 87, 0.1);
--theme--accent-secondary_contrast: #fff; --theme--accent-secondary_contrast: #fff;
--theme--accent-secondary_transparent: rgba(235, 87, 87, 0.1);
--theme--scrollbar-track: rgba(202, 204, 206, 0.04); --theme--scrollbar-track: rgba(202, 204, 206, 0.04);
--theme--scrollbar-thumb: #474c50; --theme--scrollbar-thumb: #474c50;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long