Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

@JorisAerts
Copy link

@JorisAerts JorisAerts commented Oct 30, 2025

Fixes #4149
Fixes #3095
Fixes #2153 (while at it...)

This feature is fully backward compatible, the syntax is just extended to allow more cases, just like in other frameworks.

It also adds support for multi-class keys, like "foo bar".

It also supports passing nothing, which will would be the same a passing undefined, null or false. These negative parameters allow developers to pass object references, which may or not be falsy, depending on the context.

GIGO principle; none-string values which are not falsy or nothing, will get .toString()'ed, because just ignoring them would be like eating exceptions. They will also be split, so "[object Whatever]" will be two classes.

For example:

// original functionality still supported, of course
html`
  <input class="${classMap({
      'foo': this.isValid 
      'bar': this.isNotValid 
  })}">
`;

// support for spaces within class names
html`
  <input class="${classMap({
      'foo bar': this.isValid 
      'foo baz': this.isAlsoValid 
  })}">
`;

html`
  <input class="${classMap('foo bar')}">
`;

// support for regular (spread) classes
html`
  <input class="${classMap('class-1', 'class-2')}">
`;

// support for regular classes using (nested) arrays
html`
  <input class="${classMap(['class-1', 'class-2', ['class-3', 'foo bar']])}">
`;

// support for all types of combinations (object, array, single classes)
html`
  <input class="${classMap(
    'form-control', 
    'some-other-class', 
    { 
      'is-valid': this.isValid 
    }, 
    ['some-other-class-2'], 
    {
      'foo bar': this.isAlsoValid 
      'foo baz': this.isAlsoValid 
    }
  )}">
`;

Adding more parameters does not seem to break anything, because this directive can only be used as the single directive inside a class-attribute.
It would always just have one parameter in the past usage.

I haven't changed any documentation, I'm not sure I'm expected to, but I wouldn't mind either. There's a lot more to say about classMap, although I can't see any newly introduced unexpected behaviour.

@changeset-bot
Copy link

changeset-bot bot commented Oct 30, 2025

🦋 Changeset detected

Latest commit: 4c768d8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
lit-html Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@google-cla
Copy link

google-cla bot commented Oct 30, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@JorisAerts JorisAerts changed the title Feature/class map spreading classMap overloading and parameter spreading Oct 30, 2025
@justinfagnani
Copy link
Collaborator

Thanks for the PR @JorisAerts!

I worry a bit about the complexity and performance implications of making classMap() itself this expressive, vs allowing users to use whatever plain JS utilities they want to build up the ClassInfo object. We've already had report of classMap() being slow compared to string concatenation, and I'm wary of making it bigger and slower without some more benchmarking.

The recursive object walk can be done with object spread.

The nested array support is equivalent to

const classInfo = Object.fromEntries(classes.flat(Infinity).map((c) => [c, true]));

...${classMap(classInfo)}

and I'm concerned that people would use arrays unnecessarily, when they could just put static classes in the attribute next to the classMap() expression.

I'm more on board with the fixes for #3095 and #2153

@justinfagnani justinfagnani self-requested a review December 11, 2025 20:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants