From ff617e8d95ab549948e9f67d453afe1fb8dcc3f6 Mon Sep 17 00:00:00 2001 From: Ettore Di Giacinto Date: Tue, 20 Oct 2026 15:00:10 +0000 Subject: [PATCH] fix(ui): centre the icon of a built-in tile in its icon box The drawer drew the icon of a built-in tile (Studio's palette was one) in a bare 40px box. Only the placeholder box was laid out as a centred grid with the 20px size, so the real icon sat in the top-left corner at the size of the page text. Give the built-in tile the same classes as the placeholder box, and check in a browser that the icon is centred. Assisted-by: Claude Code:claude-sonnet-5-5 node Signed-off-by: Ettore Di Giacinto --- .../http/react-ui/e2e/addon-navigation.spec.js | 18 ++++++++++++++++++ .../src/components/addons/AddonTile.jsx | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/core/http/react-ui/e2e/addon-navigation.spec.js b/core/http/react-ui/e2e/addon-navigation.spec.js index 09450158a..2663f325a 100644 --- a/core/http/react-ui/e2e/addon-navigation.spec.js +++ b/core/http/react-ui/e2e/addon-navigation.spec.js @@ -95,6 +95,24 @@ test.describe('Add-on navigation', () => { expect(appsCalled).toBe(false) }) + // The icon of a built-in tile sat in the top-left corner of its 40px box, at the + // size of the page text, because only the empty-icon box was laid out as a grid. + test('a built-in tile draws its icon centred in the icon box', async ({ page }) => { + await setup(page, { builtin: [{ id: 'guide', kind: 'page', titleKey: 'items.chat', icon: 'palette', mainPath: '/app/chat' }], studio: false }) + await page.goto('/app/addons') + const box = page.locator('.ad-icon').first() + await expect(box.locator('svg[data-icon="palette"]')).toBeVisible() + const offsets = await box.evaluate(el => { + const outer = el.getBoundingClientRect() + const inner = el.querySelector('svg').getBoundingClientRect() + return { dx: (inner.left + inner.width / 2) - (outer.left + outer.width / 2), dy: (inner.top + inner.height / 2) - (outer.top + outer.height / 2), width: inner.width, box: outer.width } + }) + expect(Math.abs(offsets.dx)).toBeLessThan(1) + expect(Math.abs(offsets.dy)).toBeLessThan(1) + expect(offsets.width).toBeGreaterThan(16) + expect(offsets.box).toBe(40) + }) + test('member without the add-ons feature and with no built-in tile goes home, and Studio and Talk are not built in', async ({ page }) => { await setup(page, { addons: false }) await page.goto('/app/addons') diff --git a/core/http/react-ui/src/components/addons/AddonTile.jsx b/core/http/react-ui/src/components/addons/AddonTile.jsx index 6b2523c7f..ff88f191c 100644 --- a/core/http/react-ui/src/components/addons/AddonTile.jsx +++ b/core/http/react-ui/src/components/addons/AddonTile.jsx @@ -17,7 +17,7 @@ export default function AddonTile({ tile, pinned, onPin, onMove, onOpenDetail }) const body = ( <> {tile.source === 'builtin' - ? + ? : } {title}