@sdata/web-vue 2.8.0 → 2.10.0

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/es/index.css CHANGED
@@ -9975,6 +9975,16 @@ body.sd-tour-active .sd-tour-popover * {
9975
9975
  .sd-menu-collapsed .sd-menu-inline-header .sd-icon {
9976
9976
  margin-right: 100%;
9977
9977
  }
9978
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-item {
9979
+ justify-content: center;
9980
+ }
9981
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-item-inner {
9982
+ display: none;
9983
+ }
9984
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-icon {
9985
+ margin-right: 0;
9986
+ line-height: 40px;
9987
+ }
9978
9988
  .sd-menu-collapse-button {
9979
9989
  position: absolute;
9980
9990
  right: 12px;
@@ -10414,6 +10424,9 @@ body.sd-tour-active .sd-tour-popover * {
10414
10424
  * Sider
10415
10425
  * 深色背景与 Menu 深色背景保持一致,避免内嵌菜单出现接缝
10416
10426
  *****************************************************/
10427
+ /*****************************************************
10428
+ * Sider rail(窄轨)
10429
+ *****************************************************/
10417
10430
  /*****************************************************
10418
10431
  * Sider light 主题
10419
10432
  *****************************************************/
@@ -10432,6 +10445,7 @@ body.sd-tour-active .sd-tour-popover * {
10432
10445
  box-sizing: border-box;
10433
10446
  }
10434
10447
  .sd-layout.sd-layout-has-sider {
10448
+ position: relative;
10435
10449
  flex-direction: row;
10436
10450
  }
10437
10451
  .sd-layout.sd-layout-has-sider > .sd-layout,
@@ -10450,7 +10464,7 @@ body.sd-tour-active .sd-tour-popover * {
10450
10464
  padding: 0 50px;
10451
10465
  color: var(--sd-color-text-1);
10452
10466
  line-height: 64px;
10453
- background: #001529;
10467
+ background: var(--sd-color-menu-dark-bg);
10454
10468
  }
10455
10469
 
10456
10470
  .sd-layout-footer {
@@ -10568,6 +10582,21 @@ body.sd-tour-active .sd-tour-popover * {
10568
10582
  .sd-layout-sider-temporary-trigger:hover {
10569
10583
  background: var(--sd-color-fill-2);
10570
10584
  }
10585
+ .sd-layout-sider-rail {
10586
+ overflow: visible;
10587
+ }
10588
+ .sd-layout-sider-rail-overlay {
10589
+ position: absolute;
10590
+ inset: 0;
10591
+ height: 100%;
10592
+ overflow: hidden;
10593
+ background: inherit;
10594
+ transition: width 0.2s cubic-bezier(0.34, 0.69, 0.1, 1), box-shadow 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
10595
+ }
10596
+ .sd-layout-sider-rail-expand {
10597
+ z-index: 20;
10598
+ box-shadow: var(--sd-shadow2-center);
10599
+ }
10571
10600
 
10572
10601
  .sd-input-tag {
10573
10602
  display: inline-flex;
@@ -10,6 +10,8 @@ export interface LayoutContextProps {
10
10
  export declare const LayoutContextInjectionKey: InjectionKey<LayoutContextProps>;
11
11
  export interface SiderContextProps {
12
12
  siderCollapsed?: boolean;
13
+ siderRail?: boolean;
14
+ siderRailWidth?: number;
13
15
  theme?: SiderTheme;
14
16
  }
15
17
  export declare const SiderContextInjectionKey: InjectionKey<SiderContextProps>;
@@ -144,6 +144,18 @@ declare const Layout: {
144
144
  type: BooleanConstructor;
145
145
  default: boolean;
146
146
  };
147
+ rail: {
148
+ type: import("vue").PropType<boolean>;
149
+ default: boolean;
150
+ };
151
+ railWidth: {
152
+ type: (StringConstructor | NumberConstructor)[];
153
+ default: number;
154
+ };
155
+ expandOnHover: {
156
+ type: BooleanConstructor;
157
+ default: boolean;
158
+ };
147
159
  drawerProps: {
148
160
  type: import("vue").PropType<import("./interface").SiderTemporaryDrawerProps>;
149
161
  default: undefined;
@@ -151,9 +163,11 @@ declare const Layout: {
151
163
  }>> & Readonly<{
152
164
  onCollapse?: ((collapsed: boolean, type: import("./interface").CollapseType) => any) | undefined;
153
165
  onBreakpoint?: ((broken: boolean) => any) | undefined;
166
+ "onUpdate:rail"?: ((rail: boolean) => any) | undefined;
154
167
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
155
168
  collapse: (collapsed: boolean, type: import("./interface").CollapseType) => any;
156
169
  breakpoint: (broken: boolean) => any;
170
+ "update:rail": (rail: boolean) => any;
157
171
  }, import("vue").PublicProps, {
158
172
  scrollbar: boolean | import("../index.ts").ScrollbarProps;
159
173
  width: string | number;
@@ -167,6 +181,9 @@ declare const Layout: {
167
181
  collapsedWidth: string | number;
168
182
  breakpoint: import("../_utils/responsive-observe.ts").SiderBreakpoint;
169
183
  temporary: boolean;
184
+ rail: boolean;
185
+ railWidth: string | number;
186
+ expandOnHover: boolean;
170
187
  drawerProps: import("./interface").SiderTemporaryDrawerProps;
171
188
  }, true, {}, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, {}, any, import("vue").ComponentProvideOptions, {
172
189
  P: {};
@@ -224,6 +241,18 @@ declare const Layout: {
224
241
  type: BooleanConstructor;
225
242
  default: boolean;
226
243
  };
244
+ rail: {
245
+ type: import("vue").PropType<boolean>;
246
+ default: boolean;
247
+ };
248
+ railWidth: {
249
+ type: (StringConstructor | NumberConstructor)[];
250
+ default: number;
251
+ };
252
+ expandOnHover: {
253
+ type: BooleanConstructor;
254
+ default: boolean;
255
+ };
227
256
  drawerProps: {
228
257
  type: import("vue").PropType<import("./interface").SiderTemporaryDrawerProps>;
229
258
  default: undefined;
@@ -231,6 +260,7 @@ declare const Layout: {
231
260
  }>> & Readonly<{
232
261
  onCollapse?: ((collapsed: boolean, type: import("./interface").CollapseType) => any) | undefined;
233
262
  onBreakpoint?: ((broken: boolean) => any) | undefined;
263
+ "onUpdate:rail"?: ((rail: boolean) => any) | undefined;
234
264
  }>, {}, {}, {}, {}, {
235
265
  scrollbar: boolean | import("../index.ts").ScrollbarProps;
236
266
  width: string | number;
@@ -244,6 +274,9 @@ declare const Layout: {
244
274
  collapsedWidth: string | number;
245
275
  breakpoint: import("../_utils/responsive-observe.ts").SiderBreakpoint;
246
276
  temporary: boolean;
277
+ rail: boolean;
278
+ railWidth: string | number;
279
+ expandOnHover: boolean;
247
280
  drawerProps: import("./interface").SiderTemporaryDrawerProps;
248
281
  }>;
249
282
  __isFragment?: never;
@@ -298,6 +331,18 @@ declare const Layout: {
298
331
  type: BooleanConstructor;
299
332
  default: boolean;
300
333
  };
334
+ rail: {
335
+ type: import("vue").PropType<boolean>;
336
+ default: boolean;
337
+ };
338
+ railWidth: {
339
+ type: (StringConstructor | NumberConstructor)[];
340
+ default: number;
341
+ };
342
+ expandOnHover: {
343
+ type: BooleanConstructor;
344
+ default: boolean;
345
+ };
301
346
  drawerProps: {
302
347
  type: import("vue").PropType<import("./interface").SiderTemporaryDrawerProps>;
303
348
  default: undefined;
@@ -305,9 +350,11 @@ declare const Layout: {
305
350
  }>> & Readonly<{
306
351
  onCollapse?: ((collapsed: boolean, type: import("./interface").CollapseType) => any) | undefined;
307
352
  onBreakpoint?: ((broken: boolean) => any) | undefined;
353
+ "onUpdate:rail"?: ((rail: boolean) => any) | undefined;
308
354
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
309
355
  collapse: (collapsed: boolean, type: import("./interface").CollapseType) => any;
310
356
  breakpoint: (broken: boolean) => any;
357
+ "update:rail": (rail: boolean) => any;
311
358
  }, string, {
312
359
  scrollbar: boolean | import("../index.ts").ScrollbarProps;
313
360
  width: string | number;
@@ -321,6 +368,9 @@ declare const Layout: {
321
368
  collapsedWidth: string | number;
322
369
  breakpoint: import("../_utils/responsive-observe.ts").SiderBreakpoint;
323
370
  temporary: boolean;
371
+ rail: boolean;
372
+ railWidth: string | number;
373
+ expandOnHover: boolean;
324
374
  drawerProps: import("./interface").SiderTemporaryDrawerProps;
325
375
  }, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & import("vue").VNodeProps & import("vue").AllowedComponentProps & import("vue").ComponentCustomProps & (new () => {
326
376
  $slots: {
@@ -337,6 +387,12 @@ declare const Layout: {
337
387
  default?: (props: {}) => any;
338
388
  } & {
339
389
  default?: (props: {}) => any;
390
+ } & {
391
+ header?: (props: {}) => any;
392
+ } & {
393
+ default?: (props: {}) => any;
394
+ } & {
395
+ default?: (props: {}) => any;
340
396
  } & {
341
397
  trigger?: (props: {}) => any;
342
398
  } & {
@@ -20,6 +20,9 @@ export interface SiderProps {
20
20
  theme?: SiderTheme;
21
21
  scrollbar?: boolean | ScrollbarProps;
22
22
  temporary?: boolean;
23
+ rail?: boolean;
24
+ railWidth?: number | string;
25
+ expandOnHover?: boolean;
23
26
  drawerProps?: SiderTemporaryDrawerProps;
24
27
  }
25
28
  export type SiderTemporaryDrawerProps = Omit<DrawerProps, 'visible' | 'defaultVisible' | 'width' | 'footer' | 'okText' | 'cancelText' | 'okLoading' | 'okButtonProps' | 'cancelButtonProps' | 'hideCancel' | 'onBeforeOk' | 'onBeforeCancel'>;
@@ -2,7 +2,7 @@ import { type PropType } from 'vue';
2
2
  import type { SiderBreakpoint } from '../_utils/responsive-observe';
3
3
  import type { CollapseType, SiderTemporaryDrawerProps } from './interface';
4
4
  import { type ScrollbarProps } from '../scrollbar';
5
- declare var __VLS_9: {}, __VLS_11: {}, __VLS_19: {}, __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_38: {}, __VLS_40: {}, __VLS_47: {};
5
+ declare var __VLS_9: {}, __VLS_11: {}, __VLS_19: {}, __VLS_21: {}, __VLS_28: {}, __VLS_30: {}, __VLS_38: {}, __VLS_40: {}, __VLS_42: {}, __VLS_50: {}, __VLS_52: {}, __VLS_59: {};
6
6
  type __VLS_Slots = {} & {
7
7
  header?: (props: typeof __VLS_9) => any;
8
8
  } & {
@@ -18,9 +18,15 @@ type __VLS_Slots = {} & {
18
18
  } & {
19
19
  default?: (props: typeof __VLS_38) => any;
20
20
  } & {
21
- trigger?: (props: typeof __VLS_40) => any;
21
+ header?: (props: typeof __VLS_40) => any;
22
22
  } & {
23
- trigger?: (props: typeof __VLS_47) => any;
23
+ default?: (props: typeof __VLS_42) => any;
24
+ } & {
25
+ default?: (props: typeof __VLS_50) => any;
26
+ } & {
27
+ trigger?: (props: typeof __VLS_52) => any;
28
+ } & {
29
+ trigger?: (props: typeof __VLS_59) => any;
24
30
  };
25
31
  declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
26
32
  collapsible: {
@@ -71,6 +77,18 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
71
77
  type: BooleanConstructor;
72
78
  default: boolean;
73
79
  };
80
+ rail: {
81
+ type: PropType<boolean>;
82
+ default: boolean;
83
+ };
84
+ railWidth: {
85
+ type: (StringConstructor | NumberConstructor)[];
86
+ default: number;
87
+ };
88
+ expandOnHover: {
89
+ type: BooleanConstructor;
90
+ default: boolean;
91
+ };
74
92
  drawerProps: {
75
93
  type: PropType<SiderTemporaryDrawerProps>;
76
94
  default: undefined;
@@ -78,6 +96,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
78
96
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
79
97
  collapse: (collapsed: boolean, type: CollapseType) => any;
80
98
  breakpoint: (broken: boolean) => any;
99
+ "update:rail": (rail: boolean) => any;
81
100
  }, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
82
101
  collapsible: {
83
102
  type: BooleanConstructor;
@@ -127,6 +146,18 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
127
146
  type: BooleanConstructor;
128
147
  default: boolean;
129
148
  };
149
+ rail: {
150
+ type: PropType<boolean>;
151
+ default: boolean;
152
+ };
153
+ railWidth: {
154
+ type: (StringConstructor | NumberConstructor)[];
155
+ default: number;
156
+ };
157
+ expandOnHover: {
158
+ type: BooleanConstructor;
159
+ default: boolean;
160
+ };
130
161
  drawerProps: {
131
162
  type: PropType<SiderTemporaryDrawerProps>;
132
163
  default: undefined;
@@ -134,6 +165,7 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
134
165
  }>> & Readonly<{
135
166
  onCollapse?: ((collapsed: boolean, type: CollapseType) => any) | undefined;
136
167
  onBreakpoint?: ((broken: boolean) => any) | undefined;
168
+ "onUpdate:rail"?: ((rail: boolean) => any) | undefined;
137
169
  }>, {
138
170
  scrollbar: boolean | ScrollbarProps;
139
171
  width: string | number;
@@ -147,6 +179,9 @@ declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPro
147
179
  collapsedWidth: string | number;
148
180
  breakpoint: SiderBreakpoint;
149
181
  temporary: boolean;
182
+ rail: boolean;
183
+ railWidth: string | number;
184
+ expandOnHover: boolean;
150
185
  drawerProps: SiderTemporaryDrawerProps;
151
186
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
152
187
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -111,6 +111,30 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
111
111
  default: false
112
112
  },
113
113
  /**
114
+ * @zh 窄轨模式:Sider 常驻为窄轨宽度(仅展示图标),与 collapsed 折叠相互独立
115
+ * @en Rail mode: Sider stays at rail width (icons only), independent from collapsed
116
+ */
117
+ rail: {
118
+ type: Boolean,
119
+ default: false
120
+ },
121
+ /**
122
+ * @zh 窄轨宽度,仅 rail=true 时生效
123
+ * @en Rail width, only effective when rail=true
124
+ */
125
+ railWidth: {
126
+ type: [Number, String],
127
+ default: 72
128
+ },
129
+ /**
130
+ * @zh 窄轨模式下,鼠标悬停 Sider 时临时展开到 width(覆盖在内容上方,不推动内容),移出后收回。仅 rail=true 时生效
131
+ * @en In rail mode, temporarily expands to width on hover (overlays content without pushing it), collapses on leave. Only effective when rail=true
132
+ */
133
+ expandOnHover: {
134
+ type: Boolean,
135
+ default: false
136
+ },
137
+ /**
114
138
  * @zh temporary 模式下透传给 Drawer 的配置(仅 temporary=true 时生效)
115
139
  * @en Drawer passthrough config (only effective when temporary=true)
116
140
  */
@@ -119,7 +143,11 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
119
143
  default: void 0
120
144
  }
121
145
  },
122
- emits: ["collapse", "breakpoint"],
146
+ emits: [
147
+ "collapse",
148
+ "breakpoint",
149
+ "update:rail"
150
+ ],
123
151
  setup(__props, { emit: __emit }) {
124
152
  var _props$collapsed;
125
153
  let siderUuid = 0;
@@ -215,8 +243,27 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
215
243
  const collapsedIcon = reverseIcon.value ? IconLeft : IconRight;
216
244
  return mergedCollapsed.value ? collapsedIcon : expandedIcon;
217
245
  });
218
- const rawWidth = computed(() => mergedCollapsed.value ? props.collapsedWidth : props.width);
246
+ const isHovering = ref(false);
247
+ const railHoverEnabled = computed(() => props.rail && props.expandOnHover);
248
+ const isRailExpanded = computed(() => railHoverEnabled.value && isHovering.value);
249
+ const onMouseEnter = () => {
250
+ if (railHoverEnabled.value) {
251
+ isHovering.value = true;
252
+ emit("update:rail", false);
253
+ }
254
+ };
255
+ const onMouseLeave = () => {
256
+ if (railHoverEnabled.value) {
257
+ isHovering.value = false;
258
+ emit("update:rail", true);
259
+ }
260
+ };
261
+ const rawWidth = computed(() => {
262
+ if (props.rail) return isRailExpanded.value ? props.width : props.railWidth;
263
+ return mergedCollapsed.value ? props.collapsedWidth : props.width;
264
+ });
219
265
  const siderWidth = computed(() => toSiderWidth(rawWidth.value));
266
+ const railReservedWidth = computed(() => toSiderWidth(props.railWidth));
220
267
  const hasZeroWidth = computed(() => Number.parseFloat(String(props.collapsedWidth || 0)) === 0);
221
268
  const renderTrigger = computed(() => {
222
269
  if (props.temporary) return !props.hideTrigger;
@@ -229,6 +276,12 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
229
276
  flex: "0 0 auto",
230
277
  width: "auto"
231
278
  };
279
+ if (props.rail) return {
280
+ flex: `0 0 ${railReservedWidth.value}`,
281
+ maxWidth: railReservedWidth.value,
282
+ minWidth: railReservedWidth.value,
283
+ width: railReservedWidth.value
284
+ };
232
285
  return {
233
286
  flex: `0 0 ${siderWidth.value}`,
234
287
  maxWidth: siderWidth.value,
@@ -236,6 +289,15 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
236
289
  width: siderWidth.value
237
290
  };
238
291
  });
292
+ const railOverlayStyle = computed(() => {
293
+ const base = {
294
+ position: "absolute",
295
+ inset: "0",
296
+ width: isRailExpanded.value ? siderWidth.value : railReservedWidth.value
297
+ };
298
+ return isRailExpanded.value ? _objectSpread2(_objectSpread2({}, base), {}, { zIndex: 20 }) : base;
299
+ });
300
+ const railOverlayCls = computed(() => [`${prefixCls}-rail-overlay`, { [`${prefixCls}-rail-expand`]: isRailExpanded.value }]);
239
301
  const siderCls = computed(() => [
240
302
  prefixCls,
241
303
  `${prefixCls}-${mergedTheme.value}`,
@@ -244,7 +306,8 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
244
306
  [`${prefixCls}-has-trigger`]: props.collapsible && !props.hideTrigger && !hasZeroWidth.value,
245
307
  [`${prefixCls}-below`]: below.value,
246
308
  [`${prefixCls}-zero-width`]: Number.parseFloat(siderWidth.value) === 0,
247
- [`${prefixCls}-temporary`]: props.temporary
309
+ [`${prefixCls}-temporary`]: props.temporary,
310
+ [`${prefixCls}-rail`]: props.rail
248
311
  }
249
312
  ]);
250
313
  const mergedDrawerProps = computed(() => _objectSpread2({
@@ -256,13 +319,23 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
256
319
  const onDrawerVisibleChange = (visible) => {
257
320
  if (visible !== !mergedCollapsed.value) handleSetCollapsed(!visible, "clickTrigger");
258
321
  };
322
+ const mergedSiderRail = computed(() => !!props.rail && !isRailExpanded.value);
323
+ const siderRailWidthValue = computed(() => props.rail && typeof props.railWidth === "number" ? props.railWidth : void 0);
259
324
  const siderContext = reactive({
260
325
  siderCollapsed: mergedCollapsed.value,
326
+ siderRail: mergedSiderRail.value,
327
+ siderRailWidth: siderRailWidthValue.value,
261
328
  theme: mergedTheme.value
262
329
  });
263
330
  watch(mergedCollapsed, (val) => {
264
331
  siderContext.siderCollapsed = val;
265
332
  });
333
+ watch(mergedSiderRail, (val) => {
334
+ siderContext.siderRail = val;
335
+ });
336
+ watch(siderRailWidthValue, (val) => {
337
+ siderContext.siderRailWidth = val;
338
+ });
266
339
  watch(mergedTheme, (val) => {
267
340
  siderContext.theme = val;
268
341
  });
@@ -272,7 +345,9 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
272
345
  ref_key: "rootEl",
273
346
  ref: rootEl,
274
347
  class: normalizeClass(siderCls.value),
275
- style: normalizeStyle(divStyle.value)
348
+ style: normalizeStyle(divStyle.value),
349
+ onMouseenter: onMouseEnter,
350
+ onMouseleave: onMouseLeave
276
351
  }, [__props.temporary ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [createVNode(unref(Drawer), mergeProps(mergedDrawerProps.value, {
277
352
  visible: !mergedCollapsed.value,
278
353
  "onUpdate:visible": onDrawerVisibleChange
@@ -295,7 +370,23 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
295
370
  key: 0,
296
371
  class: normalizeClass(`${unref(prefixCls)}-temporary-trigger`),
297
372
  onClick: toggle
298
- }, [renderSlot(_ctx.$slots, "trigger", {}, () => [createVNode(unref(IconMenu))])], 2)) : createCommentVNode("", true)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
373
+ }, [renderSlot(_ctx.$slots, "trigger", {}, () => [createVNode(unref(IconMenu))])], 2)) : createCommentVNode("", true)], 64)) : __props.rail ? (openBlock(), createElementBlock("div", {
374
+ key: 1,
375
+ class: normalizeClass(railOverlayCls.value),
376
+ style: normalizeStyle(railOverlayStyle.value)
377
+ }, [_ctx.$slots.header ? (openBlock(), createElementBlock("div", {
378
+ key: 0,
379
+ class: normalizeClass(`${unref(prefixCls)}-header`)
380
+ }, [renderSlot(_ctx.$slots, "header")], 2)) : createCommentVNode("", true), useNativeScrollbar.value ? (openBlock(), createElementBlock("div", {
381
+ key: 1,
382
+ class: normalizeClass([`${unref(prefixCls)}-children`, `${unref(prefixCls)}-children-scroll`])
383
+ }, [renderSlot(_ctx.$slots, "default")], 2)) : (openBlock(), createBlock(unref(Scrollbar), mergeProps({
384
+ key: 2,
385
+ "outer-class": `${unref(prefixCls)}-children`
386
+ }, unref(scrollbarProps)), {
387
+ default: withCtx(() => [renderSlot(_ctx.$slots, "default")]),
388
+ _: 3
389
+ }, 16, ["outer-class"]))], 6)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
299
390
  _ctx.$slots.header ? (openBlock(), createElementBlock("div", {
300
391
  key: 0,
301
392
  class: normalizeClass(`${unref(prefixCls)}-header`)
@@ -321,7 +412,7 @@ var sider_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComp
321
412
  style: normalizeStyle({ width: siderWidth.value }),
322
413
  onClick: toggle
323
414
  }, [renderSlot(_ctx.$slots, "trigger", {}, () => [(openBlock(), createBlock(resolveDynamicComponent(defaultTriggerComponent.value)))])], 6))], 64)) : createCommentVNode("", true)
324
- ], 64))], 6);
415
+ ], 64))], 38);
325
416
  };
326
417
  }
327
418
  }));
@@ -29,6 +29,9 @@
29
29
  * Sider
30
30
  * 深色背景与 Menu 深色背景保持一致,避免内嵌菜单出现接缝
31
31
  *****************************************************/
32
+ /*****************************************************
33
+ * Sider rail(窄轨)
34
+ *****************************************************/
32
35
  /*****************************************************
33
36
  * Sider light 主题
34
37
  *****************************************************/
@@ -47,6 +50,7 @@
47
50
  box-sizing: border-box;
48
51
  }
49
52
  .sd-layout.sd-layout-has-sider {
53
+ position: relative;
50
54
  flex-direction: row;
51
55
  }
52
56
  .sd-layout.sd-layout-has-sider > .sd-layout,
@@ -65,7 +69,7 @@
65
69
  padding: 0 50px;
66
70
  color: var(--sd-color-text-1);
67
71
  line-height: 64px;
68
- background: #001529;
72
+ background: var(--sd-color-menu-dark-bg);
69
73
  }
70
74
 
71
75
  .sd-layout-footer {
@@ -182,4 +186,19 @@
182
186
  }
183
187
  .sd-layout-sider-temporary-trigger:hover {
184
188
  background: var(--sd-color-fill-2);
189
+ }
190
+ .sd-layout-sider-rail {
191
+ overflow: visible;
192
+ }
193
+ .sd-layout-sider-rail-overlay {
194
+ position: absolute;
195
+ inset: 0;
196
+ height: 100%;
197
+ overflow: hidden;
198
+ background: inherit;
199
+ transition: width 0.2s cubic-bezier(0.34, 0.69, 0.1, 1), box-shadow 0.2s cubic-bezier(0.34, 0.69, 0.1, 1);
200
+ }
201
+ .sd-layout-sider-rail-expand {
202
+ z-index: 20;
203
+ box-shadow: var(--sd-shadow2-center);
185
204
  }
@@ -21,6 +21,7 @@ $text-color: var(string.unquote('#{theme.$sd-cssvars-prefix}-color-text-1'));
21
21
  }
22
22
 
23
23
  &#{&}-has-sider {
24
+ position: relative;
24
25
  flex-direction: row;
25
26
 
26
27
  > .#{$layout-prefix-cls},
@@ -195,4 +196,31 @@ $text-color: var(string.unquote('#{theme.$sd-cssvars-prefix}-color-text-1'));
195
196
  background: var(string.unquote('#{theme.$sd-cssvars-prefix}-color-fill-2'));
196
197
  }
197
198
  }
199
+
200
+ // Rail:aside 常驻窄轨态。aside 流内占位恒为 railWidth,且必须 overflow: visible,
201
+ // 否则 hover 时内部 absolute overlay 会被裁掉、无法覆盖到相邻内容上方。
202
+ &-rail {
203
+ overflow: visible;
204
+ }
205
+
206
+ // Rail 内容 overlay 容器:承载 header/children/trigger。始终保持绝对定位(脱离文档流,
207
+ // 不推动右侧内容),宽度在内联 style 上随 hover 在 railWidth ↔ 全宽之间切换。
208
+ // 这里补 width 过渡 → 平滑展开/收回;过渡只作用于浮层自身宽度,不触发相邻内容重排。
209
+ &-rail-overlay {
210
+ position: absolute;
211
+ inset: 0;
212
+ height: 100%;
213
+ overflow: hidden;
214
+ background: inherit;
215
+ transition:
216
+ width $layout-motion-duration-mid theme.$transition-timing-function-standard,
217
+ box-shadow $layout-motion-duration-mid theme.$transition-timing-function-standard;
218
+ }
219
+
220
+ // Rail 悬停展开覆盖态(作用于 overlay):全宽浮于内容上方,
221
+ // 宽度由内联 style 给定,这里补 z-index 与阴影以区分浮层与底图。
222
+ &-rail-expand {
223
+ z-index: $layout-sider-rail-expand-z-index;
224
+ box-shadow: var(string.unquote('#{theme.$sd-cssvars-prefix}-shadow2-center'));
225
+ }
198
226
  }
@@ -15,7 +15,7 @@ $layout-footer-bg: var(string.unquote('#{$sd-cssvars-prefix}-color-fill-1'));
15
15
  /*****************************************************
16
16
  * Header
17
17
  *****************************************************/
18
- $layout-header-bg: #001529;
18
+ $layout-header-bg: var(string.unquote('#{global.$sd-cssvars-prefix}-color-menu-dark-bg'));
19
19
  $layout-header-height: global.$size-16; // 64px
20
20
  $layout-header-padding-horizontal: 50px;
21
21
  $layout-header-padding: 0 $layout-header-padding-horizontal;
@@ -38,6 +38,12 @@ $layout-sider-zero-trigger-width: global.$size-10; // 40px
38
38
  $layout-sider-zero-trigger-height: global.$size-10; // 40px
39
39
  $layout-sider-zero-trigger-font-size: 18px;
40
40
 
41
+ /*****************************************************
42
+ * Sider rail(窄轨)
43
+ *****************************************************/
44
+ $layout-sider-rail-width: global.$size-18; // 72px
45
+ $layout-sider-rail-expand-z-index: 20;
46
+
41
47
  /*****************************************************
42
48
  * Sider light 主题
43
49
  *****************************************************/
package/es/menu/menu.js CHANGED
@@ -29,18 +29,29 @@ var menu_default = /* @__PURE__ */ defineComponent({
29
29
  const { theme: propTheme, mode } = toRefs(props);
30
30
  const siderContext = inject(SiderContextInjectionKey, void 0);
31
31
  const siderCollapsed = computed(() => (siderContext === null || siderContext === void 0 ? void 0 : siderContext.siderCollapsed) || false);
32
+ const siderRailCollapsed = computed(() => (siderContext === null || siderContext === void 0 ? void 0 : siderContext.siderRail) || false);
33
+ const siderMenuCollapsed = computed(() => siderCollapsed.value || siderRailCollapsed.value);
34
+ const siderRailCls = computed(() => (siderContext === null || siderContext === void 0 ? void 0 : siderContext.siderRail) ? "sd-menu-in-sider-rail" : "");
35
+ const siderMenuCollapsedWidth = computed(() => {
36
+ if (!(siderContext === null || siderContext === void 0 ? void 0 : siderContext.siderRail)) return void 0;
37
+ const railWidth = siderContext === null || siderContext === void 0 ? void 0 : siderContext.siderRailWidth;
38
+ return typeof railWidth === "number" ? railWidth : 72;
39
+ });
32
40
  const theme = computed(() => (propTheme === null || propTheme === void 0 ? void 0 : propTheme.value) || (siderContext === null || siderContext === void 0 ? void 0 : siderContext.theme) || "light");
33
41
  provide(MenuInjectionKey, void 0);
34
42
  provide(LevelInjectionKey, void 0);
35
- return () => createVNode(base_menu_default, mergeProps(props, attrs, {
36
- "theme": theme.value,
37
- "inTrigger": false,
38
- "siderCollapsed": siderCollapsed.value,
39
- "isRoot": true
40
- }), _objectSpread2(_objectSpread2({}, slots), {}, { default: mode.value === "horizontal" && slots.default ? () => createVNode(overflow_wrap_default, null, { default: () => {
41
- var _slots$default;
42
- return [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];
43
- } }) : slots.default }));
43
+ return () => {
44
+ return createVNode(base_menu_default, mergeProps(props, siderMenuCollapsedWidth.value !== void 0 ? { collapsedWidth: siderMenuCollapsedWidth.value } : {}, attrs, {
45
+ "class": [attrs.class, siderRailCls.value].filter(Boolean).join(" ") || void 0,
46
+ "theme": theme.value,
47
+ "inTrigger": false,
48
+ "siderCollapsed": siderMenuCollapsed.value,
49
+ "isRoot": true
50
+ }), _objectSpread2(_objectSpread2({}, slots), {}, { default: mode.value === "horizontal" && slots.default ? () => createVNode(overflow_wrap_default, null, { default: () => {
51
+ var _slots$default;
52
+ return [(_slots$default = slots.default) === null || _slots$default === void 0 ? void 0 : _slots$default.call(slots)];
53
+ } }) : slots.default }));
54
+ };
44
55
  }
45
56
  });
46
57
  //#endregion
@@ -554,6 +554,16 @@
554
554
  .sd-menu-collapsed .sd-menu-inline-header .sd-icon {
555
555
  margin-right: 100%;
556
556
  }
557
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-item {
558
+ justify-content: center;
559
+ }
560
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-item-inner {
561
+ display: none;
562
+ }
563
+ .sd-menu.sd-menu-in-sider-rail.sd-menu-collapsed .sd-menu-icon {
564
+ margin-right: 0;
565
+ line-height: 40px;
566
+ }
557
567
  .sd-menu-collapse-button {
558
568
  position: absolute;
559
569
  right: 12px;
@@ -449,6 +449,26 @@ $token-vars: map.merge(meta.module-variables('dropdownToken'), meta.module-varia
449
449
  }
450
450
  }
451
451
 
452
+ // 处于 Sider rail 常驻态时,折叠宽度对齐 railWidth(>48px),
453
+ // 默认靠左的图标需在 railWidth 内居中。
454
+ &.#{$menu-prefix-cls}-in-sider-rail {
455
+ &.#{$menu-prefix-cls}-collapsed {
456
+ .#{$menu-prefix-cls}-item {
457
+ justify-content: center;
458
+ }
459
+
460
+ // 折叠态文字本就 opacity:0,这里彻底移出布局,让图标借 justify-content 居中。
461
+ .#{$menu-prefix-cls}-item-inner {
462
+ display: none;
463
+ }
464
+
465
+ .#{$menu-prefix-cls}-icon {
466
+ margin-right: 0;
467
+ line-height: token-var('menu-vertical-item-height');
468
+ }
469
+ }
470
+ }
471
+
452
472
  // 折叠按钮
453
473
  &-collapse-button {
454
474
  position: absolute;