styling
SKILL.md
Styling Guidelines
Minimize Wrapper Elements
Avoid creating unnecessary wrapper divs. If classes can be applied directly to an existing semantic element with the same outcome, prefer that approach.
Good (Direct Application)
<main class="flex-1 mx-auto max-w-7xl">
{@render children()}
</main>
Avoid (Unnecessary Wrapper)
<main class="flex-1">
<div class="mx-auto max-w-7xl">
{@render children()}
</div>
</main>
This principle applies to all elements where the styling doesn't conflict with the element's semantic purpose or create layout issues.
Tailwind Best Practices
- Use the
cn()utility from$lib/utilsfor combining classes conditionally - Prefer utility classes over custom CSS
- Use
tailwind-variantsfor component variant systems - Follow the
background/foregroundconvention for colors - Leverage CSS variables for theme consistency
Disabled States: Use HTML disabled + Tailwind Variants
When an interactive element can be non-interactive (empty section, loading state, no items), use the HTML disabled attribute instead of JS conditional guards. Pair it with Tailwind's enabled: and group-disabled: variants.
Why disabled Over JS Guards
disablednatively blocks clicks—noif (!hasItems) returnneeded- Enables the
:disabledCSS pseudo-class for styling - Semantically correct for accessibility (screen readers announce "dimmed" or "unavailable")
- Tailwind's
enabled:andgroup-disabled:variants compose cleanly
Pattern
<!-- The button disables itself when count is 0 -->
<button
class="group enabled:cursor-pointer enabled:hover:opacity-80"
disabled={item.count === 0}
onclick={toggle}
>
{item.label} ({item.count})
<ChevronIcon class="group-disabled:invisible" />
</button>
Key Variants
enabled:cursor-pointer— pointer cursor only when clickableenabled:hover:bg-accent/50— hover effects only when interactivegroup-disabled:invisible— hide child elements (e.g., expand chevron) when parent is disableddisabled:opacity-50— dim the element when disabled
Anti-Pattern
<!-- Don't do this: JS guard duplicates what disabled does natively -->
<button
class="cursor-pointer hover:opacity-80"
onclick={() => { if (item.count > 0) toggle(); }}
>
The JS guard leaves cursor-pointer and hover:opacity-80 active on a non-interactive element. The user sees a clickable button that does nothing. Use disabled and let the browser + CSS handle it.
Weekly Installs
58
Repository
epicenterhq/epicenterGitHub Stars
4.3K
First Seen
Jan 20, 2026
Security Audits
Installed on
claude-code52
gemini-cli51
opencode51
codex50
antigravity47
cursor47