diff --git a/src/Toolkit/kits/shadcn/button-group/EXAMPLES.md b/src/Toolkit/kits/shadcn/button-group/EXAMPLES.md index 2fcb6f20992..f9515136f38 100644 --- a/src/Toolkit/kits/shadcn/button-group/EXAMPLES.md +++ b/src/Toolkit/kits/shadcn/button-group/EXAMPLES.md @@ -2,7 +2,7 @@ ## Default -```twig {"preview":true,"height":"220px"} +```twig {"preview":true,"height":"320px"} ``` diff --git a/src/Toolkit/kits/shadcn/button-group/manifest.json b/src/Toolkit/kits/shadcn/button-group/manifest.json index 562ee0f7661..96ead31c4fb 100644 --- a/src/Toolkit/kits/shadcn/button-group/manifest.json +++ b/src/Toolkit/kits/shadcn/button-group/manifest.json @@ -8,6 +8,6 @@ }, "dependencies": { "composer": ["twig/extra-bundle", "twig/html-extra:^3.12.0", "tales-from-a-dev/twig-tailwind-extra:^1.0.0"], - "recipe": ["separator"] + "recipe": ["dropdown-menu", "separator"] } } diff --git a/src/Toolkit/kits/shadcn/button-group/templates/components/ButtonGroup.html.twig b/src/Toolkit/kits/shadcn/button-group/templates/components/ButtonGroup.html.twig index 4ff7ea3c364..cb3dcd445e9 100644 --- a/src/Toolkit/kits/shadcn/button-group/templates/components/ButtonGroup.html.twig +++ b/src/Toolkit/kits/shadcn/button-group/templates/components/ButtonGroup.html.twig @@ -1,12 +1,14 @@ {# @prop orientation 'horizontal'|'vertical' The orientation, default to `horizontal` #} {# @block content The default block #} {%- props orientation = 'horizontal' -%} +{%- set _dropdown_h = '[&>[data-controller=dropdown-menu]:not(:first-child)_button]:rounded-l-none [&>[data-controller=dropdown-menu]:not(:first-child)_button]:border-l-0 [&>[data-controller=dropdown-menu]:not(:last-child)_button]:rounded-r-none' -%} +{%- set _dropdown_v = '[&>[data-controller=dropdown-menu]:not(:first-child)_button]:rounded-t-none [&>[data-controller=dropdown-menu]:not(:first-child)_button]:border-t-0 [&>[data-controller=dropdown-menu]:not(:last-child)_button]:rounded-b-none' -%} {%- set style = html_cva( base: 'flex w-fit items-stretch [&>*]:focus-visible:z-10 [&>*]:focus-visible:relative [&>[data-slot=select-trigger]:not([class*=\'w-\'])]:w-fit [&>input]:flex-1 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md has-[>[data-slot=button-group]]:gap-2', variants: { orientation: { - horizontal: '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none', - vertical: 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none', + horizontal: '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none ' ~ _dropdown_h, + vertical: 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none ' ~ _dropdown_v, }, }, default_variant: { diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/EXAMPLES.md b/src/Toolkit/kits/shadcn/dropdown-menu/EXAMPLES.md new file mode 100644 index 00000000000..4e4d488e0e6 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/EXAMPLES.md @@ -0,0 +1,218 @@ +# Examples + +## Default + +```twig {"preview":true,"height":"700px"} + + + Open + + + My Account + + + + + Profile + ⇧⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + Keyboard shortcuts + ⌘K + + + + + + + Team + + + + API + + + + + + Log out + ⇧⌘Q + + + +``` + +## Checkboxes + +```twig {"preview":true,"height":"440px"} + + + Open + + + Appearance + + + Status Bar + + + Activity Bar + + + Panel + + + Full Screen + + + +``` + +## Radio Group + +```twig {"preview":true,"height":"440px"} + + + Open + + + Panel Position + + + Top + Bottom + Right + + + +``` + +## Alignment + +```twig {"preview":true,"height":"360px"} +
+ + + Start + + + + + New File + + + + New Folder + + + + + + + Center + + + + + New File + + + + New Folder + + + + + + + End + + + + + New File + + + + New Folder + + + +
+``` + +## With Dialog + +```twig {"preview":true,"height":"500px"} + + + + Open + + + My Account + + + + + Profile + ⇧⌘P + + + + Billing + ⌘B + + + + Settings + ⌘S + + + + + + + + + Invite team members + + Invite your team members to collaborate. + + +
+
+ Email address + +
+
+ + + Cancel + + Send invite + +
+
+``` diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/assets/controllers/dropdown_menu_controller.js b/src/Toolkit/kits/shadcn/dropdown-menu/assets/controllers/dropdown_menu_controller.js new file mode 100644 index 00000000000..30e7abcec65 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/assets/controllers/dropdown_menu_controller.js @@ -0,0 +1,222 @@ +import { Controller } from '@hotwired/stimulus'; +import '../styles/dropdown-menu.css'; + +export default class extends Controller { + static targets = ['trigger', 'content', 'item', 'radioGroup']; + static values = { + open: Boolean, + }; + + connect() { + this._onPopoverToggle = this._onPopoverToggle.bind(this); + this.contentTarget.addEventListener('toggle', this._onPopoverToggle); + + if (this.openValue) { + requestAnimationFrame(() => this.open({ focus: false })); + } + } + + disconnect() { + this.contentTarget.removeEventListener('toggle', this._onPopoverToggle); + } + + toggle(event) { + if (event) { + event.preventDefault(); + } + this.contentTarget.togglePopover(); + } + + open({ focus } = { focus: true }) { + this.contentTarget.showPopover(); + if (focus) { + this._focusFirstItem(); + } + } + + close({ focus } = { focus: true }) { + this.contentTarget.hidePopover(); + if (focus && this.hasTriggerTarget) { + this.triggerTarget.focus(); + } + } + + closeFromItem(event) { + const item = event.currentTarget; + if (this._isItemDisabled(item)) { + event.preventDefault(); + return; + } + + if (item.dataset.closeOnSelect === 'false') { + return; + } + + this.close({ focus: true }); + } + + toggleCheckbox(event) { + const item = event.currentTarget; + if (this._isItemDisabled(item)) { + event.preventDefault(); + return; + } + + const isChecked = item.getAttribute('aria-checked') === 'true'; + const newChecked = !isChecked; + + item.setAttribute('aria-checked', String(newChecked)); + + const indicator = item.querySelector('[data-checkbox-indicator]'); + if (indicator) { + indicator.hidden = !newChecked; + } + + if (item.dataset.closeOnSelect === 'true') { + this.close({ focus: true }); + } + } + + selectRadio(event) { + const item = event.currentTarget; + if (this._isItemDisabled(item)) { + event.preventDefault(); + return; + } + + const radioGroup = item.closest('[data-dropdown-menu-target="radioGroup"]'); + if (!radioGroup) { + return; + } + + const value = item.dataset.value; + radioGroup.dataset.value = value; + + const radioItems = radioGroup.querySelectorAll('[role="menuitemradio"]'); + radioItems.forEach((radioItem) => { + const isSelected = radioItem.dataset.value === value; + radioItem.setAttribute('aria-checked', String(isSelected)); + + const indicator = radioItem.querySelector('[data-radio-indicator]'); + if (indicator) { + indicator.hidden = !isSelected; + } + }); + + if (item.dataset.closeOnSelect === 'true') { + this.close({ focus: true }); + } + } + + onTriggerKeydown(event) { + const { key } = event; + + if (key === 'ArrowDown') { + event.preventDefault(); + this.open({ focus: false }); + this._focusFirstItem(); + return; + } + + if (key === 'ArrowUp') { + event.preventDefault(); + this.open({ focus: false }); + this._focusLastItem(); + } + + // Enter/Space are handled natively by popovertarget attribute + } + + onContentKeydown(event) { + const { key } = event; + + switch (key) { + case 'Escape': + this.triggerTarget.focus(); + break; + + case 'ArrowDown': + event.preventDefault(); + this._focusNextItem(); + break; + + case 'ArrowUp': + event.preventDefault(); + this._focusPrevItem(); + break; + + case 'Home': + event.preventDefault(); + this._focusFirstItem(); + break; + + case 'End': + event.preventDefault(); + this._focusLastItem(); + break; + + case 'Tab': + this.close({ focus: false }); + break; + } + } + + _onPopoverToggle(event) { + const isOpen = event.newState === 'open'; + this._updateState(isOpen); + } + + _updateState(isOpen) { + const state = isOpen ? 'open' : 'closed'; + + this.element.dataset.state = state; + this.triggerTarget.dataset.state = state; + this.contentTarget.dataset.state = state; + this.triggerTarget.setAttribute('aria-expanded', String(isOpen)); + } + + _isItemDisabled(item) { + return ( + !item || + item.getAttribute('aria-disabled') === 'true' || + item.dataset.disabled === 'true' || + item.hasAttribute('disabled') + ); + } + + _enabledItems() { + return this.itemTargets.filter((item) => !this._isItemDisabled(item)); + } + + _focusFirstItem() { + const items = this._enabledItems(); + if (items.length > 0) { + items[0].focus(); + } + } + + _focusLastItem() { + const items = this._enabledItems(); + if (items.length > 0) { + items[items.length - 1].focus(); + } + } + + _focusNextItem() { + const items = this._enabledItems(); + if (items.length === 0) return; + + const currentIndex = items.indexOf(document.activeElement); + const nextIndex = currentIndex === -1 ? 0 : (currentIndex + 1) % items.length; + items[nextIndex].focus(); + } + + _focusPrevItem() { + const items = this._enabledItems(); + if (items.length === 0) return; + + const currentIndex = items.indexOf(document.activeElement); + const prevIndex = currentIndex === -1 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length; + items[prevIndex].focus(); + } +} diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/assets/styles/dropdown-menu.css b/src/Toolkit/kits/shadcn/dropdown-menu/assets/styles/dropdown-menu.css new file mode 100644 index 00000000000..9a8c270c9b5 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/assets/styles/dropdown-menu.css @@ -0,0 +1,160 @@ +.dropdown-menu-content { + margin: 0; +} + +.dropdown-menu-content::backdrop { + background: transparent; +} + +@supports (anchor-name: --test) { + .dropdown-menu-content { + position: fixed; + inset: unset; + + position-area: block-end span-inline-start; + margin-block-start: var(--dropdown-offset, 8px); + + position-try-fallbacks: + block-start span-inline-start, + block-end span-inline-end, + block-start span-inline-end; + + position-visibility: anchors-visible; + } + + .dropdown-menu-content[data-side="top"] { + position-area: block-start span-inline-start; + margin-block-start: 0; + margin-block-end: var(--dropdown-offset, 8px); + position-try-fallbacks: + block-end span-inline-start, + block-start span-inline-end, + block-end span-inline-end; + } + + .dropdown-menu-content[data-side="left"] { + position-area: inline-start span-block-start; + margin-block-start: 0; + margin-inline-end: var(--dropdown-offset, 8px); + position-try-fallbacks: + inline-end span-block-start, + inline-start span-block-end, + inline-end span-block-end; + } + + .dropdown-menu-content[data-side="right"] { + position-area: inline-end span-block-start; + margin-block-start: 0; + margin-inline-start: var(--dropdown-offset, 8px); + position-try-fallbacks: + inline-start span-block-start, + inline-end span-block-end, + inline-start span-block-end; + } + + .dropdown-menu-content[data-side="bottom"][data-align="center"] { + position-area: block-end; + justify-self: anchor-center; + } + + .dropdown-menu-content[data-side="top"][data-align="center"] { + position-area: block-start; + justify-self: anchor-center; + } + + .dropdown-menu-content[data-side="bottom"][data-align="end"] { + position-area: block-end span-inline-end; + } + + .dropdown-menu-content[data-side="top"][data-align="end"] { + position-area: block-start span-inline-end; + } + + .dropdown-menu-content[data-side="left"][data-align="center"] { + position-area: inline-start; + align-self: anchor-center; + } + + .dropdown-menu-content[data-side="right"][data-align="center"] { + position-area: inline-end; + align-self: anchor-center; + } + + .dropdown-menu-content[data-side="left"][data-align="end"] { + position-area: inline-start span-block-end; + } + + .dropdown-menu-content[data-side="right"][data-align="end"] { + position-area: inline-end span-block-end; + } +} + +@supports not (anchor-name: --test) { + .dropdown-menu-content { + position: absolute; + + top: 100%; + left: 0; + right: auto; + bottom: auto; + margin-top: var(--dropdown-offset, 8px); + transform: none; + } + + .dropdown-menu-content[data-side="top"] { + top: auto; + bottom: 100%; + left: 0; + right: auto; + margin-top: 0; + margin-bottom: var(--dropdown-offset, 8px); + } + + .dropdown-menu-content[data-side="left"] { + top: 0; + bottom: auto; + left: auto; + right: 100%; + margin-top: 0; + margin-right: var(--dropdown-offset, 8px); + } + + .dropdown-menu-content[data-side="right"] { + top: 0; + bottom: auto; + left: 100%; + right: auto; + margin-top: 0; + margin-left: var(--dropdown-offset, 8px); + } + + .dropdown-menu-content[data-align="center"] { + left: 50%; + right: auto; + transform: translateX(-50%); + } + + .dropdown-menu-content[data-align="end"] { + left: auto; + right: 0; + } + + .dropdown-menu-content[data-side="left"][data-align="center"], + .dropdown-menu-content[data-side="right"][data-align="center"] { + top: 50%; + left: auto; + transform: translateY(-50%); + } + + .dropdown-menu-content[data-side="right"][data-align="center"] { + left: 100%; + right: auto; + } + + .dropdown-menu-content[data-side="left"][data-align="end"], + .dropdown-menu-content[data-side="right"][data-align="end"] { + top: auto; + bottom: 0; + transform: none; + } +} diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/manifest.json b/src/Toolkit/kits/shadcn/dropdown-menu/manifest.json new file mode 100644 index 00000000000..49211dc3ab0 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/manifest.json @@ -0,0 +1,13 @@ +{ + "$schema": "../../../schema-kit-recipe-v1.json", + "type": "component", + "name": "Dropdown Menu", + "description": "A menu triggered by a button, providing a list of actions or links.", + "copy-files": { + "assets/": "assets/", + "templates/": "templates/" + }, + "dependencies": { + "composer": ["twig/extra-bundle", "twig/html-extra:^3.12.0", "tales-from-a-dev/twig-tailwind-extra:^1.0.0"] + } +} diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu.html.twig new file mode 100644 index 00000000000..f8929050b36 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu.html.twig @@ -0,0 +1,25 @@ +{# @prop id string Unique suffix identifier for generating DropdownMenu internal IDs #} +{# @prop open boolean Open (or not) the DropdownMenu at initial rendering, default to `false` #} +{# @prop side 'bottom'|'top'|'left'|'right' The preferred side of the trigger where the menu appears, default to `bottom` #} +{# @prop align 'start'|'center'|'end' How the menu aligns to the trigger, default to `start` #} +{# @prop sideOffset number The distance in pixels from the trigger, default to `8` #} +{# @block content The default block #} +{%- props id, open = false, side = 'bottom', align = 'start', sideOffset = 8 -%} + +{%- set _dropdown_menu_id = 'dropdown-menu-' ~ id -%} +{%- set _dropdown_menu_trigger_id = _dropdown_menu_id ~ '-trigger' -%} +{%- set _dropdown_menu_content_id = _dropdown_menu_id ~ '-content' -%} +{%- set _dropdown_menu_anchor_name = '--dropdown-anchor-' ~ id -%} +{%- set _dropdown_menu_side = side -%} +{%- set _dropdown_menu_align = align -%} +{%- set _dropdown_menu_side_offset = sideOffset -%} + +
+ {% block content %}{% endblock %} +
diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/CheckboxItem.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/CheckboxItem.html.twig new file mode 100644 index 00000000000..470587d4594 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/CheckboxItem.html.twig @@ -0,0 +1,25 @@ +{# @prop checked boolean Whether the checkbox is checked, default to `false` #} +{# @prop disabled boolean Whether the item is disabled, default to `false` #} +{# @prop closeOnSelect boolean Whether selecting the item closes the menu, default to `false` #} +{# @block content The default block #} +{%- props checked = false, disabled = false, closeOnSelect = false -%} + + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Content.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Content.html.twig new file mode 100644 index 00000000000..116381407d5 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Content.html.twig @@ -0,0 +1,22 @@ +{# @block content The default block #} +{%- set style = html_cva( + base: 'z-50 m-0 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md outline-none dropdown-menu-content scale-95 opacity-0 transition-all transition-discrete duration-200 open:scale-100 open:opacity-100 starting:open:scale-95 starting:open:opacity-0', +) -%} + + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Group.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Group.html.twig new file mode 100644 index 00000000000..4a2f3d96a7c --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Group.html.twig @@ -0,0 +1,4 @@ +{# @block content The default block #} +
+ {%- block content %}{% endblock -%} +
diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Item.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Item.html.twig new file mode 100644 index 00000000000..fc9a7a51dfa --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Item.html.twig @@ -0,0 +1,31 @@ +{# @prop as 'button'|'a'|'div' The HTML tag to use, default to `button` #} +{# @prop disabled boolean Whether the item is disabled, default to `false` #} +{# @prop closeOnSelect boolean Whether selecting the item closes the menu, default to `true` #} +{# @prop inset boolean Whether the item should be inset, default to `false` #} +{# @block content The default block #} +{%- props as = 'button', disabled = false, closeOnSelect = true, inset = false -%} +{%- set style = html_cva( + base: 'relative flex w-full cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg:not([class*=size-])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0', + variants: { + inset: { + true: 'pl-8', + false: '', + }, + }, +) -%} + +<{{ as }} + role="menuitem" + tabindex="-1" + data-dropdown-menu-target="item" + data-action="click->dropdown-menu#closeFromItem" + data-close-on-select="{{ closeOnSelect ? 'true' : 'false' }}" + data-disabled="{{ disabled ? 'true' : 'false' }}" + aria-disabled="{{ disabled ? 'true' : 'false' }}" + {% if as == 'button' %}type="button"{% endif %} + {% if as == 'button' and disabled %}disabled{% endif %} + class="{{ style.apply({inset: inset ? 'true' : 'false'}, attributes.render('class'))|tailwind_merge }}" + {{ attributes.without('role', 'tabindex', 'type') }} +> + {%- block content %}{% endblock -%} + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Label.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Label.html.twig new file mode 100644 index 00000000000..c9bd2b3567c --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Label.html.twig @@ -0,0 +1,19 @@ +{# @prop inset boolean Whether the label should be inset, default to `false` #} +{# @block content The default block #} +{%- props inset = false -%} +{%- set style = html_cva( + base: 'px-2 py-1.5 text-sm font-semibold', + variants: { + inset: { + true: 'pl-8', + false: '', + }, + }, +) -%} + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioGroup.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioGroup.html.twig new file mode 100644 index 00000000000..9fd760e0f03 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioGroup.html.twig @@ -0,0 +1,13 @@ +{# @prop value string|null The currently selected value, default to `null` #} +{# @block content The default block #} +{%- props value = null -%} + +
+ {%- block content %}{% endblock -%} +
diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioItem.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioItem.html.twig new file mode 100644 index 00000000000..4fb03ff9e20 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/RadioItem.html.twig @@ -0,0 +1,27 @@ +{# @prop value string The value of this radio item #} +{# @prop checked boolean Whether the item is checked, default to `false` #} +{# @prop disabled boolean Whether the item is disabled, default to `false` #} +{# @prop closeOnSelect boolean Whether selecting the item closes the menu, default to `false` #} +{# @block content The default block #} +{%- props value, checked = false, disabled = false, closeOnSelect = false -%} + + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Separator.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Separator.html.twig new file mode 100644 index 00000000000..4863634eab1 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Separator.html.twig @@ -0,0 +1,6 @@ + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Shortcut.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Shortcut.html.twig new file mode 100644 index 00000000000..af3aa18da5f --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Shortcut.html.twig @@ -0,0 +1,7 @@ +{# @block content The default block #} + + {%- block content %}{% endblock -%} + diff --git a/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Trigger.html.twig b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Trigger.html.twig new file mode 100644 index 00000000000..4c493988999 --- /dev/null +++ b/src/Toolkit/kits/shadcn/dropdown-menu/templates/components/DropdownMenu/Trigger.html.twig @@ -0,0 +1,13 @@ +{# @block content The default block #} +{%- set trigger_attrs = { + id: _dropdown_menu_trigger_id, + 'aria-haspopup': 'menu', + 'aria-controls': _dropdown_menu_content_id, + 'aria-expanded': 'false', + popovertarget: _dropdown_menu_content_id, + 'data-dropdown-menu-target': 'trigger', + 'data-action': 'keydown->dropdown-menu#onTriggerKeydown', + 'data-state': 'closed', + style: 'anchor-name: ' ~ _dropdown_menu_anchor_name, +} -%} +{%- block content %}{% endblock -%} diff --git a/src/Toolkit/kits/shadcn/kbd/templates/components/Kbd.html.twig b/src/Toolkit/kits/shadcn/kbd/templates/components/Kbd.html.twig index ef6451a97c2..56a6b5a35af 100644 --- a/src/Toolkit/kits/shadcn/kbd/templates/components/Kbd.html.twig +++ b/src/Toolkit/kits/shadcn/kbd/templates/components/Kbd.html.twig @@ -1,7 +1,7 @@ {# @block content The default block #} {%- block content %}{% endblock -%} diff --git a/src/Toolkit/tests/Functional/__snapshots__/ComponentsRenderingTest__testComponentRendering with data set Kit shadcn, component button-group, code 1__1.html b/src/Toolkit/tests/Functional/__snapshots__/ComponentsRenderingTest__testComponentRendering with data set Kit shadcn, component button-group, code 1__1.html index e91a4f59de5..ee16df6fdd9 100644 --- a/src/Toolkit/tests/Functional/__snapshots__/ComponentsRenderingTest__testComponentRendering with data set Kit shadcn, component button-group, code 1__1.html +++ b/src/Toolkit/tests/Functional/__snapshots__/ComponentsRenderingTest__testComponentRendering with data set Kit shadcn, component button-group, code 1__1.html @@ -18,27 +18,85 @@ Snooze - - - + + + + + + + + + + Reply in thread + + + + Forward + + + + Add to starred + + + + + Mute + + + + Mark as unread + + + + + Delete + + + ``` - Rendered code (prettified for testing purposes, run "php vendor/bin/phpunit -d --update-snapshots" to update snapshots): --> -
-