diff --git a/resources/assets/v2/src/js/accessibility.js b/resources/assets/v2/src/js/accessibility.js new file mode 100644 index 00000000000..08f9b9b1891 --- /dev/null +++ b/resources/assets/v2/src/js/accessibility.js @@ -0,0 +1,72 @@ +document.addEventListener('DOMContentLoaded', function() { + const sidebarToggle = document.querySelector('.sidebar-toggle'); + if (sidebarToggle) { + sidebarToggle.addEventListener('click', function() { + const isExpanded = this.getAttribute('aria-expanded') === 'true'; + this.setAttribute('aria-expanded', !isExpanded); + }); + } + + const treeviewLinks = document.querySelectorAll('.treeview > a'); + treeviewLinks.forEach(function(link) { + link.addEventListener('click', function(e) { + e.preventDefault(); + const isExpanded = this.getAttribute('aria-expanded') === 'true'; + this.setAttribute('aria-expanded', !isExpanded); + + const submenu = this.nextElementSibling; + if (submenu && submenu.classList.contains('treeview-menu')) { + submenu.style.display = isExpanded ? 'none' : 'block'; + } + }); + }); + + const modals = document.querySelectorAll('.modal'); + modals.forEach(function(modal) { + modal.addEventListener('shown.bs.modal', function() { + const firstFocusable = modal.querySelector('input, button, select, textarea, [tabindex]:not([tabindex="-1"])'); + if (firstFocusable) { + firstFocusable.focus(); + } + }); + + modal.addEventListener('hidden.bs.modal', function() { + const trigger = document.querySelector('[data-target="#' + modal.id + '"]'); + if (trigger) { + trigger.focus(); + } + }); + }); + + function announceToScreenReader(message) { + const announcement = document.createElement('div'); + announcement.setAttribute('aria-live', 'polite'); + announcement.setAttribute('aria-atomic', 'true'); + announcement.className = 'sr-only'; + announcement.textContent = message; + document.body.appendChild(announcement); + + setTimeout(function() { + document.body.removeChild(announcement); + }, 1000); + } + + const forms = document.querySelectorAll('form'); + forms.forEach(function(form) { + form.addEventListener('submit', function(e) { + const errors = form.querySelectorAll('.text-danger[role="alert"]'); + if (errors.length > 0) { + announceToScreenReader('Form has ' + errors.length + ' error' + (errors.length > 1 ? 's' : '') + '. Please review and correct.'); + } + }); + }); + + document.addEventListener('keydown', function(e) { + if (e.key === 'Escape') { + const openModals = document.querySelectorAll('.modal.in, .modal.show'); + openModals.forEach(function(modal) { + $(modal).modal('hide'); + }); + } + }); +}); diff --git a/resources/assets/v2/src/sass/app.scss b/resources/assets/v2/src/sass/app.scss index 872e5bda2d6..8f9809e0247 100644 --- a/resources/assets/v2/src/sass/app.scss +++ b/resources/assets/v2/src/sass/app.scss @@ -48,7 +48,20 @@ $success: #64B624 !default; // some local CSS -.skip-links {display: none;} +.skip-links { + position: absolute; + left: -9999px; + z-index: 999999; + padding: 8px 16px; + background: #000; + color: #fff; + text-decoration: none; + border-radius: 3px; +} +.skip-links:focus { + left: 6px; + top: 7px; +} /* Remove bottom margin from unstyled lists @@ -80,6 +93,59 @@ h3.hover-expand:hover { appearance: auto; } +.form-control:focus { + outline: 2px solid #1E6581; + outline-offset: 2px; +} + +.btn:focus { + outline: 2px solid #1E6581; + outline-offset: 2px; +} + +a:focus { + outline: 2px solid #1E6581; + outline-offset: 2px; +} + +.sidebar-toggle:focus { + outline: 2px solid #1E6581; + outline-offset: 2px; +} + +.treeview > a:focus { + outline: 2px solid #1E6581; + outline-offset: 2px; +} + +.modal:focus { + outline: none; +} + +.modal-content { + outline: 2px solid #1E6581; +} + +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } +} + +.sr-only { + position: absolute !important; + width: 1px !important; + height: 1px !important; + padding: 0 !important; + margin: -1px !important; + overflow: hidden !important; + clip: rect(0, 0, 0, 0) !important; + white-space: nowrap !important; + border: 0 !important; +} + // edit buttons .hidden-edit-button { cursor: pointer; diff --git a/resources/views/accounts/create.twig b/resources/views/accounts/create.twig index c52e127687d..01472f2be16 100644 --- a/resources/views/accounts/create.twig +++ b/resources/views/accounts/create.twig @@ -3,6 +3,8 @@ {{ Breadcrumbs.render(Route.getCurrentRoute.getName, objectType) }} {% endblock %} {% block content %} +

{{ ('create_new_' ~ objectType ~ '_account')|_ }}

+ +

{{ ('edit_' ~ objectType ~ '_account')|_ }}

+
@@ -23,7 +25,7 @@
-

{{ 'mandatoryFields'|_ }}

+

{{ 'mandatoryFields'|_ }}

{{ ExpandedForm.text('name', account.name) }} @@ -50,7 +52,7 @@
-

{{ 'optionalFields'|_ }}

+

{{ 'optionalFields'|_ }}

{{ ExpandedForm.text('iban', account.iban) }} @@ -87,7 +89,7 @@ {% if preFilled.account_role == 'ccAsset' %}
-

{{ 'credit_card_options'|_ }}

+

{{ 'credit_card_options'|_ }}

{{ ExpandedForm.select('cc_type',Config.get('firefly.ccTypes')) }} @@ -102,7 +104,7 @@ {# panel for options #}
-

{{ 'options'|_ }}

+

{{ 'options'|_ }}

{{ ExpandedForm.optionsList('update','account') }} diff --git a/resources/views/accounts/index.twig b/resources/views/accounts/index.twig index e8e12dd7a84..be92973aa51 100644 --- a/resources/views/accounts/index.twig +++ b/resources/views/accounts/index.twig @@ -10,9 +10,9 @@
-

+

{{ subTitle }} -

+
diff --git a/resources/views/accounts/reconcile/index.twig b/resources/views/accounts/reconcile/index.twig index 5cef87c7afd..1fdf6c01e90 100644 --- a/resources/views/accounts/reconcile/index.twig +++ b/resources/views/accounts/reconcile/index.twig @@ -10,14 +10,14 @@
-

{{ 'reconcile_range'|_ }}

+

{{ 'reconcile_range'|_ }}

- +
- - + + @@ -92,7 +92,7 @@
-

{{ 'reconcile_options'|_ }}

+

{{ 'reconcile_options'|_ }}

@@ -110,7 +110,7 @@
-

{{ 'transactions'|_ }}

+

{{ 'transactions'|_ }}

diff --git a/resources/views/accounts/reconcile/overview.twig b/resources/views/accounts/reconcile/overview.twig index 914a897bf60..9eabdd356a4 100644 --- a/resources/views/accounts/reconcile/overview.twig +++ b/resources/views/accounts/reconcile/overview.twig @@ -19,11 +19,18 @@ {% endfor %} -
{{ 'start_balance'|_ }}{{ 'end_balance'|_ }}{{ 'start_balance'|_ }}{{ 'end_balance'|_ }}
- - - - +
{{ 'submitted_start_balance'|_ }} ({{ start.isoFormat(monthAndDayFormat) }}){{ formatAmountByAccount(account, startBalance) }}
+ + + + + + + + + + + @@ -49,6 +56,7 @@ +
{{ 'description'|_ }}{{ 'amount'|_ }}
{{ 'submitted_start_balance'|_ }} ({{ start.isoFormat(monthAndDayFormat) }}){{ formatAmountByAccount(account, startBalance) }}
{{ trans('firefly.selected_transactions', {count: selectedIds|length}) }} {{ formatAmountByAccount(account, amount) }}

{% if diffCompare > 0 %} diff --git a/resources/views/accounts/reconcile/show.twig b/resources/views/accounts/reconcile/show.twig index bbcaaff3a14..e3324b00342 100644 --- a/resources/views/accounts/reconcile/show.twig +++ b/resources/views/accounts/reconcile/show.twig @@ -24,26 +24,26 @@

- +
- + - + {# total amount #} - + - + @@ -67,21 +67,21 @@

{{ 'transaction_journal_meta'|_ }}

-
{{ trans('list.type') }}{{ trans('list.type') }} {{ journal.transactiontype.type|_ }}
{{ trans('list.description') }}{{ trans('list.description') }} {{ journal.description }}
{{ 'total_amount'|_ }}{{ 'total_amount'|_ }} {{ formatAmountByAccount(transaction.account, transaction.amount) }}
{{ trans('list.date') }}{{ trans('list.date') }} {{ journal.date.isoFormat(monthAndDayFormat) }}
+
{# - + #} {% if journal.tags|length > 0 %} - + diff --git a/resources/views/accounts/reconcile/transactions.twig b/resources/views/accounts/reconcile/transactions.twig index be9cc0331f6..634e1ce9745 100644 --- a/resources/views/accounts/reconcile/transactions.twig +++ b/resources/views/accounts/reconcile/transactions.twig @@ -1,15 +1,15 @@ -
{{ 'categories'|_ }}{{ 'categories'|_ }} {{ journalCategories(journal)|raw }}
{{ 'tags'|_ }}{{ 'tags'|_ }} {% for tag in journal.tags %} -

+ {% if tag.tag_mode == 'nothing' %} {% endif %} @@ -92,7 +92,7 @@ {% endif %} {{ tag.tag }} -

+ {% endfor %}
+
- - - - - - - - - + + + + + + + + + diff --git a/resources/views/accounts/show.twig b/resources/views/accounts/show.twig index e2145c14655..166338b8472 100644 --- a/resources/views/accounts/show.twig +++ b/resources/views/accounts/show.twig @@ -10,7 +10,7 @@
-

+

{% if balances.balance %} {{ trans('firefly.chart_account_in_period', { balance: formatAmountBySymbol(balances.balance, currency.symbol, currency.decimal_places, true), @@ -20,7 +20,7 @@ balance: formatAmountBySymbol(balances.pc_balance, primaryCurrency.symbol, primaryCurrency.decimal_places, true), name: account.name|escape, start: start.isoFormat(monthAndDayFormat), end: end.isoFormat(monthAndDayFormat) })|raw }} {% endif %} -

+
{{ trans('list.description') }}{{ trans('list.amount') }}{{ trans('list.description') }}{{ trans('list.amount') }}
+
- - - - - - + + + + + + diff --git a/resources/views/bills/create.twig b/resources/views/bills/create.twig index cdab3ccef11..8522bebaa10 100644 --- a/resources/views/bills/create.twig +++ b/resources/views/bills/create.twig @@ -6,6 +6,8 @@ {% block content %} +

{{ 'create_new_bill'|_ }}

+ @@ -13,7 +15,7 @@
-

{{ 'mandatoryFields'|_ }}

+

{{ 'mandatoryFields'|_ }}

{{ ExpandedForm.text('name') }} @@ -30,7 +32,7 @@
-

{{ 'optionalFields'|_ }}

+

{{ 'optionalFields'|_ }}

{{ ExpandedForm.date('bill_end_date',null, {'helpText': trans('firefly.bill_end_date_help')}) }} @@ -49,7 +51,7 @@ {# panel for options #}
-

{{ 'options'|_ }}

+

{{ 'options'|_ }}

{{ ExpandedForm.optionsList('create','bill') }} diff --git a/resources/views/bills/delete.twig b/resources/views/bills/delete.twig index b0a59c80798..40e098066ef 100644 --- a/resources/views/bills/delete.twig +++ b/resources/views/bills/delete.twig @@ -12,7 +12,7 @@
-

{{ trans('form.delete_bill', {'name': bill.name}) }}

+

{{ trans('form.delete_bill', {'name': bill.name}) }}

diff --git a/resources/views/bills/edit.twig b/resources/views/bills/edit.twig index 46206470392..a2f52e1ee44 100644 --- a/resources/views/bills/edit.twig +++ b/resources/views/bills/edit.twig @@ -6,6 +6,8 @@ {% block content %} +

{{ 'edit_bill'|_ }}: {{ bill.name }}

+ @@ -15,7 +17,7 @@
-

{{ 'mandatoryFields'|_ }}

+

{{ 'mandatoryFields'|_ }}

{% if rules.count() > 0 %} @@ -37,7 +39,7 @@
-

{{ 'optionalFields'|_ }}

+

{{ 'optionalFields'|_ }}

{{ ExpandedForm.date('bill_end_date',null, {'helpText': trans('firefly.bill_end_date_help')}) }} @@ -57,7 +59,7 @@
-

{{ 'options'|_ }}

+

{{ 'options'|_ }}

{{ ExpandedForm.optionsList('update','bill') }} diff --git a/resources/views/bills/index.twig b/resources/views/bills/index.twig index 49a2905d5d0..409459925af 100644 --- a/resources/views/bills/index.twig +++ b/resources/views/bills/index.twig @@ -12,7 +12,7 @@
-

{{ title }}

+

{{ title }}

diff --git a/resources/views/bills/show.twig b/resources/views/bills/show.twig index ec55e972209..ecfcb969e40 100644 --- a/resources/views/bills/show.twig +++ b/resources/views/bills/show.twig @@ -10,7 +10,7 @@
-

{{ object.data.name }}

+

{{ object.data.name }}

@@ -24,7 +24,8 @@
-
 {{ trans('list.file_name') }}{{ trans('list.file_size') }}{{ trans('list.file_type') }}{{ trans('list.attached_to') }}{{ trans('list.file_exists') }}{{ 'actions'|_ }}{{ trans('list.file_name') }}{{ trans('list.file_size') }}{{ trans('list.file_type') }}{{ trans('list.attached_to') }}{{ trans('list.file_exists') }}
+
+ - + - + - + - + +
{% set lowAmount = formatAmountByCurrency(object.data.currency,object.data.amount_min) %} @@ -42,7 +43,7 @@
{{ 'bill_is_active'|_ }}{{ 'bill_is_active'|_ }} {% if object.data.active %} {{ 'yes'|_ }} @@ -52,7 +53,7 @@
{{ 'next_expected_match'|_ }}{{ 'next_expected_match'|_ }} {% if object.data.pay_dates|length > 0 %} @@ -63,7 +64,7 @@
{{ trans('firefly.average_bill_amount_year', {year: year}) }}{{ trans('firefly.average_bill_amount_year', {year: year}) }} {% for avg in yearAverage %} {{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }} @@ -77,7 +78,7 @@
{{ 'average_bill_amount_overall'|_ }}{{ 'average_bill_amount_overall'|_ }} {% for avg in overallAverage %} {{ formatAmountBySymbol(avg.avg, avg.currency_symbol, avg.currency_decimal_places, true) }} @@ -89,6 +90,7 @@ {% endfor %}