From c9eb6dcd7e5fbba0e2f8fccdbc2da1d4c95dd9b6 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Wed, 21 Oct 2026 11:01:29 +0000 Subject: [PATCH] fix(ui): remove the Show all link under Apps in the sidebar The link repeated the Apps entry, which opens the same drawer, and looked redundant when no app was pinned. Apps is now the only add-on entry; pinned apps still list under it in pin order. The link, its locale key and the style comment are gone, and the e2e spec and the add-ons docs now say that Apps is the only entry. Assisted-by: Claude Code:claude-sonnet-5-5 node playwright Signed-off-by: Ettore Di Giacinto --- core/http/react-ui/e2e/addon-navigation.spec.js | 14 ++++++++------ core/http/react-ui/public/locales/en/nav.json | 3 +-- core/http/react-ui/src/App.css | 2 +- core/http/react-ui/src/components/Sidebar.jsx | 9 +-------- docs/content/features/addons.md | 5 ++--- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/core/http/react-ui/e2e/addon-navigation.spec.js b/core/http/react-ui/e2e/addon-navigation.spec.js index 86435df7b..6454c6135 100644 --- a/core/http/react-ui/e2e/addon-navigation.spec.js +++ b/core/http/react-ui/e2e/addon-navigation.spec.js @@ -26,12 +26,12 @@ async function setup(page, { apps = [], pins = ['studio', 'talk'], addons = true } test.describe('Add-on navigation', () => { - test('the sidebar lists the pinned apps under Apps, in pin order, with Show all last', async ({ page }) => { + test('the sidebar lists the pinned apps under Apps, in pin order, and no Show all link', async ({ page }) => { await setup(page) await page.goto('/app') const nav = page.getByRole('navigation') await expect(nav.getByRole('link', { name: 'Chat' })).toBeVisible() - // Apps, then the pinned apps in pin order, then Show all as the last line. + // Apps, then the pinned apps in pin order; Apps is the only add-on entry. await expect(nav.getByRole('link', { name: 'Apps', exact: true })).toHaveCount(1) const pinned = nav.getByTestId('apps-pinned-link') await expect(pinned).toHaveCount(2) @@ -39,10 +39,11 @@ test.describe('Add-on navigation', () => { await expect(pinned.nth(0)).toHaveText('Studio') await expect(pinned.nth(1)).toHaveAttribute('data-app', 'talk') await expect(pinned.nth(1)).toHaveText('Talk') - await expect(nav.getByTestId('apps-show-all')).toHaveText('Show all') + await expect(nav.getByTestId('apps-show-all')).toHaveCount(0) + await expect(nav.getByText('Show all')).toHaveCount(0) const group = await nav.locator('a.nav-item').evaluateAll(els => els.map(e => e.textContent.trim())) const at = group.indexOf('Apps') - expect(group.slice(at, at + 4)).toEqual(['Apps', 'Studio', 'Talk', 'Show all']) + expect(group.slice(at, at + 4)).toEqual(['Apps', 'Studio', 'Talk']) await expect(pinned.nth(0)).toHaveAttribute('href', /\/app\/addons\/studio\//) // There is no Pinned section. await expect(page.getByTestId('pinned-nav')).toHaveCount(0) @@ -54,11 +55,12 @@ test.describe('Add-on navigation', () => { await page.goto('/app') const nav = page.getByRole('navigation') await expect(nav.getByTestId('apps-pinned-link')).toHaveText(['Talk', 'Studio']) - await expect(nav.getByTestId('apps-show-all')).toBeVisible() + await expect(nav.getByTestId('apps-show-all')).toHaveCount(0) await page.unroute('**/api/addons/pins') await page.route('**/api/addons/pins', route => route.fulfill({ json: [] })) await page.goto('/app') - await expect(nav.getByTestId('apps-show-all')).toBeVisible() + await expect(nav.getByRole('link', { name: 'Apps', exact: true })).toHaveCount(1) + await expect(nav.getByTestId('apps-show-all')).toHaveCount(0) await expect(nav.getByTestId('apps-pinned-link')).toHaveCount(0) }) diff --git a/core/http/react-ui/public/locales/en/nav.json b/core/http/react-ui/public/locales/en/nav.json index c17375216..673111fba 100644 --- a/core/http/react-ui/public/locales/en/nav.json +++ b/core/http/react-ui/public/locales/en/nav.json @@ -66,8 +66,7 @@ "trafficModels": "Models", "gpuHost": "GPU and host", "prometheus": "Prometheus", - "addons": "Apps", - "showAll": "Show all" + "addons": "Apps" }, "footer": { "github": "GitHub", diff --git a/core/http/react-ui/src/App.css b/core/http/react-ui/src/App.css index 502a504e1..8dc2259f5 100644 --- a/core/http/react-ui/src/App.css +++ b/core/http/react-ui/src/App.css @@ -9693,5 +9693,5 @@ button.lane:hover { .lai-icon--beat { animation: none; } } -/* The "Show all" line under the Apps entry: its label lines up with the labels above it. */ +/* Pinned apps under the Apps entry: their labels line up with the labels above them. */ .sidebar-nav .nav-item.nav-item--sub { padding-inline-start: 36px; } diff --git a/core/http/react-ui/src/components/Sidebar.jsx b/core/http/react-ui/src/components/Sidebar.jsx index 7ae71e40e..693a40a72 100644 --- a/core/http/react-ui/src/components/Sidebar.jsx +++ b/core/http/react-ui/src/components/Sidebar.jsx @@ -220,15 +220,8 @@ export default function Sidebar({ isOpen, onClose }) { {(legacy ? visibleTopItems : [...visibleTopItems.filter(i => i.path === '/app'), ...primary]).map(item => ( - {/* The Apps group: the pinned apps in pin order, then the full list - of apps as the last line. Show all has no active style of its - own; the Apps entry above carries it. */} + {/* The Apps group: the pinned apps in pin order, under the Apps entry. */} {!legacy && item.addonsEntry && !collapsed && } - {!legacy && item.addonsEntry && !collapsed && ( - - {t('items.showAll')} - - )} ))} diff --git a/docs/content/features/addons.md b/docs/content/features/addons.md index 300cd723a..fbabe0f99 100644 --- a/docs/content/features/addons.md +++ b/docs/content/features/addons.md @@ -1711,9 +1711,8 @@ reach **Browse**, **Installed** and **Libraries** from the drawer. The tabs are convenience: the owner checks administration again on every call, so a request that skips the page is denied the same way (403). -The sidebar has the items **Chat**, **Models** and **Apps**, and below Apps a **Show all** -link. Both open the add-ons drawer at `/app/addons`. The pinned apps are listed between them, -in pin order, as indented links with the app icon and title; nothing is listed when no app is +The sidebar has the items **Chat**, **Models** and **Apps**. **Apps** opens the add-ons drawer at +`/app/addons`. The pinned apps are listed under it, in pin order, as indented links with the app icon and title; nothing is listed when no app is pinned, and the list is hidden when the sidebar is collapsed. The user pins add-ons and changes their order with the buttons on a pinned tile in the drawer. Pins belong to the user, follow the user across browsers, and are capped at eight. A pin whose add-on is stopped opens the detail view; a pin whose add-on