Skip to content

[Toolkit][Shadcn] Remove attributes.defaults() in component templates#3653

Open
seb-jean wants to merge 23 commits into
symfony:3.xfrom
seb-jean:fix/shadcn-attributes-defaults-3x
Open

[Toolkit][Shadcn] Remove attributes.defaults() in component templates#3653
seb-jean wants to merge 23 commits into
symfony:3.xfrom
seb-jean:fix/shadcn-attributes-defaults-3x

Conversation

@seb-jean

@seb-jean seb-jean commented Jun 2, 2026

Copy link
Copy Markdown
Contributor
Q A
Bug fix? no
New feature? no
Deprecations? no
Documentation? yes
Issues Part of #3233
License MIT

@seb-jean seb-jean requested a review from Kocal as a code owner June 2, 2026 18:50
@carsonbot carsonbot added Documentation Improvements or additions to documentation Toolkit Status: Needs Review Needs to be reviewed labels Jun 2, 2026
@seb-jean seb-jean force-pushed the fix/shadcn-attributes-defaults-3x branch from 13c21e1 to c62875a Compare June 2, 2026 18:54

@Kocal Kocal left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this, but there are a few nuances to consider. I stopped the review at src/Toolkit/kits/shadcn/alert/templates/components/Alert.html.twig file btw

'data-slot': 'alert-dialog-content',
'data-size': size,
'data-alert-dialog-target': 'dialog',
'data-action': 'keydown.esc->alert-dialog#close:prevent',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, for data-action it can be different, maybe it can be useful to make it overridable, but only by using the html_attr_merge Twig filter

Comment thread src/Toolkit/kits/shadcn/alert/templates/components/Alert.html.twig Outdated
@carsonbot carsonbot added Status: Needs Work Additional work is needed and removed Status: Needs Review Needs to be reviewed labels Jun 3, 2026
@seb-jean

seb-jean commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for your feedback, @Kocal

  1. I'm wondering, then, what is the purpose of attributes.defaults({})? Is there an advantage? Should we avoid using attributes.defaults({})?

  2. With the 3.x branch update, I changed the template in src/Toolkit/kits/shadcn/label/examples/Demo.html.twig to add data-slot="test-data-slot".

<div class="flex gap-2">
    <twig:Checkbox id="terms" />
    <twig:Label for="terms" data-slot="test-data-slot">Accept terms and conditions</twig:Label>
</div>

I went to http://127.0.0.1:9044/toolkit/kits/shadcn/components/label, then opened a new tab to view the preview demo: http://127.0.0.1:9044/toolkit/component_preview?[...].

I looked at the source code, and I saw two data slots applied to the <label> element:

<label data-slot="label" class="[...]" for="terms" data-slot="test-data-slot">Accept terms and conditions</label>

Furthermore, this might need to be modified because it mentions the use of attributes.defaults({...}):

@seb-jean seb-jean force-pushed the fix/shadcn-attributes-defaults-3x branch from c62875a to a0794d9 Compare June 6, 2026 17:46
@carsonbot carsonbot added Status: Needs Review Needs to be reviewed and removed Status: Needs Work Additional work is needed labels Jun 6, 2026
@xDeSwa

xDeSwa commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

hi @seb-jean

can you try and update select component?

Current :

{# @block content The select options (`<option>` elements) #}
<select
    class="{{ ('flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 ' ~ attributes.render('class'))|tailwind_merge }}"
    {{ attributes }}
>
    {%- block content %}{% endblock -%}
</select>

Better view:

{# @block content The select options (`<option>` elements) #}
<div class="relative w-full">
    <select
        class="{{ ('flex w-full appearance-none items-center justify-between rounded-lg border bg-transparent px-3 py-2 text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30 dark:hover:bg-input/50 [&>span]:line-clamp-1 ' ~ attributes.render('class'))|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </select>

    <div class="pointer-events-none absolute right-1 mr-2 top-0 bottom-0 flex items-center justify-center text-muted-foreground">
        <twig:ux:icon name="lucide:chevron-down" class="h-4 w-4 opacity-50" />
    </div>
</div>

@seb-jean

Copy link
Copy Markdown
Contributor Author

hi @seb-jean

can you try and update select component?

Current :

{# @block content The select options (`<option>` elements) #}
<select
    class="{{ ('flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1 ' ~ attributes.render('class'))|tailwind_merge }}"
    {{ attributes }}
>
    {%- block content %}{% endblock -%}
</select>

Better view:

{# @block content The select options (`<option>` elements) #}
<div class="relative w-full">
    <select
        class="{{ ('flex w-full appearance-none items-center justify-between rounded-lg border bg-transparent px-3 py-2 text-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 dark:bg-input/30 dark:hover:bg-input/50 [&>span]:line-clamp-1 ' ~ attributes.render('class'))|tailwind_merge }}"
        {{ attributes }}
    >
        {%- block content %}{% endblock -%}
    </select>

    <div class="pointer-events-none absolute right-1 mr-2 top-0 bottom-0 flex items-center justify-center text-muted-foreground">
        <twig:ux:icon name="lucide:chevron-down" class="h-4 w-4 opacity-50" />
    </div>
</div>

I'm not going to make the change because it's outside the scope of the PR and concerns another component introduced in the PR: #3479

@seb-jean

seb-jean commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

I’m adding two examples of attributes.defaults() usage that are contradictory.

In the file ux/src/Toolkit/kits/shadcn/alert/templates/components/Alert.html.twig, the data-slot and role attributes are not included in attributes.defaults():

<div
data-slot="alert"
role="alert"
class="{{ style.apply({variant: variant}, attributes.render('class'))|tailwind_merge }}"
{{ attributes }}
>
{%- block content %}{% endblock -%}
</div>

However, in the file ux/src/Toolkit/kits/shadcn/accordion/templates/components/Accordion/Content.html.twig, the data-slot and role attributes are included in attributes.defaults():

<div
class="grid text-sm overflow-hidden transition-[grid-template-rows] duration-300 ease-out {{ not _accordionItem_isOpen ? 'hidden' }}"
{{ attributes.defaults({
id: _accordionItem_contentId,
'data-slot': 'accordion-content',
'data-accordion-target': 'content',
role: 'region',
'aria-labelledby': _accordionItem_triggerId,
'aria-hidden': not _accordionItem_isOpen ? 'true' : 'false',
'data-open': _accordionItem_isOpen ? 'true' : false,
'data-closed': not _accordionItem_isOpen ? 'true' : false,
style: _accordionItem_isOpen ? 'grid-template-rows: 1fr;' : 'grid-template-rows: 0fr;',
}).without('class') }}
>
<div class="min-h-0 min-w-0 overflow-hidden">
<div class="{{ ('pt-0 pb-2.5 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4 ' ~ attributes.render('class'))|tailwind_merge }}">
{%- block content %}{% endblock -%}
</div>
</div>
</div>

As a result, I’m not sure which approach is the recommended one or what the best practice is.
Should we avoid using attributes.defaults()? When should we use it?

@seb-jean seb-jean force-pushed the fix/shadcn-attributes-defaults-3x branch 2 times, most recently from 53a1321 to d634604 Compare June 17, 2026 15:24
@seb-jean

Copy link
Copy Markdown
Contributor Author

I made multiple commits to make the review easier.

I didn't understand the comment, could you explain how to proceed?

I kept attributes.defaults() on the Label, Separator, Button, Input and Textarea components because in Shadcn, these attributes need to be overridden:

@seb-jean seb-jean force-pushed the fix/shadcn-attributes-defaults-3x branch from d634604 to 54fd53a Compare June 17, 2026 15:29
@seb-jean seb-jean changed the title [Toolkit][Shadcn] Use attributes.defaults() in component templates [Toolkit][Shadcn] Remove attributes.defaults() in component templates Jun 17, 2026
@seb-jean seb-jean force-pushed the fix/shadcn-attributes-defaults-3x branch from 54fd53a to 2a98cae Compare June 17, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Documentation Improvements or additions to documentation Status: Needs Review Needs to be reviewed Toolkit

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants