diff --git a/apps/electron-backend-e2e/src/electron-test-fixtures.ts b/apps/electron-backend-e2e/src/electron-test-fixtures.ts index a2edd6418..8b53cfebf 100644 --- a/apps/electron-backend-e2e/src/electron-test-fixtures.ts +++ b/apps/electron-backend-e2e/src/electron-test-fixtures.ts @@ -565,7 +565,7 @@ export async function saveSettings(page: Page): Promise { export async function goToDashboard(page: Page): Promise { const dashboardLink = page - .locator('a.brand[href$="/workspace/dashboard"]') + .getByRole('link', { name: 'Dashboard', exact: true }) .first(); await expect(dashboardLink).toBeVisible(); diff --git a/apps/electron-backend-e2e/src/settings.e2e.ts b/apps/electron-backend-e2e/src/settings.e2e.ts index f0d834b90..f931dd935 100644 --- a/apps/electron-backend-e2e/src/settings.e2e.ts +++ b/apps/electron-backend-e2e/src/settings.e2e.ts @@ -247,10 +247,15 @@ test.describe('Electron Settings', () => { exact: true, }) ).toHaveCount(0); - await expect(secondLaunch.mainWindow.locator('a.brand')).toHaveAttribute( - 'href', - /\/workspace\/sources$/ - ); + await expect( + secondLaunch.mainWindow.getByRole('link', { + name: 'Sources', + exact: true, + }) + ).toHaveClass(/is-active/); + await expect( + secondLaunch.mainWindow.locator('button.brand') + ).toBeVisible(); } finally { await closeElectronApp(secondLaunch); } diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json index a635153a3..8ac8b7211 100644 --- a/apps/web/src/assets/i18n/ar.json +++ b/apps/web/src/assets/i18n/ar.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "إظهار القائمة", + "COLLAPSE_NAVIGATION": "إخفاء القائمة", "RAIL_DASHBOARD": "لوحة التحكم", "OPEN_DASHBOARD": "فتح لوحة التحكم", "RAIL_SOURCES": "المصادر", diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json index a617c041e..1b6845c78 100644 --- a/apps/web/src/assets/i18n/ary.json +++ b/apps/web/src/assets/i18n/ary.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "وسّع التنقل", + "COLLAPSE_NAVIGATION": "طوي التنقل", "RAIL_DASHBOARD": "لوحة التحكم", "OPEN_DASHBOARD": "حل لوحة التحكم", "RAIL_SOURCES": "المصادر", diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json index 7c39d2209..50af43c69 100644 --- a/apps/web/src/assets/i18n/by.json +++ b/apps/web/src/assets/i18n/by.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Разгарнуць навігацыю", + "COLLAPSE_NAVIGATION": "Згарнуць навігацыю", "RAIL_DASHBOARD": "Панэль", "OPEN_DASHBOARD": "Адкрыць панэль", "RAIL_SOURCES": "Крыніцы", diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json index f1a83f3f8..23b17854e 100644 --- a/apps/web/src/assets/i18n/de.json +++ b/apps/web/src/assets/i18n/de.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Navigation ausklappen", + "COLLAPSE_NAVIGATION": "Navigation einklappen", "RAIL_DASHBOARD": "Dashboard", "OPEN_DASHBOARD": "Dashboard öffnen", "RAIL_SOURCES": "Quellen", diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json index 775bf208d..85c8c7e4f 100644 --- a/apps/web/src/assets/i18n/el.json +++ b/apps/web/src/assets/i18n/el.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Ανάπτυξη πλοήγησης", + "COLLAPSE_NAVIGATION": "Σύμπτυξη πλοήγησης", "RAIL_DASHBOARD": "Πίνακας ελέγχου", "OPEN_DASHBOARD": "Άνοιγμα πίνακα ελέγχου", "RAIL_SOURCES": "Πηγές", diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json index 8fadf88f0..19d2c664c 100644 --- a/apps/web/src/assets/i18n/en.json +++ b/apps/web/src/assets/i18n/en.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Expand navigation", + "COLLAPSE_NAVIGATION": "Collapse navigation", "RAIL_DASHBOARD": "Dashboard", "OPEN_DASHBOARD": "Open dashboard", "RAIL_SOURCES": "Sources", diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json index a36753a51..d34633d2a 100644 --- a/apps/web/src/assets/i18n/es.json +++ b/apps/web/src/assets/i18n/es.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Ampliar navegación", + "COLLAPSE_NAVIGATION": "Contraer navegación", "RAIL_DASHBOARD": "Panel", "OPEN_DASHBOARD": "Abrir panel", "RAIL_SOURCES": "Fuentes", diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json index ab0150f91..7a029da21 100644 --- a/apps/web/src/assets/i18n/fr.json +++ b/apps/web/src/assets/i18n/fr.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Développer la navigation", + "COLLAPSE_NAVIGATION": "Réduire la navigation", "RAIL_DASHBOARD": "Tableau de bord", "OPEN_DASHBOARD": "Ouvrir le tableau de bord", "RAIL_SOURCES": "Sources", diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json index 0099b270f..034422481 100644 --- a/apps/web/src/assets/i18n/it.json +++ b/apps/web/src/assets/i18n/it.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Espandi navigazione", + "COLLAPSE_NAVIGATION": "Comprimi navigazione", "RAIL_DASHBOARD": "Dashboard", "OPEN_DASHBOARD": "Apri dashboard", "RAIL_SOURCES": "Sorgenti", diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json index e7b5bfcbb..5d340cfea 100644 --- a/apps/web/src/assets/i18n/ja.json +++ b/apps/web/src/assets/i18n/ja.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "ナビゲーションを展開", + "COLLAPSE_NAVIGATION": "ナビゲーションを折りたたむ", "RAIL_DASHBOARD": "ダッシュボード", "OPEN_DASHBOARD": "ダッシュボードを開く", "RAIL_SOURCES": "ソース", diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index f00557a87..4ad1e39a3 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "탐색 펼치기", + "COLLAPSE_NAVIGATION": "탐색 접기", "RAIL_DASHBOARD": "대시보드", "OPEN_DASHBOARD": "대시보드 열기", "RAIL_SOURCES": "소스", diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json index 62f211028..0103fce30 100644 --- a/apps/web/src/assets/i18n/nl.json +++ b/apps/web/src/assets/i18n/nl.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Navigatie uitklappen", + "COLLAPSE_NAVIGATION": "Navigatie inklappen", "RAIL_DASHBOARD": "Dashboard", "OPEN_DASHBOARD": "Open dashboard", "RAIL_SOURCES": "Bronnen", diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json index e2c93f1a4..969663a67 100644 --- a/apps/web/src/assets/i18n/pl.json +++ b/apps/web/src/assets/i18n/pl.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Rozwiń nawigację", + "COLLAPSE_NAVIGATION": "Zwiń nawigację", "RAIL_DASHBOARD": "Pulpit", "OPEN_DASHBOARD": "Otwórz pulpit", "RAIL_SOURCES": "Źródła", diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json index e49fbfc48..90ba5ab9a 100644 --- a/apps/web/src/assets/i18n/pt.json +++ b/apps/web/src/assets/i18n/pt.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Expandir navegação", + "COLLAPSE_NAVIGATION": "Recolher navegação", "RAIL_DASHBOARD": "Dashboard", "OPEN_DASHBOARD": "Abrir dashboard", "RAIL_SOURCES": "Fontes", diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json index 1d6495e75..b96f6fdfa 100644 --- a/apps/web/src/assets/i18n/ru.json +++ b/apps/web/src/assets/i18n/ru.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Развернуть навигацию", + "COLLAPSE_NAVIGATION": "Свернуть навигацию", "RAIL_DASHBOARD": "Панель", "OPEN_DASHBOARD": "Открыть панель", "RAIL_SOURCES": "Источники", diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json index 126c30ca6..12089157e 100644 --- a/apps/web/src/assets/i18n/tr.json +++ b/apps/web/src/assets/i18n/tr.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "Gezinmeyi genişlet", + "COLLAPSE_NAVIGATION": "Gezinmeyi daralt", "RAIL_DASHBOARD": "Pano", "OPEN_DASHBOARD": "Panoyu aç", "RAIL_SOURCES": "Kaynaklar", diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json index 49c2e475d..08a5afa5a 100644 --- a/apps/web/src/assets/i18n/zh.json +++ b/apps/web/src/assets/i18n/zh.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "展开导航", + "COLLAPSE_NAVIGATION": "收起导航", "RAIL_DASHBOARD": "仪表盘", "OPEN_DASHBOARD": "打开仪表盘", "RAIL_SOURCES": "源", diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json index 4bfcbde42..f6bec8e92 100644 --- a/apps/web/src/assets/i18n/zhtw.json +++ b/apps/web/src/assets/i18n/zhtw.json @@ -913,6 +913,8 @@ }, "SHELL": { "BRAND_ALT": "IPTVnator", + "EXPAND_NAVIGATION": "展開導覽", + "COLLAPSE_NAVIGATION": "收合導覽", "RAIL_DASHBOARD": "儀表板", "OPEN_DASHBOARD": "開啟儀表板", "RAIL_SOURCES": "來源", diff --git a/docs/architecture/workspace-shell.md b/docs/architecture/workspace-shell.md index 991582789..dd0287f49 100644 --- a/docs/architecture/workspace-shell.md +++ b/docs/architecture/workspace-shell.md @@ -153,6 +153,17 @@ Rail navigation is also shell-owned: 3. On dashboard, sources, settings, and global favorites, the shell falls back to the currently selected playlist so provider navigation remains available even outside a provider route. +4. The IPTVnator brand button toggles the primary rail between its default + 60px icon-only layout and an expanded, label-bearing layout. The expanded + width is content-driven by the longest visible label with equal horizontal + spacing around icons and text, capped to preserve the content area. Mobile + navigation remains compact and does not enter the expanded state. +5. Active-link markers must stay inset within the rail so selection styling is + not clipped by the rail's overflow boundary. +6. The navigation links own the rail's scroll area while the settings shortcut + remains visible in the fixed footer. +7. Expanded labels use automatic text direction and logical start alignment so + left-to-right and right-to-left translations align naturally. Command palette behavior is shell-owned but view-extensible: diff --git a/libs/workspace/shell/feature/src/lib/workspace-shell/components/workspace-shell-rail-links/workspace-shell-rail-links.component.html b/libs/workspace/shell/feature/src/lib/workspace-shell/components/workspace-shell-rail-links/workspace-shell-rail-links.component.html index 5642a1b9b..34eb36226 100644 --- a/libs/workspace/shell/feature/src/lib/workspace-shell/components/workspace-shell-rail-links/workspace-shell-rail-links.component.html +++ b/libs/workspace/shell/feature/src/lib/workspace-shell/components/workspace-shell-rail-links/workspace-shell-rail-links.component.html @@ -1,4 +1,4 @@ -