-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add list-style-image
support
#10817
Add list-style-image
support
#10817
Conversation
Note to self — the line-clamp plugin actually does do the thing I talked about where we mix usage of https://github.com/tailwindlabs/tailwindcss-line-clamp/blob/master/src/index.js#L10-L48 ...but in this case it's not clear which plugin we should be defining Main issue would be that Could work around that by filtering out the Really basic implementation for Monday-Adam's benefit, without the listStyleType: (args) => {
args.addUtilities({
'.list-none': { 'list-style-type': none },
})
createUtilityPlugin('listStyleType', [['list', ['listStyleType']]])(args)
},
listStyleImage: (args) => {
args.addUtilities({
'.list-none': { 'list-style-image': none },
})
createUtilityPlugin('listStyleImage', [['list', ['listStyleImage']]], {
type: ['lookup', 'image', 'url'],
})(args)
}, |
Talked to @reinink — just going to put all the Nice benefit is you don't need to type-hint - <div class="list-[image:var(--my-var)]">
+ <div class="list-image-[var(--my-var)]"> Same number of characters but people won't need to read the docs to figure it out. So to summarize the new changes:
So yeah that was a lot of effort for basically nothing. |
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com> Co-authored-by: Jordan Pittman <jordan@cryptica.me>
9298e59
to
22afcd5
Compare
This PR adds support for the
list-style-image
property under thelist-*
namespace.By default, only
list-none
is included, but custom values can be added using thelistStyleImage
theme configuration or using arbitrary values.Implementation
The obvious way to implement this feature is by adding a new
listStyleImage
core plugin that handles thelist-style-image
property, but it creates a documentation challenge because there are no sensible default values for us to include (since images like this are very project specific), which would basically make the documentation page empty, or at least have no table at the top. This would be the very first time that the documentation for a utility didn't include any sort of reference table which felt like a smell and led us to look for other ways to approach this feature.For a while we were convinced that the best way to implement this feature would actually be to deprecate the existing
listStyleType
utilities in favor of a genericlistStyle
plugin that targeted thelist-style
shorthand property in CSS. There's not a lot of point in setting bothlist-style-type
andlist-style-image
on an element, so combining these into a single abstraction in Tailwind felt like a nice convenience to the end user, and would allow them to configure custom types and images under a single key in theirtailwind.config.js
file.We worked on this for quite a while but ultimately decided against that approach for two reasons:
Significant complexity needed for backwards compatibility. We take backwards compatibility pretty seriously and wanted to make sure that we could introduce a new
listStyle
plugin without forcing users to have to make any changes to their project to upgrade.This meant we needed to make sure customization theme values added to
listStyleType
were automatically inherited by the newlistStyle
plugin, that calls totheme('listStyleType.disc')
still worked in both your CSS and within JS plugins, and that if you'd disabled thelistStyleType
core plugin that thelistStyle
plugin would be disabled. On top of this, we wanted to issue warnings for anyone interacting with the old APIs to motivate them to replace their use oflistStyleType
withlistStyle
.The more we worked on this, the more nasty edge cases we found where the correct behavior felt very hard to decide on, and where handling even the edge cases we did know how to handle was introducing lots of nasty conditional code throughout many different places in the codebase. This just felt like a smell and forced us to step back and consider if there were any other solutions.
The
list-style
property doesn't compose withlist-style-position
. Thelist-style
shorthand property is short forlist-style-type
,list-style-image
, andlist-style-position
. That means if you setlist-style
after setting any of those properties, those properties are overridden.This shows up as a problem when applying classes conditionally, for example:
In the above example, if we used
list-style
to implementlist-decimal
, thenmd:list-decimal
would override thelist-style-position
set bylist-inside
. In practice this probably isn't a big deal because it's pretty strange to change the bullet style conditionally, but it was a signal that using the genericlist-style
property was probably not the right solution.Ultimately we decided to go with the first implementation idea which is a dedicated
listStyleImage
plugin, but solve the documentation problem by combining bothlistStyleImage
andlistStyleType
into a single documentation page called "List Style Type / Image", much like we do with thegrid-column
,grid-column-start
, andgrid-column-end
utilities.We also decided to include
none
as a default value forlistStyleImage
just to make sure things like this would work:Because
listStyleType
also includesnone
as a default value, this means that usinglist-none
in your markup will generate two classes:We considered writing some special case code here so that we could just include
none
underlistStyleType
but automatically uselist-style
instead oflist-style-type
just for thenone
value, but that would have the same issues I mentioned in point 2 above where it breaks composability. It also just feels dirty to special case things in the codebase, and is usually a sign that we're doing something we shouldn't be doing.One minor downside to
list-none
working this way is that if for some reason you really want to set both a type and an image but unset just the type or image at a different breakpoint, you can't, becauselist-none
will always unset both:Even respecifying the one you want to keep won't work, because it will collide with the version of
list-none
that comes from that same core plugin:This feels like something we need to solve before merging, as it's another one of those weird smells that just tells me our approach here isn't right. So far, I have two ideas but am not in love with either of them:
Use different names. Maybe
list-none
is forlist-style-type
for BC reasons, andlist-image-none
orlist-no-image
is used forlist-style-image
. Would work, name options just suck.Special case
list-none
. Maybe we addlist-none
usingaddUtilities
so it is always sorted before custom values. This would work but it would be the first time we've mixedaddUtilities
andmatchUtilities
in the same plugin, and any time we do something for the first time we need to think carefully about if we want to set that precedent.Going to leave this open for now and probably waste four more hours talking about it with @reinink when he's back from vacation on Monday.