diff --git a/resources/css/components/fieldtypes/bard.css b/resources/css/components/fieldtypes/bard.css index 1477f7ddead..f785315e6d9 100644 --- a/resources/css/components/fieldtypes/bard.css +++ b/resources/css/components/fieldtypes/bard.css @@ -5,6 +5,11 @@ .bard-fieldtype:not(.form-group, .grid-cell, [data-ui-input-group]) { @apply relative rounded-lg border outline-hidden dark:border-gray-700 with-contrast:border-gray-500; } + + /* Match ui Input / Textarea read-only: dashed outer border (same :not scope as default border). */ + .bard-fieldtype:not(.form-group, .grid-cell, [data-ui-input-group]):has(.bard-editor.mode\:read-only) { + @apply border-dashed; + } } /* BARD / EDITOR =================================================== */ @@ -51,8 +56,9 @@ /* BARD / MODES =================================================== */ @layer ui { + /* Match ui Input / Textarea read-only: neutral surface (dashed border on .bard-fieldtype above). */ .bard-editor.mode\:read-only .ProseMirror { - @apply bg-gray-300 text-gray-700 dark:bg-gray-600 dark:text-gray-100; + @apply bg-white text-gray-925 dark:bg-gray-900 dark:text-gray-300; } .bard-editor.mode\:minimal .ProseMirror { diff --git a/resources/js/components/fields/WidthSelector.vue b/resources/js/components/fields/WidthSelector.vue index da07abae1af..1bd1c581f9d 100644 --- a/resources/js/components/fields/WidthSelector.vue +++ b/resources/js/components/fields/WidthSelector.vue @@ -7,6 +7,8 @@ const props = defineProps({ initialWidths: Array, size: { type: String, default: 'base' }, variant: { type: String, default: 'default' }, + /** When `true`, the value cannot be changed (read-only, same pattern as other CP controls). */ + readOnly: { type: Boolean, default: false }, }) const emit = defineEmits(['update:model-value']) @@ -16,14 +18,35 @@ const hoveringOver = ref(null) const widths = ref(props.initialWidths ?? [25, 33, 50, 66, 75, 100]) const selected = computed(() => { + if (props.readOnly) { + return props.modelValue + } if (isHovering.value) { return hoveringOver.value } return props.modelValue }) +const readOnlyChromeClass = + 'data-readonly:border-dashed! data-readonly:border-gray-300 data-readonly:with-contrast:border-gray-100 data-readonly:dark:border! data-readonly:dark:border-dashed! data-readonly:dark:border-gray-600!' + +function handleMouseEnter() { + if (props.readOnly) return + isHovering.value = true +} + +function handleMouseLeave() { + isHovering.value = false + hoveringOver.value = null +} + +function handleSegmentClick(width) { + if (props.readOnly) return + emit('update:model-value', width) +} + const wrapperClasses = cva({ - base: 'relative text-gray-600 dark:text-gray-400 font-mono antialiased bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 with-contrast:border-gray-500 overflow-hidden flex cursor-pointer', + base: 'relative text-gray-600 dark:text-gray-400 font-mono antialiased bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 with-contrast:border-gray-500 overflow-hidden flex cursor-pointer data-readonly:cursor-default', variants: { size: { base: 'h-6 w-14 text-xs rounded-md', @@ -54,18 +77,28 @@ const sizerClasses = cva({ diff --git a/resources/js/components/fieldtypes/ArrayFieldtype.vue b/resources/js/components/fieldtypes/ArrayFieldtype.vue index 17cf585429a..d9272d9d9ad 100644 --- a/resources/js/components/fieldtypes/ArrayFieldtype.vue +++ b/resources/js/components/fieldtypes/ArrayFieldtype.vue @@ -1,5 +1,13 @@ @@ -98,6 +125,14 @@ export default { }, computed: { + hasColorSelected() { + const v = this.value; + if (v == null || v === false) return false; + if (typeof v === 'string' && v.trim() === '') return false; + + return true; + }, + replicatorPreview() { if (!this.showFieldPreviews) return; diff --git a/resources/js/components/fieldtypes/DateFieldtype.vue b/resources/js/components/fieldtypes/DateFieldtype.vue index 0f0f1742f9f..1c7b0475da0 100644 --- a/resources/js/components/fieldtypes/DateFieldtype.vue +++ b/resources/js/components/fieldtypes/DateFieldtype.vue @@ -1,5 +1,13 @@