chore: Polish Settings, Certificates, and Downloads views against Fuselage#3344
chore: Polish Settings, Certificates, and Downloads views against Fuselage#3344jeanfbrito wants to merge 7 commits into
Conversation
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 <Box pi={24}> 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.
Align the Certificates tab with the rest of the SettingsView
redesign and fix the stacked-sticky-header bug.
- Extract a CertificateSection helper that renders an h4 title,
a c1 hint paragraph, and either an empty-state message or the
table. Matches the section pattern in GeneralTab / DeveloperTab.
- Drop the bogus <Box is='form'> wrapper (there is no form here)
and the outer padding={24}, which doubled the SettingsView
outer pi={24}. Replace marginBlockStart={50} between sections
with mbs={32} (on the Fuselage 4-multiple scale).
- Drop the Table sticky prop: two stacked sticky-headed tables
share one Scrollable, so the first header would stick over the
second table's rows mid-scroll. Headers now flow with content.
- Add empty-state copy for both tables ("No trusted certificates
yet." / "No certificates have been flagged.") and hint copy
explaining what each section means.
- CertificateItem drops the decorative key icon and wraps the
URL in <Box withTruncatedText title={url}> so long URLs
ellipsize instead of overflowing the column.
- ActionButton replaces <a href='#'> with Fuselage <Button small
danger>: correct semantics and a11y role for a destructive
action, no scroll-jump on click.
Bring DownloadsManagerView in line with the SettingsView redesign
and give the Downloads and Certificates lists a shared
row-affordance pattern (hairline divider + hover tint), so users
can tell which row they are about to click.
DownloadsManagerView:
- Title fontScale steps from h1 to h2 with pi/pbs/pbe rhythm
matching SettingsView. bg switches from 'light' to 'room' so
the Downloads surface obeys PaletteStyleTag theme preference
the same way Settings does.
- Filter row trims its 64px outer gutter to pi={24} and replaces
paddingInline={2} per child with mie={8}, so the four controls
sit on an even rhythm. The clear-filters affordance moves from
a destructive 'trash' icon to 'cross', gains an aria-label,
and disables itself when no filters are active.
- SelectLegacy is swapped for the current Fuselage Select used
elsewhere in the app.
- Empty-state copy: a first-run "No downloads yet" message and
a "No downloads match these filters" + Clear-filters button
when active filters exclude every row.
- Esc dismisses the view; the back IconButton gains an
aria-label. handleBackButton moves to useCallback to match
the rest of the codebase.
DownloadItem:
- Fixed literal widths (388 / 344 / 32 / mbe=26) and arbitrary
pixel values get replaced with flex + minWidth/maxWidth +
4-multiple spacing so the row reflows on narrower windows.
- Semantic color tokens replace the raw palette refs
(font-default, font-danger, font-secondary-info).
- The per-row action list moves into a Fuselage ButtonGroup.
Destructive actions (Cancel, Remove) use the danger variant
so the hierarchy reads at a glance.
- The progress bar hides for completed downloads (a full bar
at 100% conveys nothing on a finished item).
- Each row carries a 1px stroke-extra-light top border (skipped
on :first-of-type) and a hovered surface-hover background via
@rocket.chat/css-in-js. Padding shifts from mbe={24} to
symmetric pbs/pbe/pi so the hover highlight reaches edge to
edge.
ActionButton (Downloads):
- The <a href='#'> anchor is replaced with a Fuselage <Button
small secondary>: correct semantics, no scroll-jump, and the
small/secondary pairing reads quietly inside a dense row.
CertificatesManager + CertificateItem:
- The cert table drops the striped prop; on the dark settings
surface the stripe broke the tonal-step rule. TableRow gains
the action prop so Fuselage's built-in --action:hover lights
up the row, matching the Downloads cue.
i18n:
- Adds downloads.back and the four downloads.empty.* keys.
- Renames "Show in Folder" to "Show in folder" (Sentence Case
Rule).
Strategic and visual design context for /impeccable workflows. DESIGN.md is the Stitch six-section spec with tokens verified against the live Fuselage source (packages/fuselage-tokens and PaletteStyleTag), not against the hardcoded fallbacks scattered across src/ui. Key facts the spec captures: - Three themes ship: light, dark, and high-contrast. The shell must verify every color choice in all three. PRODUCT.md mandates WCAG 2.2 AA plus government and healthcare extras, so high-contrast is not optional. - Tokens are emitted by PaletteStyleTag as --rcx-color-<category>-<role>, never as palette-grade vars like --rcx-color-primary-500. The TS palette pipeline maps primary -> b, danger -> r, success -> g, warning -> y, neutral -> n; palette-grade vars exist only as SCSS fallbacks. - Primary button background is --rcx-color-button-background- primary-default (colors.b500 = #1d74f5), distinct from --rcx-color-status-background-info (light tint #d1ebfe). - Mention count badge is Badge variant='secondary', badge-background-level-1 = colors.n700 = #6c737a. Gray, not red. The badge is a count, not an alarm. - surface-room is theme-following (white in light, #1F2329 in dark). The hardcoded #2f343d in Shell/styles.tsx and SideBar/styles.tsx is a pre-PaletteStyleTag-hydration backstop only; do not treat it as a token. The sidecar at .impeccable/design.json carries tonal ramps per color, dark-theme hex values, shadow and motion tokens, and self-contained HTML/CSS snippets for the impeccable live panel. Components covered: Server Button (selected), Mention Badge, Warning Badge, Primary Button, Danger Button, Dialog, Sidebar Rail, and the shared List Row affordance (hairline divider + hover tint) used by both Downloads and Certificates.
DESIGN.md mandates that color tokens be read through their full
semantic name (font-default, font-hint, font-annotation,
font-secondary-info), never via short aliases (default, hint,
annotation) and never via palette-grade vars (neutral-600).
This commit clears every drift in src/ui.
- color='default' -> color='font-default' across SettingsView,
DownloadsManagerView, TopBar, ServersView (MarkdownContent,
DocumentViewer, PdfContent).
- color='hint' -> color='font-hint' across CertificatesManager
and ServerInfoContent (11 sites).
- color='annotation' -> color='font-annotation' across
CertificatesManager and ServerInfoContent.
- FileIcon's color='neutral-600' (banned palette-grade ref)
becomes color='font-secondary-info'.
- AvailableBrowsers and OutlookCalendarSyncInterval drop their
raw style={{ paddingTop: '4px' }} inline CSS in favor of the
Fuselage paddingBlockStart='x4' shorthand, matching
TelephonyServer and ThemeAppearance.
- Shell/styles.tsx replaces body font-family: system-ui with the
Inter-first stack documented in DESIGN.md.
DESIGN.md gains a Pre-Hydration Exception rule clarifying that
src/public/loading.css and error.css intentionally keep
system-ui and the hardcoded #2f343d background because they
render before React mounts and before PaletteStyleTag emits any
--rcx-color-* variable.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
🔇 Additional comments (1)
WalkthroughAdds a machine-readable design system and docs; migrates many UI components to semantic design tokens; refactors certificates, downloads, and settings UIs for composition, spacing, and keyboard accessibility; and updates related i18n strings. ChangesDesign System Adoption & Component Refactoring
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Theming note + verificationTheme handling is owned by Fuselage, not this shell. The desktop app consumes Verified:
So the earlier "verify all three themes" item is resolved: theme correctness flows from Fuselage, and the shell consumes it cleanly. |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (1)
.impeccable/design.json (1)
3-3: 💤 Low valueConsider using actual generation timestamp.
The
generatedAttimestamp is set to exactly midnight (00:00:00Z), which appears hardcoded. For a machine-readable design configuration, an actual generation timestamp would be more useful for tracking updates and version control.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.impeccable/design.json at line 3, The "generatedAt" value is hardcoded to "2026-05-26T00:00:00Z"; update the generator so the "generatedAt" field (key "generatedAt" in .impeccable/design.json) is populated at runtime with the actual ISO 8601 UTC timestamp (e.g., new Date().toISOString()) when the design.json is produced; ensure any code that writes this file uses that dynamic timestamp and that tests/fixtures are adjusted to allow or mock the generatedAt value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/ui/components/CertificatesManager/CertificatesManager.tsx`:
- Around line 69-75: The file currently declares multiple React components
(CertificateSection and CertificatesManagerWrapper) which triggers the
react/no-multi-comp lint rule; extract those two child components into their own
component modules (e.g., CertificateSection.tsx and
CertificatesManagerWrapper.tsx) keeping their prop types
(CertificateSectionProps, CertificatesManagerWrapperProps) and any used
MUI/utility imports, export them (named or default), then import them back into
CertificatesManager.tsx and use them so CertificatesManager.tsx contains only
the single top-level component declaration (CertificatesManager). Ensure props
and any handlers passed from CertificatesManager are preserved and update
imports/exports accordingly.
In `@src/ui/components/DownloadsManagerView/DownloadItem.tsx`:
- Around line 15-16: The Prettier formatting errors in DownloadItem.tsx are
caused by unformatted CSS template literals and a JSX prop block; run the
project's Prettier formatter or manually reformat the CSS template (the block
starting with "border-block-start: 1px solid var(--rcx-color-stroke-extra-light,
transparent);") and the JSX props inside the DownloadItem component so they
match the project's Prettier rules (consistent indentation, line breaks, and
trailing commas where configured). Locate the DownloadItem component and its
styled/template CSS and adjust whitespace and line breaks to match Prettier
output (or run npm/yarn prettier --write on the file) to resolve the
eslint/prettier violations.
In `@src/ui/components/DownloadsManagerView/index.tsx`:
- Around line 238-243: Prettier is failing on the JSX prop formatting for the
filter-row Box elements; run the project's Prettier formatter (or your editor's
auto-format) and fix the prop blocks in the DownloadsManagerView component so
they match the repo's Prettier rules (e.g., format the Box props at lines with
"display='flex' alignItems='center' pi={24} pbe={16}" and the other Box blocks
at the mentioned ranges), ensuring consistent line breaks/spacing to satisfy
prettier/prettier checks; specifically reformat the JSX prop lists for the Box
elements in index.tsx so CI no longer flags them.
In `@src/ui/components/ServerInfoContent.tsx`:
- Line 348: The JSX props on the Box element in ServerInfoContent.tsx are all on
one long line; split them across multiple lines to satisfy the max line length
and improve readability—locate the Box usage (Box fontSize='x10'
color='font-annotation' style={textWrapStyle}) inside the ServerInfoContent
component and reformat so each prop (fontSize, color, style) is on its own line,
preserving the same prop names and values (including textWrapStyle) and keeping
the same surrounding JSX structure.
In `@src/ui/components/SettingsView/GeneralTab.tsx`:
- Around line 29-36: The file declares two React components (Section and
GeneralTab) which triggers react/no-multi-comp; replace the Section component
with a non-component helper renderer and update GeneralTab to call it instead:
remove the const Section = (...) JSX component and add a plain function (e.g.,
renderSection(title, isFirst, children)) that returns the same JSX, preserve
SectionProps typing for its parameters, then update every usage of <Section ...>
inside GeneralTab to call renderSection(title, isFirst, children); this keeps
the same output while avoiding a second component declaration in the file.
In `@src/ui/components/Shell/styles.tsx`:
- Around line 37-38: The font-family declaration in
src/ui/components/Shell/styles.tsx is formatted in a way that breaks Prettier
rules; locate the CSS rule containing the font-family declaration and reformat
it to satisfy Prettier (either collapse the font list into a single properly
quoted/comma-separated line or break into Prettier-friendly wrapped lines), then
run Prettier/ESLint to confirm the file passes formatting checks; ensure the
exact token "font-family" in the styles.tsx template literal or styled component
is updated and no trailing commas or stray spacing violate the formatter.
---
Nitpick comments:
In @.impeccable/design.json:
- Line 3: The "generatedAt" value is hardcoded to "2026-05-26T00:00:00Z"; update
the generator so the "generatedAt" field (key "generatedAt" in
.impeccable/design.json) is populated at runtime with the actual ISO 8601 UTC
timestamp (e.g., new Date().toISOString()) when the design.json is produced;
ensure any code that writes this file uses that dynamic timestamp and that
tests/fixtures are adjusted to allow or mock the generatedAt value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 6d4f5fc7-e08b-4c1d-8a76-fa187008c6d8
📒 Files selected for processing (23)
.impeccable/design.jsonDESIGN.mdPRODUCT.mdsrc/i18n/en.i18n.jsonsrc/ui/components/CertificatesManager/ActionButton.tsxsrc/ui/components/CertificatesManager/CertificateItem.tsxsrc/ui/components/CertificatesManager/CertificatesManager.tsxsrc/ui/components/DownloadsManagerView/ActionButton.tsxsrc/ui/components/DownloadsManagerView/DownloadItem.tsxsrc/ui/components/DownloadsManagerView/FileIcon.tsxsrc/ui/components/DownloadsManagerView/index.tsxsrc/ui/components/ServerInfoContent.tsxsrc/ui/components/ServersView/DocumentViewer.tsxsrc/ui/components/ServersView/MarkdownContent.tsxsrc/ui/components/ServersView/PdfContent.tsxsrc/ui/components/SettingsView/GeneralTab.tsxsrc/ui/components/SettingsView/SettingsView.tsxsrc/ui/components/SettingsView/features/AvailableBrowsers.tsxsrc/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsxsrc/ui/components/SettingsView/features/OutlookCalendarSyncInterval.tsxsrc/ui/components/SettingsView/features/TelephonyServer.tsxsrc/ui/components/Shell/styles.tsxsrc/ui/components/TopBar/index.tsx
💤 Files with no reviewable changes (1)
- src/ui/components/SettingsView/features/ClearPermittedScreenCaptureServers.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: check (windows-latest)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.{ts,tsx}: Use TypeScript for all new code in this codebase unless explicitly told otherwise
Use Fuselage components from@rocket.chat/fuselagefor all UI work — only create custom components when Fuselage doesn't provide the needed functionality
Check Theme.d.ts for valid color tokens when working with Fuselage components
Use optional chaining with fallbacks for platform-specific APIs instead of mocks (e.g., process.getuid?.() ?? 1000) to ensure code works across all platforms without requiring mocks
TypeScript code must use strict mode
Use React functional components with hooks instead of class components
Redux actions must follow the FSA (Flux Standard Action) pattern
Use camelCase for file naming
Use PascalCase for component file names (React components)
Write self-documenting code through clear naming — avoid unnecessary comments
Files:
src/ui/components/DownloadsManagerView/FileIcon.tsxsrc/ui/components/ServersView/DocumentViewer.tsxsrc/ui/components/Shell/styles.tsxsrc/ui/components/CertificatesManager/CertificateItem.tsxsrc/ui/components/DownloadsManagerView/ActionButton.tsxsrc/ui/components/CertificatesManager/ActionButton.tsxsrc/ui/components/SettingsView/features/AvailableBrowsers.tsxsrc/ui/components/ServersView/PdfContent.tsxsrc/ui/components/TopBar/index.tsxsrc/ui/components/SettingsView/features/TelephonyServer.tsxsrc/ui/components/SettingsView/features/OutlookCalendarSyncInterval.tsxsrc/ui/components/CertificatesManager/CertificatesManager.tsxsrc/ui/components/SettingsView/GeneralTab.tsxsrc/ui/components/SettingsView/SettingsView.tsxsrc/ui/components/ServersView/MarkdownContent.tsxsrc/ui/components/ServerInfoContent.tsxsrc/ui/components/DownloadsManagerView/index.tsxsrc/ui/components/DownloadsManagerView/DownloadItem.tsx
🪛 ast-grep (0.42.3)
src/ui/components/ServersView/MarkdownContent.tsx
[warning] 237-237: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html
(react-unsafe-html-injection)
🪛 ESLint
src/ui/components/Shell/styles.tsx
[error] 37-37: Replace ·Inter,·-apple-system,·BlinkMacSystemFont, with ⏎············Inter,⏎············-apple-system,⏎············BlinkMacSystemFont,⏎···········
(prettier/prettier)
[error] 38-38: Replace ·Oxygen,·Ubuntu,·Cantarell,·'Helvetica·Neue', with ⏎············Oxygen,⏎············Ubuntu,⏎············Cantarell,⏎············'Helvetica·Neue',⏎···········
(prettier/prettier)
src/ui/components/CertificatesManager/CertificatesManager.tsx
[error] 69-75: Declare only one React component per file
(react/no-multi-comp)
[error] 77-105: Declare only one React component per file
(react/no-multi-comp)
src/ui/components/SettingsView/GeneralTab.tsx
[error] 38-78: Declare only one React component per file
(react/no-multi-comp)
src/ui/components/ServerInfoContent.tsx
[error] 348-348: Replace ·fontSize='x10'·color='font-annotation'·style={textWrapStyle} with ⏎····················fontSize='x10'⏎····················color='font-annotation'⏎····················style={textWrapStyle}⏎··················
(prettier/prettier)
src/ui/components/DownloadsManagerView/index.tsx
[error] 238-243: Replace ⏎········display='flex'⏎········alignItems='center'⏎········pi={24}⏎········pbe={16}⏎······ with ·display='flex'·alignItems='center'·pi={24}·pbe={16}
(prettier/prettier)
[error] 244-250: Replace ⏎··········flexGrow={3}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x160'⏎··········mie={8}⏎········ with ·flexGrow={3}·flexShrink={1}·flexBasis={0}·minWidth='x160'·mie={8}
(prettier/prettier)
[error] 258-264: Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x140'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x140'·mie={8}
(prettier/prettier)
[error] 272-278: Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x120'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x120'·mie={8}
(prettier/prettier)
[error] 286-292: Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x120'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x120'·mie={8}
(prettier/prettier)
src/ui/components/DownloadsManagerView/DownloadItem.tsx
[error] 15-16: Delete ⏎···
(prettier/prettier)
[error] 208-212: Replace ⏎················color='font-secondary-info'⏎················fontScale='c1'⏎················withTruncatedText⏎·············· with ·color='font-secondary-info'·fontScale='c1'·withTruncatedText
(prettier/prettier)
🪛 GitHub Check: check (ubuntu-latest)
src/ui/components/CertificatesManager/CertificatesManager.tsx
[failure] 77-77:
Declare only one React component per file
[failure] 69-69:
Declare only one React component per file
src/ui/components/ServerInfoContent.tsx
[failure] 348-348:
Replace ·fontSize='x10'·color='font-annotation'·style={textWrapStyle} with ⏎····················fontSize='x10'⏎····················color='font-annotation'⏎····················style={textWrapStyle}⏎··················
src/ui/components/DownloadsManagerView/index.tsx
[failure] 286-286:
Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x120'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x120'·mie={8}
[failure] 272-272:
Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x120'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x120'·mie={8}
[failure] 258-258:
Replace ⏎··········flexGrow={2}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x140'⏎··········mie={8}⏎········ with ·flexGrow={2}·flexShrink={1}·flexBasis={0}·minWidth='x140'·mie={8}
[failure] 244-244:
Replace ⏎··········flexGrow={3}⏎··········flexShrink={1}⏎··········flexBasis={0}⏎··········minWidth='x160'⏎··········mie={8}⏎········ with ·flexGrow={3}·flexShrink={1}·flexBasis={0}·minWidth='x160'·mie={8}
[failure] 238-238:
Replace ⏎········display='flex'⏎········alignItems='center'⏎········pi={24}⏎········pbe={16}⏎······ with ·display='flex'·alignItems='center'·pi={24}·pbe={16}
src/ui/components/DownloadsManagerView/DownloadItem.tsx
[failure] 15-15:
Delete ⏎···
[failure] 208-208:
Replace ⏎················color='font-secondary-info'⏎················fontScale='c1'⏎················withTruncatedText⏎·············· with ·color='font-secondary-info'·fontScale='c1'·withTruncatedText
🪛 LanguageTool
DESIGN.md
[grammar] ~179-~179: Ensure spelling is correct
Context: ...ients, no decorative iconography in the titlebar, no busy toolbar). It is not generic Sa...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[style] ~179-~179: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...aphy in the titlebar, no busy toolbar). It is not generic SaaS marketing (no hero ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[grammar] ~185-~185: Use a hyphen to join words.
Context: ...rfaces step by exactly one tint. - Inter primary, system stack fallback (`-apple-...
(QB_NEW_EN_HYPHEN)
[style] ~400-~400: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...rning'` (orange) for not-logged-in. - Do verify every color choice in light, d...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~401-~401: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...h-contrast** themes before merging. - Do use sentence case in source strings; ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~402-~402: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...at the component layer when needed. - Do apply the shared row affordance (`<Ta...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~403-~403: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ox rows) to every new list surface. - Do use Fuselage Box withTruncatedText ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~404-~404: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... URLs, file names, and identifiers. - Do use pi/pbs/pbe Fuselage spacing sho...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~409-~409: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ... dark purple, no playful microcopy. - Don't revive old Skype or legacy Teams c...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~410-~410: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ecorative iconography in titlebars. - Don't use generic SaaS marketing pattern...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~411-~411: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ds, no gradient accents on numbers. - Don't pursue Linear-empty minimalism at ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~412-~412: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ism at the cost of sidebar density. - Don't use border-left or `border-right...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~413-~413: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...al 4-pixel server selection stripe. - Don't use background-clip: text gradie...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~414-~414: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...ckground-clip: text` gradient text. - Don't introduce glassmorphism as a styli...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~421-~421: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...* wrap shell content in card grids. - Don't use modals as the first thought fo...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~422-~422: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...as the first thought for new flows. - Don't rename, recolor, or re-style Fusel...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
[style] ~423-~423: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...Dropdown, IconButton` primitives. - Don't confuse Badge variants: unread is ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
PRODUCT.md
[grammar] ~36-~36: Ensure spelling is correct
Context: ...OS traffic lights and vibrancy, Windows titlebar buttons and Mica, Linux menubar fallbac...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
[grammar] ~36-~36: Ensure spelling is correct
Context: ...indows titlebar buttons and Mica, Linux menubar fallbacks. The desktop edge over the br...
(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)
🔇 Additional comments (19)
src/ui/components/CertificatesManager/ActionButton.tsx (1)
1-8: LGTM!src/ui/components/CertificatesManager/CertificateItem.tsx (1)
1-1: LGTM!Also applies to: 20-24
src/i18n/en.i18n.json (1)
185-191: LGTM!Also applies to: 228-228, 235-241, 250-250, 255-259
src/ui/components/DownloadsManagerView/ActionButton.tsx (1)
1-8: LGTM!src/ui/components/DownloadsManagerView/FileIcon.tsx (1)
29-29: LGTM!src/ui/components/SettingsView/SettingsView.tsx (1)
41-55: LGTM!Also applies to: 58-124
src/ui/components/SettingsView/features/AvailableBrowsers.tsx (1)
87-87: LGTM!src/ui/components/SettingsView/features/OutlookCalendarSyncInterval.tsx (1)
62-62: LGTM!src/ui/components/SettingsView/features/TelephonyServer.tsx (1)
66-66: LGTM!.impeccable/design.json (1)
4-324: LGTM!DESIGN.md (1)
1-427: LGTM!PRODUCT.md (1)
1-53: LGTM!src/ui/components/ServerInfoContent.tsx (2)
127-150: LGTM!
184-303: LGTM!src/ui/components/ServersView/DocumentViewer.tsx (1)
35-35: LGTM!src/ui/components/ServersView/MarkdownContent.tsx (1)
208-237: LGTM!src/ui/components/ServersView/PdfContent.tsx (1)
81-81: LGTM!src/ui/components/TopBar/index.tsx (1)
28-28: LGTM!src/ui/components/Shell/styles.tsx (1)
37-38: ⚡ Quick winVerify that the Inter font is actually loaded (font scan didn’t complete)
font-familynow prioritizesInter, but the suggested verification run didn’t successfully execute its searches (ripgrep reportedunrecognized file type: tsx), so it doesn’t establish whether@font-face, Inter-related CSS imports, or Fuselage-provided font styles/woff2 assets exist. Re-run the check using-g '*.ts' -g '*.tsx' -g '*.css' -g '*.scss'globs (instead of--type=tsx) and confirm there are@font-face/Inter imports or woff2/font asset references from the app entrypoints/Fuselage styles.
CodeRabbit/CI flagged two lint rules on the polish branch: - react/no-multi-comp: GeneralTab.tsx and CertificatesManager.tsx each declared more than one React component. Extract the helpers into their own files (SettingsView/Section.tsx, CertificatesManager/CertificateSection.tsx) and inline the trivial wrapper Box, so each file declares a single component. - prettier/prettier: re-ran the formatter over the CSS template literal in DownloadItem.tsx and the JSX prop blocks in DownloadsManagerView/index.tsx, ServerInfoContent.tsx, and Shell/styles.tsx. No behavior, token, or copy changes. yarn lint and tsc --noEmit both clean.
electron-builder 26.0.3 rejects MimeType as a direct property of
linux.desktop ("unknown property 'MimeType'"), failing the Linux
build step in CI. MimeType is a desktop-entry key, so it belongs
inside linux.desktop.entry alongside Name, Comment, GenericName,
and Categories. The scheme handlers (rocketchat, callto, tel) are
preserved verbatim.
Summary
Polishes the three full-window panels in the desktop shell (Settings, Certificates, Downloads) so they line up with the Fuselage design system, and captures the design direction in committed
PRODUCT.md/DESIGN.mdcontext files.The visual contract in
DESIGN.mdwas built from the live Fuselage token source (@rocket.chat/fuselage-tokens+PaletteStyleTag), not from the hardcoded fallbacks scattered through the app, so the documented values match what the runtime actually emits across the light, dark, and high-contrast themes.What changed
Settings
Sectionhelper, mirroring the existing DeveloperTab pattern.h1toh2with tightened title-to-tabs spacing; Tabs share the content gutter; Scrollable inner uses padding instead of margin. Esc dismisses the view; back IconButton gains anaria-label.Certificates
CertificateSectionwith anh4title, a hint line, and an empty state. Dropped a stray<Box is='form'>, doubled padding, an off-scalemarginBlockStart, andTable sticky(two stacked sticky headers shared one scroll container).<TableRow action>provides the hover affordance;stripedremoved.Downloads
h2;bg='light'tobg='room'for theme parity with Settings; filter row trimmed to an even gutter;SelectLegacyswapped for the currentSelect; clear-filters icon corrected fromtrashtocrosswith anaria-labeland a disabled state when no filters are active.ButtonGroupwithdangeron destructive ones; progress bar hidden for completed downloads.Shared + cleanup
stroke-extra-lightdivider +surface-hoverhover tint, both theme tokens.<a href='#'>) replaced with the FuselageButtonprimitive in both ActionButtons.colorprop onto semantic token names (font-default,font-hint,font-secondary-info, etc.) across the touched views plus ServerInfoContent, ServersView, TopBar.style={{ paddingTop: '4px' }}withpaddingBlockStart='x4'in the affected settings features.Shell/styles.tsxswitched fromsystem-uito the Fuselage Inter-first stack. The pre-hydration overlays (loading.css/error.css) intentionally keepsystem-ui; documented inDESIGN.md.Design context
PRODUCT.md,DESIGN.md, and.impeccable/design.jsoncapture register, users, anti-references, principles, and the Fuselage-verified token contract for future UI work.Before:


After:
Before:


After:
Before:


After:
Notes for reviewers
npx tsc --noEmit(clean) on every commit; GitNexus upstream impact analysis was LOW on each touched surface..impeccable/design.jsonis agent-context tooling output. If the team would rather not track it, it can move to.gitignoreand drop from this PR.Test plan
Summary by CodeRabbit
New Features
Style
Bug Fixes / UX
Documentation
Localization
Chores