Skip to content

Commit ba6558f

Browse files
feat: add theme toggle action to command palette (#729)
1 parent 7b24e4a commit ba6558f

15 files changed

Lines changed: 143 additions & 21 deletions

i18n/english.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ const ui = {
273273
placeholder: "Search packages...",
274274
placeholder_filter_hint: "or use",
275275
placeholder_refine: "Add another filter...",
276+
section_actions: "Actions",
277+
action_toggle_theme_to_dark: "Switch to dark theme",
278+
action_toggle_theme_to_light: "Switch to light theme",
276279
section_presets: "Quick filters",
277280
preset_has_vulnerabilities: "Has vulnerabilities",
278281
preset_has_scripts: "Has install scripts",

i18n/french.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,9 @@ const ui = {
273273
placeholder: "Rechercher des packages...",
274274
placeholder_filter_hint: "ou utiliser",
275275
placeholder_refine: "Ajouter un autre filtre...",
276+
section_actions: "Actions",
277+
action_toggle_theme_to_dark: "Passer en thème sombre",
278+
action_toggle_theme_to_light: "Passer en thème clair",
276279
section_presets: "Filtres rapides",
277280
preset_has_vulnerabilities: "Contient des vulnérabilités",
278281
preset_has_scripts: "Scripts d'installation",

public/components/search-command/search-command-panels.js renamed to public/components/command-palette/command-palette-panels.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,32 @@ export function renderPresets({ presets, onApply }) {
159159
`;
160160
}
161161

162+
/**
163+
* @param {{ actions: Array<{ id: string, label: string, kbd: string|null }>, onExecute: Function }} props
164+
*/
165+
export function renderActions({ actions, onExecute }) {
166+
const i18n = window.i18n[currentLang()].search_command;
167+
168+
return html`
169+
<div class="section">
170+
<div class="section-title">${i18n.section_actions}</div>
171+
<div class="range-panel">
172+
<div class="range-presets">
173+
${actions.map((action) => html`
174+
<button
175+
class="range-preset"
176+
@click=${() => onExecute(action)}
177+
>
178+
${action.label}
179+
${action.kbd ? html`<kbd class="action-kbd">${action.kbd}</kbd>` : nothing}
180+
</button>
181+
`)}
182+
</div>
183+
</div>
184+
</div>
185+
`;
186+
}
187+
162188
/**
163189
* @param {{ results: Array, selectedIndex: number, helperCount: number, onFocus: Function }} props
164190
*/

public/components/search-command/search-command-styles.js renamed to public/components/command-palette/command-palette-styles.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { css } from "lit";
44
// Import Internal Dependencies
55
import { scrollbarStyle } from "../../common/scrollbar-style.js";
66

7-
export const searchCommandStyles = [
7+
export const commandPaletteStyles = [
88
scrollbarStyle,
99
css`
1010
:host {
@@ -380,5 +380,11 @@ kbd {
380380
font-size: 11px;
381381
color: var(--sc-kbd-text);
382382
}
383+
384+
.action-kbd {
385+
margin-left: 6px;
386+
opacity: 0.7;
387+
border: 1px solid var(--sc-border);
388+
}
383389
`
384390
];

public/components/search-command/search-command.js renamed to public/components/command-palette/command-palette.js

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,39 @@ import {
1313
computeMatches,
1414
getHelperValues
1515
} from "./filters.js";
16-
import { searchCommandStyles } from "./search-command-styles.js";
16+
import { commandPaletteStyles } from "./command-palette-styles.js";
1717
import {
1818
renderFlagPanel,
1919
renderRangePanel,
2020
renderListPanel,
2121
renderFilterList,
2222
renderPresets,
23+
renderActions,
2324
renderResults
24-
} from "./search-command-panels.js";
25+
} from "./command-palette-panels.js";
2526
import "./search-chip.js";
2627

27-
class SearchCommand extends LitElement {
28+
// CONSTANTS
29+
const kActions = [
30+
{ id: "toggle_theme", shortcut: "t" }
31+
];
32+
33+
function resolveKbd(shortcut) {
34+
if (!shortcut) {
35+
return null;
36+
}
37+
38+
const key = shortcut.toUpperCase();
39+
40+
return navigator.userAgent.includes("Mac") ? `⌥${key}` : `Alt+${key}`;
41+
}
42+
43+
class CommandPalette extends LitElement {
2844
#linker = null;
2945
#network = null;
3046
#packages = [];
3147

32-
static styles = searchCommandStyles;
48+
static styles = commandPaletteStyles;
3349

3450
static properties = {
3551
open: { type: Boolean },
@@ -55,6 +71,16 @@ class SearchCommand extends LitElement {
5571

5672
if (event.key === "Escape" && this.open) {
5773
this.#close();
74+
75+
return;
76+
}
77+
78+
if (this.open && event.altKey) {
79+
const action = kActions.find((a) => a.shortcut && `Key${a.shortcut.toUpperCase()}` === event.code);
80+
if (action) {
81+
event.preventDefault();
82+
this.#executeAction(action);
83+
}
5884
}
5985
};
6086

@@ -84,12 +110,12 @@ class SearchCommand extends LitElement {
84110
connectedCallback() {
85111
super.connectedCallback();
86112
document.addEventListener("keydown", this.#handleKeydown);
87-
window.addEventListener(EVENTS.SEARCH_COMMAND_INIT, this.#init);
113+
window.addEventListener(EVENTS.COMMAND_PALETTE_INIT, this.#init);
88114
}
89115

90116
disconnectedCallback() {
91117
document.removeEventListener("keydown", this.#handleKeydown);
92-
window.removeEventListener(EVENTS.SEARCH_COMMAND_INIT, this.#init);
118+
window.removeEventListener(EVENTS.COMMAND_PALETTE_INIT, this.#init);
93119
super.disconnectedCallback();
94120
}
95121

@@ -323,6 +349,17 @@ class SearchCommand extends LitElement {
323349
this.#close();
324350
}
325351

352+
#executeAction(action) {
353+
if (action.id === "toggle_theme") {
354+
const nextTheme = window.settings.config.theme === "dark" ? "light" : "dark";
355+
window.dispatchEvent(new CustomEvent(EVENTS.SETTINGS_SAVED, {
356+
detail: { ...window.settings.config, theme: nextTheme }
357+
}));
358+
}
359+
360+
this.#close();
361+
}
362+
326363
#getEmptyQueryMessage() {
327364
const i18n = window.i18n[currentLang()].search_command;
328365
if (this.queries.length === 1) {
@@ -407,6 +444,20 @@ class SearchCommand extends LitElement {
407444
}
408445
}
409446

447+
#resolveActions() {
448+
const i18n = window.i18n[currentLang()].search_command;
449+
const currentTheme = window.settings?.config?.theme ?? "light";
450+
const targetTheme = currentTheme === "dark" ? "light" : "dark";
451+
452+
return kActions.map((action) => {
453+
return {
454+
...action,
455+
label: i18n[`action_${action.id}_to_${targetTheme}`],
456+
kbd: resolveKbd(action.shortcut)
457+
};
458+
});
459+
}
460+
410461
render() {
411462
if (!this.open) {
412463
return nothing;
@@ -483,6 +534,10 @@ class SearchCommand extends LitElement {
483534
presets: PRESETS,
484535
onApply: (preset) => this.#addQuery(preset.filter, preset.value)
485536
}) : nothing}
537+
${showRichPlaceholder ? renderActions({
538+
actions: this.#resolveActions(),
539+
onExecute: (action) => this.#executeAction(action)
540+
}) : nothing}
486541
${renderResults({
487542
results: this.results,
488543
selectedIndex: this.selectedIndex,
@@ -505,4 +560,4 @@ class SearchCommand extends LitElement {
505560
}
506561
}
507562

508-
customElements.define("search-command", SearchCommand);
563+
customElements.define("command-palette", CommandPalette);
File renamed without changes.
File renamed without changes.

public/components/navigation/navigation.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export class ViewNavigation {
3737
const isTargetPopup = event.target.id === "popup--background";
3838
const isPopupOpened = document.querySelector("#popup--background.show");
3939
const isTargetInput = event.target.tagName === "INPUT";
40-
const isSearchCommandOpen = Boolean(document.querySelector("search-command")?.open);
40+
const isSearchCommandOpen = Boolean(document.querySelector("command-palette")?.open);
4141
if (isTargetPopup || isWikiOpen || isTargetInput || isPopupOpened || isSearchCommandOpen) {
4242
return;
4343
}

public/components/wiki/wiki.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class Wiki {
5858
#keydownHotkeys(event) {
5959
const isTargetInput = event.target.tagName === "INPUT";
6060
const isTargetPopup = event.target.id === "popup--background";
61-
const isSearchCommandOpen = Boolean(document.querySelector("search-command")?.open);
61+
const isSearchCommandOpen = Boolean(document.querySelector("command-palette")?.open);
6262
if (isTargetInput || isTargetPopup || isSearchCommandOpen) {
6363
return;
6464
}

public/core/events.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const EVENTS = {
1010
MODAL_OPENED: "modal-opened",
1111
NETWORK_VIEW_HID: "network-view-hid",
1212
NETWORK_VIEW_SHOWED: "network-view-showed",
13-
SEARCH_COMMAND_INIT: "search-command-init",
13+
COMMAND_PALETTE_INIT: "command-palette-init",
1414
DRILL_RESET: "drill-reset",
1515
DRILL_BACK: "drill-back",
1616
DRILL_SWITCH: "drill-switch",

0 commit comments

Comments
 (0)