@wandelbots/wandelbots-js-react-components 2.53.0-pr.feature-tabbar-support-badges.398.51d2a73 → 2.53.0-pr.feature-tabbar-support-badges.398.7789539

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wandelbots/wandelbots-js-react-components",
3
- "version": "2.53.0-pr.feature-tabbar-support-badges.398.51d2a73",
3
+ "version": "2.53.0-pr.feature-tabbar-support-badges.398.7789539",
4
4
  "description": "React UI toolkit for building applications on top of the Wandelbots platform",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -124,8 +124,11 @@ export const TabBar = externalizeComponent(
124
124
  px: 0,
125
125
  py: 0,
126
126
  overflow: "visible",
127
- paddingTop: "16px",
128
- paddingRight: "20px",
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
129
132
  }}
130
133
  >
131
134
  <Tabs
@@ -152,83 +155,122 @@ export const TabBar = externalizeComponent(
152
155
  },
153
156
  }}
154
157
  >
155
- {items.map((item, index) => (
156
- <Tab
157
- key={item.id}
158
- label={item.label}
159
- icon={item.icon}
160
- iconPosition="start"
161
- disableRipple
162
- sx={{
163
- minHeight: "32px",
164
- height: "32px",
165
- padding: "0px 10px",
166
- borderRadius: "12px",
167
- backgroundColor: (theme) =>
168
- theme.palette.backgroundPaperElevation?.[11] || "#32344B",
169
- color: "text.primary",
170
- opacity: currentValue === index ? 1 : 0.38,
171
- fontSize: "13px",
172
- transition: "all 0.2s ease-in-out",
173
- position: "relative",
174
- "&:hover": {
175
- opacity: currentValue === index ? 1 : 0.6,
176
- },
177
- "&.Mui-selected": {
178
- opacity: 1,
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",
179
199
  backgroundColor: (theme) =>
180
200
  theme.palette.backgroundPaperElevation?.[11] || "#32344B",
181
201
  color: "text.primary",
182
- },
183
- "&:focus": {
184
- outline: "none",
185
- },
186
- "&:active": {
187
- transform: "none",
188
- },
189
- ...(item.badge && {
190
- "&::after": {
191
- content: `"${item.badge.content}"`,
192
- position: "absolute",
193
- top: -6,
194
- right: -8,
195
- minWidth: "20px",
196
- height: "20px",
197
- borderRadius: "10px",
198
- backgroundColor: (theme) => {
199
- const colors = {
200
- error: theme.palette.error.main,
201
- info: theme.palette.info.main,
202
- success: theme.palette.success.main,
203
- warning: theme.palette.warning.main,
204
- primary: theme.palette.primary.main,
205
- secondary: theme.palette.secondary.main,
206
- default: theme.palette.grey[500],
207
- }
208
- return (
209
- colors[item.badge?.color || "error"] || colors.error
210
- )
211
- },
212
- color: "white",
213
- fontSize: "12px",
214
- fontWeight: 600,
215
- display: "flex",
216
- alignItems: "center",
217
- justifyContent: "center",
218
- padding: "2px 6px",
219
- zIndex: 1,
220
- pointerEvents: "none",
221
- boxShadow: "0 2px 4px rgba(0,0,0,0.2)",
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,
222
208
  },
223
- }),
224
- }}
225
- />
226
- ))}
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
+ })}
227
263
  </Tabs>
228
264
  </Box>
229
265
 
230
266
  {/* Border line */}
231
- <Box sx={{ mt: "16px", borderBottom: 1, borderColor: "divider" }} />
267
+ <Box
268
+ sx={{
269
+ mt: (theme) => theme.spacing(2),
270
+ borderBottom: 1,
271
+ borderColor: "divider",
272
+ }}
273
+ />
232
274
 
233
275
  {/* Tab Content */}
234
276
  <Box sx={{ flex: 1, overflow: "auto" }}>