Skip to content

Commit

Permalink
Fix correct header rank and keyboard naviagtion (#397)
Browse files Browse the repository at this point in the history
* add section title - improve header ranks and accessibility

* adjust styling

* wrap tabs in focusable div with tabindex - add Keyboard from dash extensions - add callback to handle keyboard navigation for Tabs

* move logic to utils - add test
  • Loading branch information
tilen1976 authored Aug 19, 2024
1 parent 3b12a66 commit a0cea9d
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 34 deletions.
139 changes: 119 additions & 20 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ python-dotenv = ">=1.0.1"
ssb-dash-components = ">=0.8.1"
dapla-toolbelt-metadata = ">=0.2.0"
gunicorn = ">=23.0.0"
dash-extensions = "^1.0.18"

[tool.poetry.group.dev.dependencies]
mypy = ">=0.950"
Expand Down Expand Up @@ -108,6 +109,7 @@ module = [
"pyarrow.parquet",
"dash.development.base_component",
"pytest_mock",
"dash_extensions",
]
ignore_missing_imports = true

Expand Down
48 changes: 35 additions & 13 deletions src/datadoc/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import logging
from pathlib import Path

import ssb_dash_components as ssb
from dapla_metadata.datasets import Datadoc
from dapla_metadata.datasets.code_list import CodeList
from dapla_metadata.datasets.statistic_subject_mapping import StatisticSubjectMapping
from dash import Dash
from dash import dcc
from dash import html
from dash_extensions import Keyboard
from flask_healthz import healthz

from datadoc import config
Expand Down Expand Up @@ -51,24 +53,44 @@ def build_app(app: type[Dash]) -> Dash:
),
build_controls_bar(),
html.Div(id="alerts-section"),
dcc.Tabs(
id="tabs",
className="ssb-tabs",
value="dataset",
children=[
dcc.Tab(
label="Datasett",
html.Div(
[
dcc.Tabs(
id="tabs",
className="ssb-tabs",
value="dataset",
className="workspace-tab",
children=[
dcc.Tab(
label="Datasett",
children=ssb.Title(
"Rediger datasett",
size=2,
className="workspace-tab-title",
),
value="dataset",
className="workspace-tab",
),
dcc.Tab(
label="Variabler",
children=ssb.Title(
"Rediger variabler",
size=2,
className="workspace-tab-title",
),
value="variables",
className="workspace-tab",
),
],
),
dcc.Tab(
label="Variabler",
value="variables",
className="workspace-tab",
html.Div(id="display-tab"),
Keyboard(
id="keyboard",
captureKeys=["ArrowLeft", "ArrowRight"],
),
],
tabIndex="0",
className="focusable-tabs-section",
),
html.Div(id="display-tab"),
],
className="main-content-app",
),
Expand Down
2 changes: 1 addition & 1 deletion src/datadoc/assets/workspace_style.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

.workspace-info-paragraph {
display: inline-block;
align-self: flex-end;
align-self: center;
margin-bottom: 0;
}

Expand Down
4 changes: 4 additions & 0 deletions src/datadoc/assets/workspace_tab.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@
.workspace-tab{
padding: 1rem;
}

.ssb-title.workspace-tab-title{
margin-top: 1rem;
}
16 changes: 16 additions & 0 deletions src/datadoc/frontend/callbacks/register_callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from datadoc.frontend.callbacks.dataset import dataset_control
from datadoc.frontend.callbacks.dataset import open_dataset_handling
from datadoc.frontend.callbacks.utils import render_tabs
from datadoc.frontend.callbacks.utils import select_tabs
from datadoc.frontend.callbacks.variables import accept_variable_metadata_date_input
from datadoc.frontend.callbacks.variables import accept_variable_metadata_input
from datadoc.frontend.callbacks.variables import populate_variables_workspace
Expand Down Expand Up @@ -203,6 +204,21 @@ def callback_render_tabs(tab: html.Article) -> html.Article | None:
"""Return correct tab content."""
return render_tabs(tab)

@app.callback(
Output("tabs", "value"),
Input("keyboard", "keydown"),
Input("tabs", "value"),
)
def switch_tabs(keydown: dict, current_tab: str) -> str:
"""Handle keyboard events and switch tabs.
This callback is designed to make Dash core component Tabs
with children Tab focusable and keyboard interactive,
enhancing accessibility by allowing users to navigate between tabs
using the arrow keys.
"""
return select_tabs(keydown, current_tab)

@app.callback(
Output(VARIABLES_INFORMATION_ID, "children"),
Input("dataset-opened-counter", "data"),
Expand Down
10 changes: 10 additions & 0 deletions src/datadoc/frontend/callbacks/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,3 +226,13 @@ def render_tabs(tab: str) -> html.Article | None:
)

return None


def select_tabs(keydown: dict, current_tab: str) -> str:
"""Return correct tab based on keydown."""
if keydown:
if keydown["key"] == "ArrowRight":
return "variables" if current_tab == "dataset" else "dataset"
if keydown["key"] == "ArrowLeft":
return "dataset" if current_tab == "variables" else "variables"
return current_tab
10 changes: 10 additions & 0 deletions tests/frontend/callbacks/test_callbacks_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from datadoc.frontend.callbacks.utils import find_existing_language_string
from datadoc.frontend.callbacks.utils import render_tabs
from datadoc.frontend.callbacks.utils import select_tabs
from datadoc.frontend.components.identifiers import ACCORDION_WRAPPER_ID
from datadoc.frontend.components.identifiers import SECTION_WRAPPER_ID

Expand Down Expand Up @@ -67,3 +68,12 @@ def test_render_tabs(tab: str, identifier: str):
result = render_tabs(tab)
assert isinstance(result, html.Article)
assert result.children[-1].id == identifier


def test_switch_tabs():
keydown_right = {"key": "ArrowRight"}
keydown_left = {"key": "ArrowLeft"}
assert select_tabs(keydown_right, "dataset") == "variables"
assert select_tabs(keydown_right, "variables") == "dataset"
assert select_tabs(keydown_left, "dataset") == "variables"
assert select_tabs(keydown_left, "variables") == "dataset"

0 comments on commit a0cea9d

Please sign in to comment.