From 91eb4fe5a032cd98eb3d2beb8df66aed41f9c4c1 Mon Sep 17 00:00:00 2001 From: Jean Brito Date: Tue, 26 May 2026 10:34:27 -0300 Subject: [PATCH 1/7] chore(settings): polish view layout, IA, and code hygiene Align SettingsView with the desktop design system (DESIGN.md): - Group GeneralTab's 19 features into 5 sections (Notifications, Performance, Calls & video, Window & appearance, Integrations) via a reusable Section helper, mirroring the DeveloperTab "Logging" header pattern. - Title row uses fontScale h2 (24/32) with alignItems=center and an mie={8} gap to the back IconButton. Step down from h1 matches the shell-quiet hierarchy in DESIGN.md. - Title block uses pi/pbs/pbe spacing so the Tabs sit close to the title typographically. Tabs wrap in so they align with the content gutter instead of running edge-to-edge. - Scrollable inner switches from m='x24' to pi/pbs/pbe (padding, not margin, inside a scroll container). - Esc key dismisses the SettingsView for keyboard users, with tabIndex={-1} on the visible root so it can capture key events. Back IconButton gains an aria-label. - TelephonyServer drops a raw style={{ paddingTop: '4px' }} in favor of paddingBlockStart='x4', matching the sibling ThemeAppearance feature. - ClearPermittedScreenCaptureServers loses a leftover console.log from its onClick handler. - en.i18n.json gains settings.back and the five new settings.sections.* keys. --- src/i18n/en.i18n.json | 6 ++ src/ui/components/SettingsView/GeneralTab.tsx | 77 ++++++++++++++----- .../components/SettingsView/SettingsView.tsx | 76 +++++++++++------- .../ClearPermittedScreenCaptureServers.tsx | 1 - .../SettingsView/features/TelephonyServer.tsx | 2 +- 5 files changed, 113 insertions(+), 49 deletions(-) diff --git a/src/i18n/en.i18n.json b/src/i18n/en.i18n.json index 3ec2400305..d18f20fc05 100644 --- a/src/i18n/en.i18n.json +++ b/src/i18n/en.i18n.json @@ -234,10 +234,16 @@ }, "settings": { "title": "Settings", + "back": "Back", "general": "General", "certificates": "Certificates", "developer": "Developer", "sections": { + "notifications": "Notifications", + "performance": "Performance", + "callsAndVideo": "Calls & video", + "windowAndAppearance": "Window & appearance", + "integrations": "Integrations", "logging": "Logging" }, "options": { diff --git a/src/ui/components/SettingsView/GeneralTab.tsx b/src/ui/components/SettingsView/GeneralTab.tsx index 3c1d6b9199..d823c029e4 100644 --- a/src/ui/components/SettingsView/GeneralTab.tsx +++ b/src/ui/components/SettingsView/GeneralTab.tsx @@ -1,4 +1,6 @@ import { Box, FieldGroup } from '@rocket.chat/fuselage'; +import type { ReactNode } from 'react'; +import { useTranslation } from 'react-i18next'; import { AvailableBrowsers } from './features/AvailableBrowsers'; import { ClearPermittedScreenCaptureServers } from './features/ClearPermittedScreenCaptureServers'; @@ -18,26 +20,59 @@ import { TransparentWindow } from './features/TransparentWindow'; import { TrayIcon } from './features/TrayIcon'; import { VideoCallWindowPersistence } from './features/VideoCallWindowPersistence'; -export const GeneralTab = () => ( - - - - - - {process.platform === 'win32' && } - - - {process.platform === 'darwin' && } - - {process.platform === 'win32' && } - - {process.platform !== 'darwin' && } - {process.platform === 'win32' && } - - - - - {!process.mas && } - +type SectionProps = { + title: string; + isFirst?: boolean; + children: ReactNode; +}; + +const Section = ({ title, isFirst, children }: SectionProps) => ( + + + {title} + + {children} ); + +export const GeneralTab = () => { + const { t } = useTranslation(); + + return ( + + +
+ + +
+ +
+ + {process.platform === 'win32' && } +
+ +
+ + + + {!process.mas && } +
+ +
+ {process.platform === 'darwin' && } + + {process.platform === 'win32' && } + + {process.platform !== 'darwin' && } + +
+ +
+ {process.platform === 'win32' && } + + +
+
+
+ ); +}; diff --git a/src/ui/components/SettingsView/SettingsView.tsx b/src/ui/components/SettingsView/SettingsView.tsx index e5ccce02d3..9e6d43e2af 100644 --- a/src/ui/components/SettingsView/SettingsView.tsx +++ b/src/ui/components/SettingsView/SettingsView.tsx @@ -1,6 +1,7 @@ import { Box, IconButton, Scrollable, Tabs } from '@rocket.chat/fuselage'; import '@rocket.chat/fuselage-polyfills'; -import { useEffect, useState } from 'react'; +import type { KeyboardEvent } from 'react'; +import { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; @@ -37,12 +38,22 @@ export const SettingsView = () => { } }, [isDeveloperModeEnabled, currentTab]); - const handleBackButton = function (): void { + const handleBackButton = useCallback((): void => { dispatch({ type: DOWNLOADS_BACK_BUTTON_CLICKED, payload: lastSelectedServerUrl, }); - }; + }, [lastSelectedServerUrl]); + + const handleKeyDown = useCallback( + (event: KeyboardEvent) => { + if (event.key === 'Escape') { + handleBackButton(); + } + }, + [handleBackButton] + ); + return ( { width='full' className='rcx-sidebar--main' bg='room' + onKeyDown={handleKeyDown} + tabIndex={isVisible ? -1 : undefined} > {!isSideBarEnabled && ( - + + + )} {t('settings.title')} - - setCurrentTab('general')} - > - {t('settings.general')} - - setCurrentTab('certificates')} - > - {t('settings.certificates')} - - {isDeveloperModeEnabled && ( + + setCurrentTab('developer')} + selected={currentTab === 'general'} + onClick={() => setCurrentTab('general')} > - {t('settings.developer')} + {t('settings.general')} - )} - + setCurrentTab('certificates')} + > + {t('settings.certificates')} + + {isDeveloperModeEnabled && ( + setCurrentTab('developer')} + > + {t('settings.developer')} + + )} + + - + {(currentTab === 'general' && ) || (currentTab === 'certificates' && ) || (currentTab === 'developer' && )} diff --git a/src/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsx b/src/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsx index 04e2014745..bb8a3a15c5 100644 --- a/src/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsx +++ b/src/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsx @@ -19,7 +19,6 @@ export const ClearPermittedScreenCaptureServers = (