@dreamlake/dockit 0.2.26 → 0.2.27

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.
@@ -10,7 +10,7 @@ import { ThemeToggle } from "./ThemeToggle.js";
10
10
  import { VersionBadge } from "./VersionBadge.js";
11
11
  import { useMerge } from "../renderer/Layout.js";
12
12
  import { TabStrip } from "./TabStrip.js";
13
- import { internalTabs, tabForUrl } from "../lib/tabs.js";
13
+ import { TABS, internalTabs, tabForUrl } from "../lib/tabs.js";
14
14
  function HiddenRevealChip() {
15
15
  const [show, setShow] = useHiddenToggle();
16
16
  if (!show) return null;
@@ -38,6 +38,7 @@ const SEARCH_INSET = `max(${SEARCH_GUTTER}px, calc((100vw - ${SEARCH_MAX_W}px) /
38
38
  function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
39
39
  const { urlPathname } = usePageContext();
40
40
  const current = findPage(urlPathname);
41
+ const hasTabs = TABS.length > 0;
41
42
  const activeTab = internalTabs().find((t) => t.id === tabForUrl(urlPathname));
42
43
  const versionChips = activeTab?.versionChips ?? siteConfig.versionChips ?? [];
43
44
  const inputRef = useRef(null);
@@ -154,11 +155,12 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
154
155
  const iconButtonMode = isBelowLg && !searchOpen;
155
156
  const closedWidth = isXlUp ? CLOSED_WIDTH_XL : isLgUp ? CLOSED_WIDTH_LG : CLOSED_WIDTH_MD;
156
157
  const brandRef = useRef(null);
158
+ const wordmarkRef = useRef(null);
157
159
  const brandMaxRight = useRef(0);
158
160
  const tabsRef = useRef(null);
159
161
  const actionsRef = useRef(null);
160
162
  const [tabsFit, setTabsFit] = useState(false);
161
- const [tabsW, setTabsW] = useState(0);
163
+ const [breadcrumbBounds, setBreadcrumbBounds] = useState({ left: 0, width: 0 });
162
164
  const [pinLeft, setPinLeft] = useState(0);
163
165
  const [searchPinLeft, setSearchPinLeft] = useState(null);
164
166
  useLayoutEffect(() => {
@@ -182,7 +184,10 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
182
184
  const packedSearchLeft = actionsLeft - 8 - closedWidth;
183
185
  const fits = (searchLeft) => w > 0 && brandClear && pin + w + 16 <= searchLeft;
184
186
  const fullPin = textRight + closedWidth + 16 <= actionsLeft && fits(pinnedSearchLeft);
185
- setTabsW(w);
187
+ const pinned = isLgUp && (fullPin || fits(packedSearchLeft));
188
+ const breadcrumbLeft = (wordmarkRef.current?.getBoundingClientRect().right ?? brand?.right ?? 0) + 10;
189
+ const breadcrumbRight = pinned ? pin : tabsEl.getBoundingClientRect().left;
190
+ setBreadcrumbBounds({ left: breadcrumbLeft, width: Math.max(0, breadcrumbRight - breadcrumbLeft - 16) });
186
191
  setPinLeft(pin);
187
192
  setSearchPinLeft(fullPin ? pinnedSearchLeft : null);
188
193
  setTabsFit(fullPin || fits(packedSearchLeft));
@@ -198,7 +203,7 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
198
203
  ro.disconnect();
199
204
  window.removeEventListener("resize", measure);
200
205
  };
201
- }, [closedWidth]);
206
+ }, [closedWidth, isLgUp, merged, urlPathname]);
202
207
  const edgePinned = isLgUp && !iconButtonMode && tabsFit;
203
208
  const searchStyle = iconButtonMode ? {
204
209
  // In-flow grid item — sits at the end of column 2 next to TabStrip.
@@ -298,7 +303,7 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
298
303
  {
299
304
  ref: brandRef,
300
305
  href: "/",
301
- className: "flex items-center gap-2.5 pl-[14px] md:pl-[18px] no-underline text-doc-template-ink hover:opacity-80 min-w-[72px] shrink-0",
306
+ className: "flex items-center gap-2.5 pl-[14px] md:pl-[18px] no-underline text-doc-template-ink hover:opacity-80 min-w-[72px] shrink-0 whitespace-nowrap",
302
307
  style: {
303
308
  fontFamily: "var(--font-doc-template-ui)",
304
309
  fontSize: 14,
@@ -308,7 +313,7 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
308
313
  ...palFade(searchOpen)
309
314
  },
310
315
  children: [
311
- /* @__PURE__ */ jsxs("span", { children: [
316
+ /* @__PURE__ */ jsxs("span", { ref: wordmarkRef, children: [
312
317
  siteConfig.brand,
313
318
  /* @__PURE__ */ jsx(
314
319
  "span",
@@ -397,16 +402,14 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
397
402
  "aria-label": "Breadcrumb",
398
403
  className: "hidden md:flex items-center gap-1.5 text-doc-template-muted uppercase pointer-events-none overflow-hidden",
399
404
  style: {
400
- // With the tab strip pinned to the content column's left
401
- // edge, the breadcrumb moves out of the grid too and starts
402
- // just right of the strip — otherwise it would fade in
403
- // underneath the tabs. (gridArea/placeSelf: see the note on
404
- // `searchStyle` about fixed-positioned grid items.)
405
- ...edgePinned ? {
405
+ // On tabbed sites the wordmark supplies the root crumb. Keep
406
+ // the remaining path in the measured gap before the tab strip.
407
+ ...hasTabs ? {
406
408
  position: "fixed",
407
409
  top: 0,
408
410
  height: 40,
409
- left: pinLeft + tabsW + 24,
411
+ left: breadcrumbBounds.left,
412
+ width: breadcrumbBounds.width,
410
413
  gridArea: "auto",
411
414
  placeSelf: "stretch"
412
415
  } : { gridColumn: 2, gridRow: 1, justifySelf: "start", marginLeft: 8 },
@@ -420,15 +423,16 @@ function Topbar({ searchOpen, onOpenSearch, onCloseSearch, query, setQuery }) {
420
423
  transition: `opacity 0.25s ease, transform 0.25s ${SPRING}`
421
424
  },
422
425
  children: [
423
- siteConfig.breadcrumbRoot && /* @__PURE__ */ jsxs(Fragment, { children: [
426
+ hasTabs && /* @__PURE__ */ jsx("span", { "aria-hidden": true, style: { opacity: 0.5 }, children: "/" }),
427
+ !hasTabs && siteConfig.breadcrumbRoot && /* @__PURE__ */ jsxs(Fragment, { children: [
424
428
  /* @__PURE__ */ jsx("span", { children: siteConfig.breadcrumbRoot }),
425
429
  /* @__PURE__ */ jsx("span", { style: { opacity: 0.5 }, children: "/" })
426
430
  ] }),
427
431
  current.section && /* @__PURE__ */ jsxs(Fragment, { children: [
428
- /* @__PURE__ */ jsx("span", { children: current.section }),
432
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: current.section }),
429
433
  /* @__PURE__ */ jsx("span", { style: { opacity: 0.5 }, children: "/" })
430
434
  ] }),
431
- /* @__PURE__ */ jsx("span", { className: "text-doc-template-ink", children: current.title })
435
+ /* @__PURE__ */ jsx("span", { className: "text-doc-template-ink truncate", "aria-current": "page", title: current.title, children: current.title })
432
436
  ]
433
437
  }
434
438
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dreamlake/dockit",
3
- "version": "0.2.26",
3
+ "version": "0.2.27",
4
4
  "description": "The DreamLake documentation shell — Vike + React + Tailwind v4 + MDX docs framework with sidebar, TOC, search, and theming",
5
5
  "license": "MIT",
6
6
  "type": "module",