diff --git a/apps/client/package.json b/apps/client/package.json index 6b8a8b60d..c769f6090 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,85 +1,95 @@ { "name": "client", "private": true, - "version": "0.80.0", + "version": "0.80.1", "scripts": { "dev": "vite", "build": "tsc && vite build", "lint": "eslint .", "preview": "vite preview", - "format": "prettier --write \"src/**/*.tsx\" \"src/**/*.ts\"" + "format": "prettier --write \"src/**/*.tsx\" \"src/**/*.ts\"", + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { - "@casl/react": "^5.0.1", + "@atlaskit/pragmatic-drag-and-drop": "1.8.1", + "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "2.1.5", + "@atlaskit/pragmatic-drag-and-drop-flourish": "2.0.15", + "@atlaskit/pragmatic-drag-and-drop-hitbox": "1.1.0", + "@atlaskit/pragmatic-drag-and-drop-live-region": "1.3.4", + "@casl/react": "5.0.1", "@docmost/editor-ext": "workspace:*", - "@emoji-mart/data": "^1.2.1", - "@emoji-mart/react": "^1.1.1", "@excalidraw/excalidraw": "0.18.0-3a5ef40", - "@mantine/core": "^8.3.18", - "@mantine/dates": "^8.3.18", - "@mantine/form": "^8.3.18", - "@mantine/hooks": "^8.3.18", - "@mantine/modals": "^8.3.18", - "@mantine/notifications": "^8.3.18", - "@mantine/spotlight": "^8.3.18", - "@tabler/icons-react": "^3.40.0", + "@mantine/core": "8.3.18", + "@mantine/dates": "8.3.18", + "@mantine/form": "8.3.18", + "@mantine/hooks": "8.3.18", + "@mantine/modals": "8.3.18", + "@mantine/notifications": "8.3.18", + "@mantine/spotlight": "8.3.18", + "@slidoapp/emoji-mart": "5.8.7", + "@slidoapp/emoji-mart-data": "1.2.4", + "@slidoapp/emoji-mart-react": "1.1.5", + "@tabler/icons-react": "3.40.0", "@tanstack/react-query": "5.90.17", - "alfaaz": "^1.1.0", - "axios": "1.15.0", - "blueimp-load-image": "^5.16.0", - "clsx": "^2.1.1", - "emoji-mart": "^5.6.0", - "file-saver": "^2.0.5", - "highlightjs-sap-abap": "^0.3.0", - "i18next": "^25.10.1", - "i18next-http-backend": "^3.0.2", - "jotai": "^2.18.1", - "jotai-optics": "^0.4.0", - "js-cookie": "^3.0.5", - "jwt-decode": "^4.0.0", + "@tanstack/react-virtual": "3.13.24", + "alfaaz": "1.1.0", + "axios": "1.16.0", + "blueimp-load-image": "5.16.0", + "clsx": "2.1.1", + "file-saver": "2.0.5", + "highlightjs-sap-abap": "0.3.0", + "i18next": "25.10.1", + "i18next-http-backend": "3.0.6", + "jotai": "2.18.1", + "jotai-optics": "0.4.0", + "js-cookie": "3.0.5", + "jwt-decode": "4.0.0", "katex": "0.16.40", - "lowlight": "^3.3.0", - "mantine-form-zod-resolver": "^1.3.0", - "mermaid": "^11.13.0", - "mitt": "^3.0.1", - "posthog-js": "1.363.1", - "react": "^18.3.1", - "react-arborist": "3.4.0", + "lowlight": "3.3.0", + "mantine-form-zod-resolver": "1.3.0", + "mermaid": "11.15.0", + "mitt": "3.0.1", + "posthog-js": "1.372.2", + "react": "18.3.1", "react-clear-modal": "^2.0.18", "react-dom": "^18.3.1", - "react-drawio": "^1.0.7", - "react-error-boundary": "^6.1.1", - "react-helmet-async": "^3.0.0", - "react-i18next": "^16.5.8", - "react-router-dom": "^7.13.1", - "semver": "^7.7.4", - "socket.io-client": "^4.8.3", - "tiptap-extension-global-drag-handle": "^0.1.18", - "zod": "^4.3.6" + "react-drawio": "1.0.7", + "react-error-boundary": "6.1.1", + "react-helmet-async": "3.0.0", + "react-i18next": "16.5.8", + "react-router-dom": "7.13.1", + "semver": "7.7.4", + "socket.io-client": "4.8.3", + "zod": "4.3.6" }, "devDependencies": { - "@eslint/js": "^9.28.0", - "@tanstack/eslint-plugin-query": "^5.94.4", - "@types/blueimp-load-image": "^5.16.6", - "@types/file-saver": "^2.0.7", - "@types/js-cookie": "^3.0.6", - "@types/katex": "^0.16.8", + "@eslint/js": "9.28.0", + "@tanstack/eslint-plugin-query": "5.94.4", + "@testing-library/jest-dom": "6.6.0", + "@testing-library/react": "16.1.0", + "@types/blueimp-load-image": "5.16.6", + "@types/file-saver": "2.0.7", + "@types/js-cookie": "3.0.6", + "@types/katex": "0.16.8", "@types/node": "22.19.1", - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^6.0.1", - "eslint": "^9.28.0", - "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.5.2", - "globals": "^15.13.0", - "optics-ts": "^2.4.1", - "postcss": "^8.5.8", - "postcss-preset-mantine": "^1.18.0", - "postcss-simple-vars": "^7.0.1", - "prettier": "^3.8.1", - "typescript": "^5.9.3", - "typescript-eslint": "^8.57.1", - "vite": "8.0.5" + "@types/react": "18.3.12", + "@types/react-dom": "18.3.1", + "@vitejs/plugin-react": "6.0.1", + "eslint": "9.28.0", + "eslint-plugin-react": "7.37.5", + "eslint-plugin-react-hooks": "7.0.1", + "eslint-plugin-react-refresh": "0.5.2", + "globals": "15.13.0", + "jsdom": "25.0.0", + "optics-ts": "2.4.1", + "postcss": "8.5.14", + "postcss-preset-mantine": "1.18.0", + "postcss-simple-vars": "7.0.1", + "prettier": "3.8.1", + "typescript": "5.9.3", + "typescript-eslint": "8.57.1", + "vite": "8.0.5", + "vitest": "4.1.6" } } diff --git a/apps/client/public/locales/de-DE/translation.json b/apps/client/public/locales/de-DE/translation.json index b6caf4d61..5c9e2d44c 100644 --- a/apps/client/public/locales/de-DE/translation.json +++ b/apps/client/public/locales/de-DE/translation.json @@ -391,7 +391,7 @@ "Write anything. Enter \"/\" for commands": "Schreiben Sie etwas. Geben Sie \"/\" für Befehle ein", "Write...": "\"Schreiben...\"", "Column count": "Spaltenanzahl", - "{{count}} Columns": "{count, plural, one {# Spalte} other {# Spalten}}", + "{{count}} Columns": "{{count}} Spalten", "Equal columns": "Gleich breite Spalten", "Left sidebar": "Linke Seitenleiste", "Right sidebar": "Rechte Seitenleiste", diff --git a/apps/client/public/locales/en-US/translation.json b/apps/client/public/locales/en-US/translation.json index 3bfe7c9f0..d59aa94b9 100644 --- a/apps/client/public/locales/en-US/translation.json +++ b/apps/client/public/locales/en-US/translation.json @@ -71,6 +71,7 @@ "Export": "Export", "Failed to create page": "Failed to create page", "Failed to delete page": "Failed to delete page", + "Failed to restore page": "Failed to restore page", "Failed to fetch recent pages": "Failed to fetch recent pages", "Failed to import pages": "Failed to import pages", "Failed to load page. An error occurred.": "Failed to load page. An error occurred.", @@ -286,6 +287,19 @@ "Add row above": "Add row above", "Add row below": "Add row below", "Delete table": "Delete table", + "Add column left": "Add column left", + "Add column right": "Add column right", + "Clear cell": "Clear cell", + "Clear cells": "Clear cells", + "Toggle header cell": "Toggle header cell", + "Toggle header column": "Toggle header column", + "Toggle header row": "Toggle header row", + "Move column left": "Move column left", + "Move column right": "Move column right", + "Move row down": "Move row down", + "Move row up": "Move row up", + "Sort A → Z": "Sort A → Z", + "Sort Z → A": "Sort Z → A", "Info": "Info", "Note": "Note", "Success": "Success", @@ -348,6 +362,8 @@ "Create block quote.": "Create block quote.", "Insert code snippet.": "Insert code snippet.", "Insert horizontal rule divider": "Insert horizontal rule divider", + "Page break": "Page break", + "Insert a page break for printing.": "Insert a page break for printing.", "Upload any image from your device.": "Upload any image from your device.", "Upload any video from your device.": "Upload any video from your device.", "Upload any audio from your device.": "Upload any audio from your device.", @@ -416,6 +432,7 @@ "{{latestVersion}} is available": "{{latestVersion}} is available", "Default page edit mode": "Default page edit mode", "Choose your preferred page edit mode. Avoid accidental edits.": "Choose your preferred page edit mode. Avoid accidental edits.", + "Choose {{format}} file": "Choose {{format}} file", "Reading": "Reading", "Delete member": "Delete member", "Member deleted successfully": "Member deleted successfully", @@ -565,6 +582,8 @@ "Move to trash": "Move to trash", "Move this page to trash?": "Move this page to trash?", "Restore page": "Restore page", + "Permanently delete": "Permanently delete", + "{{name}} moved this page to Trash {{time}}.": "{{name}} moved this page to Trash {{time}}.", "Page moved to trash": "Page moved to trash", "Page restored successfully": "Page restored successfully", "Deleted by": "Deleted by", @@ -608,25 +627,21 @@ "Image exceeds 10MB limit.": "Image exceeds 10MB limit.", "Image removed successfully": "Image removed successfully", "API key": "API key", - "API key created successfully": "API key created successfully", "API keys": "API keys", "API management": "API management", - "Are you sure you want to revoke this API key": "Are you sure you want to revoke this API key", - "Create API Key": "Create API Key", "Custom expiration date": "Custom expiration date", "Enter a descriptive token name": "Enter a descriptive token name", "Expiration": "Expiration", "Expired": "Expired", "Expires": "Expires", - "I've saved my API key": "I've saved my API key", "Last use": "Last Used", "No API keys found": "No API keys found", "No expiration": "No expiration", - "Revoke API key": "Revoke API key", "Revoked successfully": "Revoked successfully", "Select expiration date": "Select expiration date", "This action cannot be undone. Any applications using this API key will stop working.": "This action cannot be undone. Any applications using this API key will stop working.", - "Update API key": "Update API key", + "Update": "Update", + "Update {{credential}}": "Update {{credential}}", "Manage API keys for all users in the workspace": "Manage API keys for all users in the workspace", "Restrict API key creation to admins": "Restrict API key creation to admins", "Only admins and owners can create new API keys. Existing member keys will continue to work.": "Only admins and owners can create new API keys. Existing member keys will continue to work.", @@ -873,6 +888,12 @@ "Previous 7 days": "Previous 7 days", "Previous 30 days": "Previous 30 days", "Search chats...": "Search chats...", + "Search chats": "Search chats", + "Ask anything... Use @ to mention pages": "Ask anything... Use @ to mention pages", + "Ask anything or search your workspace": "Ask anything or search your workspace", + "Welcome to {{name}}": "Welcome to {{name}}", + "Add files": "Add files", + "Mention a page": "Mention a page", "Start a new chat to see it here.": "Start a new chat to see it here.", "Summarize this page": "Summarize this page", "Toggle AI Chat": "Toggle AI Chat", @@ -880,5 +901,122 @@ "Try a different search term.": "Try a different search term.", "Try again": "Try again", "Untitled chat": "Untitled chat", - "What can I help you with?": "What can I help you with?" + "What can I help you with?": "What can I help you with?", + "Are you sure you want to revoke this {{credential}}": "Are you sure you want to revoke this {{credential}}", + "Automatically provision users and groups from your identity provider via SCIM.": "Automatically provision users and groups from your identity provider via SCIM.", + "Configure your identity provider with this URL to provision users and groups.": "Configure your identity provider with this URL to provision users and groups.", + "Create {{credential}}": "Create {{credential}}", + "{{credential}} created": "{{credential}} created", + "{{credential}} created successfully": "{{credential}} created successfully", + "Created by": "Created by", + "Custom": "Custom", + "Enable SCIM": "Enable SCIM", + "Enter a descriptive name": "Enter a descriptive name", + "I've saved my {{credential}}": "I've saved my {{credential}}", + "Important": "Important", + "Make sure to copy your {{credential}} now. You won't be able to see it again!": "Make sure to copy your {{credential}} now. You won't be able to see it again!", + "Never": "Never", + "Revoke {{credential}}": "Revoke {{credential}}", + "SCIM endpoint URL": "SCIM endpoint URL", + "SCIM provisioning": "SCIM provisioning", + "SCIM takes precedence over SSO group sync while enabled.": "SCIM takes precedence over SSO group sync while enabled.", + "You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.": "You have reached the maximum of {{max}} SCIM tokens. Delete an existing token to create a new one.", + "SCIM token": "SCIM token", + "SCIM tokens": "SCIM tokens", + "This action cannot be undone. Your identity provider will stop syncing immediately.": "This action cannot be undone. Your identity provider will stop syncing immediately.", + "Toggle SCIM provisioning": "Toggle SCIM provisioning", + "Token": "Token", + "Page menu": "Page menu", + "Expand": "Expand", + "Collapse": "Collapse", + "Comment menu": "Comment menu", + "Group menu": "Group menu", + "Show hidden breadcrumbs": "Show hidden breadcrumbs", + "Breadcrumbs": "Breadcrumbs", + "Page actions": "Page actions", + "Pick emoji": "Pick emoji", + "Template menu": "Template menu", + "Chat menu": "Chat menu", + "API key menu": "API key menu", + "Jump to comment selection": "Jump to comment selection", + "Slash commands": "Slash commands", + "Mention suggestions": "Mention suggestions", + "Link suggestions": "Link suggestions", + "Diagram editor": "Diagram editor", + "Add comment": "Add comment", + "Find and replace": "Find and replace", + "Main navigation": "Main navigation", + "Space navigation": "Space navigation", + "Settings navigation": "Settings navigation", + "AI navigation": "AI navigation", + "Breadcrumb": "Breadcrumb", + "Synced block": "Synced block", + "Create a block that stays in sync across pages.": "Create a block that stays in sync across pages.", + "Editing original": "Editing original", + "Copy synced block": "Copy synced block", + "Unsync": "Unsync", + "Delete synced block": "Delete synced block", + "Synced to {{count}} other page_one": "Synced to {{count}} other page", + "Synced to {{count}} other page_other": "Synced to {{count}} other pages", + "ORIGINAL": "ORIGINAL", + "THIS PAGE": "THIS PAGE", + "No pages": "No pages", + "The original synced block no longer exists": "The original synced block no longer exists", + "You don't have access to this synced block": "You don't have access to this synced block", + "Failed to load this synced block": "Failed to load this synced block", + "Fixed editor toolbar": "Fixed editor toolbar", + "Show a formatting toolbar above the editor with quick access to common actions.": "Show a formatting toolbar above the editor with quick access to common actions.", + "Toggle fixed editor toolbar": "Toggle fixed editor toolbar", + "Normal text": "Normal text", + "More inline formatting": "More inline formatting", + "Subscript": "Subscript", + "Superscript": "Superscript", + "Inline code": "Inline code", + "Insert media": "Insert media", + "Mention": "Mention", + "Emoji": "Emoji", + "Columns": "Columns", + "More inserts": "More inserts", + "Embeds": "Embeds", + "Diagrams": "Diagrams", + "Advanced": "Advanced", + "Utility": "Utility", + "Decrease indent": "Decrease indent", + "Increase indent": "Increase indent", + "Clear formatting": "Clear formatting", + "Code block": "Code block", + "Experimental": "Experimental", + "Strikethrough": "Strikethrough", + "Undo": "Undo", + "Redo": "Redo", + "Backlinks": "Backlinks", + "Last updated by": "Last updated by", + "Last updated": "Last updated", + "Stats": "Stats", + "Word count": "Word count", + "Characters": "Characters", + "Incoming links": "Incoming links", + "Outgoing links": "Outgoing links", + "Incoming links ({{count}})": "Incoming links ({{count}})", + "Outgoing links ({{count}})": "Outgoing links ({{count}})", + "No pages link here yet.": "No pages link here yet.", + "This page doesn't link to other pages yet.": "This page doesn't link to other pages yet.", + "Verified until {{date}}": "Verified until {{date}}", + "Labels": "Labels", + "Add label": "Add label", + "No labels yet": "No labels yet", + "Already added": "Already added", + "Invalid label name": "Invalid label name", + "No matches": "No matches", + "Search or create…": "Search or create…", + "Remove label {{name}}": "Remove label {{name}}", + "Failed to add label": "Failed to add label", + "Failed to remove label": "Failed to remove label", + "No pages with this label": "No pages with this label", + "Pages tagged with this label will appear here.": "Pages tagged with this label will appear here.", + "No pages match your search.": "No pages match your search.", + "Updated {{date}}": "Updated {{date}}", + "Cell actions": "Cell actions", + "Column actions": "Column actions", + "Row actions": "Row actions" } diff --git a/apps/client/src/App.tsx b/apps/client/src/App.tsx index e5fae1bed..1fa669c17 100644 --- a/apps/client/src/App.tsx +++ b/apps/client/src/App.tsx @@ -45,6 +45,7 @@ import TemplateEditor from "@/ee/template/pages/template-editor"; import FavoritesPage from "@/pages/favorites/favorites-page"; import AiChat from "@/ee/ai-chat/pages/ai-chat.tsx"; import VerifyEmail from "@/ee/pages/verify-email.tsx"; +import LabelPage from "@/pages/label/label-page"; import ConfluenceImportPage from "@/ee/confluence-import/pages/confluence-import.tsx"; export default function App() { @@ -93,6 +94,7 @@ export default function App() { } /> } /> } /> + } /> } /> { if (disabled) return; @@ -104,6 +110,8 @@ export default function AvatarUploader({ ref={fileInputRef} onChange={handleFileInputChange} accept="image/png,image/jpeg,image/jpg" + aria-label={ariaLabel} + tabIndex={-1} style={{ display: "none" }} /> @@ -115,6 +123,8 @@ export default function AvatarUploader({ size={size} avatarUrl={currentImageUrl} name={fallbackName} + aria-label={ariaLabel} + aria-haspopup="menu" style={{ cursor: disabled || isLoading ? "default" : "pointer", opacity: isLoading ? 0.6 : 1, diff --git a/apps/client/src/components/common/copy.tsx b/apps/client/src/components/common/copy.tsx index 745fc4ba6..2144417b9 100644 --- a/apps/client/src/components/common/copy.tsx +++ b/apps/client/src/components/common/copy.tsx @@ -25,6 +25,7 @@ export default function CopyTextButton({ text, size }: CopyProps) { variant="subtle" onClick={copy} size={size} + aria-label={copied ? t("Copied") : t("Copy")} > {copied ? : } diff --git a/apps/client/src/components/common/recent-changes.tsx b/apps/client/src/components/common/recent-changes.tsx index 277ceb811..8e0e56f29 100644 --- a/apps/client/src/components/common/recent-changes.tsx +++ b/apps/client/src/components/common/recent-changes.tsx @@ -4,7 +4,7 @@ import { UnstyledButton, Badge, Table, - ActionIcon, + ThemeIcon, Button, } from "@mantine/core"; import { Link } from "react-router-dom"; @@ -49,9 +49,9 @@ export default function RecentChanges({ spaceId }: Props) { > {page.icon || ( - + - + )} diff --git a/apps/client/src/components/common/search-input.tsx b/apps/client/src/components/common/search-input.tsx index 08cbbee06..27e50fd4e 100644 --- a/apps/client/src/components/common/search-input.tsx +++ b/apps/client/src/components/common/search-input.tsx @@ -6,12 +6,14 @@ import { useTranslation } from "react-i18next"; export interface SearchInputProps { placeholder?: string; + ariaLabel?: string; debounceDelay?: number; onSearch: (value: string) => void; } export function SearchInput({ placeholder, + ariaLabel, debounceDelay = 500, onSearch, }: SearchInputProps) { @@ -28,6 +30,7 @@ export function SearchInput({ } value={value} onChange={(e) => setValue(e.currentTarget.value)} diff --git a/apps/client/src/components/icons/icon-people-circle.tsx b/apps/client/src/components/icons/icon-people-circle.tsx index 996958965..1a2daf73d 100644 --- a/apps/client/src/components/icons/icon-people-circle.tsx +++ b/apps/client/src/components/icons/icon-people-circle.tsx @@ -1,11 +1,11 @@ -import { ActionIcon, rem } from "@mantine/core"; +import { ThemeIcon } from "@mantine/core"; import React from "react"; import { IconUsersGroup } from "@tabler/icons-react"; export function IconGroupCircle() { return ( - + - + ); } diff --git a/apps/client/src/components/layouts/global/app-shell.module.css b/apps/client/src/components/layouts/global/app-shell.module.css index ed369612c..dd3b72e45 100644 --- a/apps/client/src/components/layouts/global/app-shell.module.css +++ b/apps/client/src/components/layouts/global/app-shell.module.css @@ -27,5 +27,3 @@ background: light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-5)) } } - - diff --git a/apps/client/src/components/layouts/global/aside.tsx b/apps/client/src/components/layouts/global/aside.tsx index 4f2cf5927..23ebe7b7c 100644 --- a/apps/client/src/components/layouts/global/aside.tsx +++ b/apps/client/src/components/layouts/global/aside.tsx @@ -1,4 +1,5 @@ -import { Box, ScrollArea, Text } from "@mantine/core"; +import { ActionIcon, Box, Group, ScrollArea, Text, Tooltip } from "@mantine/core"; +import { IconX } from "@tabler/icons-react"; import CommentListWithTabs from "@/features/comment/components/comment-list-with-tabs.tsx"; import { useAtom } from "jotai"; import { asideStateAtom } from "@/components/layouts/global/hooks/atoms/sidebar-atom.ts"; @@ -8,11 +9,13 @@ import { TableOfContents } from "@/features/editor/components/table-of-contents/ import { useAtomValue } from "jotai"; import { pageEditorAtom } from "@/features/editor/atoms/editor-atoms.ts"; import AsideChatPanel from "@/ee/ai-chat/components/aside-chat-panel"; +import { PageDetailsAside } from "@/features/page-details/components/page-details-aside.tsx"; export default function Aside() { - const [{ tab }] = useAtom(asideStateAtom); + const [{ tab }, setAsideState] = useAtom(asideStateAtom); const { t } = useTranslation(); const pageEditor = useAtomValue(pageEditorAtom); + const closeAside = () => setAsideState((s) => ({ ...s, isAsideOpen: false })); let title: string; let component: ReactNode; @@ -30,6 +33,10 @@ export default function Aside() { component = ; title = "AI Chat"; break; + case "details": + component = ; + title = "Details"; + break; default: component = null; title = null; @@ -40,9 +47,19 @@ export default function Aside() { {component && ( <> {tab !== "chat" && ( - - {t(title)} - + + {t(title)} + + + + + + )} {tab === "comments" || tab === "chat" ? ( diff --git a/apps/client/src/components/layouts/global/global-app-shell.tsx b/apps/client/src/components/layouts/global/global-app-shell.tsx index 64bd3dde7..4c56fe076 100644 --- a/apps/client/src/components/layouts/global/global-app-shell.tsx +++ b/apps/client/src/components/layouts/global/global-app-shell.tsx @@ -1,6 +1,7 @@ import { AppShell, Container } from "@mantine/core"; import React, { useEffect, useRef, useState } from "react"; import { useLocation } from "react-router-dom"; +import { useTranslation } from "react-i18next"; import SettingsSidebar from "@/components/settings/settings-sidebar.tsx"; import { useAtom } from "jotai"; import { @@ -23,11 +24,12 @@ export default function GlobalAppShell({ }: { children: React.ReactNode; }) { + const { t } = useTranslation(); useTrialEndAction(); const [mobileOpened] = useAtom(mobileSidebarAtom); const toggleMobile = useToggleSidebar(mobileSidebarAtom); const [desktopOpened] = useAtom(desktopSidebarAtom); - const [{ isAsideOpen }] = useAtom(asideStateAtom); + const [{ isAsideOpen, tab: asideTab }] = useAtom(asideStateAtom); const [sidebarWidth, setSidebarWidth] = useAtom(sidebarWidthAtom); const [isResizing, setIsResizing] = useState(false); const sidebarRef = useRef(null); @@ -105,6 +107,15 @@ export default function GlobalAppShell({ className={classes.navbar} withBorder={false} ref={sidebarRef} + aria-label={ + isSpaceRoute + ? t("Space navigation") + : isSettingsRoute + ? t("Settings navigation") + : isAiRoute + ? t("AI navigation") + : t("Main navigation") + } > {isSpaceRoute && (
@@ -114,16 +125,33 @@ export default function GlobalAppShell({ {isAiRoute && } {showGlobalSidebar && } - + {isSettingsRoute ? ( - {children} + + {children} + ) : ( children )} {isPageRoute && ( - +