@wandelbots/wandelbots-js-react-components 2.53.0 → 2.54.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/dist/components/TabBar.d.ts +11 -0
- package/dist/components/TabBar.d.ts.map +1 -1
- package/dist/index.cjs +26 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1374 -1280
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/TabBar.tsx +149 -35
package/package.json
CHANGED
|
@@ -13,6 +13,24 @@ export interface TabItem {
|
|
|
13
13
|
content: React.ReactNode
|
|
14
14
|
/** Optional icon component to display with the tab */
|
|
15
15
|
icon?: React.ReactElement
|
|
16
|
+
/** Optional badge configuration */
|
|
17
|
+
badge?: {
|
|
18
|
+
/** Badge content (number or string) */
|
|
19
|
+
content: React.ReactNode
|
|
20
|
+
/** Badge color variant */
|
|
21
|
+
color?:
|
|
22
|
+
| "default"
|
|
23
|
+
| "primary"
|
|
24
|
+
| "secondary"
|
|
25
|
+
| "error"
|
|
26
|
+
| "info"
|
|
27
|
+
| "success"
|
|
28
|
+
| "warning"
|
|
29
|
+
/** Maximum number to display (e.g., 99+) */
|
|
30
|
+
max?: number
|
|
31
|
+
/** Show badge even when content is zero */
|
|
32
|
+
showZero?: boolean
|
|
33
|
+
}
|
|
16
34
|
}
|
|
17
35
|
|
|
18
36
|
export interface TabBarProps {
|
|
@@ -101,62 +119,158 @@ export const TabBar = externalizeComponent(
|
|
|
101
119
|
sx={{ height: "100%", display: "flex", flexDirection: "column", ...sx }}
|
|
102
120
|
>
|
|
103
121
|
{/* Tabs */}
|
|
104
|
-
<Box
|
|
122
|
+
<Box
|
|
123
|
+
sx={{
|
|
124
|
+
px: 0,
|
|
125
|
+
py: 0,
|
|
126
|
+
overflow: "visible",
|
|
127
|
+
// Extra padding to prevent badge clipping
|
|
128
|
+
// Top: accommodates badge positioned at top: -6px with 20px height
|
|
129
|
+
// Right: accommodates badge positioned at right: -8px with 20px width
|
|
130
|
+
paddingTop: (theme) => theme.spacing(2), // 16px
|
|
131
|
+
paddingRight: (theme) => theme.spacing(2.5), // 20px
|
|
132
|
+
}}
|
|
133
|
+
>
|
|
105
134
|
<Tabs
|
|
106
135
|
value={currentValue}
|
|
107
136
|
onChange={handleTabChange}
|
|
108
137
|
sx={{
|
|
109
138
|
minHeight: "32px",
|
|
110
139
|
backgroundColor: "transparent",
|
|
140
|
+
overflow: "visible",
|
|
111
141
|
"& .MuiTabs-indicator": {
|
|
112
142
|
display: "none", // Hide the default indicator
|
|
113
143
|
},
|
|
114
144
|
"& .MuiTabs-flexContainer": {
|
|
115
145
|
gap: 2,
|
|
146
|
+
overflow: "visible",
|
|
147
|
+
paddingTop: 0,
|
|
148
|
+
paddingBottom: 0,
|
|
149
|
+
},
|
|
150
|
+
"& .MuiTabs-scroller": {
|
|
151
|
+
overflow: "visible !important",
|
|
152
|
+
},
|
|
153
|
+
"& .MuiTab-root": {
|
|
154
|
+
overflow: "visible",
|
|
116
155
|
},
|
|
117
156
|
}}
|
|
118
157
|
>
|
|
119
|
-
{items.map((item, index) =>
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
158
|
+
{items.map((item, index) => {
|
|
159
|
+
// Helper functions for badge logic
|
|
160
|
+
const getBadgeContent = () => {
|
|
161
|
+
if (!item.badge) return ""
|
|
162
|
+
const content = item.badge.content
|
|
163
|
+
const max = item.badge.max
|
|
164
|
+
|
|
165
|
+
// Handle numeric content with max limit
|
|
166
|
+
if (typeof content === "number" && max && content > max) {
|
|
167
|
+
return `${max}+`
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return String(content)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const shouldShowBadge = () => {
|
|
174
|
+
if (!item.badge) return false
|
|
175
|
+
const content = item.badge.content
|
|
176
|
+
const showZero = item.badge.showZero
|
|
177
|
+
|
|
178
|
+
// If content is 0 and showZero is false, hide badge
|
|
179
|
+
if (content === 0 && !showZero) return false
|
|
180
|
+
|
|
181
|
+
return true
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const badgeContent = getBadgeContent()
|
|
185
|
+
const showBadge = shouldShowBadge()
|
|
186
|
+
|
|
187
|
+
return (
|
|
188
|
+
<Tab
|
|
189
|
+
key={item.id}
|
|
190
|
+
label={item.label}
|
|
191
|
+
icon={item.icon}
|
|
192
|
+
iconPosition="start"
|
|
193
|
+
disableRipple
|
|
194
|
+
sx={{
|
|
195
|
+
minHeight: "32px",
|
|
196
|
+
height: "32px",
|
|
197
|
+
padding: "0px 10px",
|
|
198
|
+
borderRadius: "12px",
|
|
142
199
|
backgroundColor: (theme) =>
|
|
143
200
|
theme.palette.backgroundPaperElevation?.[11] || "#32344B",
|
|
144
201
|
color: "text.primary",
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
202
|
+
opacity: currentValue === index ? 1 : 0.38,
|
|
203
|
+
fontSize: "13px",
|
|
204
|
+
transition: "all 0.2s ease-in-out",
|
|
205
|
+
position: "relative",
|
|
206
|
+
"&:hover": {
|
|
207
|
+
opacity: currentValue === index ? 1 : 0.6,
|
|
208
|
+
},
|
|
209
|
+
"&.Mui-selected": {
|
|
210
|
+
opacity: 1,
|
|
211
|
+
backgroundColor: (theme) =>
|
|
212
|
+
theme.palette.backgroundPaperElevation?.[11] ||
|
|
213
|
+
"#32344B",
|
|
214
|
+
color: "text.primary",
|
|
215
|
+
},
|
|
216
|
+
"&:focus": {
|
|
217
|
+
outline: "none",
|
|
218
|
+
},
|
|
219
|
+
"&:active": {
|
|
220
|
+
transform: "none",
|
|
221
|
+
},
|
|
222
|
+
...(showBadge && {
|
|
223
|
+
"&::after": {
|
|
224
|
+
content: `"${badgeContent}"`,
|
|
225
|
+
position: "absolute",
|
|
226
|
+
// Position badge in top-right corner, extending outside tab bounds
|
|
227
|
+
top: -6, // Positions badge above the tab
|
|
228
|
+
right: -8, // Positions badge to the right of the tab
|
|
229
|
+
// Badge sizing - MUI Badge standard small size
|
|
230
|
+
minWidth: "20px", // Min width for single digits
|
|
231
|
+
height: "20px", // Fixed height for consistent appearance
|
|
232
|
+
borderRadius: "10px", // Half of height for circular shape
|
|
233
|
+
backgroundColor: (theme) => {
|
|
234
|
+
const colors = {
|
|
235
|
+
error: theme.palette.error.main,
|
|
236
|
+
info: theme.palette.info.main,
|
|
237
|
+
success: theme.palette.success.main,
|
|
238
|
+
warning: theme.palette.warning.main,
|
|
239
|
+
primary: theme.palette.primary.main,
|
|
240
|
+
secondary: theme.palette.secondary.main,
|
|
241
|
+
default: theme.palette.grey[500],
|
|
242
|
+
}
|
|
243
|
+
return (
|
|
244
|
+
colors[item.badge?.color || "error"] || colors.error
|
|
245
|
+
)
|
|
246
|
+
},
|
|
247
|
+
color: "white",
|
|
248
|
+
fontSize: "12px", // Readable size for badge content
|
|
249
|
+
fontWeight: 600, // Semi-bold for better visibility
|
|
250
|
+
display: "flex",
|
|
251
|
+
alignItems: "center",
|
|
252
|
+
justifyContent: "center",
|
|
253
|
+
padding: "2px 6px", // Horizontal padding for wider content (e.g., "99+")
|
|
254
|
+
zIndex: 1,
|
|
255
|
+
pointerEvents: "none", // Allow clicks to pass through to tab
|
|
256
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.2)", // Subtle depth
|
|
257
|
+
},
|
|
258
|
+
}),
|
|
259
|
+
}}
|
|
260
|
+
/>
|
|
261
|
+
)
|
|
262
|
+
})}
|
|
155
263
|
</Tabs>
|
|
156
264
|
</Box>
|
|
157
265
|
|
|
158
266
|
{/* Border line */}
|
|
159
|
-
<Box
|
|
267
|
+
<Box
|
|
268
|
+
sx={{
|
|
269
|
+
mt: (theme) => theme.spacing(2),
|
|
270
|
+
borderBottom: 1,
|
|
271
|
+
borderColor: "divider",
|
|
272
|
+
}}
|
|
273
|
+
/>
|
|
160
274
|
|
|
161
275
|
{/* Tab Content */}
|
|
162
276
|
<Box sx={{ flex: 1, overflow: "auto" }}>
|