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

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: a0b9ffe8ca601fade50ff86fc1921d6b41b84748
6
+ README.zh.md: 44b08c8ef76ec266c813c8199db8291f47db3d53
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.
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, carries the collapse toggle, and acts as the window drag region; collapsing hides the column entirely instead of leaving the rail. The package registers `HeaderLeadingControls` into the conversation header's `conversation.session.header.leading` seat — the open-sidebar and New Session controls shown, purely via CSS against the AppFrame-published `data-sidebar-collapsed` attribute, only while the column is hidden. 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 图标,并从窗口拖拽区域中排除。
45
+
46
+ ### macOS 桌面
47
+
48
+ 在 `html[data-platform='darwin']`(仅由桌面 preload 设置)下,展开的侧边栏列顶部有一条 52px 的顶部条:避开 hiddenInset 红绿灯、承载收起按钮,并作为窗口拖拽区;收起时整列隐藏而非保留轨道。本包向会话头部的 `conversation.session.header.leading` 座注册 `HeaderLeadingControls`——打开侧边栏与 New Session 两个控件,纯由 CSS 依据 AppFrame 发布的 `data-sidebar-collapsed` 属性仅在列隐藏时显示。设计依据与窗口集成约定见 [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,67 @@ 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{display:none}[data-sidebar-collapsed] .IW6AQa_controls{align-items:center;gap:8px;margin-right:8px;padding-left:68px;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)}.IW6AQa_iconButton svg{width:15px;height:15px}";
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
+ /** macOS-desktop conversation-header controls for the fully hidden sidebar. */
29
+ /**
30
+ * Sidebar-open and New Session controls in the conversation header's leading
31
+ * seat. On macOS desktop a collapsed sidebar hides entirely (no rail), taking
32
+ * both controls off screen; this occupant puts them back beside the traffic
33
+ * lights. Mounted whenever the platform matches; visibility rides the
34
+ * AppFrame-published `data-sidebar-collapsed` attribute in CSS, so no
35
+ * collapse-state pipe is added here.
36
+ * @param props - Injected sidebar actions plus the sidebar locale seat.
37
+ * @returns the two header controls, or null off macOS desktop.
38
+ */
39
+ function HeaderLeadingControls({ toggleSidebar, startSession, t }) {
40
+ if (!(0, _deepseek_ai_dsh_client_ui_primitives.isDarwinDesktop)()) return null;
41
+ return (0, react_jsx_runtime.jsxs)("div", {
42
+ className: HeaderLeadingControls_module_css_default.controls,
43
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
44
+ label: t("toggle.open"),
45
+ delayMs: 500,
46
+ children: (0, react_jsx_runtime.jsx)("button", {
47
+ type: "button",
48
+ className: HeaderLeadingControls_module_css_default.iconButton,
49
+ "aria-label": t("toggle.open"),
50
+ onClick: () => {
51
+ toggleSidebar();
52
+ },
53
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPanelLeftOutline16, { size: 16 })
54
+ })
55
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
56
+ label: t("session.new.label"),
57
+ delayMs: 500,
58
+ children: (0, react_jsx_runtime.jsx)("button", {
59
+ type: "button",
60
+ className: HeaderLeadingControls_module_css_default.iconButton,
61
+ "aria-label": t("session.new.label"),
62
+ onClick: () => {
63
+ startSession();
64
+ },
65
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: 16 })
66
+ })
67
+ })]
68
+ });
69
+ }
70
+ //#endregion
12
71
  //#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
13
72
  function r(e) {
14
73
  var t, f, n = "";
@@ -25,7 +84,7 @@ window.__ModuleLoader__.load({
25
84
  }
26
85
  //#endregion
27
86
  //#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}}";
87
+ 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;-webkit-app-region:drag;flex:none;justify-content:flex-end;align-items:center;padding:0 12px;display:flex}.hHd-Xa_topStrip .hHd-Xa_iconButton{-webkit-app-region:no-drag}.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: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;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:color-mix(in srgb, var(--dsw-alias-button-elevated-fill) 75%, transparent)}[data-platform=darwin] .hHd-Xa_newSession:hover{background:color-mix(in srgb, var(--dsw-alias-button-floating-hover) 75%, transparent)}.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
88
  const tagId = "@deepseek-ai/dsh-client-ui-sidebar/SidebarRoot.module.css";
30
89
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
31
90
  const tag = document.createElement("style");
@@ -66,6 +125,7 @@ window.__ModuleLoader__.load({
66
125
  "root": "hHd-Xa_root",
67
126
  "settingsArea": "hHd-Xa_settingsArea",
68
127
  "toggle": "hHd-Xa_toggle",
128
+ "topStrip": "hHd-Xa_topStrip",
69
129
  "wide": "hHd-Xa_wide",
70
130
  "wide-in": "hHd-Xa_wide-in"
71
131
  };
@@ -100,7 +160,7 @@ window.__ModuleLoader__.load({
100
160
  const SCROLLBAR_LINGER_MS = 2e3;
101
161
  /** Format complete-build metadata for the local brand badge. */
102
162
  function localBuildVersion() {
103
- return `0.1.6-alpha.1-e208262` + ({}.DSH_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "");
163
+ return `0.1.6-alpha.2-62b700b` + ({}.DSH_CLIENT_GIT_DIRTY === "true" ? "-dirty" : "");
104
164
  }
105
165
  /** Each panel row subscribes only to its own selection state. */
106
166
  function PanelRow({ id, label, wide, usePanelInfo, selectPanel, renderSlot }) {
@@ -151,7 +211,8 @@ window.__ModuleLoader__.load({
151
211
  window.clearTimeout(timer);
152
212
  };
153
213
  }, [collapsed]);
154
- const wide = !collapsed || !settled;
214
+ const windowsTitlebar = document.documentElement.hasAttribute("data-windows-titlebar");
215
+ const wide = windowsTitlebar ? !collapsed : !collapsed || !settled;
155
216
  const lastWideWidth = (0, react.useRef)(width);
156
217
  if (!collapsed) lastWideWidth.current = width;
157
218
  const everWide = (0, react.useRef)(!collapsed);
@@ -186,6 +247,31 @@ window.__ModuleLoader__.load({
186
247
  };
187
248
  }, [pointerInside]);
188
249
  const buildVersion = localBuildVersion();
250
+ const darwinDesktop = (0, _deepseek_ai_dsh_client_ui_primitives.isDarwinDesktop)();
251
+ const toggle = (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
252
+ label: collapsed ? t("toggle.open") : t("toggle.collapse"),
253
+ delayMs: 500,
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.IconPanelLeftOutline16, {
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,6 +284,10 @@ 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
293
  children: [wide && (0, react_jsx_runtime.jsx)("button", {
@@ -230,26 +320,7 @@ window.__ModuleLoader__.load({
230
320
  }) })
231
321
  })]
232
322
  })
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", {
237
- 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"),
240
- onClick: () => {
241
- toggleSidebar();
242
- },
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
- })]
323
+ }), !darwinDesktop && toggle]
253
324
  }),
254
325
  (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
255
326
  label: t("session.new.label"),
@@ -262,7 +333,7 @@ window.__ModuleLoader__.load({
262
333
  onClick: () => {
263
334
  startSession();
264
335
  },
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", {
336
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconNewChatOutline16, { size: wide ? 14 : windowsTitlebar ? 16 : 18 }), wide && (0, react_jsx_runtime.jsx)("span", {
266
337
  className: clsx(SidebarRoot_module_css_default.newSessionLabel, SidebarRoot_module_css_default.wide),
267
338
  children: t("session.new")
268
339
  })]
@@ -384,6 +455,10 @@ window.__ModuleLoader__.load({
384
455
  kind: "single",
385
456
  scope: "root"
386
457
  },
458
+ "sidebar.toggle.badge": {
459
+ kind: "single",
460
+ scope: "root"
461
+ },
387
462
  "sidebar.panellist": {
388
463
  kind: "list",
389
464
  scope: "root"
@@ -403,6 +478,11 @@ window.__ModuleLoader__.load({
403
478
  },
404
479
  inject: injectProps
405
480
  }, SidebarRoot));
481
+ ctx.slots.inject("conversation.session.header.leading", () => ctx.slots.register({
482
+ name: "conversation.session.header.leading",
483
+ locale: NS,
484
+ inject: injectProps
485
+ }, HeaderLeadingControls));
406
486
  syncPanels();
407
487
  }
408
488
  //#endregion
@@ -0,0 +1,16 @@
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 conversation-header leading occupant. */
4
+ export type HeaderLeadingControlsProps = PropsRuntime<'conversation.session.header.leading'> & InjectFace<SidebarRootInjected> & PropsLocale<'sidebar'>;
5
+ /**
6
+ * Sidebar-open and New Session controls in the conversation header's leading
7
+ * seat. On macOS desktop a collapsed sidebar hides entirely (no rail), taking
8
+ * both controls off screen; this occupant puts them back beside the traffic
9
+ * lights. Mounted whenever the platform matches; visibility rides the
10
+ * AppFrame-published `data-sidebar-collapsed` attribute in CSS, so no
11
+ * collapse-state pipe is added here.
12
+ * @param props - Injected sidebar actions plus the sidebar locale seat.
13
+ * @returns the two header controls, or null off macOS desktop.
14
+ */
15
+ export declare function HeaderLeadingControls({ toggleSidebar, startSession, t }: HeaderLeadingControlsProps): import("react").JSX.Element | null;
16
+ //# 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.6-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,6 +30,7 @@
30
30
  "inject": [
31
31
  "@deepseek-ai/dsh-api-workspace-controller",
32
32
  "@deepseek-ai/dsh-client-ui-renderer",
33
+ "@deepseek-ai/dsh-client-ui-conversation",
33
34
  "@deepseek-ai/dsh-client-ui-layout",
34
35
  "@deepseek-ai/dsh-client-ui-session",
35
36
  "@deepseek-ai/dsh-client-ui-workspace",
@@ -46,17 +47,18 @@
46
47
  "@types/react": "~18.3.1",
47
48
  "react": "^18.2.0",
48
49
  "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"
50
+ "@deepseek-ai/dsh-client-store": "^0.1.6-alpha.2",
51
+ "@deepseek-ai/dsh-api-workspace-controller": "^0.1.6-alpha.2",
52
+ "@deepseek-ai/dsh-client-locale": "^0.1.6-alpha.2",
53
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.6-alpha.2",
54
+ "@deepseek-ai/dsh-client-ui-conversation": "^0.1.6-alpha.2",
55
+ "@deepseek-ai/dsh-client-ui-layout": "^0.1.6-alpha.2",
56
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.6-alpha.2",
57
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.6-alpha.2",
58
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.6-alpha.2",
59
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.6-alpha.2",
60
+ "@deepseek-ai/dsh-client-ui-session": "^0.1.6-alpha.2",
61
+ "@deepseek-ai/cordis": "^4.0.2"
60
62
  },
61
63
  "files": [
62
64
  "lib/index.js",