Skip to content

💡 RFC: Add support for a directive to dynamically add classes #782

@tony-sull

Description

@tony-sull

Background & Motivation

This has come up in Discord frequently enough that it probably makes sense to have built-in support for in Astro. Adding multiple classes to an HTML element depending on local state can be cumbersome, ex:

<div class={`wrapper ${disabled ? "disabled" : ""} ${open ? "open" : ""} ${!items.count ? "empty" : ""}`}>

It'd be nice to have a recommended solution to this in Astro (included in the docs)

Proposed Solution

<div class="wrapper" attr:class={{ disabled, open, empty: !items.count }}>

The developer experience is a bit better here if you need to add more than one or two conditional classes. This feels very familiar to using something like clsx because, basically, it is! This RFC would make that functionality a first class citizen and avoid recommending an NPM dependency for such a common scenario

Alternatives considered

  • Svelte's class:name directive
  • Including a helper function similar to clsx
  • just including docs with links to those libraries with and a short example snippet

Risks, downsides, and/or tradeoffs

  • The attr namespace would be a new addition to Astro, that may not be worth adding if an NPM library solves the usecase
  • Classes get pretty overused in the frontend and this would make it even easier to throw more classes into Astro components

Open Questions

  • Does this risk creating friction with the rest of Astro's naming conventions?
  • Is it worth adding an extra directive over pointing users to clsx?
  • How does it handle <div class="primary" attr:class={{ primary: false }}/>? Does it remove the primary class? Break the build? Skip the attr:class check and log a warning?

Detailed Design

  • attr:class accepts a map of class names to boolean flags
  • Classes are added only for class names mapped to truthy values
  • attr:class does not remove inlined class names (like wrapper above)

Help make it happen!

  • I am willing to submit a PR to implement this change.
  • I am willing to submit a PR to implement this change, but would need some guidance.
  • I am not willing to submit a PR to implement this change.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions