@zat-design/sisyphus-react 4.2.0 → 4.3.0-beta.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.
@@ -9,29 +9,25 @@
9
9
  flex-direction: column;
10
10
  height: 100%;
11
11
 
12
+ &-header-wrapper {
13
+ display: grid;
14
+ grid-template-rows: 0fr;
15
+ transition: grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1);
16
+
17
+ &.tabs-visible {
18
+ grid-template-rows: 1fr;
19
+ }
20
+
21
+ > .pro-layout-tabs-header {
22
+ overflow: hidden;
23
+ }
24
+ }
25
+
12
26
  &-header {
13
27
  align-items: center;
14
- min-height: 48px;
15
- padding: 12px 0;
16
28
  border-bottom: none;
17
- position: sticky;
18
- top: 64px;
19
- z-index: 90;
20
- background: #fff;
21
- box-shadow: none;
22
- transition: box-shadow 0.3s ease;
23
-
24
- &-shadow {
25
- position: absolute;
26
- left: 0;
27
- right: 0;
28
- bottom: 0;
29
- height: 1px;
30
- background: transparent;
31
- pointer-events: none;
32
- z-index: 1;
33
- box-shadow: 1px 2px 4px 1px rgba(0, 55, 93, 0.2);
34
- }
29
+ // 去掉 sticky 和白色背景:Tab 栏现在在 ProLayout 的渐变区域
30
+ background: transparent;
35
31
 
36
32
  .pro-layout-tab-icon {
37
33
  display: none !important;
@@ -43,7 +39,7 @@
43
39
  .pro-layout-tab-list {
44
40
  display: flex;
45
41
  flex: 1;
46
- gap: 12px;
42
+ gap: 8px;
47
43
 
48
44
  &::-webkit-scrollbar {
49
45
  height: 3px;
@@ -90,7 +86,6 @@
90
86
  // 覆盖 nav 样式,使其匹配 pro-layout-tabs-header
91
87
  .@{ant-prefix}-tabs-nav {
92
88
  margin: 0;
93
- // padding: 0 var(--zaui-space-size-md, 16px);
94
89
  padding: 0;
95
90
  border-bottom: none;
96
91
 
@@ -103,7 +98,7 @@
103
98
  .@{ant-prefix}-tabs-nav-list {
104
99
  display: flex;
105
100
  flex: 1;
106
- gap: 12px;
101
+ gap: 8px;
107
102
 
108
103
  &::-webkit-scrollbar {
109
104
  height: 3px;
@@ -129,7 +124,7 @@
129
124
  display: flex;
130
125
  flex-shrink: 0;
131
126
  align-items: center;
132
- min-height: 36px;
127
+ height: 33px;
133
128
  padding: 0 !important;
134
129
  margin: 0 !important;
135
130
  background: transparent !important;
@@ -151,7 +146,6 @@
151
146
  .pro-layout-tab-item {
152
147
  width: 100%;
153
148
  height: 100%;
154
- border: 1px solid rgb(217, 217, 217);
155
149
  }
156
150
  }
157
151
 
@@ -159,9 +153,6 @@
159
153
  .@{ant-prefix}-tabs-tab-active {
160
154
  background: transparent !important;
161
155
  border: none !important;
162
- .pro-layout-tab-item {
163
- border-color: transparent !important;
164
- }
165
156
 
166
157
  &::before {
167
158
  display: none;
@@ -175,40 +166,38 @@
175
166
  }
176
167
  }
177
168
 
169
+ .pro-layout-tabs-antd {
170
+ &.@{ant-prefix}-tabs {
171
+ .@{ant-prefix}-tabs-tab {
172
+ padding: 6px 0 !important;
173
+ margin-right: 8px !important;
174
+ margin-left: 0;
175
+ background: #e5e7e9;
176
+ transition: none;
177
+ &.@{ant-prefix}-tabs-tab-active {
178
+ background: #ffffff;
179
+ }
180
+ }
181
+ .ant-tabs-nav {
182
+ margin-bottom: 0;
183
+ }
184
+ }
185
+ }
186
+
178
187
  .pro-layout-tab-item {
179
188
  position: relative;
180
189
  display: flex;
181
190
  flex-shrink: 0;
182
191
  align-items: center;
183
- min-height: 36px;
184
192
  padding: 0;
185
- background: #ffffff;
186
- border: 1px solid transparent;
187
- border-radius: 8px;
188
193
  cursor: pointer;
189
- transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
194
+ transition: all 0.2s ease;
190
195
  user-select: none;
191
196
 
192
- &:hover {
193
- background: #ffffff;
194
- border-color: rgba(0, 0, 0, 0.06);
195
- }
196
-
197
- &.active {
198
- z-index: 2;
199
- background: var(--zaui-primary);
200
- border-color: transparent;
201
-
202
- &::before {
203
- display: none;
204
- }
205
- }
206
-
207
197
  .pro-layout-tab-content {
208
198
  display: flex;
209
199
  align-items: center;
210
- min-width: 100px;
211
- padding: 6px 12px;
200
+ padding: 0 12px;
212
201
  text-align: left;
213
202
 
214
203
  .pro-layout-tab-icon {
@@ -237,7 +226,7 @@
237
226
  font-size: 14px;
238
227
  white-space: nowrap;
239
228
  text-overflow: ellipsis;
240
- transition: color 0.3s;
229
+ transition: color 0.2s;
241
230
  }
242
231
 
243
232
  .pro-layout-tab-close {
@@ -245,38 +234,35 @@
245
234
  flex-shrink: 0;
246
235
  align-items: center;
247
236
  justify-content: center;
248
- margin-left: 8px;
249
- padding: 3px;
250
- color: rgba(0, 0, 0, 0.45);
237
+ margin-left: 4px;
238
+ padding: 2px;
239
+ color: #333;
251
240
  border-radius: 4px;
252
- opacity: 0.7;
253
- transition: all 0.3s;
241
+ opacity: 1;
242
+ transition: all 0.2s;
254
243
 
255
244
  &:hover {
256
245
  color: #ff4d4f;
257
- background: rgba(255, 77, 79, 0.15);
258
- opacity: 1;
246
+ background: rgba(255, 77, 79, 0.1);
259
247
  }
260
248
  }
261
249
  }
262
250
 
251
+ // hover 时展示 close 按钮
252
+ &:hover .pro-layout-tab-close,
253
+ &.active .pro-layout-tab-close {
254
+ opacity: 1;
255
+ }
256
+
263
257
  &.active .pro-layout-tab-content {
264
258
  .pro-layout-tab-title {
265
- color: #ffffff;
259
+ color: var(--pro-layout-tabs-primary);
266
260
  font-weight: 600;
267
261
  }
268
262
 
269
263
  .pro-layout-tab-icon {
270
264
  .iconfont {
271
- color: #ffffff;
272
- }
273
- }
274
-
275
- .pro-layout-tab-close {
276
- color: #ffffff;
277
-
278
- &:hover {
279
- background: rgba(255, 255, 255, 0.2);
265
+ color: var(--pro-layout-tabs-primary);
280
266
  }
281
267
  }
282
268
  }
@@ -298,7 +284,7 @@
298
284
  @media (max-width: 768px) {
299
285
  .pro-layout-tab-item {
300
286
  .pro-layout-tab-content {
301
- padding: 6px 8px;
287
+ padding: 0 8px;
302
288
 
303
289
  .pro-layout-tab-title {
304
290
  max-width: 80px;
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable func-call-spacing */
2
2
  /* eslint-disable no-spaced-func */
3
- import { createContext, useMemo, useRef, useCallback } from 'react';
3
+ import { createContext, useMemo, useRef, useCallback, useState } from 'react';
4
4
  import classNames from 'classnames';
5
5
  import { useSetState, useToggle, useDeepCompareEffect } from 'ahooks';
6
6
  import { ProWaterMark } from "../index";
@@ -51,6 +51,10 @@ const ProLayout = props => {
51
51
  const isTabsLayout = isTabsMode(props);
52
52
  validateTabsProps(mode, tabs);
53
53
  const tabsManagerRef = useRef(null);
54
+
55
+ // Tab 栏 Portal 挂载目标及动画状态
56
+ const [tabsBarEl, setTabsBarEl] = useState(null);
57
+ const [hasTabs, setHasTabs] = useState(false);
54
58
  const [{
55
59
  notice,
56
60
  menus,
@@ -116,6 +120,8 @@ const ProLayout = props => {
116
120
  config: enhancedTabsConfig,
117
121
  dataSource: menuDataSource,
118
122
  originalOnMenuClick: onMenuClick,
123
+ tabsBarContainer: tabsBarEl,
124
+ onTabsChange: setHasTabs,
119
125
  children: children
120
126
  });
121
127
  };
@@ -214,21 +220,28 @@ const ProLayout = props => {
214
220
  [`${className}`]: className
215
221
  }),
216
222
  style: {
217
- '--header-bg-image': `url(${headerBg})`
223
+ '--header-bg-image': `url(${headerBg})`,
224
+ '--pro-layout-header-height': `${headerHeight}px`
218
225
  },
219
226
  children: [/*#__PURE__*/_jsx(Header, {
220
227
  ...headerProps
221
228
  }), /*#__PURE__*/_jsx(Notice, {
222
229
  ...noticeProps
230
+ }), /*#__PURE__*/_jsx("div", {
231
+ ref: setTabsBarEl,
232
+ className: `pro-layout-tabs-bar-wrapper${hasTabs ? ' tabs-visible' : ''}${collapsed ? ' tabs-menu-open' : ''}`,
233
+ style: {
234
+ marginTop: headerHeight + noticeHeight
235
+ }
223
236
  }), /*#__PURE__*/_jsxs("div", {
224
237
  className: contentCls,
225
238
  children: [/*#__PURE__*/_jsx(Menu, {
226
239
  ...menuProps
227
240
  }), /*#__PURE__*/_jsx("div", {
228
- className: "pro-layout-content",
241
+ className: `pro-layout-content${hasTabs ? ' pro-layout-content-has-tabs' : ''}`,
229
242
  style: {
230
243
  ...contentStyle,
231
- marginTop: headerHeight + noticeHeight
244
+ marginTop: 0
232
245
  },
233
246
  children: renderContent()
234
247
  })]
@@ -399,6 +399,11 @@ export interface TabsConfig {
399
399
  storage?: TabsStorageStrategy;
400
400
  cacheKey?: string;
401
401
  onTabChange?: (activeKey: string, activeTab: TabItem | undefined, allTabs: TabItem[]) => void;
402
+ /**
403
+ * @description 是否允许标签页拖拽排序
404
+ * @default true
405
+ */
406
+ draggable?: boolean;
402
407
  /**
403
408
  * @description 激活组件解析函数,根据 component 标识返回对应的 React 组件
404
409
  */
@@ -287,12 +287,52 @@
287
287
  }
288
288
  }
289
289
 
290
+ /** Tab 栏 Portal 挂载点(位于 header 渐变区,内容区之上) */
291
+ .pro-layout-tabs-bar-wrapper {
292
+ // 与 pro-layout-content 对齐:同样的左右边距,无内边距让 tab 从左侧直接对齐
293
+ margin-right: var(--zaui-space-size-md, 16px);
294
+ margin-left: 48px;
295
+ padding: 0;
296
+ // 滚动时固定在 header 正下方
297
+ position: sticky;
298
+ top: var(--pro-layout-header-height, 64px);
299
+ z-index: 89;
300
+ // 与 ::before 渐变层像素级对齐:滚动时遮住上滚的白色内容,同时保持渐变背景可见
301
+ // background-color 作为实体打底,防止渐变图片浅色区域透出白色内容
302
+ background-color: #f7f9fd;
303
+ background-image: var(--header-bg-image);
304
+ background-repeat: no-repeat;
305
+ background-position: top center;
306
+ background-size: 100% auto;
307
+ background-attachment: fixed;
308
+ // 高度动画:CSS Grid 技巧,支持不定高度平滑过渡
309
+ display: grid;
310
+ grid-template-rows: 0fr;
311
+ transition: margin-left 0.3s cubic-bezier(0.2, 0, 0, 1), grid-template-rows 0.3s cubic-bezier(0.4, 0, 0.2, 1);
312
+
313
+ // 菜单展开时与内容区同步右移
314
+ &.tabs-menu-open {
315
+ margin-left: 220px;
316
+ }
317
+
318
+ // Tab 存在时展开
319
+ &.tabs-visible {
320
+ grid-template-rows: 1fr;
321
+ }
322
+
323
+ // Grid 子元素需要 overflow: hidden 才能实现 0fr 收起
324
+ > * {
325
+ overflow: hidden;
326
+ min-height: 0;
327
+ }
328
+ }
329
+
290
330
  /** 内容区 */
291
331
  .pro-layout-content {
292
332
  position: relative;
293
333
  z-index: 10;
294
334
  flex: 1;
295
- margin-top: 64px;
335
+ margin-top: 0;
296
336
  margin-right: var(--zaui-space-size-md, 16px);
297
337
  margin-bottom: 0;
298
338
  margin-left: 48px;
@@ -304,6 +344,14 @@
304
344
  border-bottom: none;
305
345
  border-radius: var(--zaui-border-radius, 8px) var(--zaui-border-radius, 8px) 0 0;
306
346
  transition: all 0.24s ease;
347
+
348
+ // Tab 存在时:顶部边框透明(不用 none,避免 transition:all 产生黑色闪烁)、移除顶部圆角,与 Tab 栏无缝衔接;补上顶部 padding
349
+ &-has-tabs {
350
+ border-top-color: transparent;
351
+ border-radius: 0;
352
+ padding-top: var(--zaui-space-size-md, 16px);
353
+ border-top-right-radius: var(--zaui-border-radius, 8px);
354
+ }
307
355
  }
308
356
 
309
357
  // 纯净模式:隐藏背景图
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zat-design/sisyphus-react",
3
- "version": "4.2.0",
3
+ "version": "4.3.0-beta.1",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "es",