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 <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto committed 2026-10-21 11:01:29 +00:00
1 parent 7037f845a2
commit c9eb6dcd7e
5 files changed
+13 -20

No files matched your search

@@ -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)
})
@@ -66,8 +66,7 @@
"trafficModels": "Models",
"gpuHost": "GPU and host",
"prometheus": "Prometheus",
"addons": "Apps",
"showAll": "Show all"
"addons": "Apps"
},
"footer": {
"github": "GitHub",
+1 -1
View File
@@ -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; }
@@ -220,15 +220,8 @@ export default function Sidebar({ isOpen, onClose }) {
{(legacy ? visibleTopItems : [...visibleTopItems.filter(i => i.path === '/app'), ...primary]).map(item => (
<Fragment key={item.path}>
<NavItem item={item} onClose={onClose} collapsed={collapsed} />
{/* 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 && <AppsPinnedLinks onClose={onClose} />}
{!legacy && item.addonsEntry && !collapsed && (
<NavLink to={item.path} onClick={onClose} className="nav-item nav-item--sub" data-testid="apps-show-all">
<span className="nav-label">{t('items.showAll')}</span>
</NavLink>
)}
</Fragment>
))}
</div>
+2 -3
View File
@@ -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