Skip to content
Development

A component that worked and rendered as nothing

By Victor Da Luz
astrotailwinddocumentationdev-logastro-tools

My consent-analytics package has two visual components. One is a floating prompt that reads CSS custom properties - --surface, --fg, --accent - with sensible dark-mode fallbacks baked in. If a consuming app already defines those variables, and most of the family sites do since it’s a shared convention, the prompt matches the site’s theme with zero extra CSS. Genuinely zero-config, and the README says so.

The other component, a /privacy page explainer, is styled entirely with Tailwind utility classes: text-fg, text-muted, space-y-12. Same token names, completely different delivery mechanism. And the README’s Styling section only described the first component’s contract.

What “silently unstyled” actually looks like

A CSS-custom-property component that gets no config just uses its fallback values. Nothing breaks, nothing looks wrong, worst case it doesn’t perfectly match your theme.

A Tailwind-utility component that gets no config is a different failure entirely. The utility classes reference colors that were never generated into the site’s compiled CSS at all, because Tailwind only generates classes it can see referenced in files matched by your content glob. A new consumer who reads only the existing Styling section would set up the CSS custom properties, wire up the prompt correctly, drop in PrivacyExplainer, and get a wall of unstyled text with no error, no warning, nothing in the console.

It works, in the sense that matters most - the explainer is deliberately sourced straight from your live analytics config, so its content can never drift from what’s really injected. It just doesn’t look like anything.

That gap only exists because two components in the same package quietly picked two different styling strategies, and only one of those strategies got written down. A shared package drifting out of sync with itself is becoming a recurring theme in this family of repos.

The fix was restating a decision, not making one

Two paths were on the table: document the real requirement, or rewrite the component onto the same CSS-custom-property contract as the prompt so the package tells one consistent styling story. I documented.

Rewriting would mean re-deriving every spacing and color decision as inline custom-property-driven styles instead of Tailwind utilities - real work for a component that already renders correctly once the two missing config lines exist. The lower-risk path was making the existing requirement visible, not eliminating it.

The addition is two lines a consumer needs: alias the token colors in tailwind.config.mjs (the same block the sibling blog package already documents), and include this package in the Tailwind content glob. Now written in the one place someone would actually look before wiring the component up.

What I’d check next time

When a package has more than one visual component, check whether they all actually share a styling contract before writing - or trusting - a single Styling section that describes only one of them. “The README has a Styling section” is not the same claim as “the README’s Styling section covers everything that needs styling.”

Related reading