Skip to content

Commit da0acab

Browse files
committed
feat: add keyboard navigation for select charts
Signed-off-by: Gordon Smith <[email protected]>
1 parent 1c3b1e2 commit da0acab

File tree

18 files changed

+817
-297
lines changed

18 files changed

+817
-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: 204 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 { Column } 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,129 @@ <h1>ESM Quick Test</h1>
70153
])
71154
.tooltipValueFormat(",.0f")
72155
.showValue(true)
73-
.xAxisFocus(true)
156+
.xAxisFocus(false)
157+
.tabNavigation(true)
158+
.render()
159+
;
160+
</script>
161+
162+
<script type="module">
163+
import { Pie } from "./src/index.ts";
164+
165+
window.__pie = new Pie()
166+
.target("placeholder2")
167+
.columns(["Category", "Series-1", "Series-2"])
168+
.data([
169+
["B", 55],
170+
["C", 54],
171+
["D", 80],
172+
["E", 86],
173+
["A", 34],
174+
["F", 144]
175+
])
176+
.tabNavigation(true)
177+
.render()
178+
;
179+
</script>
180+
181+
<script type="module">
182+
import { Scatter } from "./src/index.ts";
183+
184+
window.__scatter = new Scatter()
185+
.target("placeholder3")
186+
.columns(["Category", "Series-1", "Series-2"])
187+
.data([
188+
["A", 15, 25],
189+
["B", 25, 45],
190+
["C", 40, 60],
191+
["D", 55, 75],
192+
["E", 65, 90],
193+
["F", 80, 110]
194+
])
195+
.pointShape("cross")
196+
.pointSize(10)
197+
.showValue(false)
198+
.tabNavigation(true)
74199
.render()
75200
;
76201
</script>
77202
<script>
203+
78204
function doResize() {
79-
window.__widget?.resize()?.render();
205+
window.__column?.resize()?.render();
206+
window.__pie?.resize()?.render();
207+
window.__scatter?.resize()?.render();
80208
}
209+
210+
// Add event listener for the checkbox
211+
document.getElementById('tabNavigationToggle').addEventListener('change', function (e) {
212+
window.__column
213+
.tabNavigation(e.target.checked)
214+
.lazyRender()
215+
;
216+
console.log('Tab Navigation:', e.target.checked);
217+
});
218+
219+
// Add event listener for the checkbox
220+
document.getElementById('tabNavigationTogglePie').addEventListener('change', function (e) {
221+
window.__pie
222+
.tabNavigation(e.target.checked)
223+
.lazyRender()
224+
;
225+
console.log('Tab Navigation:', e.target.checked);
226+
});
227+
228+
// Add event listener for the checkbox
229+
document.getElementById('tabNavigationToggleScatter').addEventListener('change', function (e) {
230+
window.__scatter
231+
.tabNavigation(e.target.checked)
232+
.lazyRender()
233+
;
234+
console.log('Tab Navigation:', e.target.checked);
235+
});
236+
237+
const scatterVariantSelect = document.getElementById('scatterVariantSelect');
238+
239+
function applyScatterVariant(variant) {
240+
if (!window.__scatter) return;
241+
switch (variant) {
242+
case "line":
243+
window.__scatter
244+
.interpolate("linear")
245+
.interpolateFill(false)
246+
.showValue(false)
247+
;
248+
break;
249+
case "area":
250+
window.__scatter
251+
.interpolate("linear")
252+
.interpolateFill(true)
253+
.interpolateFillOpacity(0.35)
254+
.showValue(false)
255+
;
256+
break;
257+
case "points":
258+
default:
259+
window.__scatter
260+
.interpolate("")
261+
.interpolateFill(false)
262+
.pointShape("cross")
263+
.pointSize(10)
264+
.showValue(false)
265+
;
266+
break;
267+
}
268+
window.__scatter.lazyRender();
269+
console.log('Scatter Variant:', variant);
270+
}
271+
272+
scatterVariantSelect.addEventListener('change', function (e) {
273+
applyScatterVariant(e.target.value);
274+
});
275+
276+
applyScatterVariant(scatterVariantSelect.value);
277+
278+
81279
</script>
82280
</body>
83281

packages/chart/src/Column.css

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
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:active {
44+
outline: none !important;
45+
}

0 commit comments

Comments
 (0)