@tutti-os/workbench-surface 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -7435,11 +7435,16 @@ function WorkbenchHostDock({
7435
7435
  const hoverPanelOpenTimerRef = useRef8(
7436
7436
  null
7437
7437
  );
7438
+ const labelTooltipOpenTimerRef = useRef8(
7439
+ null
7440
+ );
7438
7441
  const hoverPanelScheduledPointRef = useRef8(null);
7442
+ const labelTooltipScheduledPointRef = useRef8(null);
7439
7443
  const hoverPanelRestTargetRef = useRef8(null);
7440
7444
  const activeHoverPanelRef = useRef8(
7441
7445
  null
7442
7446
  );
7447
+ const activeLabelTooltipRef = useRef8(null);
7443
7448
  const pendingDockStateRefreshRef = useRef8(false);
7444
7449
  const slotRefs = useRef8(/* @__PURE__ */ new Map());
7445
7450
  const wallpaperToneElementRefs = useRef8(/* @__PURE__ */ new Map());
@@ -7453,6 +7458,7 @@ function WorkbenchHostDock({
7453
7458
  const [activeAttentionEntryIds, setActiveAttentionEntryIds] = useState8(/* @__PURE__ */ new Set());
7454
7459
  const [activePopup, setActivePopup] = useState8(null);
7455
7460
  const [activeHoverPanel, setActiveHoverPanel] = useState8(null);
7461
+ const [activeLabelTooltip, setActiveLabelTooltip] = useState8(null);
7456
7462
  const [activeMinimizedStackPopup, setActiveMinimizedStackPopup] = useState8(null);
7457
7463
  const [pendingActionKeys, setPendingActionKeys] = useState8(
7458
7464
  () => /* @__PURE__ */ new Set()
@@ -7488,16 +7494,29 @@ function WorkbenchHostDock({
7488
7494
  hoverPanelOpenTimerRef.current = null;
7489
7495
  hoverPanelScheduledPointRef.current = null;
7490
7496
  }, []);
7497
+ const clearLabelTooltipOpenTimer = useCallback10(() => {
7498
+ if (labelTooltipOpenTimerRef.current === null) {
7499
+ return;
7500
+ }
7501
+ clearTimeout(labelTooltipOpenTimerRef.current);
7502
+ labelTooltipOpenTimerRef.current = null;
7503
+ labelTooltipScheduledPointRef.current = null;
7504
+ }, []);
7491
7505
  useEffect9(
7492
7506
  () => () => {
7493
7507
  clearHoverPanelCloseTimer();
7494
7508
  clearHoverPanelOpenTimer();
7509
+ clearLabelTooltipOpenTimer();
7495
7510
  for (const timer of collapsingMinimizedLaunchTimerRef.current.values()) {
7496
7511
  clearTimeout(timer);
7497
7512
  }
7498
7513
  collapsingMinimizedLaunchTimerRef.current.clear();
7499
7514
  },
7500
- [clearHoverPanelCloseTimer, clearHoverPanelOpenTimer]
7515
+ [
7516
+ clearHoverPanelCloseTimer,
7517
+ clearHoverPanelOpenTimer,
7518
+ clearLabelTooltipOpenTimer
7519
+ ]
7501
7520
  );
7502
7521
  const clearCollapsingMinimizedLaunch = useCallback10((anchorKey) => {
7503
7522
  const timer = collapsingMinimizedLaunchTimerRef.current.get(anchorKey);
@@ -7684,6 +7703,23 @@ function WorkbenchHostDock({
7684
7703
  useEffect9(() => {
7685
7704
  activeHoverPanelRef.current = activeHoverPanel;
7686
7705
  }, [activeHoverPanel]);
7706
+ useEffect9(() => {
7707
+ activeLabelTooltipRef.current = activeLabelTooltip;
7708
+ }, [activeLabelTooltip]);
7709
+ const closeLabelTooltipImmediate = useCallback10(
7710
+ (targetKey) => {
7711
+ clearLabelTooltipOpenTimer();
7712
+ if (targetKey !== void 0 && activeLabelTooltipRef.current?.key !== targetKey) {
7713
+ return;
7714
+ }
7715
+ if (activeLabelTooltipRef.current === null) {
7716
+ return;
7717
+ }
7718
+ activeLabelTooltipRef.current = null;
7719
+ setActiveLabelTooltip(null);
7720
+ },
7721
+ [clearLabelTooltipOpenTimer]
7722
+ );
7687
7723
  const closeHoverPanelImmediate = useCallback10(
7688
7724
  (entryId) => {
7689
7725
  clearHoverPanelOpenTimer();
@@ -7771,6 +7807,50 @@ function WorkbenchHostDock({
7771
7807
  },
7772
7808
  [clearHoverPanelOpenTimer, showHoverPanel]
7773
7809
  );
7810
+ const showLabelTooltip = useCallback10(
7811
+ (target, anchorKey, anchorElement) => {
7812
+ const dockElement = dockMeasureRef.current;
7813
+ if (!dockElement) {
7814
+ return;
7815
+ }
7816
+ const dockRect = dockElement.getBoundingClientRect();
7817
+ const anchorRect = resolveDockLabelTooltipAnchorRect({
7818
+ dockPlacement,
7819
+ slotElement: anchorElement
7820
+ });
7821
+ clearLabelTooltipOpenTimer();
7822
+ const nextTooltip = {
7823
+ anchorKey,
7824
+ anchorRect: {
7825
+ height: anchorRect.height,
7826
+ left: anchorRect.left - dockRect.left,
7827
+ top: anchorRect.top - dockRect.top,
7828
+ width: anchorRect.width
7829
+ },
7830
+ key: target.key,
7831
+ label: target.label
7832
+ };
7833
+ activeLabelTooltipRef.current = nextTooltip;
7834
+ setActiveLabelTooltip(nextTooltip);
7835
+ },
7836
+ [clearLabelTooltipOpenTimer, dockPlacement]
7837
+ );
7838
+ const scheduleLabelTooltipAfterRest = useCallback10(
7839
+ (target, anchorKey) => {
7840
+ clearLabelTooltipOpenTimer();
7841
+ labelTooltipScheduledPointRef.current = null;
7842
+ labelTooltipOpenTimerRef.current = setTimeout(() => {
7843
+ labelTooltipOpenTimerRef.current = null;
7844
+ labelTooltipScheduledPointRef.current = null;
7845
+ const slotElement = slotRefs.current.get(anchorKey);
7846
+ if (!slotElement) {
7847
+ return;
7848
+ }
7849
+ showLabelTooltip(target, anchorKey, slotElement);
7850
+ }, dockHoverPanelOpenDelayMs);
7851
+ },
7852
+ [clearLabelTooltipOpenTimer, showLabelTooltip]
7853
+ );
7774
7854
  const resolveHoverPanelTargetAtPoint = useCallback10(
7775
7855
  (clientX, clientY) => {
7776
7856
  for (const [anchorKey, slotElement] of slotRefs.current) {
@@ -7787,6 +7867,33 @@ function WorkbenchHostDock({
7787
7867
  },
7788
7868
  []
7789
7869
  );
7870
+ const resolveLabelTooltipTargetAtPoint = useCallback10(
7871
+ (clientX, clientY) => {
7872
+ for (const [anchorKey, slotElement] of slotRefs.current) {
7873
+ if (slotElement.dataset.dockHoverPanelEntryId) {
7874
+ continue;
7875
+ }
7876
+ const key = slotElement.dataset.dockLabelTooltipKey;
7877
+ const label = slotElement.dataset.dockLabelTooltipLabel?.trim() ?? "";
7878
+ if (!key || !label) {
7879
+ continue;
7880
+ }
7881
+ const rect = slotElement.getBoundingClientRect();
7882
+ if (clientX >= rect.left - dockHoverPanelHitSlopPx && clientX <= rect.right + dockHoverPanelHitSlopPx && clientY >= rect.top - dockHoverPanelHitSlopPx && clientY <= rect.bottom + dockHoverPanelHitSlopPx) {
7883
+ return {
7884
+ anchorKey,
7885
+ slotElement,
7886
+ target: {
7887
+ key,
7888
+ label
7889
+ }
7890
+ };
7891
+ }
7892
+ }
7893
+ return null;
7894
+ },
7895
+ []
7896
+ );
7790
7897
  const isPointerInsideActiveHoverPanelRegion = useCallback10(
7791
7898
  (clientX, clientY) => {
7792
7899
  const activeHoverPanel2 = activeHoverPanelRef.current;
@@ -7847,19 +7954,57 @@ function WorkbenchHostDock({
7847
7954
  },
7848
7955
  [clearHoverPanelOpenTimer, resolveHoverPanelTargetAtPoint, showHoverPanel]
7849
7956
  );
7957
+ const scheduleLabelTooltipAtPointAfterRest = useCallback10(
7958
+ (clientX, clientY) => {
7959
+ if (activeLabelTooltipRef.current !== null) {
7960
+ return;
7961
+ }
7962
+ const scheduledPoint = labelTooltipScheduledPointRef.current;
7963
+ if (labelTooltipOpenTimerRef.current !== null && scheduledPoint && Math.abs(clientX - scheduledPoint.clientX) <= dockHoverPanelPointerRestTolerancePx && Math.abs(clientY - scheduledPoint.clientY) <= dockHoverPanelPointerRestTolerancePx) {
7964
+ return;
7965
+ }
7966
+ clearLabelTooltipOpenTimer();
7967
+ labelTooltipScheduledPointRef.current = { clientX, clientY };
7968
+ labelTooltipOpenTimerRef.current = setTimeout(() => {
7969
+ labelTooltipOpenTimerRef.current = null;
7970
+ labelTooltipScheduledPointRef.current = null;
7971
+ if (activeHoverPanelRef.current !== null) {
7972
+ return;
7973
+ }
7974
+ const target = resolveLabelTooltipTargetAtPoint(clientX, clientY);
7975
+ if (!target) {
7976
+ return;
7977
+ }
7978
+ showLabelTooltip(target.target, target.anchorKey, target.slotElement);
7979
+ }, dockHoverPanelOpenDelayMs);
7980
+ },
7981
+ [
7982
+ clearLabelTooltipOpenTimer,
7983
+ resolveLabelTooltipTargetAtPoint,
7984
+ showLabelTooltip
7985
+ ]
7986
+ );
7850
7987
  const beginDockIconInteraction = useCallback10(
7851
7988
  (anchorKey) => {
7852
7989
  hoverPanelRestTargetRef.current = null;
7853
7990
  clearHoverPanelOpenTimer();
7991
+ closeLabelTooltipImmediate();
7854
7992
  closeHoverPanelImmediate();
7855
7993
  triggerDockBounce(anchorKey);
7856
7994
  },
7857
- [clearHoverPanelOpenTimer, closeHoverPanelImmediate, triggerDockBounce]
7995
+ [
7996
+ clearHoverPanelOpenTimer,
7997
+ closeHoverPanelImmediate,
7998
+ closeLabelTooltipImmediate,
7999
+ triggerDockBounce
8000
+ ]
7858
8001
  );
7859
8002
  const beginDockMinimizedInteraction = useCallback10(
7860
8003
  (anchorKey) => {
7861
8004
  hoverPanelRestTargetRef.current = null;
7862
8005
  clearHoverPanelOpenTimer();
8006
+ clearLabelTooltipOpenTimer();
8007
+ closeLabelTooltipImmediate();
7863
8008
  closeHoverPanelImmediate();
7864
8009
  pauseDockMagnification();
7865
8010
  if (!anchorKey) {
@@ -7887,8 +8032,10 @@ function WorkbenchHostDock({
7887
8032
  },
7888
8033
  [
7889
8034
  clearHoverPanelOpenTimer,
8035
+ clearLabelTooltipOpenTimer,
7890
8036
  clearSlotMagnification,
7891
8037
  closeHoverPanelImmediate,
8038
+ closeLabelTooltipImmediate,
7892
8039
  pauseDockMagnification
7893
8040
  ]
7894
8041
  );
@@ -7916,6 +8063,7 @@ function WorkbenchHostDock({
7916
8063
  const handleDockPointerTravel = useCallback10(
7917
8064
  (clientX, clientY) => {
7918
8065
  if (activeHoverPanelRef.current !== null) {
8066
+ closeLabelTooltipImmediate();
7919
8067
  if (isPointerInsideActiveHoverPanelRegion(clientX, clientY)) {
7920
8068
  clearHoverPanelCloseTimer();
7921
8069
  return;
@@ -7924,16 +8072,27 @@ function WorkbenchHostDock({
7924
8072
  handleDockPointerLeave();
7925
8073
  return;
7926
8074
  }
8075
+ const activeLabelTooltip2 = activeLabelTooltipRef.current;
8076
+ if (activeLabelTooltip2) {
8077
+ const target = resolveLabelTooltipTargetAtPoint(clientX, clientY);
8078
+ if (target?.target.key !== activeLabelTooltip2.key) {
8079
+ closeLabelTooltipImmediate(activeLabelTooltip2.key);
8080
+ }
8081
+ }
7927
8082
  handleDockPointerMove(clientX, clientY);
7928
8083
  scheduleHoverPanelAtPointAfterRest(clientX, clientY);
8084
+ scheduleLabelTooltipAtPointAfterRest(clientX, clientY);
7929
8085
  },
7930
8086
  [
7931
8087
  clearHoverPanelCloseTimer,
8088
+ closeLabelTooltipImmediate,
7932
8089
  handleDockPointerMove,
7933
8090
  handleDockPointerLeave,
7934
8091
  isPointerInsideActiveHoverPanelRegion,
8092
+ resolveLabelTooltipTargetAtPoint,
7935
8093
  scheduleHoverPanelClose,
7936
- scheduleHoverPanelAtPointAfterRest
8094
+ scheduleHoverPanelAtPointAfterRest,
8095
+ scheduleLabelTooltipAtPointAfterRest
7937
8096
  ]
7938
8097
  );
7939
8098
  const updateDockScrollState = useCallback10(() => {
@@ -8097,10 +8256,12 @@ function WorkbenchHostDock({
8097
8256
  const closePopup = () => {
8098
8257
  clearHoverPanelCloseTimer();
8099
8258
  clearHoverPanelOpenTimer();
8259
+ clearLabelTooltipOpenTimer();
8100
8260
  hoverPanelRestTargetRef.current = null;
8101
8261
  setDockHoverPanelOpen(false);
8102
8262
  setActivePopup(null);
8103
8263
  setActiveHoverPanel(null);
8264
+ closeLabelTooltipImmediate();
8104
8265
  setActiveMinimizedStackPopup(null);
8105
8266
  };
8106
8267
  const scrollDockItems = (direction) => {
@@ -8110,6 +8271,7 @@ function WorkbenchHostDock({
8110
8271
  }
8111
8272
  resetDockMagnification();
8112
8273
  closeHoverPanelImmediate();
8274
+ closeLabelTooltipImmediate();
8113
8275
  hoverPanelRestTargetRef.current = null;
8114
8276
  const isVertical = dockPlacement === "left";
8115
8277
  const viewportSize = isVertical ? element.clientHeight : element.clientWidth;
@@ -8174,6 +8336,8 @@ function WorkbenchHostDock({
8174
8336
  onPointerLeave: () => {
8175
8337
  hoverPanelRestTargetRef.current = null;
8176
8338
  clearHoverPanelOpenTimer();
8339
+ clearLabelTooltipOpenTimer();
8340
+ closeLabelTooltipImmediate();
8177
8341
  closeHoverPanelImmediate();
8178
8342
  handleDockPointerLeave();
8179
8343
  flushPendingDockStateRefresh();
@@ -8234,6 +8398,7 @@ function WorkbenchHostDock({
8234
8398
  matchedNodes: resolvedEntry.matchedNodes
8235
8399
  });
8236
8400
  const hasHoverPanel = dockEntryHasHoverPanel(entry);
8401
+ const labelTooltipTarget2 = hasHoverPanel ? null : dockLabelTooltipTarget(`entry:${entry.id}`, entry.label);
8237
8402
  const dockButton2 = /* @__PURE__ */ jsx10(
8238
8403
  "button",
8239
8404
  {
@@ -8243,7 +8408,6 @@ function WorkbenchHostDock({
8243
8408
  "aria-disabled": clickResolution.kind === "blocked" ? true : void 0,
8244
8409
  className: "desktop-dock__btn",
8245
8410
  "data-interactive": clickResolution.kind === "blocked" ? "false" : "true",
8246
- title: entry.label,
8247
8411
  type: "button",
8248
8412
  onPointerDown: () => {
8249
8413
  if (clickResolution.kind === "blocked") {
@@ -8377,6 +8541,8 @@ function WorkbenchHostDock({
8377
8541
  "data-desktop-dock-slot": "true",
8378
8542
  "data-entry-state": entry.state?.kind ?? "enabled",
8379
8543
  "data-dock-hover-panel-entry-id": hasHoverPanel ? entry.id : void 0,
8544
+ "data-dock-label-tooltip-key": labelTooltipTarget2?.key,
8545
+ "data-dock-label-tooltip-label": labelTooltipTarget2?.label,
8380
8546
  "data-icon-size": entry.iconSize ?? "default",
8381
8547
  "data-node-state": resolvedEntry.dockNodeState,
8382
8548
  "data-popup-active": currentPopup ? "true" : void 0,
@@ -8387,6 +8553,9 @@ function WorkbenchHostDock({
8387
8553
  if (hasHoverPanel && !event.currentTarget.contains(event.relatedTarget)) {
8388
8554
  closeHoverPanelImmediate(entry.id);
8389
8555
  }
8556
+ if (labelTooltipTarget2 && !event.currentTarget.contains(event.relatedTarget)) {
8557
+ closeLabelTooltipImmediate(labelTooltipTarget2.key);
8558
+ }
8390
8559
  },
8391
8560
  onFocus: (event) => {
8392
8561
  if (hasHoverPanel) {
@@ -8395,15 +8564,41 @@ function WorkbenchHostDock({
8395
8564
  anchorKey,
8396
8565
  event.currentTarget
8397
8566
  );
8567
+ return;
8568
+ }
8569
+ if (labelTooltipTarget2) {
8570
+ showLabelTooltip(
8571
+ labelTooltipTarget2,
8572
+ anchorKey,
8573
+ event.currentTarget
8574
+ );
8398
8575
  }
8399
8576
  },
8400
8577
  onPointerEnter: () => {
8401
8578
  if (hasHoverPanel) {
8402
8579
  scheduleHoverPanelAfterRest(entry.id, anchorKey);
8580
+ return;
8581
+ }
8582
+ if (labelTooltipTarget2) {
8583
+ scheduleLabelTooltipAfterRest(
8584
+ labelTooltipTarget2,
8585
+ anchorKey
8586
+ );
8403
8587
  }
8404
8588
  },
8405
8589
  onPointerLeave: (event) => {
8406
8590
  if (!hasHoverPanel) {
8591
+ if (labelTooltipTarget2) {
8592
+ clearLabelTooltipOpenTimer();
8593
+ closeLabelTooltipImmediate(labelTooltipTarget2.key);
8594
+ const relatedTarget2 = event.relatedTarget;
8595
+ if (relatedTarget2 instanceof Node && dockMeasureRef.current?.contains(relatedTarget2)) {
8596
+ scheduleLabelTooltipAtPointAfterRest(
8597
+ event.clientX,
8598
+ event.clientY
8599
+ );
8600
+ }
8601
+ }
8407
8602
  return;
8408
8603
  }
8409
8604
  const relatedTarget = event.relatedTarget;
@@ -8432,15 +8627,19 @@ function WorkbenchHostDock({
8432
8627
  const slot = dockItem.item.slot;
8433
8628
  if (slot.kind === "stack") {
8434
8629
  const stackPopupActive = activeMinimizedStackPopup !== null ? true : void 0;
8630
+ const stackLabel = i18n.t("minimizedWindows");
8631
+ const labelTooltipTarget2 = dockLabelTooltipTarget(
8632
+ `minimized-stack:${slot.anchorKey}`,
8633
+ stackLabel
8634
+ );
8435
8635
  const stackButton = /* @__PURE__ */ jsx10(
8436
8636
  "button",
8437
8637
  {
8438
8638
  "aria-expanded": stackPopupActive,
8439
8639
  "aria-haspopup": "dialog",
8440
- "aria-label": i18n.t("minimizedWindows"),
8640
+ "aria-label": stackLabel,
8441
8641
  className: "desktop-dock__btn desktop-dock__minimized-btn",
8442
8642
  "data-interactive": "true",
8443
- title: i18n.t("minimizedWindows"),
8444
8643
  type: "button",
8445
8644
  onPointerDown: () => {
8446
8645
  beginDockMinimizedInteraction();
@@ -8512,24 +8711,58 @@ function WorkbenchHostDock({
8512
8711
  className: "desktop-dock__slot desktop-dock__slot--minimized",
8513
8712
  "data-desktop-dock-anchor-key": slot.anchorKey,
8514
8713
  "data-desktop-dock-slot": "true",
8714
+ "data-dock-label-tooltip-key": labelTooltipTarget2.key,
8715
+ "data-dock-label-tooltip-label": labelTooltipTarget2.label,
8515
8716
  "data-node-state": "minimized",
8516
8717
  "data-popup-active": stackPopupActive,
8517
8718
  "data-presence": dockItem.presence,
8518
8719
  "data-section-id": "minimized",
8519
8720
  "data-stack-dispatching": stackDispatching ? "true" : void 0,
8721
+ onBlur: (event) => {
8722
+ if (!event.currentTarget.contains(event.relatedTarget)) {
8723
+ closeLabelTooltipImmediate(labelTooltipTarget2.key);
8724
+ }
8725
+ },
8726
+ onFocus: (event) => {
8727
+ showLabelTooltip(
8728
+ labelTooltipTarget2,
8729
+ slot.anchorKey,
8730
+ event.currentTarget
8731
+ );
8732
+ },
8733
+ onPointerEnter: () => {
8734
+ scheduleLabelTooltipAfterRest(
8735
+ labelTooltipTarget2,
8736
+ slot.anchorKey
8737
+ );
8738
+ },
8739
+ onPointerLeave: (event) => {
8740
+ clearLabelTooltipOpenTimer();
8741
+ closeLabelTooltipImmediate(labelTooltipTarget2.key);
8742
+ const relatedTarget = event.relatedTarget;
8743
+ if (relatedTarget instanceof Node && dockMeasureRef.current?.contains(relatedTarget)) {
8744
+ scheduleLabelTooltipAtPointAfterRest(
8745
+ event.clientX,
8746
+ event.clientY
8747
+ );
8748
+ }
8749
+ },
8520
8750
  children: stackButton
8521
8751
  },
8522
8752
  dockItem.key
8523
8753
  );
8524
8754
  }
8525
8755
  const node = slot.node;
8756
+ const labelTooltipTarget = dockLabelTooltipTarget(
8757
+ `minimized-node:${node.id}`,
8758
+ node.title
8759
+ );
8526
8760
  const dockButton = /* @__PURE__ */ jsx10(
8527
8761
  "button",
8528
8762
  {
8529
8763
  "aria-label": i18n.t("launch", { title: node.title }),
8530
8764
  className: "desktop-dock__btn desktop-dock__minimized-btn",
8531
8765
  "data-interactive": "true",
8532
- title: node.title,
8533
8766
  type: "button",
8534
8767
  onPointerDown: () => {
8535
8768
  const restoreIntent = resolveWorkbenchMinimizedDockRestoreIntent({
@@ -8592,10 +8825,41 @@ function WorkbenchHostDock({
8592
8825
  "data-collapsing": collapsingMinimizedLaunchAnchorKeys.has(slot.anchorKey) ? "true" : void 0,
8593
8826
  "data-desktop-dock-anchor-key": slot.anchorKey,
8594
8827
  "data-desktop-dock-slot": "true",
8828
+ "data-dock-label-tooltip-key": labelTooltipTarget.key,
8829
+ "data-dock-label-tooltip-label": labelTooltipTarget.label,
8595
8830
  "data-node-state": "minimized",
8596
8831
  "data-presence": dockItem.presence,
8597
8832
  "data-promoted-from-stack": promotedNodeId === node.id ? "true" : void 0,
8598
8833
  "data-section-id": "minimized",
8834
+ onBlur: (event) => {
8835
+ if (!event.currentTarget.contains(event.relatedTarget)) {
8836
+ closeLabelTooltipImmediate(labelTooltipTarget.key);
8837
+ }
8838
+ },
8839
+ onFocus: (event) => {
8840
+ showLabelTooltip(
8841
+ labelTooltipTarget,
8842
+ slot.anchorKey,
8843
+ event.currentTarget
8844
+ );
8845
+ },
8846
+ onPointerEnter: () => {
8847
+ scheduleLabelTooltipAfterRest(
8848
+ labelTooltipTarget,
8849
+ slot.anchorKey
8850
+ );
8851
+ },
8852
+ onPointerLeave: (event) => {
8853
+ clearLabelTooltipOpenTimer();
8854
+ closeLabelTooltipImmediate(labelTooltipTarget.key);
8855
+ const relatedTarget = event.relatedTarget;
8856
+ if (relatedTarget instanceof Node && dockMeasureRef.current?.contains(relatedTarget)) {
8857
+ scheduleLabelTooltipAtPointAfterRest(
8858
+ event.clientX,
8859
+ event.clientY
8860
+ );
8861
+ }
8862
+ },
8599
8863
  children: dockButton
8600
8864
  },
8601
8865
  dockItem.key
@@ -8647,6 +8911,13 @@ function WorkbenchHostDock({
8647
8911
  handleDockPointerLeave();
8648
8912
  }
8649
8913
  }
8914
+ ) : null,
8915
+ activeLabelTooltip ? /* @__PURE__ */ jsx10(
8916
+ WorkbenchHostDockLabelTooltip,
8917
+ {
8918
+ placement: dockPlacement,
8919
+ state: activeLabelTooltip
8920
+ }
8650
8921
  ) : null
8651
8922
  ]
8652
8923
  }
@@ -8957,6 +9228,29 @@ function WorkbenchHostDockMinimizedNodePreview({
8957
9228
  function dockEntryHasHoverPanel(entry) {
8958
9229
  return Boolean(entry.state?.reason?.trim()) || (entry.hoverActions?.length ?? 0) > 0;
8959
9230
  }
9231
+ function dockLabelTooltipTarget(key, label) {
9232
+ return { key, label: label.trim() };
9233
+ }
9234
+ function resolveDockLabelTooltipAnchorRect({
9235
+ dockPlacement,
9236
+ slotElement
9237
+ }) {
9238
+ const slotRect = slotElement.getBoundingClientRect();
9239
+ if (dockPlacement === "left") {
9240
+ return {
9241
+ height: DOCK_ICON_BASE_SIZE,
9242
+ left: slotRect.left,
9243
+ top: slotRect.top + (slotRect.height - DOCK_ICON_BASE_SIZE) / 2,
9244
+ width: DOCK_ICON_BASE_SIZE
9245
+ };
9246
+ }
9247
+ return {
9248
+ height: DOCK_ICON_BASE_SIZE,
9249
+ left: slotRect.left + (slotRect.width - DOCK_ICON_BASE_SIZE) / 2,
9250
+ top: slotRect.bottom - DOCK_ICON_BASE_SIZE,
9251
+ width: DOCK_ICON_BASE_SIZE
9252
+ };
9253
+ }
8960
9254
  function renderDockBadge(entry, matchedNodeCount) {
8961
9255
  const badge = entry.badge ?? (matchedNodeCount > 1 ? {
8962
9256
  kind: "count",
@@ -8973,6 +9267,26 @@ function renderDockBadge(entry, matchedNodeCount) {
8973
9267
  }
8974
9268
  return /* @__PURE__ */ jsx10("span", { className: "desktop-dock__status-badge", "data-status": badge.status });
8975
9269
  }
9270
+ function WorkbenchHostDockLabelTooltip({
9271
+ placement,
9272
+ state
9273
+ }) {
9274
+ return /* @__PURE__ */ jsx10(
9275
+ "div",
9276
+ {
9277
+ className: "desktop-dock__label-tooltip",
9278
+ "data-dock-placement": placement,
9279
+ role: "tooltip",
9280
+ style: {
9281
+ "--desktop-dock-label-tooltip-anchor-height": `${state.anchorRect.height}px`,
9282
+ "--desktop-dock-label-tooltip-anchor-left": `${state.anchorRect.left}px`,
9283
+ "--desktop-dock-label-tooltip-anchor-top": `${state.anchorRect.top}px`,
9284
+ "--desktop-dock-label-tooltip-anchor-width": `${state.anchorRect.width}px`
9285
+ },
9286
+ children: state.label
9287
+ }
9288
+ );
9289
+ }
8976
9290
  function WorkbenchHostDockHoverPanel({
8977
9291
  entry,
8978
9292
  host,