feat(theme): add Glass design language - #3130
Conversation
Drop `transparent: true` (it makes behind-window vibrancy render near-opaque over the desktop) and switch the material to `popover`; keep `visualEffectState: active` so the menubar popup stays translucent while unfocused. Sync `nativeTheme.themeSource` with the color mode via a new SET_NATIVE_THEME IPC so dark Glass gets a dark material instead of light text on a light frost. Clear the Primer `[data-color-mode]` wrapper's opaque background so the material shows through the whole window. Also removes the Increase contrast setting, which forced Glass to a solid surface and whose useAppearance/theme wiring is intertwined with the changes above.
Under translucency: row action buttons become bare icons (no hover band or button fill) with the row text fading out under them on hover so it never collides; the scrollbar track goes transparent; and the glass tints are lowered a step so more of the material shows through.
…witch applyWindowVibrancy only cleared the window background when disabling, so switching Classic (which paints an opaque backdrop) to Glass left that backdrop in place and blocked the vibrancy material from sampling the desktop. Clear it on enable too; `#00000000` works without a transparent window because the vibrancy view provides the translucency. Adds regression tests for both toggle sides.
Handle the setNativeTheme IPC rejection (log via rendererLogError) instead of leaving an unhandled promise, matching the setWindowVibrancy call, and note that the sync is intentionally not macOS-gated. Adds coverage for the Glass-clamped path (Glass + DARK_DIMMED still syncs 'dark').
setchy
left a comment
There was a problem hiding this comment.
Marking while I have time to review.
|
| }); | ||
|
|
||
| /** | ||
| * Sync the native appearance with the app's color mode so the macOS vibrancy |
There was a problem hiding this comment.
i wasn't able to find where in macOS System Settings the vibrancy setting is. Can you point me in the right direction :)
| const mockAppearanceSettings: AppearanceSettingsState = { | ||
| designLanguage: DesignLanguage.CLASSIC, | ||
| theme: Theme.SYSTEM, | ||
| increaseContrast: false, |
There was a problem hiding this comment.
this was used to control an accessibility feature of the GitHub primer themes
There was a problem hiding this comment.
was your thoughts to control this from the macOS Accessibility increase contrast setting directly?
| /> | ||
|
|
||
| <Button aria-label="Zoom percentage" disabled size="small"> | ||
| {/* Value display, not a control: styled like the group but inert |
There was a problem hiding this comment.
we repeat this a few times - should we extract it out? or ok to duplicate?
|
Super sharp enhancement, @afonsojramos. I love that we're able to keep the design components as Primer and apply new theme/style overrides. Nice work. Left a few inline comments for my own curiosity |
|
|
||
| // Glass is always translucent; it only degrades to solid under the OS Reduce | ||
| // Transparency / Increase Contrast settings (a media query in App.css). | ||
| const vibrant = designLanguage === DesignLanguage.GLASS && !prefersReducedTransparency; |
There was a problem hiding this comment.
it might be nice to allow users to set prefersReducedTransparency just within Gitify, as well as sync it from the macOS system settings.




Summary
After simmering for 2 days @setchy 👀
Adds a second design language, Glass, next to the existing look (now Classic), selectable under Settings → Appearance. Under Glass the whole window becomes one continuous translucent material: the sidebar dissolves into icons floating on the glass, controls (buttons, selects, checkboxes, radios, count pills) render as stepped translucent tiles, notification and repo rows float as rounded cards with glass hover states, and tooltips/popovers come out frosted. Classic is pixel-unchanged: everything Glass lives behind
[data-theme='glass']plus a.gitify-translucentgate, so there is no risk to the default experience.Design decisions
popovervibrancy material, wired over IPC and ordered so switching designs at runtime never flashes black; the material also follows the app's light/dark mode vianativeThemesync. Other platforms fall back to CSSbackdrop-filter.data-color-modeboundary, so components stay stock Primer and the entire language lives inApp.css.Validation
tsc, lint and format clean.New concepts
Theme tokens that re-resolve per language (Tailwind
@theme inline)The radius/shadow/tint utilities are backed by plain CSS variables (
--gitify-*) that each design language re-points under its own[data-theme]scope. Declaring them with@theme inline(instead of@theme) makes Tailwind re-resolve the utilities against the active scope rather than freezing them at:root.This is why one component tree can serve two languages with no JS branching: the swap is a single attribute on the root. Reach for it when a whole token layer swaps at once; for one-off per-component tweaks, a direct class is simpler.
Note: I now fully prefer this theme 👀