Skip to content

Commit a799a07

Browse files
committed
css issues cleared and tab logic enhanced
1 parent 14fc988 commit a799a07

File tree

8 files changed

+66
-63
lines changed

8 files changed

+66
-63
lines changed

administrator/components/com_workflow/resources/scripts/components/canvas/WorkflowCanvas.vue

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
class="workflow-canvas"
1212
fit-view-on-init
1313
max-zoom="2.5"
14-
min-zoom="0.3"
14+
min-zoom=".3"
1515
:nodes="positionedNodes"
1616
:edges="styledEdges"
1717
:node-types="nodeTypes"
@@ -35,7 +35,7 @@
3535
pannable
3636
zoomable
3737
:node-color="(node) => node.data?.stage?.color || '#0d6efd'"
38-
:mask-color="'rgba(255, 255, 255, 0.6)'"
38+
:mask-color="'rgba(255, 255, 255, .6)'"
3939
:aria-label="translate('COM_WORKFLOW_GRAPH_MINIMAP')"
4040
/>
4141
<CustomControls aria-label="Graph controls" />
@@ -108,7 +108,7 @@ export default {
108108
const selectedTransition = ref(null);
109109
const liveRegion = ref(null);
110110
const saveStatus = ref('upToDate');
111-
const currentFocusMode = ref('stages');
111+
const currentFocusMode = ref('links');
112112
const previouslyFocusedElement = ref(null);
113113
114114
const stages = computed(() => store.getters.stages || []);
@@ -332,7 +332,7 @@ export default {
332332
333333
watch([positionedNodes, styledEdges], () => {
334334
setTimeout(() => {
335-
fitView({ padding: 0.2, duration: 300 });
335+
fitView({ padding: 0.7, duration: 300 });
336336
}, 0);
337337
});
338338

administrator/components/com_workflow/resources/scripts/components/edges/CustomEdge.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,16 @@
2222
@focus="onEdgeFocus"
2323
@blur="onEdgeBlur"
2424
>
25-
<div class="d-flex align-items-center border text-bg-info rounded shadow-sm px-2 py-1 gap-1">
26-
<h3
27-
class="h3 text-truncate text-center text-white flex-grow-1 fw-semibold"
25+
<div class="d-flex align-items-center border text-bg-primary rounded shadow-sm px-2 py-1 gap-1 h-40 m-auto">
26+
<span
27+
class="h3 d-block text-truncate text-center text-white flex-grow-1 fw-semibold h-100 m-auto align-content-center"
2828
:style="{ maxWidth: data?.isTransitionMode ? '80px' : '100%' }"
2929
:title="data?.title"
3030
>
3131
{{ data?.title }}
32-
</h3>
32+
</span>
3333
<button
34-
class="btn btn-lg btn-secondary py-0 px-1"
34+
class="btn btn-md btn-secondary py-0 px-1"
3535
:class="data?.isTransitionMode ? 'd-block' : 'd-none'"
3636
:aria-label="translate('COM_WORKFLOW_GRAPH_EDIT_TRANSITION')"
3737
:title="translate('COM_WORKFLOW_GRAPH_EDIT_TRANSITION')"
@@ -43,14 +43,14 @@
4343
/>
4444
</button>
4545
<button
46-
class="btn btn-lg btn-danger py-0 px-1"
46+
class="btn btn-md btn-danger py-0 px-1"
4747
:class="data?.isTransitionMode ? 'd-block' : 'd-none'"
4848
:aria-label="translate('COM_WORKFLOW_GRAPH_DELETE_TRANSITION')"
4949
:title="translate('COM_WORKFLOW_GRAPH_DELETE_TRANSITION')"
5050
@click.stop="data?.onDelete?.()"
5151
>
5252
<i
53-
class="icon icon-delete"
53+
class="icon icon-trash"
5454
aria-hidden="true"
5555
/>
5656
</button>

administrator/components/com_workflow/resources/scripts/components/nodes/StageNode.vue

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div
3-
class="stage-node card p-3 border shadow-sm position-relative"
3+
class="stage-node card p-2 border shadow-sm position-relative"
44
:class="{ 'shadow': isSelected, 'hover-shadow': !isSelected }"
55
:style="stageStyle"
66
tabindex="0"
@@ -39,12 +39,12 @@
3939
<!-- Stage Header -->
4040
<div class="card-header d-flex justify-content-between align-items-start p-1">
4141
<div class="flex-fill w-75 me-3 min-width-0">
42-
<h2
43-
class="h3 card-title mb-1 fw-semibold text-truncate"
42+
<span
43+
class="h3 d-block card-title mb-1 fw-semibold text-truncate"
4444
:title="stage?.title"
4545
>
4646
{{ stage.title }}
47-
</h2>
47+
</span>
4848
<p
4949
class="card-text text-muted mb-0 text-truncate"
5050
:title="stage?.description"
@@ -71,6 +71,7 @@
7171
</button>
7272
<button
7373
class="btn btn-lg btn-danger py-0 px-1"
74+
:class="stage.default ? 'd-none' : ''"
7475
:aria-label="translate('COM_WORKFLOW_GRAPH_DELETE_STAGE')"
7576
:title="translate('COM_WORKFLOW_GRAPH_DELETE_STAGE')"
7677
@click.stop="data.onDelete"
@@ -83,8 +84,8 @@
8384
</div>
8485
</div>
8586

86-
<div class="card-body p-1 pt-0">
87-
<div class="d-flex justify-content-between align-items-center mb-2">
87+
<div class="card-body px-1 py-0">
88+
<div class="d-flex justify-content-between align-items-center">
8889
<span
8990
:class="stage.published ? 'bg-success' : 'bg-danger'"
9091
class="badge rounded-pill p-1"

administrator/components/com_workflow/resources/scripts/utils/keyboard-manager.es6.js

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ export function setupGlobalShortcuts({
3838
return;
3939
}
4040

41+
const groupSelectors = {
42+
buttons: 'button[tabindex="0"], button:not([tabindex="-1"])',
43+
stages: '.stage-node[tabindex="0"]',
44+
transitions: '.edge-label[tabindex="0"]',
45+
toolbar: '.toolbar-button[tabindex="0"]',
46+
actions: '.action-button[tabindex="0"]',
47+
links: 'a[href][tabindex="0"], a[href]:not([tabindex="-1"])',
48+
};
49+
4150
function moveNode(stageId, direction, fast = false) {
4251
const el = document.querySelector(`.stage-node[data-stage-id='${stageId}']`);
4352
if (!el) return;
@@ -125,10 +134,16 @@ export function setupGlobalShortcuts({
125134
fitView();
126135
break;
127136

128-
case e.key === 'Tab':
137+
case e.key === 'Tab': {
129138
e.preventDefault();
130-
cycleMode(['stages', 'transitions', 'toolbar', 'actions', 'links', 'buttons'], state.currentFocusMode, state.liveRegion);
139+
cycleMode(['buttons', 'stages', 'transitions', 'toolbar', 'actions', 'links'], state.currentFocusMode, state.liveRegion);
140+
const tabSelector = groupSelectors[state.currentFocusMode.value];
141+
if (tabSelector) {
142+
const first = document.querySelector(tabSelector);
143+
if (first) first.focus();
144+
}
131145
break;
146+
}
132147

133148
case ['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(e.key):
134149
e.preventDefault();
@@ -145,14 +160,6 @@ export function setupGlobalShortcuts({
145160
}
146161
} else {
147162
const reverse = ['ArrowLeft', 'ArrowUp'].includes(e.key);
148-
const groupSelectors = {
149-
stages: '.stage-node[tabindex="0"]',
150-
transitions: '.edge-label[tabindex="0"]',
151-
toolbar: '.toolbar-button[tabindex="0"]',
152-
actions: '.action-button[tabindex="0"]',
153-
links: 'a[href][tabindex="0"], a[href]:not([tabindex="-1"])',
154-
buttons: 'button[tabindex="0"], button:not([tabindex="-1"])',
155-
};
156163
const selector = groupSelectors[state.currentFocusMode.value];
157164
if (selector) {
158165
cycleFocus(selector, reverse);

administrator/components/com_workflow/resources/scripts/workflowgraph.es6.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ window.WorkflowGraph = window.WorkflowGraph || {};
1010
window.WorkflowGraph.Event = EventBus;
1111

1212
document.addEventListener('DOMContentLoaded', () => {
13+
const skipToButton = document.querySelector('.skip-to button');
14+
if (skipToButton) {
15+
skipToButton.focus();
16+
}
17+
1318
const mountElement = document.getElementById('workflow-graph-root');
1419

1520
if (mountElement) {

build/media_source/com_workflow/scss/components/_workflow-graph-custom.scss

Lines changed: 20 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* ───── Layout ───── */
1+
/* ----- Layout ----- */
22
.workflow-canvas {
33
background-color: var(--primary-rgb);
44
background-image: linear-gradient(var(--primary-border-subtle) 1px, transparent 1px),
@@ -18,7 +18,11 @@
1818
min-width: 0;
1919
}
2020

21-
/* ───── Edges ───── */
21+
.h-40 {
22+
height: 40px;
23+
}
24+
25+
/* ----- Edges ----- */
2226
.vue-flow__edge-path {
2327
stroke-width: 2;
2428
transition: stroke .2s ease, stroke-width .2s ease;
@@ -33,7 +37,7 @@
3337
stroke-width: 3;
3438
}
3539

36-
/* ───── Edge Labels ───── */
40+
/* ----- Edge Labels ----- */
3741
.vue-flow__edge-label {
3842
padding: 4px 8px;
3943
font-size: 12px;
@@ -50,19 +54,13 @@
5054
border-color: var(--gray-400);
5155
}
5256

53-
/* ───── Controls & Minimap ───── */
57+
/* ----- Controls & Minimap ----- */
5458
.vue-flow__controls,
5559
.vue-flow__minimap {
5660
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, .1);
5761
}
5862

59-
.vue-flow__controls button:focus,
60-
.vue-flow__minimap:focus {
61-
outline: 2px solid var(--primary);
62-
outline-offset: 2px;
63-
}
64-
65-
/* ───── Nodes ───── */
63+
/* ----- Nodes ----- */
6664
.stage-node {
6765
position: relative;
6866
}
@@ -81,36 +79,33 @@
8179
max-width: 250px !important;
8280
}
8381

84-
/* ───── Handle ───── */
82+
/* ----- Handle ----- */
8583
.vue-flow__handle {
8684
opacity: 0;
8785
transition: opacity .2s;
8886
}
8987

90-
/* ───── Card Actions ───── */
88+
/* ----- Card Actions ----- */
9189
.stage-card-actions button {
9290
--btn-padding-x: 2px !important;
9391
--btn-padding-y: 0 !important;
9492
}
9593

96-
/* ───── Text Truncation ───── */
94+
/* ----- Text Truncation ----- */
9795
.line-clamp-2 {
9896
display: block;
9997
overflow: hidden;
10098
text-overflow: ellipsis;
10199
line-clamp: 2;
102100
}
103101

104-
/* ───── Accessibility ───── */
105-
:focus {
106-
outline: 3px solid var(--primary) !important;
107-
outline-offset: 2px;
108-
}
109-
110-
.stage-node:focus,
111-
.edge-label:focus,
112-
button:focus {
113-
box-shadow: 0 0 0 3px var(--primary);
102+
/* ----- Accessibility ----- */
103+
.stage-node:focus, .stage-node:focus-visible,
104+
.edge-label:focus, .edge-label:focus-visible,
105+
button:focus, button:focus-visible,
106+
:focus-visible, :focus:not(:disabled):not([readonly]) {
107+
border: 2px solid var(--template-link-color) !important;
108+
box-shadow: 0 0 0 .25rem rgba(42, 105, 183, .25) !important;
114109
}
115110

116111
.sr-only,
@@ -125,7 +120,7 @@ button:focus {
125120
border: 0;
126121
}
127122

128-
/* ───── Custom Controls ───── */
123+
/* ----- Custom Controls ----- */
129124
.custom-controls {
130125
position: absolute;
131126
right: 20px;
@@ -141,11 +136,6 @@ button:focus {
141136
box-shadow: 0 2px 4px rgba(0, 0, 0, .1);
142137
}
143138

144-
.custom-controls:focus {
145-
outline: 2px solid var(--primary);
146-
outline-offset: 2px;
147-
}
148-
149139
.custom-controls-button {
150140
display: flex;
151141
align-items: center;

build/media_source/com_workflow/scss/components/_workflow-vue-controls.scss

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
/* ───── Controls Container ───── */
1+
/* ----- Controls Container ----- */
22
.vue-flow__controls {
33
box-shadow: 0 0 2px 1px var(--shadow-subtle);
44
}
55

6-
/* ───── Controls Buttons ───── */
6+
/* ----- Controls Buttons ----- */
77
.vue-flow__controls-button {
88
box-sizing: content-box;
99
display: flex;
@@ -19,19 +19,19 @@
1919
border-bottom: 1px solid var(--border-light);
2020
}
2121

22-
/* ───── SVG Icon Styling ───── */
22+
/* ----- SVG Icon Styling ----- */
2323
.vue-flow__controls-button svg {
2424
width: 100%;
2525
max-width: 12px;
2626
max-height: 12px;
2727
}
2828

29-
/* ───── Button Hover ───── */
29+
/* ----- Button Hover ----- */
3030
.vue-flow__controls-button:hover {
3131
background: var(--button-hover-bg);
3232
}
3333

34-
/* ───── Button Disabled ───── */
34+
/* ----- Button Disabled ----- */
3535
.vue-flow__controls-button:disabled {
3636
pointer-events: none;
3737
}

build/media_source/com_workflow/scss/components/_workflow-vue-minimap.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.vue-flow__minimap {
2-
background-color: #fff;
2+
background-color: var(--bg-normal);
33
}
44

55
.vue-flow__minimap.pannable {

0 commit comments

Comments
 (0)