@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/{chunk-NXIZI6F7.mjs → chunk-JYITTRWG.mjs} +14 -3
- package/dist/chunk-JYITTRWG.mjs.map +1 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +165 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +153 -56
- package/dist/index.mjs.map +1 -1
- package/dist/theme.d.mts +1 -0
- package/dist/theme.d.ts +1 -0
- package/dist/theme.js +13 -2
- package/dist/theme.js.map +1 -1
- package/dist/theme.mjs +1 -1
- package/package.json +1 -1
- package/skills/forest-alkemy-plus/SKILL.md +1 -1
- package/skills/forest-alkemy-plus/references/components.md +1 -1
- package/skills/forest-alkemy-plus/references/patterns.md +2 -1
- package/dist/chunk-NXIZI6F7.mjs.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -558,6 +558,12 @@ interface AppShellProps {
|
|
|
558
558
|
* sticky AppBar (brand / search / actions + the color-mode toggle) over a
|
|
559
559
|
* SidebarNav and a main content area. Render a <Page> as children.
|
|
560
560
|
*
|
|
561
|
+
* The AppBar and the sidebar read as one continuous L-shaped chrome — they
|
|
562
|
+
* already share `bg.primary`, so the shell drops the borders that used to cut
|
|
563
|
+
* them apart. The main region is then a lifted surface tucked into the corner
|
|
564
|
+
* they form: rounded at the top-left only, flush with the right and bottom
|
|
565
|
+
* window edges.
|
|
566
|
+
*
|
|
561
567
|
* Below the "sm" breakpoint the sidebar becomes a temporary overlay drawer
|
|
562
568
|
* opened by a hamburger button in the AppBar.
|
|
563
569
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1389,7 +1389,13 @@ function buildComponents(tokens2) {
|
|
|
1389
1389
|
borderBottomLeftRadius: radius4.md,
|
|
1390
1390
|
borderBottomRightRadius: radius4.md,
|
|
1391
1391
|
opacity: 0.75,
|
|
1392
|
-
|
|
1392
|
+
// The pressed-in cue is carried by the flattened bevel (bottom
|
|
1393
|
+
// border 4px -> 1px) alone in light mode. On the dark-mode face
|
|
1394
|
+
// that geometry reads too faintly, so it keeps the inner shadow.
|
|
1395
|
+
boxShadow: "none",
|
|
1396
|
+
...theme.applyStyles("dark", {
|
|
1397
|
+
boxShadow: "inset 0 2px 4px 0 rgba(0,0,0,0.3)"
|
|
1398
|
+
}),
|
|
1393
1399
|
"&::before": { display: "none" },
|
|
1394
1400
|
// Stays pressed on hover — no bevel re-raise, no brightness lift.
|
|
1395
1401
|
"&:hover": {
|
|
@@ -3425,7 +3431,12 @@ var display = {
|
|
|
3425
3431
|
var container = {
|
|
3426
3432
|
maxWidthDesktop: 1280,
|
|
3427
3433
|
paddingDesktop: 32,
|
|
3428
|
-
paddingMobile: 16
|
|
3434
|
+
paddingMobile: 16,
|
|
3435
|
+
// Corner radius of the App Shell's content surface where it meets the
|
|
3436
|
+
// chrome. Deliberately a layout value rather than a step on the `radius`
|
|
3437
|
+
// scale: that scale governs components (and the sharper alkemy+ preset caps
|
|
3438
|
+
// it at 12), so a 24 sitting in it would misread as a component radius.
|
|
3439
|
+
shellRadius: 24
|
|
3429
3440
|
};
|
|
3430
3441
|
var widths = {
|
|
3431
3442
|
xxs: 320,
|
|
@@ -5513,7 +5524,13 @@ function SidebarNav({
|
|
|
5513
5524
|
// Match the drawer paper's width animation so the absolutely-
|
|
5514
5525
|
// positioned toggle (pinned to this box's right edge) glides with the
|
|
5515
5526
|
// sidebar instead of jumping. Constant in hover mode → no-op there.
|
|
5516
|
-
transition: "width 200ms ease-in-out"
|
|
5527
|
+
transition: "width 200ms ease-in-out",
|
|
5528
|
+
// A hover-expanded sidebar has to overlay the content, which in
|
|
5529
|
+
// AppShell sits at drawer + 1. This lives on the wrapper rather than
|
|
5530
|
+
// on `& .MuiDrawer-paper` because a consumer's `sx` replaces that
|
|
5531
|
+
// nested key wholesale (AppShell does). Only while expanded, so the
|
|
5532
|
+
// resting rail still takes the content surface's shadow.
|
|
5533
|
+
...isHover && open && { zIndex: (theme) => theme.zIndex.drawer + 2 }
|
|
5517
5534
|
},
|
|
5518
5535
|
children: [
|
|
5519
5536
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
@@ -5529,8 +5546,7 @@ function SidebarNav({
|
|
|
5529
5546
|
width: drawerWidth,
|
|
5530
5547
|
transition: "width 200ms ease-in-out",
|
|
5531
5548
|
overflowX: "hidden",
|
|
5532
|
-
boxSizing: "border-box"
|
|
5533
|
-
...isHover && { zIndex: (theme) => theme.zIndex.drawer + 2 }
|
|
5549
|
+
boxSizing: "border-box"
|
|
5534
5550
|
},
|
|
5535
5551
|
...sx
|
|
5536
5552
|
},
|
|
@@ -5545,7 +5561,19 @@ function SidebarNav({
|
|
|
5545
5561
|
},
|
|
5546
5562
|
children: [
|
|
5547
5563
|
header && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_Box.default, { sx: { flexShrink: 0 }, children: header }),
|
|
5548
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5564
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
5565
|
+
import_Box.default,
|
|
5566
|
+
{
|
|
5567
|
+
sx: {
|
|
5568
|
+
flexGrow: 1,
|
|
5569
|
+
overflowY: "auto",
|
|
5570
|
+
overflowX: "hidden",
|
|
5571
|
+
px: 1,
|
|
5572
|
+
"& > .MuiList-root": { paddingInline: 0 }
|
|
5573
|
+
},
|
|
5574
|
+
children
|
|
5575
|
+
}
|
|
5576
|
+
),
|
|
5549
5577
|
footer && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_Box.default, { sx: { flexShrink: 0 }, children: footer })
|
|
5550
5578
|
]
|
|
5551
5579
|
}
|
|
@@ -5566,7 +5594,11 @@ function SidebarNav({
|
|
|
5566
5594
|
top: "50%",
|
|
5567
5595
|
right: 0,
|
|
5568
5596
|
transform: "translate(50%, -50%)",
|
|
5569
|
-
|
|
5597
|
+
// Above both the AppShell content surface (drawer + 1, which
|
|
5598
|
+
// paints its shadow over the sidebar) and the hover-expanded
|
|
5599
|
+
// drawer (drawer + 2) — the toggle straddles the seam and has
|
|
5600
|
+
// to stay clickable and whole on top of both.
|
|
5601
|
+
zIndex: theme.zIndex.drawer + 3,
|
|
5570
5602
|
minWidth: 0,
|
|
5571
5603
|
width: 28,
|
|
5572
5604
|
height: 28,
|
|
@@ -5601,6 +5633,10 @@ function SidebarNav({
|
|
|
5601
5633
|
var itemSx = {
|
|
5602
5634
|
// Preset radius.md (4px) — same corner radius as buttons and inputs.
|
|
5603
5635
|
borderRadius: "4px",
|
|
5636
|
+
// The MuiListItemButton override sets 12px; 8px here absorbs the container's
|
|
5637
|
+
// new 8px gutter so the icon column stays exactly 16px from the sidebar edge,
|
|
5638
|
+
// where it has always been.
|
|
5639
|
+
paddingInline: "8px",
|
|
5604
5640
|
// 4px gap between stacked items, independent of the container (List/flex).
|
|
5605
5641
|
marginBottom: "4px",
|
|
5606
5642
|
"&:last-of-type": { marginBottom: 0 },
|
|
@@ -5728,63 +5764,135 @@ function AppShell({
|
|
|
5728
5764
|
)) });
|
|
5729
5765
|
const brandEl = brand != null ? brand : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ShellBrand, { product, logoVariant });
|
|
5730
5766
|
const wrapLogomark = !brand && logoVariant === "logomark" && !isMobile;
|
|
5731
|
-
return
|
|
5732
|
-
|
|
5733
|
-
|
|
5767
|
+
return (
|
|
5768
|
+
// Clipping lives here rather than on the body row below, so the content
|
|
5769
|
+
// surface's shadow can spill up over the AppBar instead of being cut off
|
|
5770
|
+
// at the row's top edge.
|
|
5771
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
5772
|
+
import_Box2.default,
|
|
5734
5773
|
{
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5774
|
+
sx: {
|
|
5775
|
+
display: "flex",
|
|
5776
|
+
flexDirection: "column",
|
|
5777
|
+
height: "100vh",
|
|
5778
|
+
overflow: "hidden",
|
|
5779
|
+
// The chrome fill belongs here, not only on the AppBar and Drawer.
|
|
5780
|
+
// `main`'s rounded top-left corner clips its own background, and the
|
|
5781
|
+
// notch between that arc and the square box corner is reached by
|
|
5782
|
+
// neither the bar nor the sidebar — so without this, whatever sits
|
|
5783
|
+
// behind the shell shows through it. Storybook's docs container is
|
|
5784
|
+
// white, which is exactly how it surfaced.
|
|
5785
|
+
backgroundColor: "background.default"
|
|
5786
|
+
},
|
|
5787
|
+
children: [
|
|
5788
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5789
|
+
import_AppBar.default,
|
|
5790
|
+
{
|
|
5791
|
+
position: "sticky",
|
|
5792
|
+
elevation: 0,
|
|
5793
|
+
sx: { zIndex: theme.zIndex.drawer + 1, borderBottom: "none" },
|
|
5794
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Toolbar.default, { variant: "dense", sx: { px: { xs: "16px", sm: "16px" } }, children: [
|
|
5795
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Box2.default, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-start", gap: 1 }, children: [
|
|
5796
|
+
isMobile && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5797
|
+
IconButton2,
|
|
5798
|
+
{
|
|
5799
|
+
variant: "icon",
|
|
5800
|
+
size: "small",
|
|
5801
|
+
color: "inherit",
|
|
5802
|
+
"aria-label": "Open navigation",
|
|
5803
|
+
onClick: () => setMobileOpen(true),
|
|
5804
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_MenuOutlined.default, { fontSize: "small" })
|
|
5805
|
+
}
|
|
5806
|
+
),
|
|
5807
|
+
wrapLogomark ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Box2.default, { sx: { width: 48, ml: "-16px", display: "flex", justifyContent: "center" }, children: brandEl }) : brandEl
|
|
5808
|
+
] }),
|
|
5809
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Box2.default, { sx: { flex: 1, display: "flex", justifyContent: "center" }, children: search === true ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Search, { size: "small", placeholder: "Search\u2026", sx: { width: "100%", maxWidth: 480 } }) : search || null }),
|
|
5810
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Box2.default, { sx: { flex: 1, display: "flex", alignItems: "center", justifyContent: "flex-end", gap: 1 }, children: [
|
|
5811
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(ColorModeToggle, {}),
|
|
5812
|
+
actions
|
|
5813
|
+
] })
|
|
5814
|
+
] })
|
|
5815
|
+
}
|
|
5816
|
+
),
|
|
5817
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_Box2.default, { sx: { display: "flex", flexGrow: 1, minHeight: 0 }, children: [
|
|
5818
|
+
!isMobile && navContent && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5819
|
+
SidebarNav,
|
|
5742
5820
|
{
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5821
|
+
open: sidebarOpen,
|
|
5822
|
+
onOpenChange: setSidebarOpen,
|
|
5823
|
+
behavior: sidebarBehavior,
|
|
5824
|
+
sx: {
|
|
5825
|
+
height: "100%",
|
|
5826
|
+
"& .MuiDrawer-paper": {
|
|
5827
|
+
position: "relative",
|
|
5828
|
+
height: "100%",
|
|
5829
|
+
// Same reason as the AppBar's border: the chrome is one piece.
|
|
5830
|
+
borderRight: "none"
|
|
5831
|
+
}
|
|
5832
|
+
},
|
|
5833
|
+
children: navContent
|
|
5749
5834
|
}
|
|
5750
5835
|
),
|
|
5751
|
-
|
|
5836
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5837
|
+
import_Box2.default,
|
|
5838
|
+
{
|
|
5839
|
+
component: "main",
|
|
5840
|
+
sx: (t) => ({
|
|
5841
|
+
flexGrow: 1,
|
|
5842
|
+
overflow: "auto",
|
|
5843
|
+
backgroundColor: "background.paper",
|
|
5844
|
+
// Lift the surface above the chrome so its shadow lands ON the
|
|
5845
|
+
// sidebar and the AppBar rather than under them. Level with the
|
|
5846
|
+
// AppBar and later in the DOM, so it wins there; the hover
|
|
5847
|
+
// sidebar sits a level higher still and keeps overlaying content.
|
|
5848
|
+
position: "relative",
|
|
5849
|
+
zIndex: t.zIndex.drawer + 1,
|
|
5850
|
+
// Longhands, not `borderTop: "1px solid"` — the shorthand resets
|
|
5851
|
+
// border-*-color to currentColor and the hairline renders as text
|
|
5852
|
+
// black however `borderColor` is ordered around it.
|
|
5853
|
+
borderStyle: "solid",
|
|
5854
|
+
borderColor: "divider",
|
|
5855
|
+
borderTopWidth: "1px",
|
|
5856
|
+
borderRightWidth: 0,
|
|
5857
|
+
borderBottomWidth: 0,
|
|
5858
|
+
borderTopLeftRadius: `${container.shellRadius}px`,
|
|
5859
|
+
// With no sidebar below "sm" a single left corner reads lopsided,
|
|
5860
|
+
// so the surface rounds both top corners and drops the left edge.
|
|
5861
|
+
borderLeftWidth: { xs: 0, sm: "1px" },
|
|
5862
|
+
borderTopRightRadius: { xs: `${container.shellRadius}px`, sm: 0 },
|
|
5863
|
+
// Up-and-left, so the lift falls onto the chrome. In dark the
|
|
5864
|
+
// surface is already a step lighter than the chrome and does most
|
|
5865
|
+
// of the lifting itself, so the shadow only has to seat the edge.
|
|
5866
|
+
// Wide and low-contrast rather than tight and dark — a diffuse
|
|
5867
|
+
// falloff reads as lift without drawing a line.
|
|
5868
|
+
boxShadow: "-2px -2px 20px -16px #1018281a, -1px -1px 6px -3px #1018281c",
|
|
5869
|
+
// Dark keeps the same `divider` hairline as light — gray-900 on
|
|
5870
|
+
// gray-950 is only a ~15-level tonal step, so the line still does
|
|
5871
|
+
// the work of defining the edge. Only the shadow changes: one
|
|
5872
|
+
// contact layer, since the surface being lighter than the chrome
|
|
5873
|
+
// already reads as raised.
|
|
5874
|
+
...t.applyStyles("dark", {
|
|
5875
|
+
boxShadow: "-1px -1px 6px -3px #00000059"
|
|
5876
|
+
})
|
|
5877
|
+
}),
|
|
5878
|
+
children
|
|
5879
|
+
}
|
|
5880
|
+
)
|
|
5752
5881
|
] }),
|
|
5753
|
-
|
|
5754
|
-
|
|
5755
|
-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
|
|
5761
|
-
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
{
|
|
5765
|
-
open: sidebarOpen,
|
|
5766
|
-
onOpenChange: setSidebarOpen,
|
|
5767
|
-
behavior: sidebarBehavior,
|
|
5768
|
-
sx: {
|
|
5769
|
-
height: "100%",
|
|
5770
|
-
"& .MuiDrawer-paper": { position: "relative", height: "100%" }
|
|
5771
|
-
},
|
|
5772
|
-
children: navContent
|
|
5773
|
-
}
|
|
5774
|
-
),
|
|
5775
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_Box2.default, { component: "main", sx: { flexGrow: 1, overflow: "auto" }, children })
|
|
5776
|
-
] }),
|
|
5777
|
-
isMobile && navContent && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5778
|
-
import_Drawer3.default,
|
|
5779
|
-
{
|
|
5780
|
-
open: mobileOpen,
|
|
5781
|
-
onClose: () => setMobileOpen(false),
|
|
5782
|
-
onClick: () => setMobileOpen(false),
|
|
5783
|
-
sx: { "& .MuiDrawer-paper": { width: 240 } },
|
|
5784
|
-
children: navContent
|
|
5882
|
+
isMobile && navContent && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
5883
|
+
import_Drawer3.default,
|
|
5884
|
+
{
|
|
5885
|
+
open: mobileOpen,
|
|
5886
|
+
onClose: () => setMobileOpen(false),
|
|
5887
|
+
onClick: () => setMobileOpen(false),
|
|
5888
|
+
sx: { "& .MuiDrawer-paper": { width: 240 } },
|
|
5889
|
+
children: navContent
|
|
5890
|
+
}
|
|
5891
|
+
)
|
|
5892
|
+
]
|
|
5785
5893
|
}
|
|
5786
5894
|
)
|
|
5787
|
-
|
|
5895
|
+
);
|
|
5788
5896
|
}
|
|
5789
5897
|
|
|
5790
5898
|
// src/components/Page/index.tsx
|