@deepseek-ai/dsh-client-ui-sidebar 0.1.6-alpha.1 → 0.1.7-alpha.1

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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-sidebar/README.md
5
- README.md: 1b520213809ca98a6819483a4ee5ea4f451841d2
6
- README.zh.md: ee694d0067db50eff52051d8d9f8fd3baac0fc27
5
+ README.md: 94bb3a70ca8c06b5838f41436bb0f2ba2751501e
6
+ README.zh.md: 86f54882ba1c96b9b50898993931757f7afef4e5
package/README.md CHANGED
@@ -37,8 +37,16 @@ Plugins add an icon component to the root-scoped `sidebar.panellist` list with a
37
37
 
38
38
  ### Collapse behavior
39
39
 
40
+ The top expand button hosts the optional, non-interactive `sidebar.toggle.badge` slot while collapsed. Its occupant supplies status and tooltip content without adding another action or changing the button's navigation behavior.
41
+
40
42
  During a live collapse, the expanded content fades out at its current width, the upper controls share one fade and leftward translation into the 56px rail, and the layout's column slide ends the motion. A page that starts collapsed renders the rail statically, and reduced-motion mode disables both transitions. The bottom-pinned `sidebar.settings` control shares the fade timing but has no horizontal translation.
41
43
 
44
+ On Windows Electron, `html[data-windows-titlebar]` fixes the sidebar toggle in the caption's top-left corner in both states, aligned with New Session's left edge only when expanded. The expanded brand sits below the caption and above New Session, with 8px of extra space above that button. Collapsing hides the brand and sidebar content and places New Session between the sidebar toggle and the Desktop-owned menus. The sidebar sets the root `--dsh-windows-menu-start` to 84px when collapsed; the Desktop preload uses it to position its menu after New Session and defaults to 48px when expanded. Caption icon buttons use centered 16px glyphs in 28px circular controls and exclude themselves from the window drag region. The sidebar toggle and New Session bubbles open below the caption, where the Desktop-owned menu text cannot cover them; an occupying `sidebar.toggle.badge` chooses its own bubble side.
45
+
46
+ ### macOS desktop
47
+
48
+ Under `html[data-platform='darwin']` (set only by the desktop preload) the expanded column opens with a 52px top strip that clears the hiddenInset traffic lights and carries the collapse toggle; the frame's own drag band (ui-layout `.leadingBand`) covers that strip, and the logo row below extends the drag surface, so the brand wordmark is not a New Session shortcut there — the dedicated New Session button keeps the action — and collapsing hides the column entirely instead of leaving the rail. The package registers `HeaderLeadingControls` into the frame's `shell.leading` window-chrome seat (ui-layout), which mounts it — the open-sidebar and New Session controls beside the traffic lights — only while the column is hidden, over every main panel. Rationale and the window-integration contract: the [macOS hidden-titlebar Agent Note](../../../.agents/notes/implemented/feature/2026-09-13-macos-hidden-titlebar-vibrancy.md).
49
+
42
50
  ### Scrollbars
43
51
 
44
52
  Scrollbars in the column are a pointer affordance: the shell rebinds the scrollbar indirection to `transparent` whenever the pointer is outside the column and keeps the thumb drawn for 2s after the pointer leaves, so a list nobody is pointing at carries no bar. The reservation that keeps rows from moving belongs to the scrolling region (ui-workspace), so revealing a thumb never reflows.
package/README.zh.md CHANGED
@@ -37,8 +37,16 @@ dsh Web 客户端的侧边栏让用户识别当前构建、启动新会话、将
37
37
 
38
38
  ### 折叠行为
39
39
 
40
+ 侧栏收起时,顶部展开按钮承载可选、不可交互的 `sidebar.toggle.badge` slot。占用方提供状态和提示内容,不增加操作,也不改变按钮的导航行为。
41
+
40
42
  实时收起时,展开内容在当前宽度淡出,上方控件共用同一段透明度渐变,并向左平移进入 56px 轨道,由布局的栏滑动结束整段动画。页面初始即为收起状态时会静态渲染轨道;减少动态效果模式会禁用两段过渡。固定在底部的 `sidebar.settings` 控件共用相同的透明度渐变时序,但不发生横向位移。
41
43
 
44
+ 在 Windows Electron 中,`html[data-windows-titlebar]` 将两种状态下的侧栏开关固定在顶栏左上角,仅在展开态与新建会话按钮左边缘对齐。展开态品牌位于顶栏下方、新建会话按钮上方,按钮上方额外留出 8px。收起后,品牌和侧栏内容隐藏,新建会话按钮排在侧栏开关与 Desktop 菜单之间。侧栏在收起态将根元素的 `--dsh-windows-menu-start` 设为 84px;Desktop preload 使用它将菜单放在新建会话之后,展开态默认为 48px。顶栏图标按钮采用 28px 圆形控件中的居中 16px 图标,并从窗口拖拽区域中排除。侧栏开关与新建会话的悬停提示在顶栏下方展开,Desktop 菜单文字不会盖住它们;占用 `sidebar.toggle.badge` 的控件自行决定气泡展开方向。
45
+
46
+ ### macOS 桌面
47
+
48
+ 在 `html[data-platform='darwin']`(仅由桌面 preload 设置)下,展开的侧边栏列顶部有一条 52px 的顶部条:避开 hiddenInset 红绿灯并承载收起按钮;框架自身的拖拽带(ui-layout `.leadingBand`)覆盖这条顶部条,其下的 logo 行延伸这块拖拽面,因此品牌 wordmark 在 macOS 上不再是 New Session 快捷入口——专用的 New Session 按钮保留该操作;收起时整列隐藏而非保留轨道。本包向框架的 `shell.leading` 窗口 chrome 座(ui-layout)注册 `HeaderLeadingControls`——打开侧边栏与 New Session 两个控件,由框架仅在列隐藏时挂载于红绿灯旁,覆盖所有主面板。设计依据与窗口集成约定见 [macOS 隐藏标题栏 Agent Note](../../../.agents/notes/implemented/feature/2026-09-13-macos-hidden-titlebar-vibrancy.zh.md)。
49
+
42
50
  ### 滚动条
43
51
 
44
52
  栏内的滚动条是一种指针可供性:只要指针不在栏内,外壳就把滚动条间接层重新绑定为 `transparent`;指针离开后滑块再保留 2 秒,因此没人指向的列表不会带着滚动条。避免行位移的空间预留属于滚动区域本身(ui-workspace),所以显示滑块不会引起重排。
package/lib/client.js CHANGED
@@ -7,8 +7,65 @@ window.__ModuleLoader__.load({
7
7
  let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
8
8
  let _deepseek_ai_dsh_client_ui_slots = require("@deepseek-ai/dsh-client-ui-slots");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
- let react = require("react");
11
10
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
11
+ let react = require("react");
12
+ //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-sidebar/src/client/HeaderLeadingControls.module.css.mjs
13
+ const css$1 = ".IW6AQa_controls{align-items:center;gap:8px;display:flex}.IW6AQa_iconButton{corner-shape:round;width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.IW6AQa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}";
14
+ const tagId$1 = "@deepseek-ai/dsh-client-ui-sidebar/HeaderLeadingControls.module.css";
15
+ if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
16
+ const tag = document.createElement("style");
17
+ tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-sidebar";
18
+ tag.dataset.pluginCss = tagId$1;
19
+ tag.textContent = css$1;
20
+ document.head.appendChild(tag);
21
+ }
22
+ var HeaderLeadingControls_module_css_default = {
23
+ "controls": "IW6AQa_controls",
24
+ "iconButton": "IW6AQa_iconButton"
25
+ };
26
+ //#endregion
27
+ //#region lib/types/client/HeaderLeadingControls.js
28
+ /** Window-chrome controls for the fully hidden sidebar (frame shell.leading seat). */
29
+ /**
30
+ * Sidebar-open and New Session controls in the frame's window-chrome seat.
31
+ * On macOS desktop a collapsed sidebar hides entirely (no rail), taking both
32
+ * controls off screen; this occupant puts them back beside the traffic
33
+ * lights. The frame mounts the seat only in that state and owns its
34
+ * placement, so the occupant renders unconditionally.
35
+ * @param props - Injected sidebar actions plus the sidebar locale seat.
36
+ * @returns the two window-chrome controls.
37
+ */
38
+ function HeaderLeadingControls({ toggleSidebar, startSession, t }) {
39
+ return (0, react_jsx_runtime.jsxs)("div", {
40
+ className: HeaderLeadingControls_module_css_default.controls,
41
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
42
+ label: t("toggle.open"),
43
+ delayMs: 500,
44
+ children: (0, react_jsx_runtime.jsx)("button", {
45
+ type: "button",
46
+ className: HeaderLeadingControls_module_css_default.iconButton,
47
+ "aria-label": t("toggle.open"),
48
+ onClick: () => {
49
+ toggleSidebar();
50
+ },
51
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutlineRegular, { size: 16 })
52
+ })
53
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
54
+ label: t("session.new.label"),
55
+ delayMs: 500,
56
+ children: (0, react_jsx_runtime.jsx)("button", {
57
+ type: "button",
58
+ className: HeaderLeadingControls_module_css_default.iconButton,
59
+ "aria-label": t("session.new.label"),
60
+ onClick: () => {
61
+ startSession();
62
+ },
63
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutlineRegular, { size: 16 })
64
+ })
65
+ })]
66
+ });
67
+ }
68
+ //#endregion
12
69
  //#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
13
70
  function r(e) {
14
71
  var t, f, n = "";
@@ -25,7 +82,7 @@ window.__ModuleLoader__.load({
25
82
  }
26
83
  //#endregion
27
84
  //#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-sidebar/src/client/SidebarRoot.module.css.mjs
28
- const css = ".hHd-Xa_root{--dsh-sidebar-inline-padding:12px;height:100%;padding:6px var(--dsh-sidebar-inline-padding);box-sizing:border-box;background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex-direction:column;font-size:14px;display:flex}.hHd-Xa_root.hHd-Xa_collapsed{padding:18px 10px 6px}.hHd-Xa_root.hHd-Xa_quietBars{--dsh-scrollbar-thumb:transparent;--dsh-scrollbar-thumb-hover:transparent}.hHd-Xa_fading>*{opacity:0;transition:opacity .15s var(--ds-ease-in-out)}.hHd-Xa_wide{animation:hHd-Xa_wide-in .2s var(--ds-ease-in-out)}@keyframes hHd-Xa_wide-in{0%{opacity:0}}.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_panelList,.hHd-Xa_railIn .hHd-Xa_regionArea{animation:hHd-Xa_rail-in .15s var(--ds-ease-in-out) backwards}.hHd-Xa_railIn .hHd-Xa_footArea{animation:hHd-Xa_rail-fade-in .15s var(--ds-ease-in-out) backwards}@keyframes hHd-Xa_rail-in{0%{opacity:0;transform:translate(49px)}}@keyframes hHd-Xa_rail-fade-in{0%{opacity:0}}.hHd-Xa_logoRow{box-sizing:border-box;flex:none;justify-content:flex-end;align-items:center;gap:8px;height:60px;margin-bottom:8px;padding:8px 0 8px 4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_logoRow{justify-content:flex-start;height:36px;margin-bottom:12px;padding:0}.hHd-Xa_brand{min-width:0;color:inherit;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;padding:0;display:inline-flex;overflow:hidden}.hHd-Xa_brandIdentity{align-items:center;gap:8px;min-width:0;height:24px;display:inline-flex}.hHd-Xa_brandMark{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_brandName{letter-spacing:.04em;align-items:center;gap:6px;min-width:0;height:24px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.hHd-Xa_fallbackBrandName{letter-spacing:0;white-space:nowrap;font-size:17px}.hHd-Xa_localBuildBrand{white-space:nowrap;flex-direction:column;flex:none;justify-content:center;align-items:flex-start;gap:1px;height:24px;display:inline-flex}.hHd-Xa_localBuildTitle{letter-spacing:0;font-size:12px;line-height:13px}.hHd-Xa_iconButton{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.hHd-Xa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_collapsed .hHd-Xa_iconButton{width:36px;height:36px}.hHd-Xa_collapsed .hHd-Xa_toggle .hHd-Xa_panelIcon{display:none}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_panelIcon{display:inline}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_railMark{display:none}.hHd-Xa_railMark{justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_collapsed .hHd-Xa_iconButton{color:var(--dsw-alias-label-primary)}.hHd-Xa_buildVersion{height:10px;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code);white-space:nowrap;border-radius:2px;flex:none;align-items:center;padding:0 3px;font-size:6px;font-weight:500;line-height:10px;display:inline-flex}.hHd-Xa_newSession{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);background:var(--dsw-alias-button-elevated-fill);height:38px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:12px;flex:none;justify-content:center;align-items:center;gap:6px;margin:0 2px 8px;padding:8px 16px;font-size:14px;font-weight:500;line-height:22px;display:flex;overflow:hidden}.hHd-Xa_newSession:hover{background:var(--dsw-alias-button-floating-hover)}.hHd-Xa_collapsed .hHd-Xa_newSession{background:0 0;border-color:#0000;align-self:flex-start;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.hHd-Xa_collapsed .hHd-Xa_newSession:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_newSessionLabel{white-space:nowrap;max-width:200px;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_newSessionLabel{max-width:0}.hHd-Xa_panelList{flex-direction:column;flex:none;gap:4px;margin-bottom:8px;display:flex}.hHd-Xa_panelRow{box-sizing:border-box;width:100%;min-height:36px;color:var(--dsw-alias-label-secondary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:8px;align-items:center;gap:8px;padding:7px 8px;line-height:22px;display:flex}.hHd-Xa_panelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_panelRow.hHd-Xa_panelActive{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary);font-weight:500}.hHd-Xa_panelRow:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.hHd-Xa_panelGlyph{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_panelTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_panelList{gap:12px;margin-bottom:12px}.hHd-Xa_collapsed .hHd-Xa_panelRow{width:36px;height:36px;color:var(--dsw-alias-label-primary);justify-content:center;padding:0}.hHd-Xa_regionArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-sidebar-inline-padding));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_regionArea{margin-left:0;margin-right:0;padding-left:0}.hHd-Xa_footArea{flex-direction:column;flex:none;display:flex}.hHd-Xa_settingsArea,.hHd-Xa_footerActions{flex:none;width:100%;min-width:0}.hHd-Xa_footerActions{display:flex}.hHd-Xa_collapsed .hHd-Xa_footArea{align-items:center}.hHd-Xa_collapsed .hHd-Xa_settingsArea,.hHd-Xa_collapsed .hHd-Xa_footerActions{justify-content:center;width:auto;display:flex}@media (prefers-reduced-motion:reduce){.hHd-Xa_wide,.hHd-Xa_fading>*,.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_panelList,.hHd-Xa_railIn .hHd-Xa_footArea,.hHd-Xa_railIn .hHd-Xa_regionArea{transition:none;animation:none}}";
85
+ const css = ".hHd-Xa_root{--dsh-sidebar-inline-padding:12px;height:100%;padding:6px var(--dsh-sidebar-inline-padding);box-sizing:border-box;background:var(--dsw-specific-sidebar-fill);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);flex-direction:column;font-size:14px;display:flex}[data-platform=darwin] .hHd-Xa_root{background:0 0}.hHd-Xa_root.hHd-Xa_collapsed{padding:18px 10px 6px}[data-windows-titlebar] .hHd-Xa_root .hHd-Xa_logoRow{height:40px;margin:0;padding:0}[data-windows-titlebar] .hHd-Xa_toggle{top:calc((var(--dsh-windows-titlebar-height) - 28px) / 2);z-index:30;-webkit-app-region:no-drag;position:fixed;left:12px}[data-windows-titlebar] .hHd-Xa_root.hHd-Xa_collapsed .hHd-Xa_logoRow{height:0}[data-windows-titlebar] .hHd-Xa_root:not(.hHd-Xa_collapsed) .hHd-Xa_brand{padding-left:4px}[data-windows-titlebar] .hHd-Xa_brandIdentity{transform:translateY(1px)}[data-windows-titlebar] .hHd-Xa_brandMark{transform:translate(1px)}[data-windows-titlebar] .hHd-Xa_brandName{font-weight:400}[data-windows-titlebar] .hHd-Xa_root.hHd-Xa_collapsed{padding:0}[data-windows-titlebar] .hHd-Xa_root:not(.hHd-Xa_collapsed) .hHd-Xa_newSession{margin-top:8px;margin-left:0}[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_panelList,[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_regionArea,[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_footArea{display:none}html[data-windows-titlebar]:has([data-sidebar-collapsed=true]){--dsh-windows-menu-start:84px}[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_newSession{top:calc((var(--dsh-windows-titlebar-height) - 28px) / 2);z-index:30;-webkit-app-region:no-drag;border:none;margin:0;padding:0;position:fixed;left:48px}[data-windows-titlebar] .hHd-Xa_railIn .hHd-Xa_iconButton,[data-windows-titlebar] .hHd-Xa_railIn .hHd-Xa_newSession{animation:none}[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_toggle,[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_newSession{corner-shape:round;width:28px;height:28px;color:var(--dsw-alias-label-secondary);border-radius:50%}[data-windows-titlebar] .hHd-Xa_collapsed .hHd-Xa_toggle .hHd-Xa_panelIcon{display:inline}.hHd-Xa_root.hHd-Xa_quietBars{--dsh-scrollbar-thumb:transparent;--dsh-scrollbar-thumb-hover:transparent}.hHd-Xa_fading>*{opacity:0;transition:opacity .15s var(--ds-ease-in-out)}.hHd-Xa_wide{animation:hHd-Xa_wide-in .2s var(--ds-ease-in-out)}@keyframes hHd-Xa_wide-in{0%{opacity:0}}.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_panelList,.hHd-Xa_railIn .hHd-Xa_regionArea{animation:hHd-Xa_rail-in .15s var(--ds-ease-in-out) backwards}.hHd-Xa_railIn .hHd-Xa_footArea{animation:hHd-Xa_rail-fade-in .15s var(--ds-ease-in-out) backwards}@keyframes hHd-Xa_rail-in{0%{opacity:0;transform:translate(49px)}}@keyframes hHd-Xa_rail-fade-in{0%{opacity:0}}.hHd-Xa_topStrip{box-sizing:border-box;height:52px;margin:-6px calc(-1 * var(--dsh-sidebar-inline-padding)) 0;flex:none;justify-content:flex-end;align-items:center;padding:0 12px 2px;display:flex}[data-fullscreen] .hHd-Xa_topStrip{justify-content:flex-start}.hHd-Xa_topStrip+.hHd-Xa_logoRow{margin-top:-12px}.hHd-Xa_logoRow{box-sizing:border-box;flex:none;justify-content:flex-end;align-items:center;gap:8px;height:60px;margin-bottom:4px;padding:8px 0 8px 4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_logoRow{justify-content:flex-start;height:36px;margin-bottom:12px;padding:0}[data-platform=darwin] .hHd-Xa_logoRow{-webkit-app-region:drag}.hHd-Xa_brand{min-width:0;color:inherit;cursor:pointer;background:0 0;border:none;flex:1;align-items:center;padding:0;display:inline-flex;overflow:hidden}[data-platform=darwin] .hHd-Xa_brand{cursor:default}.hHd-Xa_brandIdentity{align-items:center;gap:8px;min-width:0;height:24px;display:inline-flex}.hHd-Xa_brandMark{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_brandName{letter-spacing:.04em;align-items:center;gap:6px;min-width:0;height:24px;font-size:18px;font-weight:600;line-height:24px;display:inline-flex}.hHd-Xa_fallbackBrandName{letter-spacing:0;white-space:nowrap;font-size:17px}.hHd-Xa_localBuildBrand{white-space:nowrap;flex-direction:column;flex:none;justify-content:center;align-items:flex-start;gap:1px;height:24px;display:inline-flex}.hHd-Xa_localBuildTitle{letter-spacing:0;font-size:12px;line-height:13px}.hHd-Xa_iconButton{corner-shape:round;cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-secondary);background:0 0;border:none;border-radius:50%;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex;position:relative}.hHd-Xa_iconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_collapsed .hHd-Xa_iconButton{border-radius:12px;width:36px;height:36px}.hHd-Xa_collapsed .hHd-Xa_toggle .hHd-Xa_panelIcon{display:none}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_panelIcon{display:inline}.hHd-Xa_collapsed .hHd-Xa_toggle:hover .hHd-Xa_railMark{display:none}.hHd-Xa_railMark{justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_collapsed .hHd-Xa_iconButton{color:var(--dsw-alias-label-primary)}.hHd-Xa_buildVersion{height:10px;color:var(--dsw-alias-label-primary-inverted);background:var(--dsw-alias-label-primary);font-family:var(--ds-font-family-code);white-space:nowrap;border-radius:2px;flex:none;align-items:center;padding:0 3px;font-size:6px;font-weight:500;line-height:10px;display:inline-flex}.hHd-Xa_newSession{box-sizing:border-box;border:.5px solid var(--dsw-alias-border-l3);background:var(--dsw-alias-button-elevated-fill);height:38px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:12px;flex:none;justify-content:center;align-items:center;gap:6px;margin:0 2px 12px;padding:8px 16px;font-size:14px;font-weight:500;line-height:22px;display:flex;overflow:hidden}.hHd-Xa_newSession:hover{background:var(--dsw-alias-button-floating-hover)}[data-platform=darwin] .hHd-Xa_newSession{background:#ffffff8c}[data-platform=darwin] .hHd-Xa_newSession:hover{background:#ffffff4d}[data-platform=darwin] [data-ds-dark-theme] .hHd-Xa_newSession{background:#ffffff26}[data-platform=darwin] [data-ds-dark-theme] .hHd-Xa_newSession:hover{background:#fff3}.hHd-Xa_collapsed .hHd-Xa_newSession{background:0 0;border-color:#0000;align-self:flex-start;gap:0;width:36px;height:36px;margin:0 0 12px;padding:0}.hHd-Xa_collapsed .hHd-Xa_newSession:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_newSessionLabel{white-space:nowrap;max-width:200px;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_newSessionLabel{max-width:0}.hHd-Xa_panelList{flex-direction:column;flex:none;gap:4px;margin-bottom:8px;display:flex}.hHd-Xa_panelRow{box-sizing:border-box;min-height:36px;color:var(--dsw-alias-label-primary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;margin:0 2px;padding:7px 8px;line-height:22px;display:flex}.hHd-Xa_panelRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.hHd-Xa_panelRow.hHd-Xa_panelActive{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.hHd-Xa_panelRow:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:-2px}.hHd-Xa_panelGlyph{flex:none;justify-content:center;align-items:center;display:inline-flex}.hHd-Xa_panelTitle{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_panelList{gap:12px;margin-bottom:12px}.hHd-Xa_collapsed .hHd-Xa_panelRow{width:36px;height:36px;color:var(--dsw-alias-label-primary);justify-content:center;margin:0;padding:0}.hHd-Xa_regionArea{min-height:0;margin-left:-4px;margin-right:calc(-1 * var(--dsh-sidebar-inline-padding));flex-direction:column;flex:1;padding-left:4px;display:flex;overflow:hidden}.hHd-Xa_collapsed .hHd-Xa_regionArea{margin-left:0;margin-right:0;padding-left:0}.hHd-Xa_footArea{flex-direction:column;flex:none;display:flex}.hHd-Xa_settingsArea,.hHd-Xa_footerActions{flex:none;width:100%;min-width:0}.hHd-Xa_footerActions{display:flex}.hHd-Xa_collapsed .hHd-Xa_footArea{align-items:center}.hHd-Xa_collapsed .hHd-Xa_settingsArea,.hHd-Xa_collapsed .hHd-Xa_footerActions{justify-content:center;width:auto;display:flex}@media (prefers-reduced-motion:reduce){.hHd-Xa_wide,.hHd-Xa_fading>*,.hHd-Xa_railIn .hHd-Xa_iconButton,.hHd-Xa_railIn .hHd-Xa_newSession,.hHd-Xa_railIn .hHd-Xa_panelList,.hHd-Xa_railIn .hHd-Xa_footArea,.hHd-Xa_railIn .hHd-Xa_regionArea{transition:none;animation:none}}";
29
86
  const tagId = "@deepseek-ai/dsh-client-ui-sidebar/SidebarRoot.module.css";
30
87
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
31
88
  const tag = document.createElement("style");
@@ -66,6 +123,7 @@ window.__ModuleLoader__.load({
66
123
  "root": "hHd-Xa_root",
67
124
  "settingsArea": "hHd-Xa_settingsArea",
68
125
  "toggle": "hHd-Xa_toggle",
126
+ "topStrip": "hHd-Xa_topStrip",
69
127
  "wide": "hHd-Xa_wide",
70
128
  "wide-in": "hHd-Xa_wide-in"
71
129
  };
@@ -100,7 +158,7 @@ window.__ModuleLoader__.load({
100
158
  const SCROLLBAR_LINGER_MS = 2e3;
101
159
  /** Format complete-build metadata for the local brand badge. */
102
160
  function localBuildVersion() {
103
- return `0.1.6-alpha.1-e208262` + ({}.DSH_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "");
161
+ return `0.1.7-alpha.1-46bb4af` + ({}.DSH_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "");
104
162
  }
105
163
  /** Each panel row subscribes only to its own selection state. */
106
164
  function PanelRow({ id, label, wide, usePanelInfo, selectPanel, renderSlot }) {
@@ -151,7 +209,9 @@ window.__ModuleLoader__.load({
151
209
  window.clearTimeout(timer);
152
210
  };
153
211
  }, [collapsed]);
154
- const wide = !collapsed || !settled;
212
+ const windowsTitlebar = document.documentElement.hasAttribute("data-windows-titlebar");
213
+ const wide = windowsTitlebar ? !collapsed : !collapsed || !settled;
214
+ const captionTooltipSide = windowsTitlebar ? "bottom" : "right";
155
215
  const lastWideWidth = (0, react.useRef)(width);
156
216
  if (!collapsed) lastWideWidth.current = width;
157
217
  const everWide = (0, react.useRef)(!collapsed);
@@ -186,6 +246,32 @@ window.__ModuleLoader__.load({
186
246
  };
187
247
  }, [pointerInside]);
188
248
  const buildVersion = localBuildVersion();
249
+ const darwinDesktop = (0, _deepseek_ai_dsh_client_ui_primitives.isDarwinDesktop)();
250
+ const toggle = (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
251
+ label: collapsed ? t("toggle.open") : t("toggle.collapse"),
252
+ delayMs: 500,
253
+ side: captionTooltipSide,
254
+ children: (0, react_jsx_runtime.jsxs)("button", {
255
+ type: "button",
256
+ className: clsx(SidebarRoot_module_css_default.iconButton, SidebarRoot_module_css_default.toggle),
257
+ "aria-label": collapsed ? t("toggle.open") : t("toggle.collapse"),
258
+ onClick: () => {
259
+ toggleSidebar();
260
+ },
261
+ children: [
262
+ !wide && !windowsTitlebar && (0, react_jsx_runtime.jsx)("span", {
263
+ className: SidebarRoot_module_css_default.railMark,
264
+ "aria-hidden": "true",
265
+ children: renderSlot("sidebar.brand.mark", { size: 24 }, { fallback: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, { size: 24 }) })
266
+ }),
267
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutlineRegular, {
268
+ className: SidebarRoot_module_css_default.panelIcon,
269
+ size: wide || windowsTitlebar ? 16 : 18
270
+ }),
271
+ !wide && renderSlot("sidebar.toggle.badge", {})
272
+ ]
273
+ })
274
+ });
189
275
  return (0, react_jsx_runtime.jsxs)("div", {
190
276
  ref: column,
191
277
  className: clsx(SidebarRoot_module_css_default.root, !wide && SidebarRoot_module_css_default.collapsed, !wide && everWide.current && SidebarRoot_module_css_default.railIn, collapsed && wide && SidebarRoot_module_css_default.fading, !pointerInside && SidebarRoot_module_css_default.quietBars),
@@ -198,16 +284,14 @@ window.__ModuleLoader__.load({
198
284
  armLinger();
199
285
  },
200
286
  children: [
287
+ darwinDesktop && (0, react_jsx_runtime.jsx)("div", {
288
+ className: SidebarRoot_module_css_default.topStrip,
289
+ children: toggle
290
+ }),
201
291
  (0, react_jsx_runtime.jsxs)("div", {
202
292
  className: SidebarRoot_module_css_default.logoRow,
203
- children: [wide && (0, react_jsx_runtime.jsx)("button", {
204
- type: "button",
205
- className: clsx(SidebarRoot_module_css_default.brand, SidebarRoot_module_css_default.wide),
206
- "aria-label": t("session.new.label"),
207
- onClick: () => {
208
- startSession();
209
- },
210
- children: (0, react_jsx_runtime.jsxs)("span", {
293
+ children: [wide && (() => {
294
+ const identity = (0, react_jsx_runtime.jsxs)("span", {
211
295
  className: SidebarRoot_module_css_default.brandIdentity,
212
296
  "aria-hidden": "true",
213
297
  children: [(0, react_jsx_runtime.jsx)("span", {
@@ -229,32 +313,26 @@ window.__ModuleLoader__.load({
229
313
  })]
230
314
  }) })
231
315
  })]
232
- })
233
- }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
234
- label: collapsed ? t("toggle.open") : t("toggle.collapse"),
235
- delayMs: 500,
236
- children: (0, react_jsx_runtime.jsxs)("button", {
316
+ });
317
+ return darwinDesktop ? (0, react_jsx_runtime.jsx)("span", {
318
+ className: clsx(SidebarRoot_module_css_default.brand, SidebarRoot_module_css_default.wide),
319
+ children: identity
320
+ }) : (0, react_jsx_runtime.jsx)("button", {
237
321
  type: "button",
238
- className: clsx(SidebarRoot_module_css_default.iconButton, SidebarRoot_module_css_default.toggle),
239
- "aria-label": collapsed ? t("toggle.open") : t("toggle.collapse"),
322
+ className: clsx(SidebarRoot_module_css_default.brand, SidebarRoot_module_css_default.wide),
323
+ "aria-label": t("session.new.label"),
240
324
  onClick: () => {
241
- toggleSidebar();
325
+ startSession();
242
326
  },
243
- children: [!wide && (0, react_jsx_runtime.jsx)("span", {
244
- className: SidebarRoot_module_css_default.railMark,
245
- "aria-hidden": "true",
246
- children: renderSlot("sidebar.brand.mark", { size: 24 }, { fallback: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.FishLogo, { size: 24 }) })
247
- }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, {
248
- className: SidebarRoot_module_css_default.panelIcon,
249
- size: wide ? 16 : 18
250
- })]
251
- })
252
- })]
327
+ children: identity
328
+ });
329
+ })(), !darwinDesktop && toggle]
253
330
  }),
254
331
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
255
332
  label: t("session.new.label"),
256
333
  delayMs: 500,
257
334
  disabled: wide,
335
+ side: captionTooltipSide,
258
336
  children: (0, react_jsx_runtime.jsxs)("button", {
259
337
  type: "button",
260
338
  className: SidebarRoot_module_css_default.newSession,
@@ -262,7 +340,7 @@ window.__ModuleLoader__.load({
262
340
  onClick: () => {
263
341
  startSession();
264
342
  },
265
- children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: wide ? 14 : 18 }), wide && (0, react_jsx_runtime.jsx)("span", {
343
+ children: [wide ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutlineMedium, { size: 14 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutlineRegular, { size: windowsTitlebar ? 16 : 18 }), wide && (0, react_jsx_runtime.jsx)("span", {
266
344
  className: clsx(SidebarRoot_module_css_default.newSessionLabel, SidebarRoot_module_css_default.wide),
267
345
  children: t("session.new")
268
346
  })]
@@ -384,6 +462,10 @@ window.__ModuleLoader__.load({
384
462
  kind: "single",
385
463
  scope: "root"
386
464
  },
465
+ "sidebar.toggle.badge": {
466
+ kind: "single",
467
+ scope: "root"
468
+ },
387
469
  "sidebar.panellist": {
388
470
  kind: "list",
389
471
  scope: "root"
@@ -403,6 +485,11 @@ window.__ModuleLoader__.load({
403
485
  },
404
486
  inject: injectProps
405
487
  }, SidebarRoot));
488
+ ctx.slots.inject("shell.leading", () => ctx.slots.register({
489
+ name: "shell.leading",
490
+ locale: NS,
491
+ inject: injectProps
492
+ }, HeaderLeadingControls));
406
493
  syncPanels();
407
494
  }
408
495
  //#endregion
@@ -0,0 +1,15 @@
1
+ import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
2
+ import type { SidebarRootInjected } from './contract/slots.ts';
3
+ /** Full props of the shell.leading occupant. */
4
+ export type HeaderLeadingControlsProps = PropsRuntime<'shell.leading'> & InjectFace<SidebarRootInjected> & PropsLocale<'sidebar'>;
5
+ /**
6
+ * Sidebar-open and New Session controls in the frame's window-chrome seat.
7
+ * On macOS desktop a collapsed sidebar hides entirely (no rail), taking both
8
+ * controls off screen; this occupant puts them back beside the traffic
9
+ * lights. The frame mounts the seat only in that state and owns its
10
+ * placement, so the occupant renders unconditionally.
11
+ * @param props - Injected sidebar actions plus the sidebar locale seat.
12
+ * @returns the two window-chrome controls.
13
+ */
14
+ export declare function HeaderLeadingControls({ toggleSidebar, startSession, t }: HeaderLeadingControlsProps): import("react").JSX.Element;
15
+ //# sourceMappingURL=HeaderLeadingControls.d.ts.map
@@ -13,6 +13,12 @@ import type { WorkspaceId } from '@deepseek-ai/dsh-api-workspace-controller/clie
13
13
  import type { MainPanelId } from '@deepseek-ai/dsh-client-ui-layout/client';
14
14
  declare module '@deepseek-ai/dsh-client-ui-slots' {
15
15
  interface SlotMap {
16
+ /** Non-interactive notification inside the collapsed sidebar expand button. */
17
+ 'sidebar.toggle.badge': {
18
+ kind: 'single';
19
+ scope: 'root';
20
+ owner: Record<never, never>;
21
+ };
16
22
  /**
17
23
  * Brand mark rendered in the expanded brand row and collapsed rail.
18
24
  * Declared by this package's `sidebar` entry; deployments may replace
@@ -147,5 +153,5 @@ export type SidebarRootInjected = {
147
153
  * render shares, this package's injected callbacks, and the standard locale
148
154
  * seat. Panel metadata arrives through an injected observable.
149
155
  */
150
- export type SidebarRootComponentProps = PropsRuntime<'sidebar'> & PropsRenderSlots<'sidebar.brand.mark' | 'sidebar.brand.name' | 'sidebar.panellist' | 'sidebar.workspaces' | 'sidebar.settings' | 'sidebar.footer.action'> & InjectFace<SidebarRootInjected> & PropsLocale<'sidebar'>;
156
+ export type SidebarRootComponentProps = PropsRuntime<'sidebar'> & PropsRenderSlots<'sidebar.brand.mark' | 'sidebar.brand.name' | 'sidebar.toggle.badge' | 'sidebar.panellist' | 'sidebar.workspaces' | 'sidebar.settings' | 'sidebar.footer.action'> & InjectFace<SidebarRootInjected> & PropsLocale<'sidebar'>;
151
157
  //# sourceMappingURL=slots.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-sidebar",
3
3
  "description": "Sidebar plugin: session multi-level tree, search, grouping, state dots",
4
- "version": "0.1.6-alpha.1",
4
+ "version": "0.1.7-alpha.1",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -40,23 +40,23 @@
40
40
  },
41
41
  "license": "MIT",
42
42
  "peerDependencies": {
43
- "@deepseek-ai/cordis": "^4.0.2"
43
+ "@deepseek-ai/cordis": "^4.0.3"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/react": "~18.3.1",
47
47
  "react": "^18.2.0",
48
48
  "clsx": "^2.0.0",
49
- "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.1",
50
- "@deepseek-ai/dsh-api-workspace-controller": "^0.1.6-alpha.1",
51
- "@deepseek-ai/dsh-client-store": "^0.1.6-alpha.1",
52
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.6-alpha.1",
53
- "@deepseek-ai/dsh-client-ui-layout": "^0.1.6-alpha.1",
54
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.1",
55
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.1",
56
- "@deepseek-ai/dsh-client-ui-workspace": "^0.1.6-alpha.1",
57
- "@deepseek-ai/cordis": "^4.0.2",
58
- "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.1",
59
- "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.1"
49
+ "@deepseek-ai/dsh-client-locale": "^0.1.7-alpha.1",
50
+ "@deepseek-ai/dsh-client-store": "^0.1.7-alpha.1",
51
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.1.7-alpha.1",
52
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.7-alpha.1",
53
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-alpha.1",
54
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-alpha.1",
55
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.7-alpha.1",
56
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.7-alpha.1",
57
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.7-alpha.1",
58
+ "@deepseek-ai/cordis": "^4.0.3",
59
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.7-alpha.1"
60
60
  },
61
61
  "files": [
62
62
  "lib/index.js",