From 57cda5162c26fa6cc7d3f1faf1cc7602f6236955 Mon Sep 17 00:00:00 2001 From: NGPixel Date: Wed, 12 Aug 2026 16:20:57 -0400 Subject: [PATCH] fix: optimize home layout for mobile --- frontend/src/assets/icons.generated.js | 3 +- frontend/src/components/HeaderActionsMenu.vue | 184 +++++++++++ frontend/src/components/HeaderNav.vue | 306 ++++++++++++++---- frontend/src/components/HeaderSearch.vue | 82 ++++- frontend/src/components/NavSidebar.vue | 20 +- frontend/src/components/PageActionsCol.vue | 14 + frontend/src/components/PageHeader.vue | 69 +++- frontend/src/layouts/MainLayout.vue | 120 ++++++- frontend/src/pages/Index.vue | 17 +- 9 files changed, 718 insertions(+), 97 deletions(-) create mode 100644 frontend/src/components/HeaderActionsMenu.vue diff --git a/frontend/src/assets/icons.generated.js b/frontend/src/assets/icons.generated.js index 818bd318a..7dd13c0de 100644 --- a/frontend/src/assets/icons.generated.js +++ b/frontend/src/assets/icons.generated.js @@ -5,7 +5,7 @@ never waits on (or depends on) the icon service. Regenerate with `npm run icons` after adding or removing an icon; `check-icons.mjs` fails the build if this drifts. - 264 icons. + 263 icons. */ export const BUNDLED_ICONS = { "la:angle-double-right": {"body":"","width":32,"height":32}, @@ -153,7 +153,6 @@ export const BUNDLED_ICONS = { "mdi:account-group": {"body":"","width":24,"height":24}, "mdi:alert": {"body":"","width":24,"height":24}, "mdi:alert-box": {"body":"","width":24,"height":24}, - "mdi:alpha-t-box-outline": {"body":"","width":24,"height":24}, "mdi:arrow-right": {"body":"","width":24,"height":24}, "mdi:arrow-vertical-lock": {"body":"","width":24,"height":24}, "mdi:basketball": {"body":"","width":24,"height":24}, diff --git a/frontend/src/components/HeaderActionsMenu.vue b/frontend/src/components/HeaderActionsMenu.vue new file mode 100644 index 000000000..d0bd94760 --- /dev/null +++ b/frontend/src/components/HeaderActionsMenu.vue @@ -0,0 +1,184 @@ + + + + + diff --git a/frontend/src/components/HeaderNav.vue b/frontend/src/components/HeaderNav.vue index ad5181f4c..c80fb1195 100644 --- a/frontend/src/components/HeaderNav.vue +++ b/frontend/src/components/HeaderNav.vue @@ -8,99 +8,141 @@ -
+
{{ siteStore.title }}
- + + - - Create New Page - - - - File Manager - - - {{ t('inbox.title') }} - - - {{ t('common.header.admin') }} - + +
+ + +
+ +
+
+ + diff --git a/frontend/src/components/HeaderSearch.vue b/frontend/src/components/HeaderSearch.vue index 948d2a133..5585423b0 100644 --- a/frontend/src/components/HeaderSearch.vue +++ b/frontend/src/components/HeaderSearch.vue @@ -1,5 +1,11 @@
Search Operators
-
!foo or -bar to exclude "foo" and "bar".
-
bana* for to match any term starting with "bana" (e.g. banana).
-
foo,bar or foo|bar to search for "foo" OR "bar".
-
"foo bar" to match exactly the phrase "foo bar".
+
+ !foo or -bar to exclude "foo" and "bar". +
+
+ bana* for to match any term starting with "bana" (e.g. banana). +
+
+ foo,bar or foo|bar to search for "foo" OR "bar". +
+
+ "foo bar" to match exactly the phrase "foo bar". +
@@ -105,6 +129,18 @@ import { useSiteStore } from '@/stores/site' import { orderBy } from 'es-toolkit/array' +// PROPS + +const props = defineProps({ + /** + * Render as a row of its own rather than inline in the header bar. What the phone header opens; + * see `HeaderNav`. + */ + row: { + type: Boolean, + default: false + } +}) // STORES @@ -190,6 +226,18 @@ function checkSearchFocus(ev) { } } +/** + * Put the caret in the field. + * + * Exposed because in `row` form the field is not focused by being mounted: focusing it is what draws + * the panel below it, and a panel appearing mid-slide is layout and a `backdrop-filter` blur landing + * in the middle of an animation. `HeaderNav` owns that transition, so it calls this when the slide has + * finished -- see its `@after-enter`. + */ +function focus() { + searchField.value?.focus() +} + function clearSearch() { siteStore.search = '' searchField.value.focus() @@ -217,6 +265,8 @@ onBeforeUnmount(() => { window.removeEventListener('keydown', handleKeyPress) } }) + +defineExpose({ focus })