@womp/kookie-ui 0.32.0 → 0.34.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/components.css +288 -35
- package/dist/cjs/components/_internal/pane-chrome.js +1 -1
- package/dist/cjs/components/_internal/pane-chrome.js.map +2 -2
- package/dist/cjs/components/_internal/shell-bottom.d.ts +7 -2
- package/dist/cjs/components/_internal/shell-bottom.d.ts.map +1 -1
- package/dist/cjs/components/_internal/shell-bottom.js +1 -1
- package/dist/cjs/components/_internal/shell-bottom.js.map +3 -3
- package/dist/cjs/components/_internal/shell-inspector.d.ts +7 -2
- package/dist/cjs/components/_internal/shell-inspector.d.ts.map +1 -1
- package/dist/cjs/components/_internal/shell-inspector.js +1 -1
- package/dist/cjs/components/_internal/shell-inspector.js.map +3 -3
- package/dist/cjs/components/_internal/shell-pane.js +1 -1
- package/dist/cjs/components/_internal/shell-pane.js.map +2 -2
- package/dist/cjs/components/_internal/shell-sidebar.d.ts +7 -2
- package/dist/cjs/components/_internal/shell-sidebar.d.ts.map +1 -1
- package/dist/cjs/components/_internal/shell-sidebar.js +1 -1
- package/dist/cjs/components/_internal/shell-sidebar.js.map +3 -3
- package/dist/cjs/components/_internal/shell-store.d.ts +6 -6
- package/dist/cjs/components/_internal/shell-store.d.ts.map +1 -1
- package/dist/cjs/components/_internal/shell-store.js +1 -1
- package/dist/cjs/components/_internal/shell-store.js.map +3 -3
- package/dist/cjs/components/command.d.ts +133 -0
- package/dist/cjs/components/command.d.ts.map +1 -0
- package/dist/cjs/components/command.js +3 -0
- package/dist/cjs/components/command.js.map +7 -0
- package/dist/cjs/components/index.d.ts +1 -0
- package/dist/cjs/components/index.d.ts.map +1 -1
- package/dist/cjs/components/index.js +2 -2
- package/dist/cjs/components/index.js.map +4 -4
- package/dist/cjs/components/navigator.js +1 -1
- package/dist/cjs/components/navigator.js.map +2 -2
- package/dist/cjs/components/shell.context.js +1 -1
- package/dist/cjs/components/shell.context.js.map +2 -2
- package/dist/cjs/components/shell.d.ts +25 -7
- package/dist/cjs/components/shell.d.ts.map +1 -1
- package/dist/cjs/components/shell.hooks.js +1 -1
- package/dist/cjs/components/shell.hooks.js.map +2 -2
- package/dist/cjs/components/shell.js +1 -1
- package/dist/cjs/components/shell.js.map +3 -3
- package/dist/cjs/components/toolbar.js +1 -1
- package/dist/cjs/components/toolbar.js.map +2 -2
- package/dist/cjs/index.js +5 -5
- package/dist/cjs/index.js.map +4 -4
- package/dist/esm/chunk-5BXCPANF.js +3 -0
- package/dist/esm/{chunk-GHWEXMF6.js.map → chunk-5BXCPANF.js.map} +3 -3
- package/dist/esm/{chunk-K35JUIUT.js → chunk-API4DAPY.js} +2 -2
- package/dist/esm/{chunk-ZG2XQUOH.js → chunk-B447PNRD.js} +2 -2
- package/dist/esm/{chunk-QDAM2I6O.js → chunk-BR6Z2CAE.js} +2 -2
- package/dist/esm/{chunk-W35ZKQMQ.js → chunk-CAM66IXC.js} +2 -2
- package/dist/esm/chunk-GZPB6MRQ.js +3 -0
- package/dist/esm/chunk-GZPB6MRQ.js.map +7 -0
- package/dist/esm/{chunk-4G3FJUER.js → chunk-INGT6DB6.js} +2 -2
- package/dist/esm/{chunk-4ZHBNYXM.js → chunk-J6B7UCZN.js} +2 -2
- package/dist/esm/chunk-KDJM4NQQ.js +3 -0
- package/dist/esm/chunk-KDJM4NQQ.js.map +7 -0
- package/dist/esm/{chunk-LTUW36HM.js → chunk-KGCGT4MJ.js} +2 -2
- package/dist/esm/chunk-NO2JCJWI.js +3 -0
- package/dist/esm/chunk-NO2JCJWI.js.map +7 -0
- package/dist/esm/{chunk-6WHKGVWY.js → chunk-NZJRXZYX.js} +2 -2
- package/dist/esm/{chunk-NFSW36RG.js → chunk-ODHCDJ3Y.js} +2 -2
- package/dist/esm/chunk-SHKPQ3RI.js +2 -0
- package/dist/esm/chunk-UMQOTGJC.js +3 -0
- package/dist/esm/chunk-UMQOTGJC.js.map +7 -0
- package/dist/esm/chunk-XD676L6S.js +3 -0
- package/dist/esm/chunk-XD676L6S.js.map +7 -0
- package/dist/esm/{chunk-6SGJWML7.js → chunk-XKYPJTRN.js} +2 -2
- package/dist/esm/components/_internal/pane-chrome.js +1 -1
- package/dist/esm/components/_internal/shell-bottom.d.ts +7 -2
- package/dist/esm/components/_internal/shell-bottom.d.ts.map +1 -1
- package/dist/esm/components/_internal/shell-bottom.js +1 -1
- package/dist/esm/components/_internal/shell-inspector.d.ts +7 -2
- package/dist/esm/components/_internal/shell-inspector.d.ts.map +1 -1
- package/dist/esm/components/_internal/shell-inspector.js +1 -1
- package/dist/esm/components/_internal/shell-pane.js +1 -1
- package/dist/esm/components/_internal/shell-sidebar.d.ts +7 -2
- package/dist/esm/components/_internal/shell-sidebar.d.ts.map +1 -1
- package/dist/esm/components/_internal/shell-sidebar.js +1 -1
- package/dist/esm/components/_internal/shell-store.d.ts +6 -6
- package/dist/esm/components/_internal/shell-store.d.ts.map +1 -1
- package/dist/esm/components/_internal/shell-store.js +1 -1
- package/dist/esm/components/alert-dialog.js +1 -1
- package/dist/esm/components/command.d.ts +133 -0
- package/dist/esm/components/command.d.ts.map +1 -0
- package/dist/esm/components/command.js +3 -0
- package/dist/esm/components/command.js.map +7 -0
- package/dist/esm/components/dialog.js +1 -1
- package/dist/esm/components/index.d.ts +1 -0
- package/dist/esm/components/index.d.ts.map +1 -1
- package/dist/esm/components/index.js +1 -1
- package/dist/esm/components/navigator.js +1 -1
- package/dist/esm/components/sheet.js +1 -1
- package/dist/esm/components/shell.context.js +1 -1
- package/dist/esm/components/shell.d.ts +25 -7
- package/dist/esm/components/shell.d.ts.map +1 -1
- package/dist/esm/components/shell.hooks.js +1 -1
- package/dist/esm/components/shell.js +1 -1
- package/dist/esm/components/sidebar.js +1 -1
- package/dist/esm/components/toolbar.js +1 -1
- package/dist/esm/hooks/index.js +1 -1
- package/dist/esm/index.js +1 -1
- package/package.json +1 -1
- package/src/components/_internal/shell-bottom.tsx +11 -6
- package/src/components/_internal/shell-inspector.tsx +11 -6
- package/src/components/_internal/shell-sidebar.tsx +11 -6
- package/src/components/_internal/shell-store.tsx +13 -13
- package/src/components/command.css +197 -0
- package/src/components/command.tsx +432 -0
- package/src/components/index.css +1 -0
- package/src/components/index.tsx +24 -0
- package/src/components/shell.css +133 -47
- package/src/components/shell.tsx +50 -32
- package/src/styles/tokens/color.css +2 -0
- package/styles.css +289 -35
- package/tokens/base.css +1 -0
- package/tokens.css +1 -0
- package/dist/esm/chunk-4B3S2DM7.js +0 -3
- package/dist/esm/chunk-4B3S2DM7.js.map +0 -7
- package/dist/esm/chunk-AKMRPGNP.js +0 -3
- package/dist/esm/chunk-AKMRPGNP.js.map +0 -7
- package/dist/esm/chunk-GHWEXMF6.js +0 -3
- package/dist/esm/chunk-RSG4XWHU.js +0 -2
- package/dist/esm/chunk-ZBSGH74F.js +0 -3
- package/dist/esm/chunk-ZBSGH74F.js.map +0 -7
- package/dist/esm/chunk-ZHXEEOGI.js +0 -3
- package/dist/esm/chunk-ZHXEEOGI.js.map +0 -7
- /package/dist/esm/{chunk-K35JUIUT.js.map → chunk-API4DAPY.js.map} +0 -0
- /package/dist/esm/{chunk-ZG2XQUOH.js.map → chunk-B447PNRD.js.map} +0 -0
- /package/dist/esm/{chunk-QDAM2I6O.js.map → chunk-BR6Z2CAE.js.map} +0 -0
- /package/dist/esm/{chunk-W35ZKQMQ.js.map → chunk-CAM66IXC.js.map} +0 -0
- /package/dist/esm/{chunk-4G3FJUER.js.map → chunk-INGT6DB6.js.map} +0 -0
- /package/dist/esm/{chunk-4ZHBNYXM.js.map → chunk-J6B7UCZN.js.map} +0 -0
- /package/dist/esm/{chunk-LTUW36HM.js.map → chunk-KGCGT4MJ.js.map} +0 -0
- /package/dist/esm/{chunk-6WHKGVWY.js.map → chunk-NZJRXZYX.js.map} +0 -0
- /package/dist/esm/{chunk-NFSW36RG.js.map → chunk-ODHCDJ3Y.js.map} +0 -0
- /package/dist/esm/{chunk-RSG4XWHU.js.map → chunk-SHKPQ3RI.js.map} +0 -0
- /package/dist/esm/{chunk-6SGJWML7.js.map → chunk-XKYPJTRN.js.map} +0 -0
package/src/components/shell.css
CHANGED
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
/* ── Frame ─────────────────────────────────────────────────────────────────── */
|
|
27
27
|
|
|
28
28
|
.kui-ShellRoot {
|
|
29
|
-
/*
|
|
30
|
-
--shell-
|
|
29
|
+
/* The air around a pane pulled off the frame (`flush={false}`). Declared here, so the documented override on the Root works. */
|
|
30
|
+
--shell-gap: var(--space-3);
|
|
31
31
|
/* Written inline by the Root while a Rail shows; stated here so a nested Shell never inherits its parent's. */
|
|
32
32
|
--shell-rail-offset: 0px;
|
|
33
33
|
/* How far the stuck header reaches down the screen while the page scrolls. Stated here so a nested Shell never inherits its parent's. */
|
|
@@ -938,68 +938,154 @@
|
|
|
938
938
|
position: fixed;
|
|
939
939
|
}
|
|
940
940
|
|
|
941
|
-
/* ──
|
|
941
|
+
/* ── Flush and off the frame (from v2, 0.33.0) ─────────────────────────────── */
|
|
942
942
|
|
|
943
943
|
/*
|
|
944
|
-
*
|
|
945
|
-
*
|
|
946
|
-
*
|
|
947
|
-
*
|
|
944
|
+
* Every pane says one thing about itself: whether it joins the app frame (`flush`, the default)
|
|
945
|
+
* or is pulled off it as a card (`flush={false}`). Whether a card floats or sits on the Shell's
|
|
946
|
+
* background is not stated anywhere; it falls out of the content's own answer, here, so it is
|
|
947
|
+
* right at first paint:
|
|
948
|
+
*
|
|
949
|
+
* - A flush pane is level with the page: square, no fill, no shadow, and one hairline in
|
|
950
|
+
* `--color-border` on its inner edge. Each seam is drawn by exactly one pane, and the content
|
|
951
|
+
* draws none, so two neighbours never double a line.
|
|
952
|
+
* - With the content flush, a card floats over it: the content's grid area grows underneath.
|
|
953
|
+
* - With the content off the frame, nothing floats. The Shell paints its background and every
|
|
954
|
+
* pane, flush or not, sits on it; the content is a card, and a flush pane draws no hairline
|
|
955
|
+
* toward it, because a line beside a card's own edge is a second boundary.
|
|
948
956
|
*/
|
|
949
|
-
|
|
950
|
-
.kui-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
957
|
+
|
|
958
|
+
.kui-ShellHeader[data-flush],
|
|
959
|
+
.kui-ShellPane[data-flush],
|
|
960
|
+
.kui-ShellContent[data-flush] {
|
|
961
|
+
border: 0 solid var(--color-border);
|
|
962
|
+
border-radius: 0;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
.kui-ShellHeader[data-flush] {
|
|
966
|
+
border-block-end-width: 1px;
|
|
967
|
+
}
|
|
968
|
+
|
|
969
|
+
.kui-ShellRail[data-flush],
|
|
970
|
+
.kui-ShellPanel[data-flush],
|
|
971
|
+
.kui-ShellSidebar[data-flush] {
|
|
972
|
+
border-inline-end-width: 1px;
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
.kui-ShellInspector[data-flush] {
|
|
976
|
+
border-inline-start-width: 1px;
|
|
955
977
|
}
|
|
956
978
|
|
|
957
|
-
.kui-
|
|
958
|
-
|
|
959
|
-
|
|
979
|
+
.kui-ShellBottom[data-flush] {
|
|
980
|
+
border-block-start-width: 1px;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/* A seam needs something on the other side. Against a card content there is only the gap. The
|
|
984
|
+
Panel and the Rail face the content only when no flush pane stands between them. */
|
|
985
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) > .kui-ShellHeader[data-flush] {
|
|
986
|
+
border-block-end-width: 0;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) > .kui-ShellSidebar[data-flush],
|
|
990
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])):not(:has(> .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellPanel[data-flush],
|
|
991
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])):not(:has(> .kui-ShellPanel[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']), > .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellRail[data-flush] {
|
|
992
|
+
border-inline-end-width: 0;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) > .kui-ShellInspector[data-flush] {
|
|
996
|
+
border-inline-start-width: 0;
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) > .kui-ShellBottom[data-flush] {
|
|
1000
|
+
border-block-start-width: 0;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
/* Off the frame: a card, with its own air on every side. */
|
|
1004
|
+
.kui-ShellHeader:not([data-flush]),
|
|
1005
|
+
.kui-ShellPane:not([data-flush]),
|
|
1006
|
+
.kui-ShellContent:not([data-flush]) {
|
|
1007
|
+
margin: var(--shell-gap);
|
|
960
1008
|
border-radius: var(--radius-surface-1);
|
|
961
|
-
background: var(--color-page);
|
|
1009
|
+
background-color: var(--color-page);
|
|
962
1010
|
box-shadow: var(--surface-chrome);
|
|
963
1011
|
}
|
|
964
1012
|
|
|
1013
|
+
/* A header card rests level with the panes below it, so its shadow falls behind them, not on them. */
|
|
1014
|
+
.kui-ShellHeader:not([data-flush]) {
|
|
1015
|
+
z-index: 1;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/* With the content off the frame, the Shell paints the background the cards sit on. */
|
|
1019
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) {
|
|
1020
|
+
background-color: var(--neutral-2);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
965
1023
|
/*
|
|
966
|
-
* Two
|
|
967
|
-
*
|
|
968
|
-
*
|
|
969
|
-
* the frame (the JS mirror's data-presentation and data-mode), so a closed,
|
|
970
|
-
* hidden or floating pane never takes the gap away. Before hydration the
|
|
971
|
-
* gap is doubled.
|
|
1024
|
+
* Two cards side by side share one gap rather than doubling it: the later card in the row drops
|
|
1025
|
+
* its margin on the side that meets the earlier one, so card to card and card to edge come out
|
|
1026
|
+
* equal. Only a pane shown in the frame counts.
|
|
972
1027
|
*/
|
|
973
|
-
.kui-ShellRoot:has(> .kui-ShellRail[data-
|
|
974
|
-
.kui-ShellRoot:has(> .kui-ShellPanel[data-
|
|
975
|
-
.kui-ShellRoot:has(> .kui-ShellRail[data-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
.kui-ShellRoot:has(> .kui-
|
|
980
|
-
.kui-ShellRoot:has(> .kui-ShellPanel[data-inset][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(
|
|
981
|
-
:has(> .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))
|
|
982
|
-
)
|
|
983
|
-
> .kui-ShellContent[data-inset],
|
|
984
|
-
.kui-ShellRoot:has(> .kui-ShellRail[data-inset][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(
|
|
985
|
-
:has(> .kui-ShellPanel[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']), > .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))
|
|
986
|
-
)
|
|
987
|
-
> .kui-ShellContent[data-inset],
|
|
988
|
-
.kui-ShellRoot:has(> .kui-ShellContent[data-inset]) > .kui-ShellInspector[data-inset][data-presentation='fixed'] {
|
|
1028
|
+
.kui-ShellRoot:has(> .kui-ShellRail:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellPanel:not([data-flush])[data-presentation='fixed'],
|
|
1029
|
+
.kui-ShellRoot:has(> .kui-ShellPanel:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellSidebar:not([data-flush])[data-presentation='fixed'],
|
|
1030
|
+
.kui-ShellRoot:has(> .kui-ShellRail:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(:has(> .kui-ShellPanel[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellSidebar:not([data-flush])[data-presentation='fixed'],
|
|
1031
|
+
.kui-ShellRoot:has(> .kui-ShellSidebar:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellContent:not([data-flush]),
|
|
1032
|
+
.kui-ShellRoot:has(> .kui-ShellPanel:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(:has(> .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellContent:not([data-flush]),
|
|
1033
|
+
.kui-ShellRoot:has(> .kui-ShellRail:not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(:has(> .kui-ShellPanel[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']), > .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellContent:not([data-flush]),
|
|
1034
|
+
.kui-ShellRoot:has(> .kui-ShellContent:not([data-flush])) > .kui-ShellInspector:not([data-flush])[data-presentation='fixed'] {
|
|
989
1035
|
margin-inline-start: 0;
|
|
990
1036
|
}
|
|
991
1037
|
|
|
992
|
-
.kui-ShellRoot:has(
|
|
993
|
-
|
|
994
|
-
> .kui-ShellPanel[data-inset][data-presentation='fixed'][data-mode]:not([data-mode='collapsed']),
|
|
995
|
-
> .kui-ShellSidebar[data-inset][data-presentation='fixed'][data-mode]:not([data-mode='collapsed']),
|
|
996
|
-
> .kui-ShellContent[data-inset],
|
|
997
|
-
> .kui-ShellInspector[data-inset][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])
|
|
998
|
-
)
|
|
999
|
-
> .kui-ShellBottom[data-inset] {
|
|
1038
|
+
.kui-ShellRoot:has(> .kui-ShellHeader:not([data-flush])) > :is(.kui-ShellPane:not(.kui-ShellBottom), .kui-ShellContent):not([data-flush]),
|
|
1039
|
+
.kui-ShellRoot:has(> :is(.kui-ShellRail, .kui-ShellPanel, .kui-ShellSidebar, .kui-ShellInspector):not([data-flush])[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']), > .kui-ShellContent:not([data-flush])) > .kui-ShellBottom:not([data-flush]) {
|
|
1000
1040
|
margin-block-start: 0;
|
|
1001
1041
|
}
|
|
1002
1042
|
|
|
1043
|
+
/* A card content pays no air toward a flush side pane in the frame: the pane's padding is the
|
|
1044
|
+
air. Toward a flush header it keeps its gap, since a header's row has no padding below it. */
|
|
1045
|
+
.kui-ShellRoot:has(> .kui-ShellSidebar[data-flush][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellContent:not([data-flush]),
|
|
1046
|
+
.kui-ShellRoot:has(> .kui-ShellPanel[data-flush][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(:has(> .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellContent:not([data-flush]),
|
|
1047
|
+
.kui-ShellRoot:has(> .kui-ShellRail[data-flush][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])):not(:has(> .kui-ShellPanel[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']), > .kui-ShellSidebar[data-presentation='fixed'][data-mode]:not([data-mode='collapsed']))) > .kui-ShellContent:not([data-flush]) {
|
|
1048
|
+
margin-inline-start: 0;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.kui-ShellRoot:has(> .kui-ShellInspector[data-flush][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellContent:not([data-flush]) {
|
|
1052
|
+
margin-inline-end: 0;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
.kui-ShellRoot:has(> .kui-ShellBottom[data-flush][data-presentation='fixed'][data-mode]:not([data-mode='collapsed'])) > .kui-ShellContent:not([data-flush]) {
|
|
1056
|
+
margin-block-end: 0;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/*
|
|
1060
|
+
* Floating: with the content flush, a card is over it, and the content's grid area grows to the
|
|
1061
|
+
* card's own line so the content runs underneath. It grows only on the sides something floats
|
|
1062
|
+
* on. The Rail and the Panel float over the content only when no flush pane stands between.
|
|
1063
|
+
* The panes already sit above the content (`z-index` 1 against the content's isolated layer).
|
|
1064
|
+
*/
|
|
1065
|
+
.kui-ShellRoot:has(> .kui-ShellSidebar:not([data-flush])) > .kui-ShellContent[data-flush] {
|
|
1066
|
+
grid-column-start: sidebar-start;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
.kui-ShellRoot:has(> .kui-ShellPanel:not([data-flush])):not(:has(> .kui-ShellSidebar[data-flush])) > .kui-ShellContent[data-flush] {
|
|
1070
|
+
grid-column-start: panel-start;
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
.kui-ShellRoot:has(> .kui-ShellRail:not([data-flush])):not(:has(> .kui-ShellPanel[data-flush], > .kui-ShellSidebar[data-flush])) > .kui-ShellContent[data-flush] {
|
|
1074
|
+
grid-column-start: rail-start;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.kui-ShellRoot:has(> .kui-ShellInspector:not([data-flush])) > .kui-ShellContent[data-flush] {
|
|
1078
|
+
grid-column-end: inspector-end;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
.kui-ShellRoot:has(> .kui-ShellHeader:not([data-flush])) > .kui-ShellContent[data-flush] {
|
|
1082
|
+
grid-row-start: header-start;
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
.kui-ShellRoot:has(> .kui-ShellBottom:not([data-flush])) > .kui-ShellContent[data-flush] {
|
|
1086
|
+
grid-row-end: bottom-end;
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1003
1089
|
/* ── On a phone, the page scrolls (0.27.0) ────────────────────────────────── */
|
|
1004
1090
|
|
|
1005
1091
|
/*
|
package/src/components/shell.tsx
CHANGED
|
@@ -36,16 +36,16 @@ import { usePane, paneAttributes, usePresentationTable } from './_internal/shell
|
|
|
36
36
|
import { splitHandles, useInitialPaneSize, useResizablePane } from './_internal/shell-resizable.js';
|
|
37
37
|
import {
|
|
38
38
|
FIXED_TABLE,
|
|
39
|
-
|
|
39
|
+
ShellFrameContext,
|
|
40
40
|
ShellStoreContext,
|
|
41
41
|
createShellStore,
|
|
42
42
|
setShellPeek,
|
|
43
43
|
subscribeShellStore,
|
|
44
|
-
|
|
44
|
+
useFrameRegistration,
|
|
45
45
|
usePaneEntry,
|
|
46
46
|
useShellStore,
|
|
47
47
|
warnOnce,
|
|
48
|
-
type
|
|
48
|
+
type FramePaneId,
|
|
49
49
|
} from './_internal/shell-store.js';
|
|
50
50
|
import { navigationRest, detailRest, toPaneValue, startAnchoredGrowth, withoutRemovedPaneProps } from './_internal/shell-rest.js';
|
|
51
51
|
import { useShell, useSidebarMode } from './shell.context.js';
|
|
@@ -145,20 +145,20 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
|
|
|
145
145
|
const rootRef = React.useRef<HTMLDivElement | null>(null);
|
|
146
146
|
const composedRef = useComposedRefs(ref, rootRef);
|
|
147
147
|
|
|
148
|
-
//
|
|
149
|
-
const [
|
|
150
|
-
const
|
|
151
|
-
|
|
148
|
+
// The panes pulled off the frame (`flush={false}`). Only the Rail's is read, for the offset below.
|
|
149
|
+
const [offFrame, setOffFrame] = React.useState<ReadonlySet<FramePaneId>>(() => new Set());
|
|
150
|
+
const registerOffFrame = React.useCallback((id: FramePaneId) => {
|
|
151
|
+
setOffFrame((prev) => (prev.has(id) ? prev : new Set(prev).add(id)));
|
|
152
152
|
}, []);
|
|
153
|
-
const
|
|
154
|
-
|
|
153
|
+
const unregisterOffFrame = React.useCallback((id: FramePaneId) => {
|
|
154
|
+
setOffFrame((prev) => {
|
|
155
155
|
if (!prev.has(id)) return prev;
|
|
156
156
|
const next = new Set(prev);
|
|
157
157
|
next.delete(id);
|
|
158
158
|
return next;
|
|
159
159
|
});
|
|
160
160
|
}, []);
|
|
161
|
-
const
|
|
161
|
+
const frameContext = React.useMemo(() => ({ registerOffFrame, unregisterOffFrame }), [registerOffFrame, unregisterOffFrame]);
|
|
162
162
|
|
|
163
163
|
const closeOverlays = React.useCallback(() => {
|
|
164
164
|
for (const entry of store.entries.values()) {
|
|
@@ -444,10 +444,10 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
|
|
|
444
444
|
};
|
|
445
445
|
|
|
446
446
|
// A floating Panel sits beside the Rail when the Rail is showing, and
|
|
447
|
-
// beside its card when the Rail is
|
|
447
|
+
// beside its card when the Rail is off the frame.
|
|
448
448
|
const rail = store.entries.get('rail');
|
|
449
449
|
const railShown = rail !== undefined && rail.value !== undefined && rail.value !== 'closed';
|
|
450
|
-
const railOffset = railShown ? (
|
|
450
|
+
const railOffset = railShown ? (offFrame.has('rail') ? `calc(${rail.size}px + 2 * var(--shell-gap))` : `${rail.size}px`) : undefined;
|
|
451
451
|
|
|
452
452
|
// `full` writes no inline height: the stylesheet states it as 100vh with a
|
|
453
453
|
// 100dvh override where supported, and an inline value would beat both.
|
|
@@ -459,7 +459,7 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
|
|
|
459
459
|
<ShellContentContext.Provider value={false}>
|
|
460
460
|
<ShellWindowContext.Provider value={windowShell}>
|
|
461
461
|
<ShellHeaderHeightContext.Provider value={setHeaderHeight}>
|
|
462
|
-
<
|
|
462
|
+
<ShellFrameContext.Provider value={frameContext}>
|
|
463
463
|
{/* A Shell inside a portalled surface's Theme starts with no band, like any other. */}
|
|
464
464
|
<PaneBandSizeContext.Provider value={undefined}>
|
|
465
465
|
{/* The Root is not a widget: it hears Escape bubbling up from the panes,
|
|
@@ -472,7 +472,6 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
|
|
|
472
472
|
data-height={height === 'auto' && !contained ? 'auto' : undefined}
|
|
473
473
|
data-contained={contained || undefined}
|
|
474
474
|
data-window={windowShell || undefined}
|
|
475
|
-
data-has-inset={insetPanes.size > 0 || undefined}
|
|
476
475
|
data-overlay-live={liveCount > 0 || undefined}
|
|
477
476
|
onKeyDown={handleKeyDown}
|
|
478
477
|
onFocus={handleFocus}
|
|
@@ -490,7 +489,7 @@ const Root = React.forwardRef<HTMLDivElement, ShellRootProps>(({ className, chil
|
|
|
490
489
|
<div className="kui-ShellScrim" aria-hidden onClick={closeOverlays} />
|
|
491
490
|
</div>
|
|
492
491
|
</PaneBandSizeContext.Provider>
|
|
493
|
-
</
|
|
492
|
+
</ShellFrameContext.Provider>
|
|
494
493
|
</ShellHeaderHeightContext.Provider>
|
|
495
494
|
</ShellWindowContext.Provider>
|
|
496
495
|
</ShellContentContext.Provider>
|
|
@@ -504,9 +503,14 @@ Root.displayName = 'Shell.Root';
|
|
|
504
503
|
|
|
505
504
|
interface ShellHeaderProps extends React.ComponentPropsWithoutRef<'header'> {
|
|
506
505
|
height?: number;
|
|
506
|
+
/**
|
|
507
|
+
* Sets whether the header joins the app frame. The default is `true`: a hairline under it. Set
|
|
508
|
+
* `flush={false}` to make it a card off the frame.
|
|
509
|
+
*/
|
|
510
|
+
flush?: boolean;
|
|
507
511
|
}
|
|
508
512
|
|
|
509
|
-
const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, height = DEFAULT_HEADER_HEIGHT, style, ...props }, ref) => {
|
|
513
|
+
const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, height = DEFAULT_HEADER_HEIGHT, flush = true, style, ...props }, ref) => {
|
|
510
514
|
// Rows that stick beneath the header while the page scrolls need its height. The stylesheet
|
|
511
515
|
// assumes the default, so only another height is told to the Root.
|
|
512
516
|
const setHeaderHeight = React.useContext(ShellHeaderHeightContext);
|
|
@@ -520,6 +524,7 @@ const Header = React.forwardRef<HTMLElement, ShellHeaderProps>(({ className, hei
|
|
|
520
524
|
{...props}
|
|
521
525
|
ref={ref}
|
|
522
526
|
className={classNames('kui-ShellHeader', className)}
|
|
527
|
+
data-flush={flush || undefined}
|
|
523
528
|
style={
|
|
524
529
|
{
|
|
525
530
|
...style,
|
|
@@ -541,7 +546,6 @@ interface LeftProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
|
541
546
|
collapsible?: boolean;
|
|
542
547
|
onExpand?: () => void;
|
|
543
548
|
onCollapse?: () => void;
|
|
544
|
-
inset?: boolean;
|
|
545
549
|
}
|
|
546
550
|
|
|
547
551
|
/**
|
|
@@ -572,14 +576,19 @@ type RailProps = React.ComponentPropsWithoutRef<'div'> & {
|
|
|
572
576
|
onExpand?: () => void;
|
|
573
577
|
/** @deprecated Use `onOpenChange`. */
|
|
574
578
|
onCollapse?: () => void;
|
|
575
|
-
/**
|
|
576
|
-
|
|
579
|
+
/**
|
|
580
|
+
* Sets whether this pane joins the app frame. The default is `true`: the pane sits against its
|
|
581
|
+
* neighbours with one hairline between them. Set `flush={false}` to pull it off the frame as a
|
|
582
|
+
* card. It then floats over the content if the content is flush, and otherwise sits on the
|
|
583
|
+
* Shell's background beside a card content.
|
|
584
|
+
*/
|
|
585
|
+
flush?: boolean;
|
|
577
586
|
} & (RailControlledProps | RailUncontrolledProps);
|
|
578
587
|
|
|
579
588
|
const RAIL_PROP_NAMES = { controlled: 'open', default: 'defaultOpen' };
|
|
580
589
|
|
|
581
590
|
const Rail = React.forwardRef<HTMLDivElement, RailProps>((props, ref) => {
|
|
582
|
-
const { className, presentation, expandedSize = 64, collapsible: _collapsible, onExpand, onCollapse, children, style, open, defaultOpen, onOpenChange,
|
|
591
|
+
const { className, presentation, expandedSize = 64, collapsible: _collapsible, onExpand, onCollapse, children, style, open, defaultOpen, onOpenChange, flush = true, id, ...domProps } = props;
|
|
583
592
|
const { table, attributes } = usePresentationTable(presentation, 'fixed');
|
|
584
593
|
const pane = usePane({
|
|
585
594
|
name: 'rail',
|
|
@@ -595,7 +604,7 @@ const Rail = React.forwardRef<HTMLDivElement, RailProps>((props, ref) => {
|
|
|
595
604
|
onCollapse,
|
|
596
605
|
size: expandedSize,
|
|
597
606
|
});
|
|
598
|
-
|
|
607
|
+
useFrameRegistration('rail', flush);
|
|
599
608
|
const composedRef = useComposedRefs(ref, pane.setElement);
|
|
600
609
|
|
|
601
610
|
return (
|
|
@@ -606,7 +615,7 @@ const Rail = React.forwardRef<HTMLDivElement, RailProps>((props, ref) => {
|
|
|
606
615
|
ref={composedRef}
|
|
607
616
|
className={classNames('kui-ShellPane', 'kui-ShellRail', className)}
|
|
608
617
|
{...paneAttributes(pane, attributes)}
|
|
609
|
-
data-
|
|
618
|
+
data-flush={flush || undefined}
|
|
610
619
|
tabIndex={pane.overlaying ? -1 : domProps.tabIndex}
|
|
611
620
|
style={{ ...style, '--rail-size': `${expandedSize}px` } as CSSPropertiesWithVars}
|
|
612
621
|
>
|
|
@@ -644,8 +653,13 @@ type PanelPublicProps = PaneBaseProps &
|
|
|
644
653
|
onSizeChange?: (size: number, meta: PanelSizeChangeMeta) => void;
|
|
645
654
|
sizeUpdate?: 'throttle' | 'debounce';
|
|
646
655
|
sizeUpdateMs?: number;
|
|
647
|
-
/**
|
|
648
|
-
|
|
656
|
+
/**
|
|
657
|
+
* Sets whether this pane joins the app frame. The default is `true`: the pane sits against its
|
|
658
|
+
* neighbours with one hairline between them. Set `flush={false}` to pull it off the frame as a
|
|
659
|
+
* card. It then floats over the content if the content is flush, and otherwise sits on the
|
|
660
|
+
* Shell's background beside a card content.
|
|
661
|
+
*/
|
|
662
|
+
flush?: boolean;
|
|
649
663
|
};
|
|
650
664
|
type PanelComponent = React.ForwardRefExoticComponent<PanelPublicProps & React.RefAttributes<HTMLDivElement>> & {
|
|
651
665
|
Handle: HandleComponent;
|
|
@@ -688,7 +702,7 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>((props, ref) =>
|
|
|
688
702
|
onSizeChange,
|
|
689
703
|
sizeUpdate,
|
|
690
704
|
sizeUpdateMs = 50,
|
|
691
|
-
|
|
705
|
+
flush = true,
|
|
692
706
|
id,
|
|
693
707
|
...domProps
|
|
694
708
|
} = props;
|
|
@@ -713,7 +727,7 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>((props, ref) =>
|
|
|
713
727
|
onCollapse,
|
|
714
728
|
size: expandedSize,
|
|
715
729
|
});
|
|
716
|
-
|
|
730
|
+
useFrameRegistration('panel', flush);
|
|
717
731
|
|
|
718
732
|
React.useEffect(() => {
|
|
719
733
|
if (snapPoints !== undefined || collapseThreshold !== undefined || paneId !== undefined || persistence !== undefined) {
|
|
@@ -774,7 +788,7 @@ const Panel = React.forwardRef<HTMLDivElement, PanelPublicProps>((props, ref) =>
|
|
|
774
788
|
ref={composedRef}
|
|
775
789
|
className={classNames('kui-ShellPane', 'kui-ShellPanel', className)}
|
|
776
790
|
{...paneAttributes(pane, presentationAttributes)}
|
|
777
|
-
data-
|
|
791
|
+
data-flush={flush || undefined}
|
|
778
792
|
tabIndex={pane.overlaying ? -1 : domProps.tabIndex}
|
|
779
793
|
style={
|
|
780
794
|
{
|
|
@@ -799,18 +813,22 @@ Panel.Handle = PanelHandle;
|
|
|
799
813
|
/* ── Content ───────────────────────────────────────────────────────────────── */
|
|
800
814
|
|
|
801
815
|
interface ShellContentProps extends React.ComponentPropsWithoutRef<'main'> {
|
|
802
|
-
/**
|
|
803
|
-
|
|
816
|
+
/**
|
|
817
|
+
* Sets whether the work area joins the app frame. The default is `true`. Set `flush={false}`
|
|
818
|
+
* to make it a card on the Shell's background; the panes beside it then sit on that background
|
|
819
|
+
* too, and draw no hairline toward it.
|
|
820
|
+
*/
|
|
821
|
+
flush?: boolean;
|
|
804
822
|
}
|
|
805
823
|
|
|
806
824
|
/**
|
|
807
825
|
* The work area. It scrolls as it is; with a `Shell.Scroll` child it becomes a column and the
|
|
808
826
|
* Scroll scrolls instead, so a `Shell.PaneHeader float` beside it stays pinned over the page.
|
|
809
827
|
*/
|
|
810
|
-
const Content = React.forwardRef<HTMLElement, ShellContentProps>(({ className,
|
|
811
|
-
|
|
828
|
+
const Content = React.forwardRef<HTMLElement, ShellContentProps>(({ className, flush = true, children, ...props }, ref) => {
|
|
829
|
+
useFrameRegistration('content', flush);
|
|
812
830
|
return (
|
|
813
|
-
<main {...props} ref={ref} className={classNames('kui-ShellContent', className)} data-
|
|
831
|
+
<main {...props} ref={ref} className={classNames('kui-ShellContent', className)} data-flush={flush || undefined}>
|
|
814
832
|
{/* Each pane holds its own page store, so a band's title can mirror the page beside it. */}
|
|
815
833
|
<ShellContentContext.Provider value={true}>
|
|
816
834
|
<PageScope>{children}</PageScope>
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
--color-page: white;
|
|
9
9
|
--color-overlay: var(--black-a6);
|
|
10
10
|
--color-surface: white;
|
|
11
|
+
/* A rule between two regions, such as the hairline between two flush Shell panes. The same role and value as v2's. */
|
|
12
|
+
--color-border: var(--neutral-6, var(--gray-6));
|
|
11
13
|
/* A background for an app page that holds raised surfaces. No component reads it. */
|
|
12
14
|
--color-ground: var(--neutral-1, var(--gray-1));
|
|
13
15
|
|