refactor: restyle command palette via tokens
This commit is contained in:
@@ -126,18 +126,18 @@ const CommandPalette: Component<CommandPaletteProps> = (props) => {
|
||||
return (
|
||||
<Dialog open={props.open} onOpenChange={(open) => !open && props.onClose()}>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay class="fixed inset-0 bg-black/50 z-50" />
|
||||
<Dialog.Overlay class="modal-overlay" />
|
||||
<div class="fixed inset-0 z-50 flex items-start justify-center pt-[20vh]">
|
||||
<Dialog.Content
|
||||
class="bg-white dark:bg-gray-800 rounded-lg shadow-2xl w-full max-w-2xl max-h-[60vh] flex flex-col"
|
||||
class="modal-surface w-full max-w-2xl max-h-[60vh]"
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<Dialog.Title class="sr-only">Command Palette</Dialog.Title>
|
||||
<Dialog.Description class="sr-only">Search and execute commands</Dialog.Description>
|
||||
|
||||
<div class="p-4 border-b border-gray-200 dark:border-gray-700">
|
||||
<div class="modal-search-container">
|
||||
<div class="flex items-center gap-3">
|
||||
<svg class="w-5 h-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<svg class="w-5 h-5 modal-search-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
@@ -154,15 +154,15 @@ const CommandPalette: Component<CommandPaletteProps> = (props) => {
|
||||
setSelectedIndex(0)
|
||||
}}
|
||||
placeholder="Type a command or search..."
|
||||
class="flex-1 bg-transparent outline-none text-gray-900 dark:text-gray-100 placeholder-gray-400"
|
||||
class="modal-search-input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div ref={listRef} class="flex-1 overflow-y-auto">
|
||||
<div ref={listRef} class="modal-list-container">
|
||||
<Show
|
||||
when={filteredCommands().length > 0}
|
||||
fallback={<div class="p-8 text-center text-gray-500">No commands found for "{query()}"</div>}
|
||||
fallback={<div class="modal-empty-state">No commands found for "{query()}"</div>}
|
||||
>
|
||||
<For each={Array.from(groupedCommands().entries())}>
|
||||
{([category, commands]) => {
|
||||
@@ -174,7 +174,7 @@ const CommandPalette: Component<CommandPaletteProps> = (props) => {
|
||||
|
||||
return (
|
||||
<div class="py-2">
|
||||
<div class="px-4 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide">
|
||||
<div class="modal-section-header">
|
||||
{category}
|
||||
</div>
|
||||
<For each={commands}>
|
||||
@@ -185,16 +185,16 @@ const CommandPalette: Component<CommandPaletteProps> = (props) => {
|
||||
type="button"
|
||||
data-command-index={commandIndex}
|
||||
onClick={() => handleCommandClick(command.id)}
|
||||
class={`w-full px-4 py-3 flex items-start gap-3 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors cursor-pointer border-none text-left ${
|
||||
commandIndex === selectedIndex() ? "bg-blue-50 dark:bg-blue-900/20" : ""
|
||||
class={`modal-item ${
|
||||
commandIndex === selectedIndex() ? "modal-item-highlight" : ""
|
||||
}`}
|
||||
onMouseEnter={() => setSelectedIndex(commandIndex)}
|
||||
>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="font-medium text-gray-900 dark:text-gray-100">
|
||||
<div class="modal-item-label">
|
||||
{typeof command.label === "function" ? command.label() : command.label}
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 mt-0.5">
|
||||
<div class="modal-item-description">
|
||||
{command.description}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -219,7 +219,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
<Show when={focusMode() === "recent" && selectedIndex() === index()}>
|
||||
<kbd class="px-1.5 py-0.5 text-xs font-semibold text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded">
|
||||
<kbd class="kbd">
|
||||
↵
|
||||
</kbd>
|
||||
</Show>
|
||||
@@ -256,7 +256,7 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
||||
<FolderPlus class="w-4 h-4" />
|
||||
<span>{props.isLoading ? "Opening..." : "Browse Folders"}</span>
|
||||
</div>
|
||||
<kbd class="px-1.5 py-0.5 text-xs font-semibold bg-blue-700 border border-blue-500 rounded">
|
||||
<kbd class="kbd">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
</button>
|
||||
@@ -303,31 +303,21 @@ const FolderSelectionView: Component<FolderSelectionViewProps> = (props) => {
|
||||
<div class="flex items-center justify-center flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
<Show when={folders().length > 0}>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded font-mono">
|
||||
↑
|
||||
</kbd>
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded font-mono">
|
||||
↓
|
||||
</kbd>
|
||||
<kbd class="kbd">↑</kbd>
|
||||
<kbd class="kbd">↓</kbd>
|
||||
<span>Navigate</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded font-mono">
|
||||
Enter
|
||||
</kbd>
|
||||
<kbd class="kbd">Enter</kbd>
|
||||
<span>Select</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded font-mono">
|
||||
Del
|
||||
</kbd>
|
||||
<kbd class="kbd">Del</kbd>
|
||||
<span>Remove</span>
|
||||
</div>
|
||||
</Show>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 rounded">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
<kbd class="kbd">Cmd+Enter</kbd>
|
||||
<span>Browse</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -211,7 +211,7 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
|
||||
</div>
|
||||
</div>
|
||||
<Show when={focusMode() === "sessions" && selectedIndex() === index()}>
|
||||
<kbd class="px-1.5 py-0.5 text-xs font-semibold text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded flex-shrink-0">
|
||||
<kbd class="kbd flex-shrink-0">
|
||||
↵
|
||||
</kbd>
|
||||
</Show>
|
||||
@@ -281,7 +281,7 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
|
||||
</svg>
|
||||
<span>Create Session</span>
|
||||
</div>
|
||||
<kbd class="px-1.5 py-0.5 text-xs font-semibold bg-blue-700 border border-blue-500 rounded flex-shrink-0 dark:bg-blue-600 dark:border-blue-400">
|
||||
<kbd class="kbd flex-shrink-0">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
</Show>
|
||||
@@ -302,42 +302,26 @@ const InstanceWelcomeView: Component<InstanceWelcomeViewProps> = (props) => {
|
||||
<div class="px-4 py-2 bg-white dark:bg-gray-900 border-t border-gray-200 dark:border-gray-700 flex-shrink-0">
|
||||
<div class="flex items-center justify-center flex-wrap gap-3 text-xs text-gray-500 dark:text-gray-400">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
↑
|
||||
</kbd>
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
↓
|
||||
</kbd>
|
||||
<kbd class="kbd">↑</kbd>
|
||||
<kbd class="kbd">↓</kbd>
|
||||
<span>Navigate</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
PgUp
|
||||
</kbd>
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
PgDn
|
||||
</kbd>
|
||||
<kbd class="kbd">PgUp</kbd>
|
||||
<kbd class="kbd">PgDn</kbd>
|
||||
<span>Jump</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
Home
|
||||
</kbd>
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
End
|
||||
</kbd>
|
||||
<kbd class="kbd">Home</kbd>
|
||||
<kbd class="kbd">End</kbd>
|
||||
<span>First/Last</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded font-mono text-xs">
|
||||
Enter
|
||||
</kbd>
|
||||
<kbd class="kbd">Enter</kbd>
|
||||
<span>Resume</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<kbd class="px-1.5 py-0.5 bg-gray-100 dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded text-xs">
|
||||
Cmd+Enter
|
||||
</kbd>
|
||||
<kbd class="kbd">Cmd+Enter</kbd>
|
||||
<span>New Session</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -36,13 +36,11 @@ const Kbd: Component<KbdProps> = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<kbd
|
||||
class={`font-mono bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded text-xs inline-flex items-center gap-0.5 ${props.class || ""}`}
|
||||
>
|
||||
<kbd class={`kbd ${props.class || ""}`}>
|
||||
<For each={parts()}>
|
||||
{(part, index) => (
|
||||
<>
|
||||
{index() > 0 && <span class="opacity-50">+</span>}
|
||||
{index() > 0 && <span class="kbd-separator">+</span>}
|
||||
<span>{part.text}</span>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -1040,4 +1040,87 @@
|
||||
.selector-loading-spinner {
|
||||
@apply w-4 h-4 animate-spin;
|
||||
color: var(--accent-primary);
|
||||
}
|
||||
|
||||
/* Modal utilities */
|
||||
.modal-overlay {
|
||||
@apply fixed inset-0 z-50;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.modal-surface {
|
||||
@apply rounded-lg shadow-2xl flex flex-col;
|
||||
background-color: var(--surface-base);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-search-container {
|
||||
@apply p-4 border-b;
|
||||
border-color: var(--border-base);
|
||||
}
|
||||
|
||||
.modal-search-input {
|
||||
@apply flex-1 bg-transparent outline-none;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-search-input::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.modal-search-icon {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.modal-list-container {
|
||||
@apply flex-1 overflow-y-auto;
|
||||
}
|
||||
|
||||
.modal-section-header {
|
||||
@apply px-4 py-2 text-xs font-semibold uppercase tracking-wide;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.modal-item {
|
||||
@apply w-full px-4 py-3 flex items-start gap-3 transition-colors cursor-pointer border-none text-left;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-item:hover {
|
||||
background-color: var(--surface-hover);
|
||||
}
|
||||
|
||||
.modal-item-highlight {
|
||||
background-color: rgba(0, 102, 255, 0.1);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .modal-item-highlight {
|
||||
background-color: rgba(0, 128, 255, 0.2);
|
||||
}
|
||||
|
||||
.modal-item-label {
|
||||
@apply font-medium;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.modal-item-description {
|
||||
@apply text-sm mt-0.5;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.modal-empty-state {
|
||||
@apply p-8 text-center;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
/* Keyboard utilities */
|
||||
.kbd {
|
||||
@apply inline-flex items-center gap-0.5 font-mono text-xs px-1.5 py-0.5 rounded;
|
||||
background-color: var(--surface-secondary);
|
||||
border: 1px solid var(--border-base);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.kbd-separator {
|
||||
@apply opacity-50;
|
||||
}
|
||||
Reference in New Issue
Block a user