From 4d3974ab06021921ddd4446372e36a4648942aa7 Mon Sep 17 00:00:00 2001 From: Alexander Ackermann Date: Thu, 29 Oct 2026 16:19:27 +0100 Subject: [PATCH] fix: raise contrast, target sizes and visibility of small UI parts Checkbox borders, tile checkboxes, slider tracks, the upload progress frame, the highlighted select option and the active inline filter now reach 3:1, top bar and search icons get 24px targets, the + button no longer covers sidebar controls, long names wrap and the tile selection zone shows a pointer. All with existing design system tokens and patterns. --- .../src/components/OcCheckbox/OcCheckbox.vue | 2 +- .../src/components/OcRange/OcRange.vue | 2 +- .../components/OcSearchBar/OcSearchBar.vue | 2 +- .../src/components/OcSelect/OcSelect.spec.ts | 19 +++++++++++++++++++ .../src/components/OcSelect/OcSelect.vue | 6 ++---- .../src/components/Spaces/SpacesList.vue | 2 +- .../SideBar/Shares/Collaborators/ListItem.vue | 2 +- .../SideBar/Shares/Links/ListItem.vue | 2 +- .../__snapshots__/ListItem.spec.ts.snap | 2 +- .../__snapshots__/Projects.spec.ts.snap | 2 +- .../trash/__snapshots__/Overview.spec.ts.snap | 2 +- .../web-app-search/src/portals/SearchBar.vue | 4 ++-- .../src/components/FilesList/ResourceTile.vue | 2 +- .../components/FilesList/ResourceTiles.vue | 2 +- .../components/Filters/ItemFilterInline.vue | 2 ++ .../src/components/SearchBarFilter.vue | 2 +- .../src/components/SideBar/SideBarPanels.vue | 2 +- .../components/SideBar/Spaces/SpaceInfo.vue | 2 +- .../__snapshots__/ResourceTile.spec.ts.snap | 4 ++-- .../__snapshots__/ResourceTiles.spec.ts.snap | 8 ++++---- .../Filters/ItemFilterInline.spec.ts | 7 +++++++ .../__snapshots__/SpaceInfo.spec.ts.snap | 2 +- .../components/Topbar/ApplicationsMenu.vue | 2 +- .../src/components/Topbar/FeedbackLink.vue | 1 + .../components/Topbar/NotificationBell.vue | 4 ++-- .../web-runtime/src/components/UploadInfo.vue | 1 + .../NotificationBell.spec.ts.snap | 2 +- 27 files changed, 59 insertions(+), 31 deletions(-) diff --git a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue index 5b3786d93b5..d82a4013bb8 100644 --- a/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue +++ b/packages/design-system/src/components/OcCheckbox/OcCheckbox.vue @@ -12,7 +12,7 @@ 'align-middle', 'm-0.5', 'border-2', - 'border-role-outline/80', + 'border-role-outline', 'outline-0', 'outline-role-secondary', 'focus-visible:outline', diff --git a/packages/design-system/src/components/OcRange/OcRange.vue b/packages/design-system/src/components/OcRange/OcRange.vue index a1cc7d0714e..74d5d31957e 100644 --- a/packages/design-system/src/components/OcRange/OcRange.vue +++ b/packages/design-system/src/components/OcRange/OcRange.vue @@ -17,7 +17,7 @@ :max="max" :step="step" :disabled="disabled" - class="oc-range h-1.5 appearance-none rounded-sm bg-role-surface-container-high outline-0 outline-role-secondary hover:opacity-100 focus-visible:outline not-disabled:cursor-pointer disabled:cursor-not-allowed" + class="oc-range h-1.5 appearance-none rounded-sm bg-role-outline outline-0 outline-role-secondary hover:opacity-100 focus-visible:outline not-disabled:cursor-pointer disabled:cursor-not-allowed" :class="[inlineLabel ? 'grow basis-0' : 'w-full', inputClass]" @input="onInput" @change="onChange" diff --git a/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue b/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue index ed56aa6d980..1ffb2a7a6fa 100644 --- a/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue +++ b/packages/design-system/src/components/OcSearchBar/OcSearchBar.vue @@ -20,7 +20,7 @@ { wrapper.unmount() }) }) + describe('keyboard highlight', () => { + const options = [{ label: 'label1' }, { label: 'label2' }] + + it('outlines the highlighted option while typing, not only after arrow keys', async () => { + const wrapper = getWrapper({ options }) + await wrapper.find(selectors.ocSelect).trigger('mousemove') + await wrapper.find(selectors.searchInput).trigger('keydown', { key: 'l' }) + expect(wrapper.find(selectors.ocSelect).classes()).toContain('oc-select-keyboard-navigation') + }) + it('drops the outline when the mouse is used', async () => { + const wrapper = getWrapper({ options }) + await wrapper.find(selectors.searchInput).trigger('keydown', { key: 'l' }) + expect(wrapper.find(selectors.ocSelect).classes()).toContain('oc-select-keyboard-navigation') + await wrapper.find(selectors.ocSelect).trigger('mousemove') + expect(wrapper.find(selectors.ocSelect).classes()).not.toContain( + 'oc-select-keyboard-navigation' + ) + }) + }) describe('required mark', () => { it('marks the search input as required for assistive technologies', () => { const wrapper = getWrapper({ requiredMark: true }) diff --git a/packages/design-system/src/components/OcSelect/OcSelect.vue b/packages/design-system/src/components/OcSelect/OcSelect.vue index 694411853f5..27f134f51dd 100644 --- a/packages/design-system/src/components/OcSelect/OcSelect.vue +++ b/packages/design-system/src/components/OcSelect/OcSelect.vue @@ -321,7 +321,7 @@ function dropdownShouldOpen({ noDrop, open, mutableLoading }: Record void>) { } function onKeydown(e: KeyboardEvent) { - if (e.key === 'ArrowDown' || e.key === 'ArrowUp') { - keyboardNavigation.value = true - } + keyboardNavigation.value = true if (!['Enter', 'Tab', 'Escape'].includes(e.key)) { dropdownEnabled.value = true } diff --git a/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue b/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue index 39629969a70..972b87f66c0 100644 --- a/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue +++ b/packages/web-app-admin-settings/src/components/Spaces/SpacesList.vue @@ -50,7 +50,7 @@