Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{# @prop open boolean Open (or not) the AlertDialog at initial rendering, default to `false` #}
{# @prop id string Unique suffix identifier for generating AlertDialog internal IDs #}
{# @block content The default block #}
{%- props open = false, id -%}

Expand Down
85 changes: 85 additions & 0 deletions src/Toolkit/kits/shadcn/dialog/EXAMPLES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Examples

## Default

```twig {"preview":true,"height":"500px"}
<twig:Dialog id="delete_account">
<twig:Dialog:Trigger>
<twig:Button {{ ...trigger_attrs }}>Open</twig:Button>
</twig:Dialog:Trigger>
<twig:Dialog:Content>
<twig:Dialog:Header>
<twig:Dialog:Title>Are you absolutely sure?</twig:Dialog:Title>
<twig:Dialog:Description>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</twig:Dialog:Description>
</twig:Dialog:Header>
</twig:Dialog:Content>
</twig:Dialog>
```

## Custom close button

```twig {"preview":true,"height":"500px"}
<twig:Dialog id="share_link">
<twig:Dialog:Trigger>
<twig:Button variant="outline" {{ ...trigger_attrs }}>Share</twig:Button>
</twig:Dialog:Trigger>
<twig:Dialog:Content class="sm:max-w-md">
<twig:Dialog:Header>
<twig:Dialog:Title>Share link</twig:Dialog:Title>
<twig:Dialog:Description>
Anyone who has this link will be able to view this.
</twig:Dialog:Description>
</twig:Dialog:Header>
<div class="flex items-center gap-2">
<div class="grid flex-1 gap-2">
<twig:Label for="link" class="sr-only">Link</twig:Label>
<twig:Input id="link" value="https://ui.shadcn.com/docs/installation" readonly />
</div>
</div>
<twig:Dialog:Footer class="sm:justify-start">
<twig:Dialog:Close>
<twig:Button type="button" variant="secondary" {{ ...close_attrs }}>
Close
</twig:Button>
</twig:Dialog:Close>
</twig:Dialog:Footer>
</twig:Dialog:Content>
</twig:Dialog>
```

## With form

```twig {"preview":true,"height":"500px"}
<twig:Dialog id="edit_profile">
<twig:Dialog:Trigger>
<twig:Button {{ ...trigger_attrs }} variant="outline">Open Dialog</twig:Button>
</twig:Dialog:Trigger>
<twig:Dialog:Content class="sm:max-w-[425px]">
<twig:Dialog:Header>
<twig:Dialog:Title>Edit profile</twig:Dialog:Title>
<twig:Dialog:Description>
Make changes to your profile here. Click save when you&apos;re done.
</twig:Dialog:Description>
</twig:Dialog:Header>
<div class="grid gap-4">
<div class="grid gap-3">
<twig:Label for="name">Name</twig:Label>
<twig:Input id="name" name="name" value="Pedro Duarte" />
</div>
<div class="grid gap-3">
<twig:Label for="username">Username</twig:Label>
<twig:Input id="username" name="username" value="@peduarte" />
</div>
</div>
<twig:Dialog:Footer>
<twig:Dialog:Close>
<twig:Button variant="outline" {{ ...close_attrs }}>Cancel</twig:Button>
</twig:Dialog:Close>
<twig:Button type="submit">Save changes</twig:Button>
</twig:Dialog:Footer>
</twig:Dialog:Content>
</twig:Dialog>
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Controller } from '@hotwired/stimulus';
import { enter, leave } from 'el-transition';

export default class extends Controller {

static targets = ['trigger', 'overlay', 'dialog', 'content'];

async open() {
this.dialogTarget.showModal();

await Promise.all([enter(this.overlayTarget), enter(this.contentTarget)]);

if (this.hasTriggerTarget) {
this.triggerTarget.setAttribute('aria-expanded', 'true');
}
}

async closeOnClickOutside({ target }) {
if (target === this.overlayTarget) {
await this.close()
}
}

async close() {
await Promise.all([leave(this.overlayTarget), leave(this.contentTarget)]);

this.dialogTarget.close();

if (this.hasTriggerTarget) {
this.triggerTarget.setAttribute('aria-expanded', 'false');
}
}
}
15 changes: 15 additions & 0 deletions src/Toolkit/kits/shadcn/dialog/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"$schema": "../../../schema-kit-recipe-v1.json",
"type": "component",
"name": "Dialog",
"description": "A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.",
"copy-files": {
"assets/": "assets/",
"templates/": "templates/"
},
"dependencies": {
"composer": ["symfony/ux-icons", "twig/extra-bundle", "twig/html-extra:^3.12.0", "tales-from-a-dev/twig-tailwind-extra"],
"npm": ["el-transition"],
"importmap": ["el-transition"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{# @prop open boolean Open (or not) the Dialog at initial rendering, default to `false` #}
Copy link
Member

Choose a reason for hiding this comment

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

Missing @prop for id

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just added it.

{# @prop id string Unique suffix identifier for generating Dialog internal IDs #}
{# @block content The default block #}
{%- props open = false, id -%}

{%- set _dialog_open = open %}
{%- set _dialog_id = 'dialog-' ~ id -%}
{%- set _dialog_title_id = _dialog_id ~ '-title' -%}
{%- set _dialog_description_id = _dialog_id ~ '-description' -%}
<div {{ attributes.defaults({
'data-controller': 'dialog',
'aria-labelledby': _dialog_title_id,
'aria-describedby': _dialog_description_id,
}) }}>
{% block content %}{% endblock %}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{# @block content The default block #}
{%- set close_attrs = {
'data-action': 'click->dialog#close',
} -%}
{%- block content %}{% endblock -%}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{# @prop showCloseButton boolean Whether the close button is shown, default to `true` #}
{# @block content The default block #}
{%- props showCloseButton = true -%}

<dialog
id="{{ _dialog_id }}"
{{ _dialog_open ? 'open' }}
class="{{ 'fixed inset-0 size-auto max-h-none max-w-none overflow-y-auto bg-transparent backdrop:bg-transparent ' ~ attributes.render('class')|tailwind_merge }}"
data-dialog-target="dialog"
data-action="keydown.esc->dialog#close:prevent click->dialog#closeOnClickOutside"
{{ attributes.without('id') }}
>
<div
data-dialog-target="overlay"
data-transition-enter="transition ease-out duration-100"
data-transition-enter-start="transform opacity-0"
data-transition-enter-end="transform opacity-100"
data-transition-leave="transition ease-in duration-75"
data-transition-leave-start="transform opacity-100"
data-transition-leave-end="transform opacity-0"
class="{{ _dialog_open ? '' : 'hidden' }} fixed inset-0 z-50 bg-black/50"
></div>

<section
tabindex="0"
class="flex min-h-full items-end justify-center p-4 text-center focus:outline-none sm:items-center sm:p-0"
>

<div
data-transition-enter="transition ease-out duration-200"
data-transition-enter-start="transform opacity-0 scale-95"
data-transition-enter-end="transform opacity-100 scale-100"
data-transition-leave="transition ease-in duration-75"
data-transition-leave-start="transform opacity-100 scale-100"
data-transition-leave-end="transform opacity-0 scale-95"
class="{{ _dialog_open ? '' : 'hidden' }} bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg sm:max-w-lg"
data-dialog-target="content"
>
{%- block content %}{% endblock -%}
{% if showCloseButton %}
<button type="button" class="ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4" data-action="click->dialog#close">
<twig:ux:icon name="lucide:x" />
<span class="sr-only">Close</span>
</button>
{% endif %}
</div>
</section>
</dialog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{# @block content The default block #}
<p
id="{{ _dialog_description_id }}"
class="{{ 'text-muted-foreground text-sm ' ~ attributes.render('class')|tailwind_merge }}"
{{ attributes.without('id') }}
>
{%- block content %}{% endblock -%}
</p>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{# @block content The default block #}
<footer
class="{{ 'flex flex-col-reverse gap-2 sm:flex-row sm:justify-end ' ~ attributes.render('class')|tailwind_merge }}"
{{ attributes }}
>
{%- block content %}{% endblock -%}
</footer>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{# @block content The default block #}
<header
class="{{ 'flex flex-col gap-2 text-center sm:text-left ' ~ attributes.render('class')|tailwind_merge }}"
{{ attributes }}
>
{%- block content %}{% endblock -%}
</header>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{# @block content The default block #}
<h2
id="{{ _dialog_title_id }}"
class="{{ 'text-lg leading-none font-semibold ' ~ attributes.render('class')|tailwind_merge }}"
{{ attributes.without('id') }}
>
{%- block content %}{% endblock -%}
</h2>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{# @block content The default block #}
{%- set trigger_attrs = {
'data-action': 'click->dialog#open',
'data-dialog-target': 'trigger',
'aria-haspopup': 'dialog',
'aria-expanded': _dialog_open ? 'true' : 'false',
} -%}
{%- block content %}{% endblock -%}
2 changes: 1 addition & 1 deletion src/Toolkit/kits/shadcn/label/EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

```twig {"preview":true}
<div class="grid w-full max-w-sm items-center gap-1.5">
<twig:Label for="email" class="after:content-['*'] after:ml-0.5 after:text-red-500">Email</twig:Label>
<twig:Label for="email" class="gap-0 after:content-['*'] after:ml-0.5 after:text-red-500">Email</twig:Label>
<twig:Input type="email" id="email" placeholder="Enter your email" />
</div>
```
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{# @block content The default block #}
<label
class="{{ ('text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 ' ~ attributes.render('class'))|tailwind_merge }}"
class="{{ ('flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50 ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes }}
>
{%- block content %}{% endblock -%}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
<div class="flex items-center space-x-2">
<input type="checkbox" class="peer size-4 inline-block align-middle accent-primary " id="terms">

<label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="terms">Accept terms and conditions</label>
<label class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50" for="terms">Accept terms and conditions</label>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
<div class="flex items-center space-x-2">
<input type="checkbox" class="peer size-4 inline-block align-middle accent-primary " id="terms" disabled>

<label class="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="terms">Accept terms and conditions</label>
<label class="flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50" for="terms">Accept terms and conditions</label>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!--
- Kit: Shadcn UI
- Component: Dialog
- Code:
```twig
<twig:Dialog id="delete_account">
<twig:Dialog:Trigger>
<twig:Button {{ ...trigger_attrs }}>Open</twig:Button>
</twig:Dialog:Trigger>
<twig:Dialog:Content>
<twig:Dialog:Header>
<twig:Dialog:Title>Are you absolutely sure?</twig:Dialog:Title>
<twig:Dialog:Description>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</twig:Dialog:Description>
</twig:Dialog:Header>
</twig:Dialog:Content>
</twig:Dialog>
```
- Rendered code (prettified for testing purposes, run "php vendor/bin/phpunit -d --update-snapshots" to update snapshots): -->
<div data-controller="dialog" aria-labelledby="dialog-delete_account-title" aria-describedby="dialog-delete_account-description">
<button data-slot="button" class="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&amp;_svg]:pointer-events-none [&amp;_svg:not([class*='size-'])]:size-4 shrink-0 [&amp;_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive bg-primary text-primary-foreground hover:bg-primary/90 h-9 px-4 py-2 has-[&gt;svg]:px-3" data-action="click-&gt;dialog#open" data-dialog-target="trigger" aria-haspopup="dialog" aria-expanded="false">Open</button>
<dialog id="dialog-delete_account" class="fixed inset-0 size-auto max-h-none max-w-none overflow-y-auto bg-transparent backdrop:bg-transparent " data-dialog-target="dialog" data-action="keydown.esc-&gt;dialog#close:prevent click-&gt;dialog#closeOnClickOutside">
<div data-dialog-target="overlay" data-transition-enter="transition ease-out duration-100" data-transition-enter-start="transform opacity-0" data-transition-enter-end="transform opacity-100" data-transition-leave="transition ease-in duration-75" data-transition-leave-start="transform opacity-100" data-transition-leave-end="transform opacity-0" class="hidden fixed inset-0 z-50 bg-black/50"></div>

<section tabindex="0" class="flex min-h-full items-end justify-center p-4 text-center focus:outline-none sm:items-center sm:p-0">

<div data-transition-enter="transition ease-out duration-200" data-transition-enter-start="transform opacity-0 scale-95" data-transition-enter-end="transform opacity-100 scale-100" data-transition-leave="transition ease-in duration-75" data-transition-leave-start="transform opacity-100 scale-100" data-transition-leave-end="transform opacity-0 scale-95" class="hidden bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg sm:max-w-lg" data-dialog-target="content">
<header class="flex flex-col gap-2 text-center sm:text-left "><h2 id="dialog-delete_account-title" class="text-lg leading-none font-semibold ">Are you absolutely sure?</h2>
<p id="dialog-delete_account-description" class="text-muted-foreground text-sm ">This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</p>
</header>
<button type="button" class="ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&amp;_svg]:pointer-events-none [&amp;_svg]:shrink-0 [&amp;_svg:not([class*='size-'])]:size-4" data-action="click-&gt;dialog#close">
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" fill="currentColor" aria-hidden="true"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M18 6L6 18M6 6l12 12"></path></svg>
<span class="sr-only">Close</span>
</button>
</div>
</section>
</dialog>
</div>
Loading
Loading