Repository navigation
Reuse Steam's native Friends styles for theme compatibility - #1
Merged
Merged
Conversation
Steam themes target Friends' native class names, so the custom tab and list bypassed theme styling. Resolve unique desktop modules at runtime and keep CSS limited to layout with gated fallbacks.
Real class-map excerpts guard the desktop Friends filters against similarly named Gamepad and mini-profile modules.
CSS module filters no longer represent valid desktop styling evidence. Keep coverage on the live sibling-copy path that can genuinely fail.
Steam's literal classes depend on exact tags, attributes, ancestors, and state. Recreate only the contexts proven by desktop CSS while keeping Recent Chats geometry explicit and ungated.
Successful module resolution did not prove that desktop Friends selectors matched the injected DOM. Retain only live tab-class copying, whose missing-sibling case is observable.
Record the selectors, required DOM context, and contributed properties for every retained native class. Treat the installed stylesheet as ground truth instead of JavaScript export names.
Valve's desktop tab class has transitions but no hover rule and uses the default cursor. Add a theme-neutral animated overlay and pointer cursor without changing active-tab styling.
Themed tab rules sized the injected tab differently because it lived in a wrapper div with its own flex context, so the tab element is now the host itself, mounted beside the native tab with symmetric inline padding. The toolbar background becomes a translucent neutral instead of a Steam hue, and the list reserves a stable scrollbar gutter since themes may zero the container's scrollbar-side padding.
Live-theme testing surfaced breakage the static CSS audit could not: themes force row margins, collapse the labelHolder hook, hide tab labels, and strip scrollbar-side container padding. Rows drop the labelHolder class and explicit width, the card scrolls instead of the container, the tab matches native content-box sizing and pins its label opacity, and the search form borrows MemberListOptionsContainer for Valve's brighter placeholder. Toolbar and field colors switch to translucent neutrals only when injected theme stylesheets are detected (html.rcp-themed), keeping default Steam pixel-faithful.
Documents the rcp-themed detection mechanism, the deliberate dual treatment of toolbar/field colors, and the hardening lessons from live themes behind each structural choice.
Valve's borrowed rules misbehaved in our always-open context (badge pinned over the timestamp, #555 query text, both tabs reading active, dead clear-button hover, global 14px scrollbar), so the plugin now overrides those specific properties. Theme detection keys solely on Millennium's per-document link#millennium-injected marker — weaker signals false- positived on default Steam. Also hardened: the tab requires socialListTab before trusting a copied class list and re-adopts a late-rendering sibling, the state-token filter is an explicit stop-list, avatars retry after a transient load error, and anchor discovery can no longer match the plugin's own injected panel.
Theme-specific active states and input and row rules were still being overridden by plugin CSS. Manage native selection directly and leave themed colors to Steam while correcting unread and avatar geometry.
Dropping the themed field colors entirely left Steam's default #262930 field under themes that never style friendSearchInput. The translucent fallback now lives in a separate sheet inserted before Millennium's theme stylesheet: source order lets it beat Steam's defaults while any theme rule at Steam's own specificity still wins. A :focus variant matches Valve's focus-rule specificity so the field doesn't revert while typing.
Recent chats previously reused online colors for every conversation. Apply Steam's live presence states while keeping group and unresolved rows neutral.
Broadcast, group, and unresolved rows lack native friend-row hover rules. Reuse Steam's neutral group-chat treatment at zero specificity so theme rules still win.
Keep group and unknown semantics in the data model while rendering them with Steam's online and offline classes. Broadcast rows now rely entirely on Steam's native styling.
Themes can scope away foregrounds to Steam's nested persona text hooks while styling the outer hover independently. Reuse only those text hooks and neutralize their native layout effects.
Theme options can restyle the reused native persona text tokens with important font rules, shrinking only away rows. Pinning the plugin's own typography keeps every row consistent.
Themes like SpaceTheme color names and subtext only through Steam's nested labelHolder and persona text tokens, so away-only adoption left the other rows on Valve defaults with a mismatched palette. All rows now share the nested structure and the existing geometry/typography pins.
Alex979
marked this pull request as ready for review
August 19, 2026 16:41
This was referenced Aug 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
A PluginDatabase reviewer pointed out in SteamClientHomebrew/PluginDatabase#221 (comment) that the plugin re-implemented Steam's Friends styling by hand, with hardcoded colors and fonts. That meant Millennium themes couldn't touch it. Every theme would need special-case support for the Chats tab, and any Steam restyle would leave the plugin looking out of date.
What changed
The injected UI now uses Steam's own class names instead of imitating them:
activeTabclass between the two tabs, so theme and high-contrast active styling always follows the actually-selected tab.The plugin also detects whether a Millennium theme is active: default Steam keeps its exact original look, while themed clients get neutral translucent fallbacks for the toolbar strip and search field. The search fallback is deliberately weak, it sits before the theme's stylesheet in the cascade, so any theme that styles Steam's own search field overrides it automatically. Themes that never touch the field get a translucent neutral instead of Steam's default colors.
docs/steam-class-mapping.mddocuments every borrowed class with the Steam CSS rule that backs it, for future Steam-update triage.How it was tested
bun run typecheck,bun test(35 tests), andbun run buildall pass.Notes for review
docs/steam-class-mapping.mdrecords every spot where a native rule is overridden on purpose.Theme Screenshots
Steam Default
Minimal Dark
SpaceTheme
Material