Skip to content

Commit cb35c53

Browse files
committed
feat: add keyboard navigation for select charts
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent 1c3b1e2 commit cb35c53

File tree

18 files changed

+910
-297
lines changed

18 files changed

+910
-297
lines changed

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/chart/index.html

Lines changed: 218 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,43 @@
1616
margin-top: 50px;
1717
}
1818

19-
#placeholder {
19+
.controls {
20+
max-width: 800px;
21+
margin: 20px auto;
22+
padding: 15px;
23+
background-color: #fff;
24+
border-radius: 5px;
25+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
26+
}
27+
28+
.control-group {
29+
margin: 10px 0;
30+
}
31+
32+
.control-group label {
33+
display: flex;
34+
align-items: center;
35+
cursor: pointer;
36+
font-size: 14px;
37+
}
38+
39+
.control-group input[type="checkbox"] {
40+
margin-right: 10px;
41+
cursor: pointer;
42+
width: 18px;
43+
height: 18px;
44+
}
45+
46+
.control-group .description {
47+
margin-left: 28px;
48+
font-size: 12px;
49+
color: #666;
50+
font-style: italic;
51+
}
52+
53+
#placeholder,
54+
#placeholder2,
55+
#placeholder3 {
2056
width: 100%;
2157
height: 500px;
2258
background-color: #fff;
@@ -29,9 +65,56 @@
2965

3066
<body onresize="doResize()">
3167
<h1>ESM Quick Test</h1>
32-
<div id="placeholder"></div>
68+
69+
<div class="controls">
70+
<div class="control-group">
71+
<label>
72+
<input type="checkbox" checked id="tabNavigationToggleScatter">
73+
Enable Tab Navigation for Scatter Chart
74+
</label>
75+
<div class="description">
76+
When enabled, you can use Tab to navigate through points and Space/Enter to select them
77+
</div>
78+
</div>
79+
<div class="control-group">
80+
<label for="scatterVariantSelect" style="cursor: default;">
81+
Scatter Variant
82+
</label>
83+
<select id="scatterVariantSelect" style="margin-left: 0; width: 220px; padding: 4px;">
84+
<option value="points" selected>Points Only</option>
85+
<option value="line">Points + Line</option>
86+
<option value="area">Line + Area Fill</option>
87+
</select>
88+
<div class="description">
89+
Quickly preview how scatter behaves with lines or area fill enabled
90+
</div>
91+
</div>
92+
<div class="control-group">
93+
<label>
94+
<input type="checkbox" checked id="tabNavigationToggle">
95+
Enable Tab Navigation for Column Chart
96+
</label>
97+
<div class="description">
98+
When enabled, you can use Tab to navigate through columns and Space/Enter to select them
99+
</div>
100+
</div>
101+
<div class="control-group">
102+
<label>
103+
<input type="checkbox" checked id="tabNavigationTogglePie">
104+
Enable Tab Navigation for Pie Chart
105+
</label>
106+
<div class="description">
107+
When enabled, you can use Tab to navigate through slices and Space/Enter to select them
108+
</div>
109+
</div>
110+
</div>
111+
112+
<div id="placeholder2" tabindex="0"></div>
113+
<div id="placeholder3" tabindex="0"></div>
114+
<div id="placeholder" tabindex="0"></div>
115+
33116
<script type="module">
34-
import { Area, Column } from "@hpcc-js/chart";
117+
import { Area, Bar, Column, Pie } from "./src/index.ts";
35118

36119
const simple = {
37120
ND: {
@@ -57,7 +140,7 @@ <h1>ESM Quick Test</h1>
57140
}
58141
};
59142

60-
window.__widget = new Column()
143+
window.__column = new Column()
61144
.target("placeholder")
62145
.columns(["Category", "Series-1", "Series-2"])
63146
.data([
@@ -70,14 +153,143 @@ <h1>ESM Quick Test</h1>
70153
])
71154
.tooltipValueFormat(",.0f")
72155
.showValue(true)
73-
.xAxisFocus(true)
156+
.xAxisFocus(false)
157+
.tabNavigation(true) // Start with tab navigation disabled
158+
.render()
159+
;
160+
161+
// window.__column = new Pie()
162+
// .target("placeholder")
163+
// .columns(["Category", "Series-1", "Series-2"])
164+
// .data([
165+
// ["B", 55],
166+
// ["C", 54],
167+
// ["D", 80],
168+
// ["E", 86],
169+
// ["A", 34],
170+
// ["F", 144]
171+
// ])
172+
// .render()
173+
// ;
174+
</script>
175+
176+
<script type="module">
177+
import { Area, Column, Pie } from "./src/index.ts";
178+
179+
window.__pie = new Pie()
180+
.target("placeholder2")
181+
.columns(["Category", "Series-1", "Series-2"])
182+
.data([
183+
["B", 55],
184+
["C", 54],
185+
["D", 80],
186+
["E", 86],
187+
["A", 34],
188+
["F", 144]
189+
])
190+
.tabNavigation(true)
191+
.render()
192+
;
193+
</script>
194+
195+
<script type="module">
196+
import { Scatter } from "./src/index.ts";
197+
198+
window.__scatter = new Scatter()
199+
.target("placeholder3")
200+
.columns(["Category", "Series-1", "Series-2"])
201+
.data([
202+
["A", 15, 25],
203+
["B", 25, 45],
204+
["C", 40, 60],
205+
["D", 55, 75],
206+
["E", 65, 90],
207+
["F", 80, 110]
208+
])
209+
.pointShape("cross")
210+
.pointSize(10)
211+
.showValue(false)
212+
.tabNavigation(true)
74213
.render()
75214
;
76215
</script>
77216
<script>
217+
78218
function doResize() {
79-
window.__widget?.resize()?.render();
219+
window.__column?.resize()?.render();
220+
window.__pie?.resize()?.render();
221+
window.__scatter?.resize()?.render();
80222
}
223+
224+
// Add event listener for the checkbox
225+
document.getElementById('tabNavigationToggle').addEventListener('change', function (e) {
226+
window.__column
227+
.tabNavigation(e.target.checked)
228+
.lazyRender()
229+
;
230+
console.log('Tab Navigation:', e.target.checked);
231+
});
232+
233+
// Add event listener for the checkbox
234+
document.getElementById('tabNavigationTogglePie').addEventListener('change', function (e) {
235+
window.__pie
236+
.tabNavigation(e.target.checked)
237+
.lazyRender()
238+
;
239+
console.log('Tab Navigation:', e.target.checked);
240+
});
241+
242+
// Add event listener for the checkbox
243+
document.getElementById('tabNavigationToggleScatter').addEventListener('change', function (e) {
244+
window.__scatter
245+
.tabNavigation(e.target.checked)
246+
.lazyRender()
247+
;
248+
console.log('Tab Navigation:', e.target.checked);
249+
});
250+
251+
const scatterVariantSelect = document.getElementById('scatterVariantSelect');
252+
253+
function applyScatterVariant(variant) {
254+
if (!window.__scatter) return;
255+
switch (variant) {
256+
case "line":
257+
window.__scatter
258+
.interpolate("linear")
259+
.interpolateFill(false)
260+
.showValue(false)
261+
;
262+
break;
263+
case "area":
264+
window.__scatter
265+
.interpolate("linear")
266+
.interpolateFill(true)
267+
.interpolateFillOpacity(0.35)
268+
.showValue(false)
269+
;
270+
break;
271+
case "points":
272+
default:
273+
window.__scatter
274+
.interpolate("")
275+
.interpolateFill(false)
276+
.pointShape("cross")
277+
.pointSize(10)
278+
.showValue(false)
279+
;
280+
break;
281+
}
282+
window.__scatter.lazyRender();
283+
console.log('Scatter Variant:', variant);
284+
}
285+
286+
scatterVariantSelect.addEventListener('change', function (e) {
287+
applyScatterVariant(e.target.value);
288+
});
289+
290+
applyScatterVariant(scatterVariantSelect.value);
291+
292+
81293
</script>
82294
</body>
83295

packages/chart/src/Column.css

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,49 @@
11
.chart_Column .columnRect {
2-
fill: steelblue;
3-
cursor: pointer;
2+
fill: steelblue;
3+
cursor: pointer;
44
}
55

66
.chart_Column .data.axis path {
7-
display: none;
7+
display: none;
88
}
99

1010
.chart_Column .columnRect {
1111
stroke: transparent;
12-
border-width: 1.5px;
12+
border-width: 2px;
1313
}
1414

15-
.chart_Column .columnRect.selected {
16-
stroke: red;
15+
.chart_Column .dataCell.selected .columnRect {
16+
stroke: #dc3545 !important;
17+
stroke-width: 3px !important;
18+
paint-order: fill stroke !important;
19+
transition: all 0.2s ease;
1720
}
21+
22+
.chart_Column .dataCell:hover .columnRect {
23+
stroke: rgba(108, 117, 125, 0.6);
24+
stroke-width: 2px;
25+
filter: brightness(1.05);
26+
}
27+
28+
.chart_Column .dataCell:focus .columnRect {
29+
stroke: #007bff !important;
30+
stroke-width: 3px !important;
31+
paint-order: fill stroke !important;
32+
transition: all 0.2s ease;
33+
}
34+
35+
.chart_Column .dataCell.selected:focus .columnRect {
36+
stroke: #6f42c1 !important;
37+
}
38+
39+
.chart_Column .dataCell:focus-visible {
40+
outline: none;
41+
}
42+
43+
.chart_Column .dataCell:focus {
44+
outline: none !important;
45+
}
46+
47+
.chart_Column .dataCell:active {
48+
outline: none !important;
49+
}

0 commit comments

Comments
 (0)