@womp/kookie-ui 0.9.1 → 0.11.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 +145 -26
- package/dist/cjs/components/app-bar.d.ts +49 -0
- package/dist/cjs/components/app-bar.d.ts.map +1 -0
- package/dist/cjs/components/app-bar.js +2 -0
- package/dist/cjs/components/app-bar.js.map +7 -0
- package/dist/cjs/components/chatbar.js +2 -2
- package/dist/cjs/components/chatbar.js.map +4 -4
- package/dist/cjs/components/context-menu.js +1 -1
- package/dist/cjs/components/context-menu.js.map +4 -4
- package/dist/cjs/components/dropdown-menu.js +1 -1
- package/dist/cjs/components/dropdown-menu.js.map +4 -4
- package/dist/cjs/components/index.d.ts +2 -1
- package/dist/cjs/components/index.d.ts.map +1 -1
- package/dist/cjs/components/index.js +5 -5
- package/dist/cjs/components/index.js.map +4 -4
- package/dist/cjs/components/message-scroller.d.ts +6 -0
- package/dist/cjs/components/message-scroller.d.ts.map +1 -1
- package/dist/cjs/components/message-scroller.js +2 -2
- package/dist/cjs/components/message-scroller.js.map +4 -4
- package/dist/cjs/components/scroll-area.d.ts.map +1 -1
- package/dist/cjs/components/scroll-area.js +1 -1
- package/dist/cjs/components/scroll-area.js.map +4 -4
- package/dist/cjs/components/scroll-area.props.d.ts +10 -0
- package/dist/cjs/components/scroll-area.props.d.ts.map +1 -1
- package/dist/cjs/components/scroll-area.props.js +1 -1
- package/dist/cjs/components/scroll-area.props.js.map +2 -2
- package/dist/cjs/components/sidebar.js +1 -1
- package/dist/cjs/components/sidebar.js.map +4 -4
- package/dist/cjs/components/table.js +1 -1
- package/dist/cjs/components/table.js.map +4 -4
- package/dist/cjs/components/theme-panel.js +3 -3
- package/dist/cjs/components/theme-panel.js.map +4 -4
- package/dist/cjs/components/toolbar.d.ts +88 -36
- package/dist/cjs/components/toolbar.d.ts.map +1 -1
- package/dist/cjs/components/toolbar.js +4 -1
- package/dist/cjs/components/toolbar.js.map +4 -4
- package/dist/cjs/components/toolbar.props.d.ts +28 -0
- package/dist/cjs/components/toolbar.props.d.ts.map +1 -0
- package/dist/cjs/components/toolbar.props.js +2 -0
- package/dist/cjs/components/toolbar.props.js.map +7 -0
- package/dist/cjs/hooks/use-scroll-edges.d.ts +12 -0
- package/dist/cjs/hooks/use-scroll-edges.d.ts.map +1 -0
- package/dist/cjs/hooks/use-scroll-edges.js +2 -0
- package/dist/cjs/hooks/use-scroll-edges.js.map +7 -0
- package/dist/cjs/index.js +5 -5
- package/dist/cjs/index.js.map +4 -4
- package/dist/cjs/props/index.js +1 -1
- package/dist/cjs/props/index.js.map +2 -2
- package/dist/esm/{chunk-ABSKRHVM.js → chunk-36A5BYCN.js} +2 -2
- package/dist/esm/{chunk-73QGEY2I.js → chunk-3R4YLW4A.js} +2 -2
- package/dist/esm/{chunk-ZZLZGHZQ.js → chunk-4LDVSTXI.js} +2 -2
- package/dist/esm/{chunk-YQRSAP46.js → chunk-53SZ4Y23.js} +2 -2
- package/dist/esm/chunk-54JFIP5S.js +2 -0
- package/dist/esm/chunk-54JFIP5S.js.map +7 -0
- package/dist/esm/chunk-5BWLY27A.js +2 -0
- package/dist/esm/chunk-5BWLY27A.js.map +7 -0
- package/dist/esm/{chunk-X3JM2565.js → chunk-6G3MPL4A.js} +2 -2
- package/dist/esm/{chunk-DSJY5RI3.js → chunk-7JJT42J2.js} +2 -2
- package/dist/esm/chunk-C7EVYSWK.js +1 -0
- package/dist/esm/chunk-COWZAUZR.js +2 -0
- package/dist/esm/chunk-COWZAUZR.js.map +7 -0
- package/dist/esm/{chunk-ERY5TH2M.js → chunk-CYU6BLZ5.js} +2 -2
- package/dist/esm/{chunk-MWIIGYAJ.js → chunk-D6PHTHF2.js} +2 -2
- package/dist/esm/{chunk-YTD3AJAU.js → chunk-ENLFKWYV.js} +2 -2
- package/dist/esm/{chunk-4XGGX2V2.js → chunk-ISOLUTZF.js} +2 -2
- package/dist/esm/{chunk-LXWPEDPZ.js → chunk-IYCPYN4Z.js} +2 -2
- package/dist/esm/{chunk-RJP5QUXO.js → chunk-L5PID6BU.js} +2 -2
- package/dist/esm/{chunk-BW5CO4PZ.js → chunk-METRW4HG.js} +2 -2
- package/dist/esm/{chunk-PYHEBG5I.js → chunk-MJOXEUBT.js} +2 -2
- package/dist/esm/{chunk-PHC3QBV3.js → chunk-MZXHKM4V.js} +2 -2
- package/dist/esm/chunk-OIUCV5HK.js +2 -0
- package/dist/esm/chunk-OIUCV5HK.js.map +7 -0
- package/dist/esm/{chunk-NIM7DIVH.js → chunk-PQKJNRMR.js} +2 -2
- package/dist/esm/{chunk-65GAANJD.js → chunk-UYCPDGWA.js} +2 -2
- package/dist/esm/chunk-XLMTTSRO.js +2 -0
- package/dist/esm/chunk-XLMTTSRO.js.map +7 -0
- package/dist/esm/chunk-XPRPYCII.js +2 -0
- package/dist/esm/{chunk-5KICSAT7.js.map → chunk-XPRPYCII.js.map} +2 -2
- package/dist/esm/{chunk-QWVU2TW4.js → chunk-ZK7A2MZZ.js} +2 -2
- package/dist/esm/chunk-ZUOK3KFY.js +2 -0
- package/dist/esm/chunk-ZUOK3KFY.js.map +7 -0
- package/dist/esm/components/_internal/base-button.js +1 -1
- package/dist/esm/components/alert-dialog.js +1 -1
- package/dist/esm/components/app-bar.d.ts +49 -0
- package/dist/esm/components/app-bar.d.ts.map +1 -0
- package/dist/esm/components/app-bar.js +2 -0
- package/dist/esm/components/app-bar.js.map +7 -0
- package/dist/esm/components/button.js +1 -1
- package/dist/esm/components/chatbar.js +1 -1
- package/dist/esm/components/checkbox-cards.js +1 -1
- package/dist/esm/components/context-menu.js +1 -1
- package/dist/esm/components/dialog.js +1 -1
- package/dist/esm/components/dropdown-menu.js +1 -1
- package/dist/esm/components/icon-button.js +1 -1
- package/dist/esm/components/index.d.ts +2 -1
- package/dist/esm/components/index.d.ts.map +1 -1
- package/dist/esm/components/index.js +1 -1
- package/dist/esm/components/message-scroller.d.ts +6 -0
- package/dist/esm/components/message-scroller.d.ts.map +1 -1
- package/dist/esm/components/message-scroller.js +1 -1
- package/dist/esm/components/notice.js +1 -1
- package/dist/esm/components/scroll-area.d.ts.map +1 -1
- package/dist/esm/components/scroll-area.js +1 -1
- package/dist/esm/components/scroll-area.props.d.ts +10 -0
- package/dist/esm/components/scroll-area.props.d.ts.map +1 -1
- package/dist/esm/components/scroll-area.props.js +1 -1
- package/dist/esm/components/sheet.js +1 -1
- package/dist/esm/components/shell.js +1 -1
- package/dist/esm/components/sidebar.js +1 -1
- package/dist/esm/components/table.js +1 -1
- package/dist/esm/components/theme-panel.js +1 -1
- package/dist/esm/components/toggle-button.js +1 -1
- package/dist/esm/components/toggle-icon-button.js +1 -1
- package/dist/esm/components/toolbar.d.ts +88 -36
- package/dist/esm/components/toolbar.d.ts.map +1 -1
- package/dist/esm/components/toolbar.js +1 -1
- package/dist/esm/components/toolbar.props.d.ts +28 -0
- package/dist/esm/components/toolbar.props.d.ts.map +1 -0
- package/dist/esm/components/toolbar.props.js +2 -0
- package/dist/esm/components/toolbar.props.js.map +7 -0
- package/dist/esm/components/user-card.js +1 -1
- package/dist/esm/hooks/use-scroll-edges.d.ts +12 -0
- package/dist/esm/hooks/use-scroll-edges.d.ts.map +1 -0
- package/dist/esm/hooks/use-scroll-edges.js +2 -0
- package/dist/esm/hooks/use-scroll-edges.js.map +7 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/props/index.js +1 -1
- package/package.json +1 -1
- package/src/components/app-bar.css +204 -0
- package/src/components/app-bar.tsx +256 -0
- package/src/components/index.css +2 -0
- package/src/components/index.tsx +13 -1
- package/src/components/message-scroller.tsx +24 -5
- package/src/components/scroll-area.css +44 -0
- package/src/components/scroll-area.props.tsx +8 -0
- package/src/components/scroll-area.tsx +7 -1
- package/src/components/toolbar.css +87 -160
- package/src/components/toolbar.props.tsx +27 -0
- package/src/components/toolbar.tsx +259 -193
- package/src/hooks/use-scroll-edges.ts +46 -0
- package/src/styles/tokens/color.css +19 -0
- package/styles.css +159 -26
- package/tokens/base.css +14 -0
- package/tokens.css +14 -0
- package/dist/esm/chunk-47LMOIW3.js +0 -2
- package/dist/esm/chunk-47LMOIW3.js.map +0 -7
- package/dist/esm/chunk-5KICSAT7.js +0 -2
- package/dist/esm/chunk-CTA5ODAO.js +0 -2
- package/dist/esm/chunk-CTA5ODAO.js.map +0 -7
- package/dist/esm/chunk-JKS2YXMS.js +0 -1
- package/dist/esm/chunk-W4WWN3RC.js +0 -2
- package/dist/esm/chunk-W4WWN3RC.js.map +0 -7
- /package/dist/esm/{chunk-ABSKRHVM.js.map → chunk-36A5BYCN.js.map} +0 -0
- /package/dist/esm/{chunk-73QGEY2I.js.map → chunk-3R4YLW4A.js.map} +0 -0
- /package/dist/esm/{chunk-ZZLZGHZQ.js.map → chunk-4LDVSTXI.js.map} +0 -0
- /package/dist/esm/{chunk-YQRSAP46.js.map → chunk-53SZ4Y23.js.map} +0 -0
- /package/dist/esm/{chunk-X3JM2565.js.map → chunk-6G3MPL4A.js.map} +0 -0
- /package/dist/esm/{chunk-DSJY5RI3.js.map → chunk-7JJT42J2.js.map} +0 -0
- /package/dist/esm/{chunk-JKS2YXMS.js.map → chunk-C7EVYSWK.js.map} +0 -0
- /package/dist/esm/{chunk-ERY5TH2M.js.map → chunk-CYU6BLZ5.js.map} +0 -0
- /package/dist/esm/{chunk-MWIIGYAJ.js.map → chunk-D6PHTHF2.js.map} +0 -0
- /package/dist/esm/{chunk-YTD3AJAU.js.map → chunk-ENLFKWYV.js.map} +0 -0
- /package/dist/esm/{chunk-4XGGX2V2.js.map → chunk-ISOLUTZF.js.map} +0 -0
- /package/dist/esm/{chunk-LXWPEDPZ.js.map → chunk-IYCPYN4Z.js.map} +0 -0
- /package/dist/esm/{chunk-RJP5QUXO.js.map → chunk-L5PID6BU.js.map} +0 -0
- /package/dist/esm/{chunk-BW5CO4PZ.js.map → chunk-METRW4HG.js.map} +0 -0
- /package/dist/esm/{chunk-PYHEBG5I.js.map → chunk-MJOXEUBT.js.map} +0 -0
- /package/dist/esm/{chunk-PHC3QBV3.js.map → chunk-MZXHKM4V.js.map} +0 -0
- /package/dist/esm/{chunk-NIM7DIVH.js.map → chunk-PQKJNRMR.js.map} +0 -0
- /package/dist/esm/{chunk-65GAANJD.js.map → chunk-UYCPDGWA.js.map} +0 -0
- /package/dist/esm/{chunk-QWVU2TW4.js.map → chunk-ZK7A2MZZ.js.map} +0 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/* stylelint-disable selector-max-specificity */
|
|
2
|
+
/* AppBar Component */
|
|
3
|
+
|
|
4
|
+
.rt-AppBar {
|
|
5
|
+
position: absolute;
|
|
6
|
+
z-index: 1;
|
|
7
|
+
|
|
8
|
+
/* --rt-app-bar-height and --rt-app-bar-width are set on parent element via JS */
|
|
9
|
+
/* (the old --rt-toolbar-* names are still set too, for layouts written before the rename) */
|
|
10
|
+
/* Use pt/pb/pl/pr="var(--rt-app-bar-height)" on content to avoid overlap */
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Grid layout for true centering */
|
|
14
|
+
.rt-AppBarInner {
|
|
15
|
+
display: grid;
|
|
16
|
+
grid-template-columns: 1fr auto 1fr;
|
|
17
|
+
align-items: center;
|
|
18
|
+
width: 100%;
|
|
19
|
+
height: 100%;
|
|
20
|
+
gap: var(--space-2);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Vertical app bars use row-based grid */
|
|
24
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarInner {
|
|
25
|
+
grid-template-columns: 1fr;
|
|
26
|
+
grid-template-rows: 1fr auto 1fr;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarLeft {
|
|
30
|
+
grid-column: 1;
|
|
31
|
+
grid-row: 1;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarCenter {
|
|
35
|
+
grid-column: 1;
|
|
36
|
+
grid-row: 2;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarRight {
|
|
40
|
+
grid-column: 1;
|
|
41
|
+
grid-row: 3;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
45
|
+
/* */
|
|
46
|
+
/* Anchor positions */
|
|
47
|
+
/* */
|
|
48
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
49
|
+
|
|
50
|
+
.rt-AppBar:where([data-anchor='top']) {
|
|
51
|
+
top: 0;
|
|
52
|
+
left: 0;
|
|
53
|
+
right: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.rt-AppBar:where([data-anchor='bottom']) {
|
|
57
|
+
bottom: 0;
|
|
58
|
+
left: 0;
|
|
59
|
+
right: 0;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.rt-AppBar:where([data-anchor='left']) {
|
|
63
|
+
top: 0;
|
|
64
|
+
bottom: 0;
|
|
65
|
+
left: 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.rt-AppBar:where([data-anchor='right']) {
|
|
69
|
+
top: 0;
|
|
70
|
+
bottom: 0;
|
|
71
|
+
right: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
75
|
+
/* */
|
|
76
|
+
/* Inset mode (default) */
|
|
77
|
+
/* Edge-to-edge positioning */
|
|
78
|
+
/* */
|
|
79
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
80
|
+
|
|
81
|
+
/* Remove border-radius in inset mode */
|
|
82
|
+
.rt-AppBar:where(:not([data-floating])) {
|
|
83
|
+
--base-card-border-radius: 0;
|
|
84
|
+
border-radius: 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* Override Card's box-shadow to only show exposed edge */
|
|
88
|
+
/* Top anchor: only show bottom border */
|
|
89
|
+
.rt-AppBar:where([data-anchor='top']:not([data-floating])) {
|
|
90
|
+
&::after {
|
|
91
|
+
box-shadow: inset 0 -1px 0 0 var(--gray-6);
|
|
92
|
+
}
|
|
93
|
+
:where([data-panel-background='translucent'], [data-material='translucent']) &::after,
|
|
94
|
+
&:where([data-panel-background='translucent'], [data-material='translucent'])::after {
|
|
95
|
+
box-shadow: inset 0 -1px 0 0 var(--gray-a6);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Bottom anchor: only show top border */
|
|
100
|
+
.rt-AppBar:where([data-anchor='bottom']:not([data-floating])) {
|
|
101
|
+
&::after {
|
|
102
|
+
box-shadow: inset 0 1px 0 0 var(--gray-6);
|
|
103
|
+
}
|
|
104
|
+
:where([data-panel-background='translucent'], [data-material='translucent']) &::after,
|
|
105
|
+
&:where([data-panel-background='translucent'], [data-material='translucent'])::after {
|
|
106
|
+
box-shadow: inset 0 1px 0 0 var(--gray-a6);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/* Left anchor: only show right border */
|
|
111
|
+
.rt-AppBar:where([data-anchor='left']:not([data-floating])) {
|
|
112
|
+
&::after {
|
|
113
|
+
box-shadow: inset -1px 0 0 0 var(--gray-6);
|
|
114
|
+
}
|
|
115
|
+
:where([data-panel-background='translucent'], [data-material='translucent']) &::after,
|
|
116
|
+
&:where([data-panel-background='translucent'], [data-material='translucent'])::after {
|
|
117
|
+
box-shadow: inset -1px 0 0 0 var(--gray-a6);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* Right anchor: only show left border */
|
|
122
|
+
.rt-AppBar:where([data-anchor='right']:not([data-floating])) {
|
|
123
|
+
&::after {
|
|
124
|
+
box-shadow: inset 1px 0 0 0 var(--gray-6);
|
|
125
|
+
}
|
|
126
|
+
:where([data-panel-background='translucent'], [data-material='translucent']) &::after,
|
|
127
|
+
&:where([data-panel-background='translucent'], [data-material='translucent'])::after {
|
|
128
|
+
box-shadow: inset 1px 0 0 0 var(--gray-a6);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* Ghost variant in normal mode has no border */
|
|
133
|
+
.rt-AppBar:where(.rt-variant-ghost:not([data-floating]))::after {
|
|
134
|
+
box-shadow: none;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Soft variant in normal mode has no border */
|
|
138
|
+
.rt-AppBar:where(.rt-variant-soft:not([data-floating]))::after {
|
|
139
|
+
box-shadow: none;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
143
|
+
/* */
|
|
144
|
+
/* Floating mode */
|
|
145
|
+
/* Full card treatment */
|
|
146
|
+
/* */
|
|
147
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
148
|
+
|
|
149
|
+
/* Floating mode: margin controlled via offset prop in JS */
|
|
150
|
+
/* Inherits Card's border-radius (not overridden like inset mode) */
|
|
151
|
+
|
|
152
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
153
|
+
/* */
|
|
154
|
+
/* Title truncation */
|
|
155
|
+
/* */
|
|
156
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
157
|
+
|
|
158
|
+
.rt-AppBarTitle {
|
|
159
|
+
/* Ensure title can truncate within flex container */
|
|
160
|
+
min-width: 0;
|
|
161
|
+
flex-shrink: 1;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
165
|
+
/* */
|
|
166
|
+
/* Section alignment */
|
|
167
|
+
/* */
|
|
168
|
+
/* * * * * * * * * * * * * * * * * * * */
|
|
169
|
+
|
|
170
|
+
.rt-AppBarSection {
|
|
171
|
+
min-width: 0;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.rt-AppBarLeft {
|
|
175
|
+
grid-column: 1;
|
|
176
|
+
justify-self: start;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.rt-AppBarCenter {
|
|
180
|
+
grid-column: 2;
|
|
181
|
+
justify-self: center;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/* Ensure Right always stays in the right column */
|
|
185
|
+
.rt-AppBarRight {
|
|
186
|
+
grid-column: 3;
|
|
187
|
+
justify-self: end;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/* Vertical app bar section alignment */
|
|
191
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarLeft {
|
|
192
|
+
align-self: start;
|
|
193
|
+
justify-self: center;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarCenter {
|
|
197
|
+
align-self: center;
|
|
198
|
+
justify-self: center;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
.rt-AppBar:where([data-anchor='left'], [data-anchor='right']) .rt-AppBarRight {
|
|
202
|
+
align-self: end;
|
|
203
|
+
justify-self: center;
|
|
204
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { Card } from './card.js';
|
|
5
|
+
import { Flex } from './flex.js';
|
|
6
|
+
import { Heading } from './heading.js';
|
|
7
|
+
|
|
8
|
+
import type { CardProps } from './card.js';
|
|
9
|
+
import type { FlexProps } from './flex.js';
|
|
10
|
+
|
|
11
|
+
// ============================================================================
|
|
12
|
+
// AppBar Root
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
type AppBarRootElement = React.ElementRef<'div'>;
|
|
16
|
+
type Anchor = 'top' | 'bottom' | 'left' | 'right';
|
|
17
|
+
type SpaceScale = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9';
|
|
18
|
+
|
|
19
|
+
interface AppBarRootProps extends Omit<CardProps, 'asChild'> {
|
|
20
|
+
/**
|
|
21
|
+
* Which edge to anchor to. Sets position: sticky and the appropriate edge.
|
|
22
|
+
* @default "top"
|
|
23
|
+
*/
|
|
24
|
+
anchor?: Anchor;
|
|
25
|
+
/**
|
|
26
|
+
* Floating mode adds margin from edges for a detached look with absolute positioning.
|
|
27
|
+
* When false (default), uses inset mode with negative margins to go edge-to-edge inside Cards.
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
floating?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Margin offset from edges when floating. Uses space scale values.
|
|
33
|
+
* @default "2"
|
|
34
|
+
*/
|
|
35
|
+
offset?: SpaceScale;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* An app bar: the band anchored to one edge of a pane, with left, center and right sections
|
|
40
|
+
* and a title. It publishes its height (or width) to its parent as `--rt-app-bar-height`
|
|
41
|
+
* (`--rt-app-bar-width`) so content can pad itself clear of it.
|
|
42
|
+
*
|
|
43
|
+
* This component was called `Toolbar` until 0.11.0. It is not a `role="toolbar"`: for a row of
|
|
44
|
+
* controls with one tab stop and arrow-key navigation, use `Toolbar`.
|
|
45
|
+
*/
|
|
46
|
+
const AppBarRoot = React.forwardRef<AppBarRootElement, AppBarRootProps>(
|
|
47
|
+
(props, forwardedRef) => {
|
|
48
|
+
const {
|
|
49
|
+
anchor = 'top',
|
|
50
|
+
floating = false,
|
|
51
|
+
offset = '2',
|
|
52
|
+
size = '1',
|
|
53
|
+
variant = 'ghost',
|
|
54
|
+
material,
|
|
55
|
+
className,
|
|
56
|
+
style,
|
|
57
|
+
children,
|
|
58
|
+
...restProps
|
|
59
|
+
} = props;
|
|
60
|
+
|
|
61
|
+
const isHorizontal = anchor === 'top' || anchor === 'bottom';
|
|
62
|
+
const internalRef = React.useRef<HTMLDivElement>(null);
|
|
63
|
+
|
|
64
|
+
// Merge refs
|
|
65
|
+
const mergedRef = React.useCallback(
|
|
66
|
+
(node: HTMLDivElement | null) => {
|
|
67
|
+
(internalRef as React.MutableRefObject<HTMLDivElement | null>).current = node;
|
|
68
|
+
if (typeof forwardedRef === 'function') {
|
|
69
|
+
forwardedRef(node);
|
|
70
|
+
} else if (forwardedRef) {
|
|
71
|
+
forwardedRef.current = node;
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
[forwardedRef],
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
// Expose height/width as CSS variable on parent element
|
|
78
|
+
React.useEffect(() => {
|
|
79
|
+
const element = internalRef.current;
|
|
80
|
+
if (!element) return;
|
|
81
|
+
|
|
82
|
+
const parent = element.parentElement;
|
|
83
|
+
if (!parent) return;
|
|
84
|
+
|
|
85
|
+
const update = () => {
|
|
86
|
+
let dimension = isHorizontal ? element.offsetHeight : element.offsetWidth;
|
|
87
|
+
|
|
88
|
+
// For floating mode, include the margin in the total space
|
|
89
|
+
if (floating) {
|
|
90
|
+
const computedStyle = getComputedStyle(element);
|
|
91
|
+
const margin = parseFloat(computedStyle.marginTop) || 0;
|
|
92
|
+
dimension += margin * 2;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// `--rt-toolbar-*` are the names this bar published while it was called Toolbar.
|
|
96
|
+
// They are still written so existing layouts keep their offset; prefer `--rt-app-bar-*`.
|
|
97
|
+
if (isHorizontal) {
|
|
98
|
+
parent.style.setProperty('--rt-app-bar-height', `${dimension}px`);
|
|
99
|
+
parent.style.setProperty('--rt-toolbar-height', `${dimension}px`);
|
|
100
|
+
} else {
|
|
101
|
+
parent.style.setProperty('--rt-app-bar-width', `${dimension}px`);
|
|
102
|
+
parent.style.setProperty('--rt-toolbar-width', `${dimension}px`);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
update();
|
|
107
|
+
|
|
108
|
+
const resizeObserver = new ResizeObserver(update);
|
|
109
|
+
resizeObserver.observe(element);
|
|
110
|
+
|
|
111
|
+
return () => resizeObserver.disconnect();
|
|
112
|
+
}, [isHorizontal, floating]);
|
|
113
|
+
|
|
114
|
+
const computedStyle = floating
|
|
115
|
+
? { margin: `var(--space-${offset})`, ...style }
|
|
116
|
+
: style;
|
|
117
|
+
|
|
118
|
+
return (
|
|
119
|
+
<Card
|
|
120
|
+
ref={mergedRef}
|
|
121
|
+
size={size}
|
|
122
|
+
variant={variant}
|
|
123
|
+
material={material}
|
|
124
|
+
data-anchor={anchor}
|
|
125
|
+
data-floating={floating || undefined}
|
|
126
|
+
className={classNames('rt-AppBar', className)}
|
|
127
|
+
style={computedStyle}
|
|
128
|
+
{...restProps}
|
|
129
|
+
>
|
|
130
|
+
<div className="rt-AppBarInner">
|
|
131
|
+
{children}
|
|
132
|
+
</div>
|
|
133
|
+
</Card>
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
);
|
|
137
|
+
AppBarRoot.displayName = 'AppBar.Root';
|
|
138
|
+
|
|
139
|
+
// ============================================================================
|
|
140
|
+
// AppBar Left (for horizontal) / Start (alias)
|
|
141
|
+
// ============================================================================
|
|
142
|
+
|
|
143
|
+
type AppBarSectionElement = React.ElementRef<'div'>;
|
|
144
|
+
type AppBarSectionProps = FlexProps;
|
|
145
|
+
|
|
146
|
+
const AppBarLeft = React.forwardRef<AppBarSectionElement, AppBarSectionProps>(
|
|
147
|
+
({ gap = '2', align = 'center', className, children, ...props }, forwardedRef) => (
|
|
148
|
+
<Flex
|
|
149
|
+
ref={forwardedRef}
|
|
150
|
+
align={align}
|
|
151
|
+
gap={gap}
|
|
152
|
+
className={classNames('rt-AppBarSection', 'rt-AppBarLeft', className)}
|
|
153
|
+
{...props}
|
|
154
|
+
>
|
|
155
|
+
{children}
|
|
156
|
+
</Flex>
|
|
157
|
+
),
|
|
158
|
+
);
|
|
159
|
+
AppBarLeft.displayName = 'AppBar.Left';
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// AppBar Center
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
const AppBarCenter = React.forwardRef<AppBarSectionElement, AppBarSectionProps>(
|
|
166
|
+
({ gap = '2', align = 'center', justify = 'center', className, children, ...props }, forwardedRef) => (
|
|
167
|
+
<Flex
|
|
168
|
+
ref={forwardedRef}
|
|
169
|
+
align={align}
|
|
170
|
+
justify={justify}
|
|
171
|
+
gap={gap}
|
|
172
|
+
className={classNames('rt-AppBarSection', 'rt-AppBarCenter', className)}
|
|
173
|
+
{...props}
|
|
174
|
+
>
|
|
175
|
+
{children}
|
|
176
|
+
</Flex>
|
|
177
|
+
),
|
|
178
|
+
);
|
|
179
|
+
AppBarCenter.displayName = 'AppBar.Center';
|
|
180
|
+
|
|
181
|
+
// ============================================================================
|
|
182
|
+
// AppBar Right (for horizontal) / End (alias)
|
|
183
|
+
// ============================================================================
|
|
184
|
+
|
|
185
|
+
const AppBarRight = React.forwardRef<AppBarSectionElement, AppBarSectionProps>(
|
|
186
|
+
({ gap = '2', align = 'center', justify = 'end', className, children, ...props }, forwardedRef) => (
|
|
187
|
+
<Flex
|
|
188
|
+
ref={forwardedRef}
|
|
189
|
+
align={align}
|
|
190
|
+
justify={justify}
|
|
191
|
+
gap={gap}
|
|
192
|
+
className={classNames('rt-AppBarSection', 'rt-AppBarRight', className)}
|
|
193
|
+
{...props}
|
|
194
|
+
>
|
|
195
|
+
{children}
|
|
196
|
+
</Flex>
|
|
197
|
+
),
|
|
198
|
+
);
|
|
199
|
+
AppBarRight.displayName = 'AppBar.Right';
|
|
200
|
+
|
|
201
|
+
// ============================================================================
|
|
202
|
+
// AppBar Title
|
|
203
|
+
// ============================================================================
|
|
204
|
+
|
|
205
|
+
type AppBarTitleElement = React.ElementRef<typeof Heading>;
|
|
206
|
+
type AppBarTitleProps = React.ComponentPropsWithoutRef<typeof Heading>;
|
|
207
|
+
|
|
208
|
+
const AppBarTitle = React.forwardRef<AppBarTitleElement, AppBarTitleProps>(
|
|
209
|
+
({ className, size = '2', weight = 'medium', truncate = true, children, ...props }, forwardedRef) => (
|
|
210
|
+
<Heading
|
|
211
|
+
ref={forwardedRef}
|
|
212
|
+
size={size}
|
|
213
|
+
weight={weight}
|
|
214
|
+
truncate={truncate}
|
|
215
|
+
className={classNames('rt-AppBarTitle', className)}
|
|
216
|
+
{...props}
|
|
217
|
+
>
|
|
218
|
+
{children}
|
|
219
|
+
</Heading>
|
|
220
|
+
),
|
|
221
|
+
);
|
|
222
|
+
AppBarTitle.displayName = 'AppBar.Title';
|
|
223
|
+
|
|
224
|
+
// ============================================================================
|
|
225
|
+
// Exports
|
|
226
|
+
// ============================================================================
|
|
227
|
+
|
|
228
|
+
const AppBar = AppBarRoot as typeof AppBarRoot & {
|
|
229
|
+
Root: typeof AppBarRoot;
|
|
230
|
+
Left: typeof AppBarLeft;
|
|
231
|
+
Center: typeof AppBarCenter;
|
|
232
|
+
Right: typeof AppBarRight;
|
|
233
|
+
Title: typeof AppBarTitle;
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
AppBar.Root = AppBarRoot;
|
|
237
|
+
AppBar.Left = AppBarLeft;
|
|
238
|
+
AppBar.Center = AppBarCenter;
|
|
239
|
+
AppBar.Right = AppBarRight;
|
|
240
|
+
AppBar.Title = AppBarTitle;
|
|
241
|
+
|
|
242
|
+
export {
|
|
243
|
+
AppBar,
|
|
244
|
+
AppBarRoot as Root,
|
|
245
|
+
AppBarLeft as Left,
|
|
246
|
+
AppBarCenter as Center,
|
|
247
|
+
AppBarRight as Right,
|
|
248
|
+
AppBarTitle as Title,
|
|
249
|
+
};
|
|
250
|
+
export type {
|
|
251
|
+
AppBarRootProps as RootProps,
|
|
252
|
+
AppBarSectionProps as LeftProps,
|
|
253
|
+
AppBarSectionProps as CenterProps,
|
|
254
|
+
AppBarSectionProps as RightProps,
|
|
255
|
+
AppBarTitleProps as TitleProps,
|
|
256
|
+
};
|
package/src/components/index.css
CHANGED
|
@@ -57,6 +57,8 @@
|
|
|
57
57
|
@import './text-area.css';
|
|
58
58
|
@import './text-field.css';
|
|
59
59
|
@import './theme-panel.css';
|
|
60
|
+
/* AppBar keeps the place its old toolbar.css had: it extends Card and must come after card.css */
|
|
61
|
+
@import './app-bar.css';
|
|
60
62
|
@import './toolbar.css';
|
|
61
63
|
@import './tooltip.css';
|
|
62
64
|
@import './user-card.css';
|
package/src/components/index.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { AccessibleIcon, type AccessibleIconProps } from './accessible-icon.js';
|
|
2
2
|
export * as Accordion from './accordion.js';
|
|
3
3
|
export * as AlertDialog from './alert-dialog.js';
|
|
4
|
+
export { AppBar } from './app-bar.js';
|
|
4
5
|
export { AspectRatio, type AspectRatioProps } from './aspect-ratio.js';
|
|
5
6
|
export { Avatar, type AvatarProps } from './avatar.js';
|
|
6
7
|
export { Badge, type BadgeProps } from './badge.js';
|
|
@@ -71,7 +72,18 @@ export {
|
|
|
71
72
|
export { Theme, ThemeContext, type ThemeContextValue, type ThemeProps, useThemeContext } from './theme.js';
|
|
72
73
|
export { ToggleButton, type ToggleButtonProps } from './toggle-button.js';
|
|
73
74
|
export { ToggleIconButton, type ToggleIconButtonProps } from './toggle-icon-button.js';
|
|
74
|
-
export {
|
|
75
|
+
export {
|
|
76
|
+
Toolbar,
|
|
77
|
+
ToolbarGroup,
|
|
78
|
+
ToolbarButton,
|
|
79
|
+
ToolbarSeparator,
|
|
80
|
+
ToolbarTitle,
|
|
81
|
+
type ToolbarProps,
|
|
82
|
+
type ToolbarGroupProps,
|
|
83
|
+
type ToolbarButtonProps,
|
|
84
|
+
type ToolbarSeparatorProps,
|
|
85
|
+
type ToolbarTitleProps,
|
|
86
|
+
} from './toolbar.js';
|
|
75
87
|
export { Tooltip, type TooltipProps } from './tooltip.js';
|
|
76
88
|
export { UserCard, type UserCardProps } from './user-card.js';
|
|
77
89
|
export { VirtualMenu, type VirtualMenuProps, type VirtualMenuItemProps, type VirtualMenuRenderItemProps } from './virtual-menu.js';
|
|
@@ -40,7 +40,10 @@ import {
|
|
|
40
40
|
type MessageScrollerVisibilityState,
|
|
41
41
|
} from '@shadcn/react/message-scroller';
|
|
42
42
|
|
|
43
|
+
import { useComposedRefs } from 'radix-ui/internal';
|
|
44
|
+
|
|
43
45
|
import { IconButton, type IconButtonProps } from './icon-button.js';
|
|
46
|
+
import { useScrollEdges } from '../hooks/use-scroll-edges.js';
|
|
44
47
|
|
|
45
48
|
interface RootProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
46
49
|
/**
|
|
@@ -78,14 +81,30 @@ interface ViewportProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
|
78
81
|
'aria-label'?: string;
|
|
79
82
|
/** Keep the reader's place when older messages are added above. Default `true`. */
|
|
80
83
|
preserveScrollOnPrepend?: boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Fades messages toward the top and bottom edges while there is more past them. A floating
|
|
86
|
+
* band over an edge (a toolbar, a goal tray, a composer) can set `--scroll-fade-start` or
|
|
87
|
+
* `--scroll-fade-end` to its height, so messages fade as they pass under it. Default `true`.
|
|
88
|
+
*/
|
|
89
|
+
fade?: boolean;
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
/** The scrolling element. */
|
|
84
|
-
const Viewport = React.forwardRef<HTMLDivElement, ViewportProps>(({ className, 'aria-label': label, ...props }, forwardedRef) =>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
const Viewport = React.forwardRef<HTMLDivElement, ViewportProps>(({ className, 'aria-label': label, fade = true, ...props }, forwardedRef) => {
|
|
94
|
+
const setEdgesElement = useScrollEdges<HTMLDivElement>(fade);
|
|
95
|
+
const ref = useComposedRefs(forwardedRef, setEdgesElement);
|
|
96
|
+
return (
|
|
97
|
+
// The primitive names an unnamed viewport "Messages", in English. An empty name is skipped by
|
|
98
|
+
// accessible-name computation, so a transcript is only named when the app names it.
|
|
99
|
+
<Primitive.Viewport
|
|
100
|
+
aria-label={label ?? ''}
|
|
101
|
+
{...props}
|
|
102
|
+
ref={ref}
|
|
103
|
+
data-fade={fade ? '' : undefined}
|
|
104
|
+
className={classNames('rt-MessageScrollerViewport', className)}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
});
|
|
89
108
|
Viewport.displayName = 'MessageScroller.Viewport';
|
|
90
109
|
|
|
91
110
|
type ContentProps = React.ComponentPropsWithoutRef<'div'>;
|
|
@@ -144,3 +144,47 @@
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
/***************************************************************************************************
|
|
149
|
+
* *
|
|
150
|
+
* SCROLL FADE *
|
|
151
|
+
* *
|
|
152
|
+
***************************************************************************************************/
|
|
153
|
+
|
|
154
|
+
/*
|
|
155
|
+
* Content dissolves toward an edge that has more past it. A mask, not a painted gradient: a paint
|
|
156
|
+
* has to fade toward a colour, and the right colour differs on every surface, while a mask fades
|
|
157
|
+
* the content itself and lets whatever is behind show through.
|
|
158
|
+
*
|
|
159
|
+
* `--scroll-overflow-start/-end` are how far content is hidden past each edge, written by
|
|
160
|
+
* Kookie's scroll-edges hook. `min()` against the fade length is the whole behaviour: an edge
|
|
161
|
+
* with nothing past it fades over 0px, and the fade ramps in over the first pixels of scrolling.
|
|
162
|
+
* A floating band over an edge sets `--scroll-fade-start` or `--scroll-fade-end` to its height.
|
|
163
|
+
*
|
|
164
|
+
* Shared by ScrollArea (on its viewport) and MessageScroller (on its viewport). Scrollbars are
|
|
165
|
+
* siblings of the viewport, outside the mask, so the thumb stays crisp.
|
|
166
|
+
*/
|
|
167
|
+
:where(.rt-ScrollAreaRoot[data-fade]) > .rt-ScrollAreaViewport,
|
|
168
|
+
.rt-MessageScrollerViewport:where([data-fade]) {
|
|
169
|
+
mask-image: linear-gradient(
|
|
170
|
+
to bottom,
|
|
171
|
+
transparent 0%,
|
|
172
|
+
black min(var(--scroll-overflow-start, 0px), var(--scroll-fade-start, var(--scroll-fade-size))),
|
|
173
|
+
black calc(100% - min(var(--scroll-overflow-end, 0px), var(--scroll-fade-end, var(--scroll-fade-size)))),
|
|
174
|
+
transparent 100%
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
:root,
|
|
179
|
+
.radix-themes {
|
|
180
|
+
--scroll-fade-size: var(--space-6);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/*
|
|
184
|
+
* A band is above the scroller it floats over and above nothing else. The reach hooks inherit,
|
|
185
|
+
* so a scroller nested inside another takes the designed length, not its ancestor's band.
|
|
186
|
+
*/
|
|
187
|
+
:where(.rt-ScrollAreaViewport, .rt-MessageScrollerViewport) :where(.rt-ScrollAreaRoot, .rt-MessageScrollerViewport) {
|
|
188
|
+
--scroll-fade-start: initial;
|
|
189
|
+
--scroll-fade-end: initial;
|
|
190
|
+
}
|
|
@@ -11,9 +11,17 @@ const scrollAreaPropDefs = {
|
|
|
11
11
|
size: { type: 'enum', className: 'rt-r-size', values: sizes, default: '1', responsive: true },
|
|
12
12
|
...radiusPropDef,
|
|
13
13
|
scrollbars: { type: 'enum', values: scrollbarsValues, default: 'both' },
|
|
14
|
+
/**
|
|
15
|
+
* Fades the content toward the top and bottom edges while there is more content past them.
|
|
16
|
+
* An edge with nothing hidden past it does not fade. A floating band over an edge can set
|
|
17
|
+
* `--scroll-fade-start` or `--scroll-fade-end` to its height, so content fades as it passes
|
|
18
|
+
* under the band.
|
|
19
|
+
*/
|
|
20
|
+
fade: { type: 'boolean', default: false },
|
|
14
21
|
} satisfies {
|
|
15
22
|
size: PropDef<(typeof sizes)[number]>;
|
|
16
23
|
scrollbars: PropDef<(typeof scrollbarsValues)[number]>;
|
|
24
|
+
fade: PropDef<boolean>;
|
|
17
25
|
};
|
|
18
26
|
|
|
19
27
|
export { scrollAreaPropDefs };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { ScrollArea as ScrollAreaPrimitive } from 'radix-ui';
|
|
4
|
+
import { useComposedRefs } from 'radix-ui/internal';
|
|
4
5
|
|
|
5
6
|
import { scrollAreaPropDefs } from './scroll-area.props.js';
|
|
7
|
+
import { useScrollEdges } from '../hooks/use-scroll-edges.js';
|
|
6
8
|
import { extractMarginProps } from '../helpers/extract-margin-props.js';
|
|
7
9
|
import { getMarginStyles } from '../helpers/get-margin-styles.js';
|
|
8
10
|
import { getResponsiveClassNames } from '../helpers/get-responsive-styles.js';
|
|
@@ -35,14 +37,18 @@ const ScrollArea = React.forwardRef<ScrollAreaElement, ScrollAreaProps>((props,
|
|
|
35
37
|
size = scrollAreaPropDefs.size.default,
|
|
36
38
|
radius = scrollAreaPropDefs.radius.default,
|
|
37
39
|
scrollbars = scrollAreaPropDefs.scrollbars.default,
|
|
40
|
+
fade = scrollAreaPropDefs.fade.default,
|
|
38
41
|
...viewportProps
|
|
39
42
|
} = marginRest;
|
|
43
|
+
const setEdgesElement = useScrollEdges<HTMLDivElement>(fade);
|
|
44
|
+
const viewportRef = useComposedRefs(forwardedRef, setEdgesElement);
|
|
40
45
|
|
|
41
46
|
return (
|
|
42
47
|
<ScrollAreaPrimitive.Root
|
|
43
48
|
type={type}
|
|
44
49
|
scrollHideDelay={scrollHideDelay}
|
|
45
50
|
className={classNames('rt-ScrollAreaRoot', marginClassNames, className)}
|
|
51
|
+
data-fade={fade ? '' : undefined}
|
|
46
52
|
style={mergeStyles(marginCustomProperties, style)}
|
|
47
53
|
asChild={asChild}
|
|
48
54
|
>
|
|
@@ -50,7 +56,7 @@ const ScrollArea = React.forwardRef<ScrollAreaElement, ScrollAreaProps>((props,
|
|
|
50
56
|
<>
|
|
51
57
|
<ScrollAreaPrimitive.Viewport
|
|
52
58
|
{...viewportProps}
|
|
53
|
-
ref={
|
|
59
|
+
ref={viewportRef}
|
|
54
60
|
className="rt-ScrollAreaViewport"
|
|
55
61
|
>
|
|
56
62
|
{children}
|