Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions resources/js/components/fieldtypes/ToggleFieldtype.vue
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,7 @@
@update:model-value="update"
:disabled="config.disabled || isReadOnly"
:id="fieldId"
:aria-label="__(config.display)"
:model-value="value"
:read-only="isReadOnly"
/>
Expand Down
6 changes: 4 additions & 2 deletions resources/js/components/ui/Checkbox/Item.vue
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
<script setup>
import { CheckboxIndicator, CheckboxRoot } from 'reka-ui';
import { computed, useAttrs, useId } from 'vue';
import { computed, useAttrs, useId, useSlots } from 'vue';
import { cva } from 'cva';
import { twMerge } from 'tailwind-merge';
import { injectCheckboxContext } from './Group.vue';

defineOptions({ inheritAttrs: false });

const attrs = useAttrs();
const slots = useSlots();

const props = defineProps({
/** Optional ID for the checkbox input */
Expand DownExpand Up@@ -100,7 +101,8 @@ const conditionalProps = computed(() => {
props_obj['aria-describedby'] = `${props.id}-description`;
}

if (props.solo && (props.label || props.value)) {
// Providing the name ourselves stops Reka from deriving it from the label's innerText, which forces a layout.
if ((props.solo || !slots.default) && (props.label || props.value)) {
props_obj['aria-label'] = props.label || props.value;
}

Expand Down
18 changes: 18 additions & 0 deletions resources/js/tests/components/CheckboxItem.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,3 +30,21 @@ test('aria-describedby and the description element share the custom id', () => {
expect(wrapper.find('[role="checkbox"]').attributes('aria-describedby')).toBe('custom-checkbox-id-description');
expect(wrapper.find('p').attributes('id')).toBe('custom-checkbox-id-description');
});

test('the label prop is rendered as the aria-label', () => {
const wrapper = mount(Checkbox, {
props: { label: 'Subscribe' },
});

expect(wrapper.find('[role="checkbox"]').attributes('aria-label')).toBe('Subscribe');
});

test('no aria-label is rendered when the label comes from the slot', () => {
const wrapper = mount(Checkbox, {
props: { value: 'subscribe' },
slots: { default: () => 'Subscribe' },
});

expect(wrapper.find('[role="checkbox"]').attributes('aria-label')).toBeUndefined();
});

17 changes: 17 additions & 0 deletions resources/js/tests/components/Switch.test.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
import { mount } from '@vue/test-utils';
import { expect, test } from 'vitest';
import Switch from '@/components/ui/Switch.vue';

test('an aria-label attribute falls through to the switch element', () => {
const wrapper = mount(Switch, {
attrs: { 'aria-label': 'Publish this entry' },
});

expect(wrapper.find('[role="switch"]').attributes('aria-label')).toBe('Publish this entry');
});

test('no aria-label is rendered when no aria-label attribute is given', () => {
const wrapper = mount(Switch);

expect(wrapper.find('[role="switch"]').attributes('aria-label')).toBeUndefined();
});
Loading