From f1546d0e50affb5582827f1757789fffdb6c9c37 Mon Sep 17 00:00:00 2001 From: ktx-vaidehi Date: Mon, 3 Aug 2026 14:30:35 +0530 Subject: [PATCH] feat(lib): add disableDrag prop to OTab Lets a single tab opt out of drag-to-reorder while OTabs is reorderable (e.g. its label is being renamed inline). The grip stays visible but the tab is no longer draggable and shows a text cursor instead of grab. --- web/src/lib/navigation/Tabs/OTab.types.ts | 6 ++++++ web/src/lib/navigation/Tabs/OTab.vue | 8 ++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/web/src/lib/navigation/Tabs/OTab.types.ts b/web/src/lib/navigation/Tabs/OTab.types.ts index 757d10656e..afad608d65 100644 --- a/web/src/lib/navigation/Tabs/OTab.types.ts +++ b/web/src/lib/navigation/Tabs/OTab.types.ts @@ -12,6 +12,12 @@ export interface OTabProps { icon?: string; /** Prevents interaction with this tab */ disable?: boolean; + /** + * Opt this single tab out of drag-to-reorder even while OTabs is reorderable + * (e.g. its label is being renamed inline). The grip stays visible but the tab + * is no longer draggable and shows a text cursor instead of grab. + */ + disableDrag?: boolean; /** Tooltip shown on hover — especially useful when disable is true to explain why */ tooltip?: string; } diff --git a/web/src/lib/navigation/Tabs/OTab.vue b/web/src/lib/navigation/Tabs/OTab.vue index d6cb8d33ef..57bd57cdc1 100644 --- a/web/src/lib/navigation/Tabs/OTab.vue +++ b/web/src/lib/navigation/Tabs/OTab.vue @@ -15,6 +15,7 @@ defineOptions({ inheritAttrs: false }); const props = withDefaults(defineProps(), { disable: false, + disableDrag: false, }); defineSlots(); @@ -25,6 +26,8 @@ const isActive = computed(() => context?.value.modelValue === props.nam const isDense = computed(() => context?.value.dense ?? false); const isVertical = computed(() => context?.value.isVertical ?? false); const isReorderable = computed(() => context?.value.reorderable ?? false); +/** Reorderable, and this tab hasn't opted out (e.g. while its label is edited). */ +const isDraggable = computed(() => isReorderable.value && !props.disableDrag); /** This tab is the one being dragged → dim it. */ const isDragging = computed( () => isReorderable.value && context?.value.draggingName === props.name, @@ -143,10 +146,11 @@ const heightClasses = computed(() => { baseClasses, stateClasses, heightClasses, - isReorderable ? 'cursor-grab active:cursor-grabbing' : '', + isDraggable ? 'cursor-grab active:cursor-grabbing' : '', + isReorderable && disableDrag ? 'cursor-text' : '', isDragging ? 'opacity-40' : '', ]" - :draggable="isReorderable || undefined" + :draggable="isDraggable || undefined" :data-otab-name="name" v-bind="$attrs" >