Merge pull request #7289 from tchak/feat-stimulus-menu-button
Améliore l'accessibilité des boutons qui font apparaître un menu
This commit is contained in:
commit
bc9a90bd08
21 changed files with 323 additions and 74 deletions
|
@ -6,6 +6,7 @@ import { GeoAreaController } from './geo_area_controller';
|
|||
import { TurboInputController } from './turbo_input_controller';
|
||||
import { AutosaveController } from './autosave_controller';
|
||||
import { AutosaveStatusController } from './autosave_status_controller';
|
||||
import { MenuButtonController } from './menu_button_controller';
|
||||
|
||||
const Stimulus = Application.start();
|
||||
Stimulus.register('react', ReactController);
|
||||
|
@ -14,3 +15,4 @@ Stimulus.register('geo-area', GeoAreaController);
|
|||
Stimulus.register('turbo-input', TurboInputController);
|
||||
Stimulus.register('autosave', AutosaveController);
|
||||
Stimulus.register('autosave-status', AutosaveStatusController);
|
||||
Stimulus.register('menu-button', MenuButtonController);
|
||||
|
|
257
app/javascript/controllers/menu_button_controller.ts
Normal file
257
app/javascript/controllers/menu_button_controller.ts
Normal file
|
@ -0,0 +1,257 @@
|
|||
import { ApplicationController } from './application_controller';
|
||||
|
||||
export class MenuButtonController extends ApplicationController {
|
||||
static targets = ['button', 'menu'];
|
||||
|
||||
declare readonly buttonTarget: HTMLButtonElement;
|
||||
declare readonly menuTarget: HTMLElement;
|
||||
|
||||
#isOpen = false;
|
||||
#teardown?: () => void;
|
||||
|
||||
connect() {
|
||||
this.setup();
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
this.#teardown?.();
|
||||
}
|
||||
|
||||
private get isMenu() {
|
||||
return !(this.element as HTMLElement).dataset.popover;
|
||||
}
|
||||
|
||||
private setup() {
|
||||
this.buttonTarget.setAttribute(
|
||||
'aria-haspopup',
|
||||
this.isMenu ? 'menu' : 'true'
|
||||
);
|
||||
this.buttonTarget.setAttribute('aria-controls', this.menuTarget.id);
|
||||
if (!this.buttonTarget.id) {
|
||||
this.buttonTarget.id = `${this.menuTarget.id}_button`;
|
||||
}
|
||||
|
||||
this.menuTarget.setAttribute('aria-labelledby', this.buttonTarget.id);
|
||||
this.menuTarget.setAttribute('role', this.isMenu ? 'menu' : 'region');
|
||||
this.menuTarget.classList.add('fade-in-down');
|
||||
this.menuTarget.setAttribute('tab-index', '-1');
|
||||
|
||||
if (this.isMenu) {
|
||||
for (const menuItem of this.menuTarget.querySelectorAll('a')) {
|
||||
menuItem.setAttribute('role', 'menuitem');
|
||||
}
|
||||
}
|
||||
|
||||
this.on('click', (event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (this.buttonTarget == target || this.buttonTarget.contains(target)) {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.#isOpen) {
|
||||
this.close();
|
||||
} else {
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
});
|
||||
this.on('keydown', (event: KeyboardEvent) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (this.buttonTarget == target) {
|
||||
this.onButtonKeydown(event);
|
||||
} else if (
|
||||
this.isMenu &&
|
||||
(this.menuTarget == target || this.menuTarget.contains(target))
|
||||
) {
|
||||
this.onMenuKeydown(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private open(focusMenuItem: 'first' | 'last' = 'first') {
|
||||
this.buttonTarget.setAttribute('aria-expanded', '');
|
||||
this.menuTarget.parentElement?.classList.add('open');
|
||||
this.menuTarget.focus();
|
||||
|
||||
const onClickBody = (event: Event) => {
|
||||
const target = event.target as HTMLElement;
|
||||
if (this.isClickOutside(target)) {
|
||||
this.menuTarget.classList.remove('fade-in-down');
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
requestAnimationFrame(() => {
|
||||
if (focusMenuItem == 'first') {
|
||||
this.setFocusToFirstMenuitem();
|
||||
} else {
|
||||
this.setFocusToLastMenuitem();
|
||||
}
|
||||
document.body.addEventListener('click', onClickBody);
|
||||
});
|
||||
|
||||
this.#isOpen = true;
|
||||
this.#teardown = () =>
|
||||
document.body.removeEventListener('click', onClickBody);
|
||||
}
|
||||
|
||||
private close() {
|
||||
this.buttonTarget.removeAttribute('aria-expanded');
|
||||
this.menuTarget.parentElement?.classList.remove('open');
|
||||
this.#teardown?.();
|
||||
this.setFocusToMenuitem(null);
|
||||
this.#isOpen = false;
|
||||
}
|
||||
|
||||
private isClickOutside(target: HTMLElement) {
|
||||
return (
|
||||
target.isConnected &&
|
||||
!this.element.contains(target) &&
|
||||
!target.closest('reach-portal') &&
|
||||
this.#isOpen
|
||||
);
|
||||
}
|
||||
|
||||
private get currentMenuItem() {
|
||||
return this.menuTarget.querySelector<HTMLElement>(
|
||||
'[role="menuitem"]:focus'
|
||||
);
|
||||
}
|
||||
|
||||
private get menuItems() {
|
||||
return [
|
||||
...this.menuTarget.querySelectorAll<HTMLElement>('[role="menuitem"]')
|
||||
];
|
||||
}
|
||||
|
||||
private setFocusToMenuitem(menuItem: HTMLElement | null) {
|
||||
if (menuItem) {
|
||||
menuItem.focus();
|
||||
} else {
|
||||
this.buttonTarget.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private setFocusToFirstMenuitem() {
|
||||
this.setFocusToMenuitem(this.menuItems[0]);
|
||||
}
|
||||
|
||||
private setFocusToLastMenuitem() {
|
||||
const length = this.menuItems.length;
|
||||
this.setFocusToMenuitem(this.menuItems[length - 1]);
|
||||
}
|
||||
|
||||
setFocusToPreviousMenuitem() {
|
||||
const { currentMenuItem, menuItems } = this;
|
||||
|
||||
if (currentMenuItem) {
|
||||
const index = menuItems.indexOf(currentMenuItem);
|
||||
if (index == 0) {
|
||||
this.setFocusToLastMenuitem();
|
||||
} else {
|
||||
this.setFocusToMenuitem(menuItems[index - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setFocusToNextMenuitem() {
|
||||
const { currentMenuItem, menuItems } = this;
|
||||
|
||||
if (currentMenuItem) {
|
||||
const index = menuItems.indexOf(currentMenuItem);
|
||||
if (index == menuItems.length - 1) {
|
||||
this.setFocusToFirstMenuitem();
|
||||
} else {
|
||||
this.setFocusToMenuitem(menuItems[index + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
performMenuAction(target: EventTarget | null) {
|
||||
target?.dispatchEvent(new Event('click'));
|
||||
}
|
||||
|
||||
private onButtonKeydown(event: KeyboardEvent) {
|
||||
let stopPropagation = false;
|
||||
switch (event.key) {
|
||||
case ' ':
|
||||
case 'Enter':
|
||||
case 'ArrowDown':
|
||||
case 'Down':
|
||||
this.open();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Esc':
|
||||
case 'Escape':
|
||||
this.close();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Up':
|
||||
case 'ArrowUp':
|
||||
this.open('last');
|
||||
stopPropagation = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (stopPropagation) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
onMenuKeydown(event: KeyboardEvent) {
|
||||
let stopPropagation = false;
|
||||
if (event.ctrlKey || event.altKey || event.metaKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.shiftKey) {
|
||||
if (event.key == 'Tab') {
|
||||
this.close();
|
||||
stopPropagation = true;
|
||||
}
|
||||
} else {
|
||||
switch (event.key) {
|
||||
case ' ':
|
||||
this.performMenuAction(event.target);
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Esc':
|
||||
case 'Escape':
|
||||
this.close();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Up':
|
||||
case 'ArrowUp':
|
||||
this.setFocusToPreviousMenuitem();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
case 'Down':
|
||||
this.setFocusToNextMenuitem();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Home':
|
||||
case 'PageUp':
|
||||
this.setFocusToFirstMenuitem();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'End':
|
||||
case 'PageDown':
|
||||
this.setFocusToLastMenuitem();
|
||||
stopPropagation = true;
|
||||
break;
|
||||
case 'Tab':
|
||||
this.close();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (stopPropagation) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
import { delegate } from '@utils';
|
||||
|
||||
delegate('click', 'body', (event) => {
|
||||
if (!event.target.closest('.dropdown, [data-reach-combobox-popover]')) {
|
||||
[...document.querySelectorAll('.dropdown')].forEach((element) => {
|
||||
const button = element.querySelector('.dropdown-button');
|
||||
button.setAttribute('aria-expanded', false);
|
||||
element.classList.remove('open', 'fade-in-down');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
delegate('click', '.dropdown-button', (event) => {
|
||||
event.stopPropagation();
|
||||
const button = event.target.closest('.dropdown-button');
|
||||
const parent = button.parentElement;
|
||||
if (parent.classList.contains('dropdown')) {
|
||||
parent.classList.toggle('open');
|
||||
var buttonExpanded = button.getAttribute('aria-expanded') === 'true';
|
||||
button.setAttribute('aria-expanded', !buttonExpanded);
|
||||
}
|
||||
});
|
|
@ -13,7 +13,6 @@ import '../shared/ujs-error-handling';
|
|||
import { registerComponents } from '../controllers/react_controller';
|
||||
import '../controllers';
|
||||
|
||||
import '../new_design/dropdown';
|
||||
import '../new_design/form-validation';
|
||||
import '../new_design/procedure-context';
|
||||
import '../new_design/procedure-form';
|
||||
|
|
|
@ -40,3 +40,16 @@ const fragment = document.createDocumentFragment();
|
|||
if (fragment.children == undefined) {
|
||||
polyfillChildren(DocumentFragment.prototype);
|
||||
}
|
||||
|
||||
// IE 11 has no isConnected on Node
|
||||
function polyfillIsConnected(proto) {
|
||||
Object.defineProperty(proto, 'isConnected', {
|
||||
get: function () {
|
||||
return document.documentElement.contains(this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (!('isConnected' in Node.prototype)) {
|
||||
polyfillIsConnected(Node.prototype);
|
||||
}
|
||||
|
|
|
@ -33,10 +33,10 @@
|
|||
= link_to admin_procedure_path(procedure), class: 'button mr-1 edit-procedure' do
|
||||
%span.icon.edit
|
||||
Modifier
|
||||
.dropdown
|
||||
.button.dropdown-button.procedures-actions-btn{ 'aria-expanded' => 'false', 'aria-controls' => 'actions-menu' }
|
||||
.dropdown{ data: { controller: 'menu-button' } }
|
||||
.button.dropdown-button.procedures-actions-btn{ data: { menu_button_target: 'button' } }
|
||||
Actions
|
||||
#actions-menu.dropdown-content.fade-in-down
|
||||
#actions-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items.pl-0
|
||||
- if !procedure.close? && !procedure.discarded?
|
||||
%li
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
%li= link_to("Dossier nº #{dossier.id}", expert_avis_path(avis.procedure, avis))
|
||||
|
||||
.header-actions
|
||||
%span.dropdown.print-menu-opener
|
||||
%button.button.dropdown-button.icon-only{ 'aria-expanded' => 'false', 'aria-controls' => 'print-pj-menu' }
|
||||
%span.dropdown.print-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only{ data: { menu_button_target: 'button' } }
|
||||
%span.icon.attached
|
||||
%ul.print-menu.dropdown-content
|
||||
%ul.print-menu.dropdown-content#print-pj-menu{ data: { menu_button_target: 'menu' } }
|
||||
%li= link_to "Télécharger le dossier et toutes ses pièces jointes", telecharger_pjs_expert_avis_path(avis.procedure, avis), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||
|
||||
%nav.tabs
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%span.dropdown.print-menu-opener
|
||||
%button.button.dropdown-button.icon-only{ title: 'imprimer', 'aria-label': 'imprimer', 'aria-expanded' => 'false', 'aria-controls' => 'print-menu' }
|
||||
%span.dropdown.print-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only{ title: 'imprimer', 'aria-label': 'imprimer', data: { menu_button_target: 'button' } }
|
||||
%span.icon.printer
|
||||
%ul#print-menu.print-menu.dropdown-content
|
||||
%ul#print-menu.print-menu.dropdown-content{ data: { menu_button_target: 'menu' } }
|
||||
%li
|
||||
= link_to "Tout le dossier", print_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||
%li
|
||||
|
@ -12,10 +12,10 @@
|
|||
%li
|
||||
= link_to "Export GeoJSON", geo_data_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||
|
||||
%span.dropdown.print-menu-opener
|
||||
%button.button.dropdown-button.icon-only{ 'aria-expanded' => 'false', 'aria-controls' => 'print-pj-menu' }
|
||||
%span.dropdown.print-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only{ data: { menu_button_target: 'button' } }
|
||||
%span.icon.attached
|
||||
%ul#print-pj-menu.print-menu.dropdown-content
|
||||
%ul#print-pj-menu.print-menu.dropdown-content{ data: { menu_button_target: 'menu' } }
|
||||
%li= link_to "Télécharger le dossier et toutes ses pièces jointes", telecharger_pjs_instructeur_dossier_path(dossier.procedure, dossier), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||
|
||||
= render partial: "instructeurs/procedures/dossier_actions",
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
.dropdown
|
||||
.dropdown{ data: { controller: 'menu-button', popover: 'true' } }
|
||||
-# Dropdown button title
|
||||
%button.button.primary.dropdown-button{ class: button_or_label_class(dossier), 'aria-expanded' => 'false', 'aria-controls' => 'state-menu' }
|
||||
%button.button.primary.dropdown-button{ class: button_or_label_class(dossier), data: { menu_button_target: 'button' } }
|
||||
= dossier_display_state dossier
|
||||
|
||||
-# Dropdown content
|
||||
#state-menu.dropdown-content.fade-in-down
|
||||
#state-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
|
||||
- if dossier.en_construction?
|
||||
-# ------------------------------------------------------
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
= link_to restore_instructeur_dossier_path(procedure_id, dossier_id), method: :patch, class: "button" do
|
||||
= t('views.instructeurs.dossiers.restore')
|
||||
- elsif close_to_expiration || Dossier::TERMINE.include?(state)
|
||||
.dropdown.user-dossier-actions
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'actions-menu' }
|
||||
.dropdown.user-dossier-actions{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
Actions
|
||||
#actions-menu.dropdown-content.fade-in-down
|
||||
#actions-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
- if close_to_expiration
|
||||
%li
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%span.dropdown
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'download-menu' }
|
||||
%span.dropdown{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t(".download", count: count)
|
||||
#download-menu.dropdown-content.fade-in-down{ style: 'width: 450px' }
|
||||
#download-menu.dropdown-content.fade-in-down{ style: 'width: 450px', data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
- exports_list(exports, statut).each do |item|
|
||||
- format = item[:format]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
%span.dropdown
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'filter-menu' }
|
||||
%span.dropdown{ data: { controller: 'menu-button', popover: 'true' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('views.instructeurs.dossiers.filters.title')
|
||||
#filter-menu.dropdown-content.left-aligned.fade-in-down
|
||||
#filter-menu.dropdown-content.left-aligned.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
= form_tag add_filter_instructeur_procedure_path(procedure), method: :post, class: 'dropdown-form large' do
|
||||
= label_tag :field, t('views.instructeurs.dossiers.filters.column')
|
||||
= select_tag :field, options_for_select(displayed_fields_options)
|
||||
|
|
|
@ -77,10 +77,10 @@
|
|||
= render partial: "header_field", locals: { field: field, classname: field['classname'] }
|
||||
|
||||
%th.action-col.follow-col
|
||||
%span.dropdown
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'custom-menu' }
|
||||
%span.dropdown{ data: { controller: 'menu-button', popover: 'true' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('views.instructeurs.dossiers.personalize')
|
||||
#custom-menu.dropdown-content.fade-in-down
|
||||
#custom-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
= form_tag update_displayed_fields_instructeur_procedure_path(@procedure), method: :patch, class: 'dropdown-form large columns-form' do
|
||||
= hidden_field_tag :values, nil
|
||||
= react_component("ComboMultiple",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
.dropdown.invite-user-action
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'invite-content' }
|
||||
.dropdown.invite-user-action{ data: { controller: 'menu-button', popover: 'true' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
%span.icon.person
|
||||
- if dossier.invites.count > 0
|
||||
= t('views.invites.dropdown.view_invited_people')
|
||||
|
@ -10,5 +10,5 @@
|
|||
- else
|
||||
= t('views.invites.dropdown.invite_to_edit')
|
||||
|
||||
#invite-content.dropdown-content.fade-in-down
|
||||
#invite-content.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
= render partial: "invites/form", locals: { dossier: dossier }
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.dropdown.header-menu-opener
|
||||
%button.button.dropdown-button.icon-only.header-menu-button{ title: "Mon compte", 'aria-expanded' => 'false', 'aria-controls' => 'mon_compte_menu' }
|
||||
.dropdown.header-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only.header-menu-button{ title: "Mon compte", data: { menu_button_target: 'button' } }
|
||||
.hidden Mon compte
|
||||
= image_tag "icons/account-circle.svg", alt: 'Mon compte', width: 24, height: 24, loading: 'lazy'
|
||||
%ul.header-menu.dropdown-content#mon_compte_menu
|
||||
%ul.header-menu.dropdown-content#mon_compte_menu{ data: { menu_button_target: 'menu' } }
|
||||
%li
|
||||
.menu-item{ title: current_email }
|
||||
= current_email
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
.dropdown.locale-dropdown.header-menu-opener
|
||||
%button.button.dropdown-button.icon-only.header-menu-button{ title: t('.languages'), aria: { expanded: 'false', controls: 'locale_menu' } }
|
||||
.dropdown.locale-dropdown.header-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only.header-menu-button{ title: t('.languages'), data: { menu_button_target: 'button' } }
|
||||
.hidden t('.languages')
|
||||
= image_tag "icons/translate-icon.svg", alt: t('.languages'), width: 24, height: 24, lazy: true, aria: { hidden: true }
|
||||
%ul.header-menu.dropdown-content
|
||||
%ul.header-menu.dropdown-content{ data: { menu_button_target: 'menu' } }
|
||||
%li
|
||||
= active_link_to save_locale_path(locale: :fr), method: :post, class: "menu-item menu-link", active: I18n.locale == :fr do
|
||||
Français
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.dropdown.help-dropdown
|
||||
%button.button.primary.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'help-menu' }
|
||||
.dropdown.help-dropdown{ data: { controller: 'menu-button' } }
|
||||
%button.button.primary.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('help')
|
||||
#help-menu.dropdown-content.fade-in-down
|
||||
#help-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
- title = dossier.brouillon? ? "Besoin d’aide pour remplir votre dossier ?" : "Une question sur votre dossier ?"
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.dropdown.help-dropdown
|
||||
%button.button.primary.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'help-menu' }
|
||||
.dropdown.help-dropdown{ data: { controller: 'menu-button' } }
|
||||
%button.button.primary.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('help')
|
||||
#help-menu.dropdown-content.fade-in-down
|
||||
#help-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
= render partial: 'shared/help/dropdown_items/faq_item'
|
||||
= render partial: 'shared/help/dropdown_items/email_item'
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
.dropdown.help-dropdown
|
||||
%button.button.primary.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'help-menu' }
|
||||
.dropdown.help-dropdown{ data: { controller: 'menu-button' } }
|
||||
%button.button.primary.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('help')
|
||||
#help-menu.dropdown-content.fade-in-down
|
||||
#help-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
- if procedure.service.present?
|
||||
= render partial: 'shared/help/dropdown_items/service_item',
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
- has_actions = has_edit_action || has_delete_action || has_new_dossier_action || has_transfer_action
|
||||
|
||||
- if has_actions
|
||||
.dropdown.user-dossier-actions
|
||||
%button.button.dropdown-button{ 'aria-expanded' => 'false', 'aria-controls' => 'actions-menu' }
|
||||
.dropdown.user-dossier-actions{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button{ data: { menu_button_target: 'button' } }
|
||||
= t('views.users.dossiers.dossier_action.actions')
|
||||
#actions-menu.dropdown-content.fade-in-down
|
||||
#actions-menu.dropdown-content.fade-in-down{ data: { menu_button_target: 'menu' } }
|
||||
%ul.dropdown-items
|
||||
- if has_edit_action
|
||||
- if dossier.brouillon?
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
%span.dropdown.print-menu-opener
|
||||
%button.button.dropdown-button.icon-only{ title: t('views.users.dossiers.show.header.print'), 'aria-label': 'imprimer', 'aria-expanded' => 'false', 'aria-controls' => 'print-menu' }
|
||||
%span.dropdown.print-menu-opener{ data: { controller: 'menu-button' } }
|
||||
%button.button.dropdown-button.icon-only{ title: t('views.users.dossiers.show.header.print'), 'aria-label': 'imprimer', data: { menu_button_target: 'button' } }
|
||||
%span.icon.printer
|
||||
%ul#print-menu.print-menu.dropdown-content
|
||||
%ul#print-menu.print-menu.dropdown-content{ data: { menu_button_target: 'menu' } }
|
||||
%li
|
||||
= link_to t('views.users.dossiers.show.header.print_dossier'), dossier_path(dossier, format: :pdf), target: "_blank", rel: "noopener", class: "menu-item menu-link"
|
||||
|
|
Loading…
Reference in a new issue