Skip to content

Commit 1800cf7

Browse files
committed
fix: restore selection styling and clean focus outline
1 parent 8a699c5 commit 1800cf7

File tree

2 files changed

+23
-8
lines changed

2 files changed

+23
-8
lines changed

kolibri/plugins/qti_viewer/frontend/components/interactions/ChoiceInteraction.vue

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -228,19 +228,27 @@
228228
229229
// Keep orderedIdentifiers in sync so that provided functions
230230
// (isFocusTarget, setFocusedIndex) can map identifier -> index.
231-
// Use nextTick to avoid mutating reactive state during render,
232-
// which would trigger an infinite re-render loop in Vue 2.
233231
const ids = orderedChoices.map(c => c.identifier);
234232
const idsChanged =
235233
ids.length !== orderedIdentifiers.value.length ||
236234
ids.some((id, i) => id !== orderedIdentifiers.value[i]);
237235
if (idsChanged || focusedIndex.value >= ids.length) {
238-
nextTick(() => {
236+
const isInitialPopulation = orderedIdentifiers.value.length === 0;
237+
if (isInitialPopulation) {
238+
// Set synchronously on first render so SimpleChoice components
239+
// get the correct tabindex="0" on their initial render.
240+
// No re-render loop risk since this only runs once.
239241
orderedIdentifiers.value = ids;
240-
if (focusedIndex.value >= ids.length) {
241-
focusedIndex.value = Math.max(0, ids.length - 1);
242-
}
243-
});
242+
} else {
243+
// Use nextTick for subsequent updates to avoid mutating
244+
// reactive state during render (infinite re-render in Vue 2).
245+
nextTick(() => {
246+
orderedIdentifiers.value = ids;
247+
if (focusedIndex.value >= ids.length) {
248+
focusedIndex.value = Math.max(0, ids.length - 1);
249+
}
250+
});
251+
}
244252
}
245253
246254
const choicesList = h(

kolibri/plugins/qti_viewer/frontend/components/interactions/SimpleChoice.vue

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'::before': {
1010
border: `2px solid ${selected ? $themeTokens.textInverted : $themeTokens.annotation}`,
1111
},
12-
':focus': $coreOutline,
12+
':focus': coreOutline,
1313
})
1414
"
1515
:aria-selected="selected"
@@ -72,12 +72,19 @@
7272
};
7373
});
7474
75+
// Define focus outline that matches Kolibri's standard
76+
const coreOutline = {
77+
outline: '3px solid rgb(51, 172, 245)',
78+
outlineOffset: '2px'
79+
};
80+
7581
return {
7682
selected,
7783
isFocused,
7884
handleClick,
7985
handleFocus,
8086
extraStyles,
87+
coreOutline,
8188
};
8289
},
8390
props: {

0 commit comments

Comments
 (0)