From 5792fb3225939f89af3fda336041cd63cabff431 Mon Sep 17 00:00:00 2001 From: lazerg Date: Mon, 10 Aug 2026 18:52:09 +0500 Subject: [PATCH 1/2] Respect the read-only state in the button group fieldtype --- resources/js/components/ui/Button/Button.vue | 3 +- .../fieldtypes/ButtonGroupFieldtype.test.js | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 resources/js/tests/components/fieldtypes/ButtonGroupFieldtype.test.js diff --git a/resources/js/components/ui/Button/Button.vue b/resources/js/components/ui/Button/Button.vue index 65e17d859b6..88c419456d0 100644 --- a/resources/js/components/ui/Button/Button.vue +++ b/resources/js/components/ui/Button/Button.vue @@ -25,6 +25,7 @@ const props = defineProps({ inset: { type: Boolean, default: false }, /** When `true`, the button shows an animated loading icon */ loading: { type: Boolean, default: false }, + readOnly: { type: Boolean, default: false }, /** When `true`, the button will be rounded */ round: { type: Boolean, default: false }, /** Controls the size of the button. Options: `2xs`, `xs`, `sm`, `base`, `lg` */ @@ -126,7 +127,7 @@ const restAttrs = computed(() => { :is="tag" v-bind="restAttrs" :class="buttonClasses" - :disabled="disabled || loading" + :disabled="disabled || loading || readOnly" :data-ui-group-target="['subtle', 'ghost'].includes(props.variant) ? null : true" :href :target diff --git a/resources/js/tests/components/fieldtypes/ButtonGroupFieldtype.test.js b/resources/js/tests/components/fieldtypes/ButtonGroupFieldtype.test.js new file mode 100644 index 00000000000..bdaa6b54534 --- /dev/null +++ b/resources/js/tests/components/fieldtypes/ButtonGroupFieldtype.test.js @@ -0,0 +1,41 @@ +import { mount } from '@vue/test-utils'; +import { expect, test } from 'vitest'; +import ButtonGroupFieldtype from '@/components/fieldtypes/ButtonGroupFieldtype.vue'; + +window.ResizeObserver = class { + observe() {} + unobserve() {} + disconnect() {} +}; + +const options = [ + { key: 'option_1', value: 'Option 1' }, + { key: 'option_2', value: 'Option 2' }, +]; + +test('value can be updated', async () => { + const wrapper = mount(ButtonGroupFieldtype, { + props: { + value: 'option_1', + handle: 'button_group', + config: { options }, + }, + }); + + await wrapper.findAll('button')[1].trigger('click'); + expect(wrapper.emitted('update:value')[0]).toEqual(['option_2']); +}); + +test('value cannot be updated when read only', async () => { + const wrapper = mount(ButtonGroupFieldtype, { + props: { + value: 'option_1', + handle: 'button_group', + config: { options }, + readOnly: true, + }, + }); + + await wrapper.findAll('button')[1].trigger('click'); + expect(wrapper.emitted('update:value')).toBeUndefined(); +}); From 26c8cfe8aacc7a86c474be5e171fcd0387baf970 Mon Sep 17 00:00:00 2001 From: Jason Varga Date: Tue, 11 Aug 2026 14:45:36 -0400 Subject: [PATCH 2/2] Prevent read-only Button with href rendering as a clickable link --- resources/js/components/ui/Button/Button.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/js/components/ui/Button/Button.vue b/resources/js/components/ui/Button/Button.vue index 88c419456d0..64294008ba9 100644 --- a/resources/js/components/ui/Button/Button.vue +++ b/resources/js/components/ui/Button/Button.vue @@ -43,7 +43,7 @@ const slots = useSlots(); const hasDefaultSlot = !!slots.default; const tag = computed(() => { if (props.as) return props.as; - if (props.href && !props.disabled && !props.loading) { + if (props.href && !props.disabled && !props.loading && !props.readOnly) { return props.target === '_blank' ? 'a' : Link; } return 'button';