Skip to main content

Supporting Dark Themes

Zach Hawtof headshot
Zach Hawtof November 16, 2025

Explore how Tightknit has integrated dark mode support, enhancing user experience with 90% coverage of dark styles, improved accessibility, and a consistent theming model.

View as Markdown
Supporting Dark Themes
  • Working title: Supporting dark mode in Tightknit
  • Category: Product
  • Slug: dark-mode
  • One‑liner: We introduced dark‑mode‑aware branding sets, moved branding to root‑level CSS variables, and enabled Tailwind's dark styles—delivering a 90% complete dark experience with minimal risk to existing sites.

Dark mode has gone from "nice to have" to a baseline expectation. For communities that live in Tightknit all day, the ability to reduce glare at night, improve focus, and keep brand identity intact matters.

Over the past week, we shipped the first phase of dark mode across the web app and companion sites. This post breaks down what changed, why we changed it, how Orchid Security's Dark Matter theme shaped the work, and what's next.

The Orchid Security story: Dark Matter, real constraints

Orchid Security wanted a truly dark brand aesthetic—"Dark Matter"—for their companion site. Early tests surfaced real problems: harsh white outlines, unreadable button text in menus, and components that ignored branding because they rendered outside the app tree.

We turned that feedback into a focused implementation plan:

  • Introduce a theme_mode on branding sets (light or dark) so dark themes don't fight light‑biased defaults.
  • Move branding from scattered styles to root‑level CSS variables so Radix portals and overlays inherit the correct colors.
  • Activate shadcn/Tailwind dark styles via a .dark class on the branding root, then derive tokens for borders, surfaces, and text to eliminate "white halo" artifacts.

After an overnight push to wire these pieces together, we got to a "90% there" dark experience for Orchid—good enough to unblock their launch—while tracking the last 10% of visual nits for cleanup.

What changed (for everyone)

  • Per‑brand theme mode in branding sets
    • We added theme_mode and automatically infer the right mode from your background color's luminance so sites "just look right" when you choose a dark background.
  • Root‑level CSS variables instead of inline overrides
    • Branding now compiles into CSS variables at the root and a tk-branding scope, so everything—including portals and overlay components—gets the correct colors.
  • Tailwind + shadcn dark support, activated the right way
    • We toggle .dark on the tk-branding root, then use color‑mix‑based tokens for borders, surfaces, and text to avoid hard‑coded light‑mode artifacts.
  • Safer defaults for existing customers
    • Light‑mode tokens were tuned so changes are barely noticeable, minimizing regressions while unlocking dark mode for those who want it.

Why this approach

  • Portals and overlays must inherit branding
    • Root variables ensure modals, popovers, and other out‑of‑tree elements pick up brand colors consistently—no more menu dialogs stuck in light mode.
  • Accessibility by design
    • We're validating contrast and structure with Playwright + axe‑core to reduce color‑contrast issues as we extend dark mode coverage.
  • Predictable theming model
    • A single source of truth (CSS variables) with a simple mode switch (.dark) is more maintainable than per‑component overrides.

What's improved already

  • Real usage, real feedback
    • Orchid's Dark Matter testing revealed outlines, dropdowns, skeletons, and dialogs that needed dark tokens. Those are now addressed or tracked with clear owners.
  • 90% coverage today
    • Initial rollout covers core surfaces and shadcn components. Remaining rough edges include stray borders and a few default tokens that still assume light backgrounds.

What's next

  • Finish the last 10%
    • Remove remaining white outlines and extend token coverage across all components and states.
  • Better logo and media handling
    • Ensure logos with baked white backgrounds and media in cards render correctly on dark surfaces.
  • Broader automated checks
    • Expand automated a11y checks to specifically test color contrast across both modes in common flows.

For developers: the gist

  • Mode detection
    • theme_mode derives from branding color luminance and is stored with the branding set.
  • Activation
    • We scope styles under body.tk-branding and toggle .dark to switch to dark variables. Tokens use color‑mix for borders and surfaces to maintain subtle depth in both modes.
  • Why variables
    • Root variables guarantee consistent theming for portals and embedded UIs—no more one‑off overrides that miss overlays or menus.

Rollout status

  • Enabled and merged; light‑mode customers should see negligible visual changes. Dark‑mode branding sets look great overall; we're closing remaining visual gaps before calling it "done."

Thank you

Huge thanks to Stephen and Danny for the late‑night push and reviews. Customer feedback from Orchid's team was essential in shaping this rollout.

Related customer

Related posts

Boost engagement and scale your community faster with Tightknit