Skip to content

Commit a2cc97d

Browse files
authored
fix(Checkbox,Switch,Select): expose handlers in slot attrs for renderless mode (#298)
* fix(Checkbox,Switch,Select): expose handlers in slot attrs for renderless mode CheckboxSelectAll, SwitchSelectAll, and SelectActivator bound onClick and onKeydown via `@click`/`@keydown` directives on <Atom> and omitted both from the slot attrs. In renderless mode Atom renders no element, so the directives bind nothing and the consumer's spread `attrs` lacks the handlers — a renderless custom element couldn't toggle/select or respond to the keyboard. Move onClick/onKeydown into each component's slot attrs (and type) and drop the directives. SelectAll components route them through their existing mergeProps(attrs, slotProps.attrs); SelectActivator binds slotProps.attrs directly. Single binding to Atom, no double-fire. Same renderless handler-loss family as ComboboxItem/SelectItem (already correct) and the dialog action components. * test(Checkbox,Switch,Select): cover renderless onClick/onKeydown for select-all and activator
1 parent 3db42e8 commit a2cc97d

6 files changed

Lines changed: 53 additions & 6 deletions

File tree

packages/0/src/components/Checkbox/CheckboxSelectAll.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@
6161
'tabindex': 0 | undefined
6262
'data-state': CheckboxState
6363
'data-disabled': true | undefined
64+
'onClick': () => void
65+
'onKeydown': (e: KeyboardEvent) => void
6466
}
6567
}
6668
</script>
@@ -159,6 +161,8 @@
159161
'tabindex': isDisabled.value ? undefined : 0,
160162
'data-state': dataState.value,
161163
'data-disabled': isDisabled.value ? true : undefined,
164+
onClick,
165+
onKeydown,
162166
},
163167
}))
164168
</script>
@@ -168,8 +172,6 @@
168172
v-bind="mergeProps(attrs, slotProps.attrs)"
169173
:as
170174
:renderless
171-
@click="onClick"
172-
@keydown="onKeydown"
173175
>
174176
<slot v-bind="slotProps" />
175177
</Atom>

packages/0/src/components/Checkbox/index.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,15 @@ describe('checkbox', () => {
10171017
expect(wrapper.find('.custom').exists()).toBe(true)
10181018
expect(capturedProps.attrs.role).toBe('checkbox')
10191019
})
1020+
1021+
it('should expose onClick and onKeydown in slot attrs for renderless mode', () => {
1022+
const { selectAllProps } = mountGroup({ withSelectAll: true })
1023+
1024+
// Pre-fix these handlers lived on @click/@keydown directives (lost in
1025+
// renderless mode); they must be exposed through slot attrs instead.
1026+
expect(selectAllProps!().attrs.onClick).toBeTypeOf('function')
1027+
expect(selectAllProps!().attrs.onKeydown).toBeTypeOf('function')
1028+
})
10201029
})
10211030
})
10221031

packages/0/src/components/Select/SelectActivator.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040
'aria-haspopup': 'listbox'
4141
'aria-controls': string
4242
'data-open': true | undefined
43+
'onClick': () => void
44+
'onKeydown': (e: KeyboardEvent) => void
4345
}
4446
}
4547
</script>
@@ -121,6 +123,8 @@
121123
'aria-haspopup': 'listbox',
122124
'aria-controls': context.listboxId,
123125
'data-open': context.isOpen.value || undefined,
126+
onClick,
127+
onKeydown,
124128
},
125129
}))
126130
</script>
@@ -131,8 +135,6 @@
131135
:as
132136
:style
133137
v-bind="slotProps.attrs"
134-
@click="onClick"
135-
@keydown="onKeydown"
136138
>
137139
<slot v-bind="slotProps" />
138140
</Atom>

packages/0/src/components/Select/index.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,29 @@ describe('select', () => {
979979
})
980980

981981
describe('root slot props', () => {
982+
it('should expose onClick and onKeydown in Select.Activator slot attrs', () => {
983+
let captured: any
984+
mount(
985+
defineComponent({
986+
render () {
987+
return h(Select.Root as any, {}, {
988+
default: () => h(Select.Activator as any, {}, {
989+
default: (props: any) => {
990+
captured = props
991+
return h('button', 'open')
992+
},
993+
}),
994+
})
995+
},
996+
}),
997+
)
998+
999+
// Pre-fix these handlers lived on @click/@keydown directives (lost in
1000+
// renderless mode); they must be exposed through slot attrs instead.
1001+
expect(captured.attrs.onClick).toBeTypeOf('function')
1002+
expect(captured.attrs.onKeydown).toBeTypeOf('function')
1003+
})
1004+
9821005
it('should expose isOpen, open, close, toggle, id, isDisabled', async () => {
9831006
let rootSlotProps: any
9841007

packages/0/src/components/Switch/SwitchSelectAll.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
'tabindex': 0 | undefined
7070
'data-state': SwitchState
7171
'data-disabled': true | undefined
72+
'onClick': () => void
73+
'onKeydown': (e: KeyboardEvent) => void
7274
}
7375
}
7476
</script>
@@ -154,6 +156,8 @@
154156
'tabindex': isDisabled.value ? undefined : 0,
155157
'data-state': dataState.value,
156158
'data-disabled': isDisabled.value ? true : undefined,
159+
onClick,
160+
onKeydown,
157161
},
158162
}))
159163
</script>
@@ -163,8 +167,6 @@
163167
v-bind="mergeProps(attrs, slotProps.attrs)"
164168
:as
165169
:renderless
166-
@click="onClick"
167-
@keydown="onKeydown"
168170
>
169171
<slot v-bind="slotProps" />
170172
</Atom>

packages/0/src/components/Switch/index.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,15 @@ describe('switch', () => {
776776
expect(wrapper.find('.custom').exists()).toBe(true)
777777
expect(capturedProps.attrs.role).toBe('switch')
778778
})
779+
780+
it('should expose onClick and onKeydown in slot attrs for renderless mode', () => {
781+
const { selectAllProps } = mountGroup({ withSelectAll: true })
782+
783+
// Pre-fix these handlers lived on @click/@keydown directives (lost in
784+
// renderless mode); they must be exposed through slot attrs instead.
785+
expect(selectAllProps!().attrs.onClick).toBeTypeOf('function')
786+
expect(selectAllProps!().attrs.onKeydown).toBeTypeOf('function')
787+
})
779788
})
780789

781790
// eslint-disable-next-line vitest/prefer-lowercase-title

0 commit comments

Comments
 (0)