theme overlay keeps its size across the favourites filter, f flips the filter
This commit is contained in:
@@ -199,7 +199,7 @@ export const ThemeSwitcher = () => {
|
|||||||
onClick={(ev) => ev.stopPropagation()}
|
onClick={(ev) => ev.stopPropagation()}
|
||||||
>
|
>
|
||||||
{/* The filter, mirrored from the dropdown — same state, so the two surfaces never disagree
|
{/* The filter, mirrored from the dropdown — same state, so the two surfaces never disagree
|
||||||
about what "the list" currently is. `tab` does the same thing from the keyboard. */}
|
about what "the list" currently is. `f` does the same thing from the keyboard. */}
|
||||||
<div className="mb-2 text-center">
|
<div className="mb-2 text-center">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -217,7 +217,11 @@ export const ThemeSwitcher = () => {
|
|||||||
{overlayList.length === 0 && (
|
{overlayList.length === 0 && (
|
||||||
<p className="px-2 py-6 text-center text-xs opacity-60">{t('theme.noFavourites')}</p>
|
<p className="px-2 py-6 text-center text-xs opacity-60">{t('theme.noFavourites')}</p>
|
||||||
)}
|
)}
|
||||||
<ul className="flex max-h-[70vh] flex-col gap-1 overflow-y-auto">
|
{/* FIXED dimensions, not max/content: flipping the favourites filter must not resize the
|
||||||
|
panel — the list is 200+ themes on one side of the flip and a handful on the other, and
|
||||||
|
a modal that jumps between two sizes on every `f` reads as broken. Long names truncate;
|
||||||
|
they already did when the widest name happened to be filtered out. */}
|
||||||
|
<ul className="flex h-[70vh] w-[26rem] max-w-[80vw] flex-col gap-1 overflow-y-auto">
|
||||||
{overlayList.map((entry) => {
|
{overlayList.map((entry) => {
|
||||||
const isFocused = entry.id === focused;
|
const isFocused = entry.id === focused;
|
||||||
return (
|
return (
|
||||||
@@ -250,9 +254,7 @@ export const ThemeSwitcher = () => {
|
|||||||
? t('theme.unstarNamed', { name: entry.name })
|
? t('theme.unstarNamed', { name: entry.name })
|
||||||
: t('theme.starNamed', { name: entry.name })
|
: t('theme.starNamed', { name: entry.name })
|
||||||
}
|
}
|
||||||
title={
|
title={isFavorite(entry.id) ? t('theme.removeFromFavourites') : t('theme.addToFavourites')}
|
||||||
isFavorite(entry.id) ? t('theme.removeFromFavouritesKey') : t('theme.addToFavouritesKey')
|
|
||||||
}
|
|
||||||
onClick={(ev) => {
|
onClick={(ev) => {
|
||||||
// Or the row's own onClick applies the theme and closes the overlay, which is
|
// Or the row's own onClick applies the theme and closes the overlay, which is
|
||||||
// the opposite of what starring is for.
|
// the opposite of what starring is for.
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Zu Favoriten hinzufügen (f)",
|
"addToFavouritesKey": "Zu Favoriten hinzufügen (f)",
|
||||||
"removeFromFavouritesKey": "Aus Favoriten entfernen (f)",
|
"removeFromFavouritesKey": "Aus Favoriten entfernen (f)",
|
||||||
"active": "aktiv",
|
"active": "aktiv",
|
||||||
"browseHint": "j/k oder ↑/↓ bewegen · l oder → Vorschau · f markieren · Tab Favoriten · h oder ← zurücksetzen · Eingabetaste behalten · Esc abbrechen"
|
"browseHint": "j/k oder ↑/↓ bewegen · l oder → Vorschau · f Favoriten · h oder ← zurücksetzen · Eingabetaste behalten · Esc abbrechen"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Gehe zu…",
|
"placeholder": "Gehe zu…",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Add to favourites (f)",
|
"addToFavouritesKey": "Add to favourites (f)",
|
||||||
"removeFromFavouritesKey": "Remove from favourites (f)",
|
"removeFromFavouritesKey": "Remove from favourites (f)",
|
||||||
"active": "active",
|
"active": "active",
|
||||||
"browseHint": "j/k or ↑/↓ move · l or → preview · f star · tab favourites · h or ← reset · enter keep · esc cancel"
|
"browseHint": "j/k or ↑/↓ move · l or → preview · f favourites · h or ← reset · enter keep · esc cancel"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Go to…",
|
"placeholder": "Go to…",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Añadir a favoritos (f)",
|
"addToFavouritesKey": "Añadir a favoritos (f)",
|
||||||
"removeFromFavouritesKey": "Quitar de favoritos (f)",
|
"removeFromFavouritesKey": "Quitar de favoritos (f)",
|
||||||
"active": "activo",
|
"active": "activo",
|
||||||
"browseHint": "j/k o ↑/↓ mover · l o → previsualizar · f marcar · tab favoritos · h o ← reiniciar · enter mantener · esc cancelar"
|
"browseHint": "j/k o ↑/↓ mover · l o → previsualizar · f favoritos · h o ← reiniciar · enter mantener · esc cancelar"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Ir a…",
|
"placeholder": "Ir a…",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Ajouter aux favoris (f)",
|
"addToFavouritesKey": "Ajouter aux favoris (f)",
|
||||||
"removeFromFavouritesKey": "Retirer des favoris (f)",
|
"removeFromFavouritesKey": "Retirer des favoris (f)",
|
||||||
"active": "actif",
|
"active": "actif",
|
||||||
"browseHint": "j/k ou ↑/↓ déplacer · l ou → aperçu · f marquer · tab favoris · h ou ← réinitialiser · entrée garder · esc annuler"
|
"browseHint": "j/k ou ↑/↓ déplacer · l ou → aperçu · f favoris · h ou ← réinitialiser · entrée garder · esc annuler"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Aller à…",
|
"placeholder": "Aller à…",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Adicionar aos favoritos (f)",
|
"addToFavouritesKey": "Adicionar aos favoritos (f)",
|
||||||
"removeFromFavouritesKey": "Remover dos favoritos (f)",
|
"removeFromFavouritesKey": "Remover dos favoritos (f)",
|
||||||
"active": "ativo",
|
"active": "ativo",
|
||||||
"browseHint": "j/k ou ↑/↓ mover · l ou → pré-visualizar · f marcar · tab favoritos · h ou ← reiniciar · enter manter · esc cancelar"
|
"browseHint": "j/k ou ↑/↓ mover · l ou → pré-visualizar · f favoritos · h ou ← reiniciar · enter manter · esc cancelar"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Ir para…",
|
"placeholder": "Ir para…",
|
||||||
|
|||||||
@@ -494,7 +494,7 @@
|
|||||||
"addToFavouritesKey": "Lägg till i favoriter (f)",
|
"addToFavouritesKey": "Lägg till i favoriter (f)",
|
||||||
"removeFromFavouritesKey": "Ta bort från favoriter (f)",
|
"removeFromFavouritesKey": "Ta bort från favoriter (f)",
|
||||||
"active": "aktiv",
|
"active": "aktiv",
|
||||||
"browseHint": "j/k eller ↑/↓ flytta · l eller → förhandsgranska · f stjärna · tab favoriter · h eller ← återställ · enter behåll · esc avbryt"
|
"browseHint": "j/k eller ↑/↓ flytta · l eller → förhandsgranska · f favoriter · h eller ← återställ · enter behåll · esc avbryt"
|
||||||
},
|
},
|
||||||
"spotlight": {
|
"spotlight": {
|
||||||
"placeholder": "Gå till…",
|
"placeholder": "Gå till…",
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ import type { ThemeId } from './themes';
|
|||||||
* action invited the guess that `ctrl+shift+j` moved down — which opens the browser console instead. One
|
* action invited the guess that `ctrl+shift+j` moved down — which opens the browser console instead. One
|
||||||
* spelling, no guessing.
|
* spelling, no guessing.
|
||||||
*
|
*
|
||||||
* Inside the list `f` stars or unstars what is FOCUSED, so a browse and a shortlist are one pass.
|
* Inside the list `f` flips the favourites-only filter. It used to star what was focused, but starring
|
||||||
|
* already has a chord (`ctrl+shift+f`, and `l` applies the focused theme first when it is not the one
|
||||||
|
* worn), so the single letter goes to the thing that had none.
|
||||||
*
|
*
|
||||||
* Inside the list the vim keys stay, UNMODIFIED — `j`/`k`/`l`/`h` alongside the arrows. No modifier means
|
* Inside the list the vim keys stay, UNMODIFIED — `j`/`k`/`l`/`h` alongside the arrows. No modifier means
|
||||||
* no collision with anything the browser owns, and this is a vim person's application.
|
* no collision with anything the browser owns, and this is a vim person's application.
|
||||||
@@ -39,7 +41,7 @@ import type { ThemeId } from './themes';
|
|||||||
* Browsing walks `browseOrder` — the list as DISPLAYED — not the registry. The two orders must be the
|
* Browsing walks `browseOrder` — the list as DISPLAYED — not the registry. The two orders must be the
|
||||||
* same list or the focus visibly jumps, which is exactly what happened when the overlay lifted
|
* same list or the focus visibly jumps, which is exactly what happened when the overlay lifted
|
||||||
* favourites to a top block while stepping walked registry order. The overlay now shows one plain
|
* favourites to a top block while stepping walked registry order. The overlay now shows one plain
|
||||||
* rotation and `tab` flips a favourites-only filter (`onToggleFilter`); either way, what you see is
|
* rotation and `f` flips a favourites-only filter (`onToggleFilter`); either way, what you see is
|
||||||
* what `j`/`k` walk.
|
* what `j`/`k` walk.
|
||||||
*
|
*
|
||||||
* ── Not a UI ──
|
* ── Not a UI ──
|
||||||
@@ -49,7 +51,7 @@ import type { ThemeId } from './themes';
|
|||||||
*/
|
*/
|
||||||
type ThemeKeysOptions = {
|
type ThemeKeysOptions = {
|
||||||
/**
|
/**
|
||||||
* Star or unstar the focused theme — bound to `f` while the list is open.
|
* Star or unstar the CURRENT theme — bound to `ctrl+shift+f`, from anywhere.
|
||||||
*
|
*
|
||||||
* Passed in rather than owned here: favourites are per ACCOUNT and live behind an API, which is app
|
* Passed in rather than owned here: favourites are per ACCOUNT and live behind an API, which is app
|
||||||
* knowledge. This hook owns keys and selection and nothing else.
|
* knowledge. This hook owns keys and selection and nothing else.
|
||||||
@@ -60,7 +62,7 @@ type ThemeKeysOptions = {
|
|||||||
* browse falls back to the full registry rotation.
|
* browse falls back to the full registry rotation.
|
||||||
*/
|
*/
|
||||||
browseOrder?: readonly ThemeId[];
|
browseOrder?: readonly ThemeId[];
|
||||||
/** Flip the favourites-only filter — bound to `tab` while the list is open. App state, like the stars. */
|
/** Flip the favourites-only filter — bound to `f` while the list is open. App state, like the stars. */
|
||||||
onToggleFilter?: () => void;
|
onToggleFilter?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,13 +189,7 @@ export function useThemeKeys(options: ThemeKeysOptions = {}) {
|
|||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case 'f':
|
case 'f':
|
||||||
case 'F':
|
case 'F':
|
||||||
// Star or unstar what is focused, without moving or applying it.
|
// Favourites only ↔ everything. Starring is `ctrl+shift+f`, handled above before this switch.
|
||||||
event.preventDefault();
|
|
||||||
onToggleFavorite.current?.(focus);
|
|
||||||
return;
|
|
||||||
case 'Tab':
|
|
||||||
// Favourites only ↔ everything. preventDefault or the browser also moves focus, and the
|
|
||||||
// overlay has nothing focusable to move it to.
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
onToggleFilter.current?.();
|
onToggleFilter.current?.();
|
||||||
return;
|
return;
|
||||||
|
|||||||
Reference in New Issue
Block a user