@@ -387,6 +387,37 @@ const createCommand = computed(() => {
387387const { copied : createCopied, copy : copyCreate } = useClipboard ({ copiedDuring: 2000 })
388388const copyCreateCommand = () => copyCreate (createCommand .value )
389389
390+ const tablistNavigationKeys = new Set ([' ArrowRight' , ' ArrowLeft' , ' Home' , ' End' ])
391+
392+ function onTabListKeydown(event : KeyboardEvent ) {
393+ if (! tablistNavigationKeys .has (event .key )) return
394+ const tablist = event .currentTarget as HTMLElement | null
395+ if (! tablist ) return
396+
397+ const tabs = Array .from (tablist .querySelectorAll <HTMLElement >(' [role="tab"]' ))
398+ const count = Math .min (tabs .length , packageManagers .length )
399+ if (! count ) return
400+
401+ event .preventDefault ()
402+
403+ let activeIndex = packageManagers .findIndex (pm => pm .id === selectedPM .value )
404+ if (activeIndex < 0 ) activeIndex = 0
405+
406+ let nextIndex = activeIndex
407+ if (event .key === ' ArrowRight' ) nextIndex = (activeIndex + 1 ) % count
408+ if (event .key === ' ArrowLeft' ) nextIndex = (activeIndex - 1 + count ) % count
409+ if (event .key === ' Home' ) nextIndex = 0
410+ if (event .key === ' End' ) nextIndex = count - 1
411+
412+ const nextTab = tabs [nextIndex ]
413+ const nextId = packageManagers [nextIndex ]?.id
414+ if (nextId && nextId !== selectedPM .value ) {
415+ selectedPM .value = nextId
416+ }
417+
418+ nextTick (() => nextTab ?.focus ())
419+ }
420+
390421// Primary run command parts
391422const runCommandParts = computed (() => {
392423 if (! executableInfo .value ?.hasExecutable ) return []
@@ -947,12 +978,18 @@ function handleClick(event: MouseEvent) {
947978 class =" flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md"
948979 role =" tablist"
949980 aria-label =" Package manager"
981+ @keydown =" onTabListKeydown"
950982 >
951983 <button
952984 v-for =" pm in packageManagers"
953985 :key =" pm.id"
986+ :id =" `pm-tab-${pm.id}`"
954987 role =" tab"
955988 :aria-selected =" isMounted && selectedPM === pm.id"
989+ :aria-controls =" `pm-panel-${pm.id}`"
990+ :tabindex =" isMounted && selectedPM === pm.id ? 0 : -1"
991+ :data-pm-id =" pm.id"
992+ type =" button"
956993 class =" px-2 py-1.5 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 inline-flex items-center gap-1.5"
957994 :class ="
958995 isMounted && selectedPM === pm.id
@@ -966,7 +1003,15 @@ function handleClick(event: MouseEvent) {
9661003 </button >
9671004 </div >
9681005 </div >
969- <div class =" relative group" >
1006+ <div
1007+ v-for =" pm in packageManagers"
1008+ :key =" pm.id"
1009+ role =" tabpanel"
1010+ :id =" `pm-panel-${pm.id}`"
1011+ :aria-labelledby =" `pm-tab-${pm.id}`"
1012+ v-show =" selectedPM === pm.id"
1013+ class =" relative group"
1014+ >
9701015 <!-- Terminal-style execute command -->
9711016 <div class =" bg-bg-subtle border border-border rounded-lg overflow-hidden" >
9721017 <div class =" flex gap-1.5 px-3 pt-2 sm:px-4 sm:pt-3" >
@@ -1027,12 +1072,18 @@ function handleClick(event: MouseEvent) {
10271072 class =" flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md overflow-x-auto"
10281073 role =" tablist"
10291074 :aria-label =" $t('package.get_started.pm_label')"
1075+ @keydown =" onTabListKeydown"
10301076 >
10311077 <button
10321078 v-for =" pm in packageManagers"
10331079 :key =" pm.id"
1080+ :id =" `pm-tab-${pm.id}`"
10341081 role =" tab"
10351082 :aria-selected =" isMounted && selectedPM === pm.id"
1083+ :aria-controls =" `pm-panel-${pm.id}`"
1084+ :tabindex =" isMounted && selectedPM === pm.id ? 0 : -1"
1085+ :data-pm-id =" pm.id"
1086+ type =" button"
10361087 class =" px-2 py-1.5 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 inline-flex items-center gap-1.5"
10371088 :class ="
10381089 isMounted && selectedPM === pm.id
@@ -1046,7 +1097,15 @@ function handleClick(event: MouseEvent) {
10461097 </button >
10471098 </div >
10481099 </div >
1049- <div class =" relative group" >
1100+ <div
1101+ v-for =" pm in packageManagers"
1102+ :key =" pm.id"
1103+ role =" tabpanel"
1104+ :id =" `pm-panel-${pm.id}`"
1105+ :aria-labelledby =" `pm-tab-${pm.id}`"
1106+ v-show =" selectedPM === pm.id"
1107+ class =" relative group"
1108+ >
10501109 <!-- Terminal-style install command -->
10511110 <div class =" bg-bg-subtle border border-border rounded-lg overflow-hidden" >
10521111 <div class =" flex gap-1.5 px-3 pt-2 sm:px-4 sm:pt-3" >
0 commit comments