Merge pull request #1120 from ProjectInfinity/command-palette-redesign

feat: redesign CommandPalette
This commit is contained in:
Jan Prochazka
2025-05-29 12:50:18 +02:00
committed by GitHub

View File

@@ -164,109 +164,175 @@
}} }}
data-testid='CommandPalette_main' data-testid='CommandPalette_main'
> >
<div class="pages"> <div
<div class="overlay"
class="page" on:click={() => {
class:selected={$visibleCommandPalette == 'menu'} $visibleCommandPalette = null;
on:click={() => { }}
$visibleCommandPalette = 'menu'; />
domInput.focus(); <div class="palette">
}} <div class="pages">
> <div
<FontIcon icon="icon menu" /> Commands class="page"
class:selected={$visibleCommandPalette == 'menu'}
on:click={() => {
$visibleCommandPalette = 'menu';
domInput.focus();
}}
>
<FontIcon icon="icon menu" /> Commands
</div>
<div
class="page"
class:selected={$visibleCommandPalette == 'database'}
on:click={() => {
$visibleCommandPalette = 'database';
domInput.focus();
}}
>
<FontIcon icon="icon database" /> Database
</div>
</div> </div>
<div <div class="mainInner">
class="page" <div class="search">
class:selected={$visibleCommandPalette == 'database'} <input
on:click={() => { type="text"
$visibleCommandPalette = 'database'; bind:this={domInput}
domInput.focus(); bind:value={filter}
}} on:keydown={handleKeyDown}
> placeholder={parentCommand?.text ||
<FontIcon icon="icon database" /> Database ($visibleCommandPalette == 'database' ? 'Search in database' : 'Search in commands')}
</div> />
</div> </div>
<div class="mainInner"> <div class="content">
<div class="search"> {#each filteredItems as command, index}
<input <div
type="text" class="command"
bind:this={domInput} class:selected={index == selectedIndex}
bind:value={filter} on:click={() => handleCommand(command)}
on:keydown={handleKeyDown} bind:this={domItems[index]}
placeholder={parentCommand?.text || >
($visibleCommandPalette == 'database' ? 'Search in database' : 'Search in commands')} <div>
/> {#if command.icon}
</div> <span class="mr-1"><FontIcon icon={command.icon} /></span>
<div class="content"> {/if}
{#each filteredItems as command, index} {@html command.text}
<div </div>
class="command" {#if command.keyText}
class:selected={index == selectedIndex} <div class="shortcut">{formatKeyText(command.keyText)}</div>
on:click={() => handleCommand(command)}
bind:this={domItems[index]}
>
<div>
{#if command.icon}
<span class="mr-1"><FontIcon icon={command.icon} /></span>
{/if} {/if}
{@html command.text}
</div> </div>
{#if command.keyText} {/each}
<div class="shortcut">{formatKeyText(command.keyText)}</div> </div>
{/if}
</div>
{/each}
</div> </div>
</div> </div>
</div> </div>
<style> <style>
.main { .main {
width: 500px; position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: flex;
justify-content: center;
align-items: flex-start;
padding-top: 100px;
}
.overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.4);
z-index: 1;
}
.palette {
position: relative;
z-index: 2;
width: 600px;
background: var(--theme-bg-2); background: var(--theme-bg-2);
border-radius: 4px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
} }
.mainInner { .mainInner {
padding: 5px; padding: 8px;
} }
.content { .content {
max-height: 400px; max-height: 500px;
overflow-y: scroll; overflow-y: auto;
margin-top: 8px;
} }
.search { .search {
display: flex; display: flex;
margin-bottom: 8px;
} }
input { input {
width: 100%; width: 100%;
padding: 8px;
background: var(--theme-bg-1);
border: 1px solid var(--theme-border);
border-radius: 4px;
color: var(--theme-font);
font-size: 14px;
} }
input:focus {
outline: none;
border-color: var(--theme-accent);
}
.command { .command {
padding: 5px; padding: 8px 12px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center;
cursor: pointer;
border-radius: 4px;
} }
.command:hover { .command:hover {
background: var(--theme-bg-3); background: var(--theme-bg-3);
} }
.command.selected { .command.selected {
background: var(--theme-bg-selected); background: var(--theme-bg-selected);
} }
.shortcut { .shortcut {
background: var(--theme-bg-3); background: var(--theme-bg-3);
padding: 2px 6px;
border-radius: 3px;
font-size: 12px;
color: var(--theme-font-dimmed);
} }
.pages { .pages {
display: flex; display: flex;
border-bottom: 1px solid var(--theme-border);
} }
.page { .page {
padding: 5px; padding: 8px 16px;
border: 1px solid var(--theme-border);
cursor: pointer; cursor: pointer;
color: var(--theme-font-dimmed);
border-bottom: 2px solid transparent;
} }
.page:hover { .page:hover {
color: var(--theme-font-hover); color: var(--theme-font);
} }
.page.selected { .page.selected {
background: var(--theme-bg-1); color: var(--theme-font);
border-bottom-color: var(--theme-accent);
} }
</style> </style>