@matteoaliano/forest-ui 1.2.3 → 1.2.4

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/index.mjs CHANGED
@@ -38,7 +38,7 @@ import {
38
38
  toggleColors,
39
39
  warning,
40
40
  widths
41
- } from "./chunk-NXIZI6F7.mjs";
41
+ } from "./chunk-JYITTRWG.mjs";
42
42
 
43
43
  // src/provider/ForestProvider.tsx
44
44
  import { useMemo } from "react";
@@ -1243,7 +1243,13 @@ function SidebarNav({
1243
1243
  // Match the drawer paper's width animation so the absolutely-
1244
1244
  // positioned toggle (pinned to this box's right edge) glides with the
1245
1245
  // sidebar instead of jumping. Constant in hover mode → no-op there.
1246
- transition: "width 200ms ease-in-out"
1246
+ transition: "width 200ms ease-in-out",
1247
+ // A hover-expanded sidebar has to overlay the content, which in
1248
+ // AppShell sits at drawer + 1. This lives on the wrapper rather than
1249
+ // on `& .MuiDrawer-paper` because a consumer's `sx` replaces that
1250
+ // nested key wholesale (AppShell does). Only while expanded, so the
1251
+ // resting rail still takes the content surface's shadow.
1252
+ ...isHover && open && { zIndex: (theme) => theme.zIndex.drawer + 2 }
1247
1253
  },
1248
1254
  children: [
1249
1255
  /* @__PURE__ */ jsx18(
@@ -1259,8 +1265,7 @@ function SidebarNav({
1259
1265
  width: drawerWidth,
1260
1266
  transition: "width 200ms ease-in-out",
1261
1267
  overflowX: "hidden",
1262
- boxSizing: "border-box",
1263
- ...isHover && { zIndex: (theme) => theme.zIndex.drawer + 2 }
1268
+ boxSizing: "border-box"
1264
1269
  },
1265
1270
  ...sx
1266
1271
  },
@@ -1275,7 +1280,19 @@ function SidebarNav({
1275
1280
  },
1276
1281
  children: [
1277
1282
  header && /* @__PURE__ */ jsx18(Box2, { sx: { flexShrink: 0 }, children: header }),
1278
- /* @__PURE__ */ jsx18(Box2, { sx: { flexGrow: 1, overflowY: "auto", overflowX: "hidden" }, children }),
1283
+ /* @__PURE__ */ jsx18(
1284
+ Box2,
1285
+ {
1286
+ sx: {
1287
+ flexGrow: 1,
1288
+ overflowY: "auto",
1289
+ overflowX: "hidden",
1290
+ px: 1,
1291
+ "& > .MuiList-root": { paddingInline: 0 }
1292
+ },
1293
+ children
1294
+ }
1295
+ ),
1279
1296
  footer && /* @__PURE__ */ jsx18(Box2, { sx: { flexShrink: 0 }, children: footer })
1280
1297
  ]
1281
1298
  }
@@ -1296,7 +1313,11 @@ function SidebarNav({
1296
1313
  top: "50%",
1297
1314
  right: 0,
1298
1315
  transform: "translate(50%, -50%)",
1299
- zIndex: theme.zIndex.drawer + 1,
1316
+ // Above both the AppShell content surface (drawer + 1, which
1317
+ // paints its shadow over the sidebar) and the hover-expanded
1318
+ // drawer (drawer + 2) — the toggle straddles the seam and has
1319
+ // to stay clickable and whole on top of both.
1320
+ zIndex: theme.zIndex.drawer + 3,
1300
1321
  minWidth: 0,
1301
1322
  width: 28,
1302
1323
  height: 28,
@@ -1331,6 +1352,10 @@ function SidebarNav({
1331
1352
  var itemSx = {
1332
1353
  // Preset radius.md (4px) — same corner radius as buttons and inputs.
1333
1354
  borderRadius: "4px",
1355
+ // The MuiListItemButton override sets 12px; 8px here absorbs the container's
1356
+ // new 8px gutter so the icon column stays exactly 16px from the sidebar edge,
1357
+ // where it has always been.
1358
+ paddingInline: "8px",
1334
1359
  // 4px gap between stacked items, independent of the container (List/flex).
1335
1360
  marginBottom: "4px",
1336
1361
  "&:last-of-type": { marginBottom: 0 },
@@ -1458,63 +1483,135 @@ function AppShell({
1458
1483
  )) });
1459
1484
  const brandEl = brand != null ? brand : /* @__PURE__ */ jsx19(ShellBrand, { product, logoVariant });
1460
1485
  const wrapLogomark = !brand && logoVariant === "logomark" && !isMobile;
1461
- return /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", flexDirection: "column", height: "100vh" }, children: [
1462
- /* @__PURE__ */ jsx19(
1463
- default51,
1486
+ return (
1487
+ // Clipping lives here rather than on the body row below, so the content
1488
+ // surface's shadow can spill up over the AppBar instead of being cut off
1489
+ // at the row's top edge.
1490
+ /* @__PURE__ */ jsxs4(
1491
+ Box3,
1464
1492
  {
1465
- position: "sticky",
1466
- elevation: 0,
1467
- sx: { zIndex: theme.zIndex.drawer + 1 },
1468
- children: /* @__PURE__ */ jsxs4(default52, { variant: "dense", sx: { px: { xs: "16px", sm: "16px" } }, children: [
1469
- /* @__PURE__ */ jsxs4(Box3, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-start", gap: 1 }, children: [
1470
- isMobile && /* @__PURE__ */ jsx19(
1471
- IconButton2,
1493
+ sx: {
1494
+ display: "flex",
1495
+ flexDirection: "column",
1496
+ height: "100vh",
1497
+ overflow: "hidden",
1498
+ // The chrome fill belongs here, not only on the AppBar and Drawer.
1499
+ // `main`'s rounded top-left corner clips its own background, and the
1500
+ // notch between that arc and the square box corner is reached by
1501
+ // neither the bar nor the sidebar — so without this, whatever sits
1502
+ // behind the shell shows through it. Storybook's docs container is
1503
+ // white, which is exactly how it surfaced.
1504
+ backgroundColor: "background.default"
1505
+ },
1506
+ children: [
1507
+ /* @__PURE__ */ jsx19(
1508
+ default51,
1509
+ {
1510
+ position: "sticky",
1511
+ elevation: 0,
1512
+ sx: { zIndex: theme.zIndex.drawer + 1, borderBottom: "none" },
1513
+ children: /* @__PURE__ */ jsxs4(default52, { variant: "dense", sx: { px: { xs: "16px", sm: "16px" } }, children: [
1514
+ /* @__PURE__ */ jsxs4(Box3, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-start", gap: 1 }, children: [
1515
+ isMobile && /* @__PURE__ */ jsx19(
1516
+ IconButton2,
1517
+ {
1518
+ variant: "icon",
1519
+ size: "small",
1520
+ color: "inherit",
1521
+ "aria-label": "Open navigation",
1522
+ onClick: () => setMobileOpen(true),
1523
+ children: /* @__PURE__ */ jsx19(MenuOutlined, { fontSize: "small" })
1524
+ }
1525
+ ),
1526
+ wrapLogomark ? /* @__PURE__ */ jsx19(Box3, { sx: { width: 48, ml: "-16px", display: "flex", justifyContent: "center" }, children: brandEl }) : brandEl
1527
+ ] }),
1528
+ /* @__PURE__ */ jsx19(Box3, { sx: { flex: 1, display: "flex", justifyContent: "center" }, children: search === true ? /* @__PURE__ */ jsx19(Search, { size: "small", placeholder: "Search\u2026", sx: { width: "100%", maxWidth: 480 } }) : search || null }),
1529
+ /* @__PURE__ */ jsxs4(Box3, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 1 }, children: [
1530
+ /* @__PURE__ */ jsx19(ColorModeToggle, {}),
1531
+ actions
1532
+ ] })
1533
+ ] })
1534
+ }
1535
+ ),
1536
+ /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", flexGrow: 1, minHeight: 0 }, children: [
1537
+ !isMobile && navContent && /* @__PURE__ */ jsx19(
1538
+ SidebarNav,
1472
1539
  {
1473
- variant: "icon",
1474
- size: "small",
1475
- color: "inherit",
1476
- "aria-label": "Open navigation",
1477
- onClick: () => setMobileOpen(true),
1478
- children: /* @__PURE__ */ jsx19(MenuOutlined, { fontSize: "small" })
1540
+ open: sidebarOpen,
1541
+ onOpenChange: setSidebarOpen,
1542
+ behavior: sidebarBehavior,
1543
+ sx: {
1544
+ height: "100%",
1545
+ "& .MuiDrawer-paper": {
1546
+ position: "relative",
1547
+ height: "100%",
1548
+ // Same reason as the AppBar's border: the chrome is one piece.
1549
+ borderRight: "none"
1550
+ }
1551
+ },
1552
+ children: navContent
1479
1553
  }
1480
1554
  ),
1481
- wrapLogomark ? /* @__PURE__ */ jsx19(Box3, { sx: { width: 48, ml: "-16px", display: "flex", justifyContent: "center" }, children: brandEl }) : brandEl
1555
+ /* @__PURE__ */ jsx19(
1556
+ Box3,
1557
+ {
1558
+ component: "main",
1559
+ sx: (t) => ({
1560
+ flexGrow: 1,
1561
+ overflow: "auto",
1562
+ backgroundColor: "background.paper",
1563
+ // Lift the surface above the chrome so its shadow lands ON the
1564
+ // sidebar and the AppBar rather than under them. Level with the
1565
+ // AppBar and later in the DOM, so it wins there; the hover
1566
+ // sidebar sits a level higher still and keeps overlaying content.
1567
+ position: "relative",
1568
+ zIndex: t.zIndex.drawer + 1,
1569
+ // Longhands, not `borderTop: "1px solid"` — the shorthand resets
1570
+ // border-*-color to currentColor and the hairline renders as text
1571
+ // black however `borderColor` is ordered around it.
1572
+ borderStyle: "solid",
1573
+ borderColor: "divider",
1574
+ borderTopWidth: "1px",
1575
+ borderRightWidth: 0,
1576
+ borderBottomWidth: 0,
1577
+ borderTopLeftRadius: `${container.shellRadius}px`,
1578
+ // With no sidebar below "sm" a single left corner reads lopsided,
1579
+ // so the surface rounds both top corners and drops the left edge.
1580
+ borderLeftWidth: { xs: 0, sm: "1px" },
1581
+ borderTopRightRadius: { xs: `${container.shellRadius}px`, sm: 0 },
1582
+ // Up-and-left, so the lift falls onto the chrome. In dark the
1583
+ // surface is already a step lighter than the chrome and does most
1584
+ // of the lifting itself, so the shadow only has to seat the edge.
1585
+ // Wide and low-contrast rather than tight and dark — a diffuse
1586
+ // falloff reads as lift without drawing a line.
1587
+ boxShadow: "-2px -2px 20px -16px #1018281a, -1px -1px 6px -3px #1018281c",
1588
+ // Dark keeps the same `divider` hairline as light — gray-900 on
1589
+ // gray-950 is only a ~15-level tonal step, so the line still does
1590
+ // the work of defining the edge. Only the shadow changes: one
1591
+ // contact layer, since the surface being lighter than the chrome
1592
+ // already reads as raised.
1593
+ ...t.applyStyles("dark", {
1594
+ boxShadow: "-1px -1px 6px -3px #00000059"
1595
+ })
1596
+ }),
1597
+ children
1598
+ }
1599
+ )
1482
1600
  ] }),
1483
- /* @__PURE__ */ jsx19(Box3, { sx: { flex: 1, display: "flex", justifyContent: "center" }, children: search === true ? /* @__PURE__ */ jsx19(Search, { size: "small", placeholder: "Search\u2026", sx: { width: "100%", maxWidth: 480 } }) : search || null }),
1484
- /* @__PURE__ */ jsxs4(Box3, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 1 }, children: [
1485
- /* @__PURE__ */ jsx19(ColorModeToggle, {}),
1486
- actions
1487
- ] })
1488
- ] })
1489
- }
1490
- ),
1491
- /* @__PURE__ */ jsxs4(Box3, { sx: { display: "flex", flexGrow: 1, overflow: "hidden" }, children: [
1492
- !isMobile && navContent && /* @__PURE__ */ jsx19(
1493
- SidebarNav,
1494
- {
1495
- open: sidebarOpen,
1496
- onOpenChange: setSidebarOpen,
1497
- behavior: sidebarBehavior,
1498
- sx: {
1499
- height: "100%",
1500
- "& .MuiDrawer-paper": { position: "relative", height: "100%" }
1501
- },
1502
- children: navContent
1503
- }
1504
- ),
1505
- /* @__PURE__ */ jsx19(Box3, { component: "main", sx: { flexGrow: 1, overflow: "auto" }, children })
1506
- ] }),
1507
- isMobile && navContent && /* @__PURE__ */ jsx19(
1508
- MuiDrawer3,
1509
- {
1510
- open: mobileOpen,
1511
- onClose: () => setMobileOpen(false),
1512
- onClick: () => setMobileOpen(false),
1513
- sx: { "& .MuiDrawer-paper": { width: 240 } },
1514
- children: navContent
1601
+ isMobile && navContent && /* @__PURE__ */ jsx19(
1602
+ MuiDrawer3,
1603
+ {
1604
+ open: mobileOpen,
1605
+ onClose: () => setMobileOpen(false),
1606
+ onClick: () => setMobileOpen(false),
1607
+ sx: { "& .MuiDrawer-paper": { width: 240 } },
1608
+ children: navContent
1609
+ }
1610
+ )
1611
+ ]
1515
1612
  }
1516
1613
  )
1517
- ] });
1614
+ );
1518
1615
  }
1519
1616
 
1520
1617
  // src/components/Page/index.tsx