Skip to content

Commit

Permalink
Add a component for action menus
Browse files Browse the repository at this point in the history
  • Loading branch information
javiereguiluz committed Dec 15, 2024
1 parent 81e468d commit 1c9d979
Show file tree
Hide file tree
Showing 18 changed files with 137 additions and 64 deletions.
3 changes: 3 additions & 0 deletions assets/css/easyadmin-theme/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,9 @@ a.user-menu-wrapper .user-details:hover {
margin: 0 10px 0 4px;
font-size: 15px;
}
.dropdown-menu .icon {
display: inline-flex;
}

.dropdown-menu .dropdown-item,
.dropdown-menu .dropdown-header {
Expand Down
9 changes: 7 additions & 2 deletions assets/css/easyadmin-theme/datagrids.css
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,18 @@ table.datagrid {
border: 1px solid transparent;
border-radius: var(--border-radius);
color: var(--dropdown-toggle-color);
padding: 3px 5px;
display: block;
padding: 1px 3px;
}
/* hides the caret added automatically by Bootstrap */
.datagrid .dropdown-actions .dropdown-toggle:after { display: none; }
.datagrid .dropdown-actions .dropdown-toggle:hover { cursor: pointer; }

.datagrid .dropdown-actions .dropdown-toggle svg { vertical-align: top; }
.datagrid .dropdown-actions .dropdown-toggle .icon {
display: block;
font-size: 21px;
inline-size: unset;
}

.datagrid .dropdown-actions .dropdown-menu { z-index: var(--zindex-900); }

Expand Down
4 changes: 4 additions & 0 deletions assets/icons/internal/dots-horizontal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions config/services.php
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
use EasyCorp\Bundle\EasyAdminBundle\Security\AuthorizationChecker;
use EasyCorp\Bundle\EasyAdminBundle\Security\SecurityVoter;
use EasyCorp\Bundle\EasyAdminBundle\Twig\Component\Alert;
use EasyCorp\Bundle\EasyAdminBundle\Twig\Component\ActionMenu;
use EasyCorp\Bundle\EasyAdminBundle\Twig\Component\Flag;
use EasyCorp\Bundle\EasyAdminBundle\Twig\Component\Icon;
use EasyCorp\Bundle\EasyAdminBundle\Twig\EasyAdminTwigExtension;
Expand Down Expand Up @@ -407,5 +408,8 @@

->set(Alert::class)
->tag('twig.component')

->set(ActionMenu::class)
->tag('twig.component')
;
};
2 changes: 1 addition & 1 deletion public/app.fc5841f9.css → public/app.055a0b6d.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion public/entrypoints.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"entrypoints": {
"app": {
"css": [
"/app.fc5841f9.css"
"/app.055a0b6d.css"
],
"js": [
"/app.1ecd6d7a.js"
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"app.css": "app.fc5841f9.css",
"app.css": "app.055a0b6d.css",
"app.js": "app.1ecd6d7a.js",
"form.js": "form.bcec6c2a.js",
"page-layout.js": "page-layout.3347892e.js",
Expand Down
12 changes: 12 additions & 0 deletions src/DependencyInjection/EasyAdminExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,17 @@ public function prepend(ContainerBuilder $builder): void
],
],
]);

$bundleTemplatesOverrideDir = $builder->getParameter('kernel.project_dir').'/templates/bundles/EasyAdminBundle/';
$builder->prependExtensionConfig('twig', [
'paths' => is_dir($bundleTemplatesOverrideDir)
? [
'templates/bundles/EasyAdminBundle/' => null,
dirname(__DIR__).'/../templates/' => 'ea',
]
: [
dirname(__DIR__).'/../templates/' => 'ea',
],
]);
}
}
8 changes: 8 additions & 0 deletions src/Twig/Component/ActionMenu.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace EasyCorp\Bundle\EasyAdminBundle\Twig\Component;

class ActionMenu
{

}
3 changes: 3 additions & 0 deletions templates/components/ActionMenu.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div {{ attributes.defaults({class: 'dropdown'}) }}>
<twig:block name="content"></twig:block>
</div>
1 change: 1 addition & 0 deletions templates/components/ActionMenu/ActionList.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<twig:block name="content"></twig:block>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
<div class="dropdown-divider"></div>
3 changes: 3 additions & 0 deletions templates/components/ActionMenu/ActionList/Header.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<li {{ attributes.defaults({class: 'dropdown-header'})}}>
<twig:block name="content"></twig:block>
</li>
23 changes: 23 additions & 0 deletions templates/components/ActionMenu/ActionList/Item.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{% props
label = null,
renderLabelRaw = false,
icon = null,
url = null,
%}

<li>
<a {{ attributes.defaults({class: 'dropdown-item', href: url}) }}>
{%- if icon %}<twig:ea:Icon {{ ...attributes.nested('icon').defaults({name: icon}) }} /> {% endif -%}
{%- if label is not empty -%}<span {{ attributes.nested('label') }}>{{ renderLabelRaw ? label|raw : label }}</span>{%- endif -%}
</a>
</li>
{#
<li>
<a class="dropdown-item {{ action.cssClass }}"
href="{{ action.linkUrl }}"
{% for name, value in action.htmlAttributes %}{{ name }}="{{ (value.trans is defined ? value|trans : value)|e('html_attr') }}" {% endfor %}>
{%- if action.icon %}<twig:ea:Icon name="{{ action.icon }}" class="action-icon" /> {% endif -%}
{%- if action.label is not empty -%}<span class="action-label">{{ action.label|trans|raw }}</span>{%- endif -%}
</a>
</li>
#}
11 changes: 11 additions & 0 deletions templates/components/ActionMenu/Button.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% props
withoutDropdownToggleMarker = false,
%}

{% set css_class = html_classes({
'dropdown-toggle': not withoutDropdownToggleMarker,
}) %}

<a {{ attributes.defaults({class: css_class, href: '#', role: 'button', 'data-bs-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false'}) }}>
<twig:block name="content"></twig:block>
</a>
3 changes: 3 additions & 0 deletions templates/components/ActionMenu/Overlay.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<div class="dropdown-menu dropdown-menu-end">
<twig:block name="content"></twig:block>
</div>
31 changes: 16 additions & 15 deletions templates/crud/index.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -160,21 +160,22 @@
<td class="actions {{ ea.crud.showEntityActionsAsDropdown ? 'actions-as-dropdown' }}">
{% if entity.actions.count > 0 %}
{% if ea.crud.showEntityActionsAsDropdown %}
<div class="dropdown dropdown-actions">
<a class="dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{# don't use FontAwesome 'fa-ellipsis-h' icon here because it doesn't look good #}
{# this icon is 'dots-horizontal' icon from https://heroicons.com/ #}
<svg xmlns="http://www.w3.org/2000/svg" height="21" width="21" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 12h.01M12 12h.01M19 12h.01M6 12a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0zm7 0a1 1 0 11-2 0 1 1 0 012 0z" />
</svg>
</a>

<div class="dropdown-menu dropdown-menu-right">
{% for action in entity.actions %}
{{ include(action.templatePath, { action: action, entity: entity, isIncludedInDropdown: ea.crud.showEntityActionsAsDropdown }, with_context = false) }}
{% endfor %}
</div>
</div>
<twig:ea:ActionMenu class="dropdown-actions">
<twig:ea:ActionMenu:Button>
<twig:ea:Icon name="internal:dots-horizontal" />
</twig:ea:ActionMenu:Button>

<twig:ea:ActionMenu:Overlay>
<twig:ea:ActionMenu:ActionList>
{% for action in entity.actions %}
<twig:ea:ActionMenu:ActionList:Item
:class="action.cssClass" :url="action.linkUrl"
:icon="action.icon" icon:class="action-icon"
:label="action.label|trans" label:class="action-label" renderLabelRaw />
{% endfor %}
</twig:ea:ActionMenu:ActionList>
</twig:ea:ActionMenu:Overlay>
</twig:ea:ActionMenu>
{% else %}
{% for action in entity.actions %}
{{ include(action.templatePath, { action: action, entity: entity, isIncludedInDropdown: ea.crud.showEntityActionsAsDropdown }, with_context = false) }}
Expand Down
79 changes: 35 additions & 44 deletions templates/layout.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -117,58 +117,49 @@

{% set settings_dropdown %}
{% if ea.dashboardLocales or ea.dashboardHasDarkModeEnabled %}
<div class="dropdown dropdown-settings">
<a class="dropdown-settings-button" type="button" data-bs-toggle="dropdown" data-bs-offset="0,5" aria-expanded="false">
<twig:ea:ActionMenu class="dropdown-settings">
<twig:ea:ActionMenu:Button class="dropdown-settings-button" data-bs-offset="0,5" withoutDropdownToggleMarker>
<twig:ea:Icon name="internal:gear" />
</a>
</twig:ea:ActionMenu:Button>

<ul class="dropdown-menu dropdown-menu-end">
{% if ea.dashboardLocales %}
<li class="dropdown-header dropdown-locales-label">
<twig:ea:ActionMenu:Overlay>
<twig:ea:ActionMenu:ActionList>
<twig:ea:ActionMenu:ActionList:Header class="dropdown-locales-label">
{{ 'settings.locale'|trans(domain = 'EasyAdminBundle') }}
</li>
</twig:ea:ActionMenu:ActionList:Header>

{% for localeDto in ea.dashboardLocales %}
<li>
<a href="{{ ea_url().set('_locale', localeDto.locale) }}" class="dropdown-item{% if app.request.locale == localeDto.locale %} active{% endif %}">
{% if localeDto.icon %}
<twig:ea:Icon name="{{ localeDto.icon }}" />
{% endif %}
{{ localeDto.name }}
</a>
</li>
<twig:ea:ActionMenu:ActionList:Item
:class="app.request.locale == localeDto.locale ? 'active'"
:url="ea_url().set('_locale', localeDto.locale)"
:icon="localeDto.icon" :label="localeDto.name" />
{% endfor %}
{% endif %}

{% if ea.dashboardHasDarkModeEnabled %}
{% if ea.dashboardLocales %}
<div class="dropdown-divider"></div>
{% endif %}
{% if ea.dashboardHasDarkModeEnabled %}
{% if ea.dashboardLocales %}
<twig:ea:ActionMenu:ActionList:Divider/>
{% endif %}

<li class="dropdown-header dropdown-appearance-label">
{{ 'settings.appearance.label'|trans(domain = 'EasyAdminBundle') }}
</li>
<li>
<a href="#" class="dropdown-item dropdown-appearance-item" data-ea-color-scheme="light">
<twig:ea:Icon name="internal:sun" />
{{ 'settings.appearance.light'|trans(domain = 'EasyAdminBundle') }}
</a>
</li>
<li>
<a href="#" class="dropdown-item dropdown-appearance-item" data-ea-color-scheme="dark">
<twig:ea:Icon name="internal:moon" />
{{ 'settings.appearance.dark'|trans(domain = 'EasyAdminBundle') }}
</a>
</li>
<li>
<a href="#" class="dropdown-item dropdown-appearance-item active" data-ea-color-scheme="auto">
<twig:ea:Icon name="internal:desktop" />
{{ 'settings.appearance.auto'|trans(domain = 'EasyAdminBundle') }}
</a>
</li>
{% endif %}
</ul>
</div>
<twig:ea:ActionMenu:ActionList:Header class="dropdown-appearance-label">
{{ 'settings.appearance.label'|trans(domain = 'EasyAdminBundle') }}
</twig:ea:ActionMenu:ActionList:Header>

<twig:ea:ActionMenu:ActionList:Item
class="dropdown-appearance-item"
url="#" icon="internal:sun" data-ea-color-scheme="light"
:label="'settings.appearance.light'|trans(domain = 'EasyAdminBundle')" />
<twig:ea:ActionMenu:ActionList:Item
class="dropdown-appearance-item"
url="#" icon="internal:moon" data-ea-color-scheme="dark"
:label="'settings.appearance.dark'|trans(domain = 'EasyAdminBundle')" />
<twig:ea:ActionMenu:ActionList:Item
class="dropdown-appearance-item active"
url="#" icon="internal:desktop" data-ea-color-scheme="auto"
:label="'settings.appearance.auto'|trans(domain = 'EasyAdminBundle')" />
{% endif %}
</twig:ea:ActionMenu:ActionList>
</twig:ea:ActionMenu:Overlay>
</twig:ea:ActionMenu>
{% endif %}
{% endset %}

Expand Down

0 comments on commit 1c9d979

Please sign in to comment.