Skip to content
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

Dynamic conditional CSS classes #7294

Open
janosh opened this issue Feb 19, 2022 · 8 comments · May be fixed by #11299
Open

Dynamic conditional CSS classes #7294

janosh opened this issue Feb 19, 2022 · 8 comments · May be fixed by #11299

Comments

@janosh
Copy link
Contributor

janosh commented Feb 19, 2022

Describe the problem

In components that want to support use with CSS frameworks like Tailwind, it would be nice to allow users to pass in custom class names as props which are applied depending on an internal condition in the component:

Describe the proposed solution

MyComponent.svelte:

export let dynamicClass = ''

let cond = false

<button class:{dynamicClass}={cond} on:click={() => cond = true}>click me</button>

Alternatives considered

This already works

<button class={cond ? dynamicClass : ''} on:click={() => cond = true}>click me</button>

but it looks cleaner here than in the real world where you might already have class attr in which case you need to manually combine classes before applying.

Importance

nice to have

@windyclory
Copy link

class={cond && dynamicClass}

@janosh
Copy link
Contributor Author

janosh commented Feb 20, 2022

@windyclory Gives class="false" if !cond.

@adiguba
Copy link
Contributor

adiguba commented Mar 12, 2022

What about using a reactive-variable ?

<script>
export let dynamicClass = ''
let cond = false

$: theDynamicClass = cond ? dynamicClass : '';
</script>

<button class="my-class-name {theDynamicClass}" on:click={() => cond = !cond}>click me</button>

@janosh
Copy link
Contributor Author

janosh commented Mar 12, 2022

@adiguba Sure that's what I'm using now and it works but I think the syntax could be improved. That's what I meant with "looks cleaner here than in the real world where [...] you need to manually combine classes".

@ankarhem
Copy link

ankarhem commented May 23, 2022

I'm interested in this as well. I haven't touched svelte source before but I tried to make an initial assessment. Maybe someone else could chime in on an idea on how to implement it. But by playing around with the parser I got the impression we would need a new node type to solve this problem.

If someone with deeper knowledge about the parser could give some insight into how the AST could be structured it would probably be easier for someone to pick this one up.

@tytusplanck-8451
Copy link

tytusplanck-8451 commented Jun 20, 2022

Something more nuanced would be great.. even using the class directive like this class:{applyLogicAndReturnClass()} would work pretty good.

@lightyaer
Copy link

I think I have a similar issue,
I am building components from tailwind and daisyui classes, and need to set conditional classes from a long list of props.

Wanted to know if something like this is doable.

 export const classes = {
    'btn-primary': color === 'primary',
    'btn-secondary': color === 'secondary',
    'btn-accent': color === 'accent',
    'btn-ghost': color === 'ghost',
    'btn-link': color === 'link',
    'btn-square': shape === 'square',
    'btn-circle': shape === 'circle',
    'btn-active': active,
    'btn-outline': outline,
    'btn-disabled': disabled,
    'btn-loading': loading,
}

and then set class={classes} to apple classes.

These are some of the props here, but the actual list is quite long.

Current work-around is building a string by iterating through classes object and set class={classString}

Wonder if this could be integrated into svelte itself.
Btw, the proposed approach works in React, Vue and even SolidJS.

@KyleFontenot
Copy link

Ran into a use-case for this as well. I think syntactically, it would be nice to have it similar to how SolidJS uses computed values in classList:

<div class:[dynamicprop]> 

where bracket notation denotes a computed value inside an object like {[styles.fancydiv] : true}

@Rich-Harris Rich-Harris added this to the one day milestone Apr 2, 2024
@RaiVaibhav RaiVaibhav linked a pull request Apr 23, 2024 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants