rift-ds 1.17.0 → 1.19.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/behaviors/useAnchoredPosition.d.ts +3 -1
- package/behaviors/useAnchoredPosition.js +1 -0
- package/behaviors/useTopLayer.d.ts +35 -0
- package/behaviors/useTopLayer.js +22 -0
- package/bin/templates/blocks/app/dashboard/page.module.css +4 -3
- package/bin/templates/blocks/app/dashboard/page.tsx +1 -1
- package/bin/templates/blocks/components/blocks/AppShell.module.css +50 -0
- package/bin/templates/blocks/components/blocks/AppShell.tsx +25 -6
- package/chat/ChatLauncher.js +23 -0
- package/chat/ChatThreads.d.ts +3 -1
- package/chat/ChatThreads.js +3 -1
- package/chat/ChatWidget.css +8 -3
- package/components/AiButton/AiButton.css +11 -0
- package/components/AiButton/AiButton.d.ts +2 -0
- package/components/AiButton/AiButton.js +3 -1
- package/components/AppSidebar/AppSidebar.css +142 -52
- package/components/AppSidebar/AppSidebar.d.ts +2 -2
- package/components/AppSidebar/AppSidebar.js +16 -9
- package/components/Chart/BarChart.js +1 -0
- package/components/Chart/Chart.css +6 -0
- package/components/Chart/ComboChart.js +1 -0
- package/components/Chart/StackedBarChart.js +1 -0
- package/components/CommandPaletteTrigger/CommandPaletteTrigger.css +13 -1
- package/components/Composer/Composer.css +72 -0
- package/components/Composer/Composer.d.ts +5 -1
- package/components/Composer/Composer.js +8 -1
- package/components/DataTable/DataTable.css +7 -3
- package/components/Popover/Popover.d.ts +2 -0
- package/components/Popover/Popover.js +2 -1
- package/components/SegmentedControl/SegmentedControl.css +3 -1
- package/components/SegmentedControl/SegmentedControl.js +2 -0
- package/components/SidebarPanel/SidebarPanel.css +10 -2
- package/components/SidebarPanel/SidebarPanel.d.ts +1 -1
- package/components/SidebarPanel/SidebarPanel.js +5 -2
- package/components/SiteHeader/SiteHeader.css +63 -5
- package/components/SiteHeader/SiteHeader.d.ts +11 -3
- package/components/SiteHeader/SiteHeader.js +51 -16
- package/components/SourceChip/SourceChip.css +5 -1
- package/components/SourceChip/SourceChip.js +3 -0
- package/components/Stat/Stat.css +57 -0
- package/components/Stat/Stat.d.ts +8 -2
- package/components/Stat/Stat.js +4 -2
- package/components/TableToolbar/TableToolbar.css +130 -1
- package/components/TableToolbar/TableToolbar.d.ts +52 -0
- package/components/TableToolbar/TableToolbar.js +232 -32
- package/components/ThemeToggle/ThemeToggle.css +26 -0
- package/components/ThemeToggle/ThemeToggle.d.ts +11 -1
- package/components/ThemeToggle/ThemeToggle.js +36 -5
- package/components/Toast/Toast.css +4 -0
- package/components/Toast/Toast.d.ts +9 -0
- package/components/Toast/Toast.js +9 -2
- package/components/Tooltip/Tooltip.css +9 -4
- package/components/Tooltip/Tooltip.d.ts +4 -2
- package/components/Tooltip/Tooltip.js +16 -4
- package/index.js +2 -1
- package/package.json +1 -1
- package/tokens/motion.d.ts +2 -0
- package/tokens/motion.js +2 -0
- package/tokens/tokens-light.css +4 -3
|
@@ -268,6 +268,9 @@
|
|
|
268
268
|
opacity: 1;
|
|
269
269
|
}
|
|
270
270
|
|
|
271
|
+
/* The trailing pill holds a beat off the row's end, so it sits as far in
|
|
272
|
+
from the rail's edge as the icon does at the start. A word is a quiet
|
|
273
|
+
pill; a count takes the count badge pair (the --count rule below). */
|
|
271
274
|
.ds-app-sidebar__btn-badge {
|
|
272
275
|
font-family: var(--font-caption-family);
|
|
273
276
|
font-size: var(--font-caption-size);
|
|
@@ -277,6 +280,7 @@
|
|
|
277
280
|
background-color: var(--color-bg-container-tertiary);
|
|
278
281
|
border-radius: var(--radius-pill);
|
|
279
282
|
padding: var(--padding-050) var(--padding-200);
|
|
283
|
+
margin-inline-end: var(--padding-100);
|
|
280
284
|
min-width: 0;
|
|
281
285
|
flex-shrink: 1;
|
|
282
286
|
overflow: hidden;
|
|
@@ -288,6 +292,61 @@
|
|
|
288
292
|
opacity: 1;
|
|
289
293
|
}
|
|
290
294
|
|
|
295
|
+
/* On a filled row the quiet pill steps back to the page ground, or it
|
|
296
|
+
would share the row's fill and dissolve into it. */
|
|
297
|
+
.ds-app-sidebar__btn--active .ds-app-sidebar__btn-badge:not(.ds-app-sidebar__btn-badge--count),
|
|
298
|
+
.ds-app-sidebar__btn:hover .ds-app-sidebar__btn-badge:not(.ds-app-sidebar__btn-badge--count),
|
|
299
|
+
.ds-app-sidebar__sub-btn--active .ds-app-sidebar__btn-badge:not(.ds-app-sidebar__btn-badge--count),
|
|
300
|
+
.ds-app-sidebar__sub-btn:hover .ds-app-sidebar__btn-badge:not(.ds-app-sidebar__btn-badge--count) {
|
|
301
|
+
background-color: var(--color-bg-page-primary);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* A count: a solid pill on the count badge pair, the "how many" mark
|
|
305
|
+
BottomNav and TableToolbar share, which reads on any row fill. */
|
|
306
|
+
.ds-app-sidebar__btn-badge--count {
|
|
307
|
+
color: var(--color-count-badge-text);
|
|
308
|
+
background-color: var(--color-count-badge-bg);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* The icon's seat: the same box as the icon, there to anchor the corner
|
|
312
|
+
copy of the count. */
|
|
313
|
+
.ds-app-sidebar__btn-seat {
|
|
314
|
+
position: relative;
|
|
315
|
+
display: inline-flex;
|
|
316
|
+
flex-shrink: 0;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/* The collapsed rail's count rides the icon's top-end corner, BottomNav's
|
|
320
|
+
badge in size and pair. Its end edge sits on the row's padding edge, so
|
|
321
|
+
it stays inside the collapsed row's clip, and it grows back over the
|
|
322
|
+
icon; it fades out as the trailing pill fades in. */
|
|
323
|
+
.ds-app-sidebar__btn-corner-badge {
|
|
324
|
+
position: absolute;
|
|
325
|
+
top: calc(var(--padding-100) * -1);
|
|
326
|
+
inset-inline-end: calc(var(--padding-200) * -1);
|
|
327
|
+
box-sizing: border-box;
|
|
328
|
+
min-width: 16px;
|
|
329
|
+
height: 16px;
|
|
330
|
+
padding: 0 var(--padding-100);
|
|
331
|
+
border-radius: var(--radius-pill);
|
|
332
|
+
background-color: var(--color-count-badge-bg);
|
|
333
|
+
color: var(--color-count-badge-text);
|
|
334
|
+
font-family: var(--font-caption-family);
|
|
335
|
+
font-size: var(--font-caption-size);
|
|
336
|
+
font-weight: var(--font-paragraph-sm-emphasis-weight);
|
|
337
|
+
line-height: var(--font-caption-line-height);
|
|
338
|
+
text-align: center;
|
|
339
|
+
white-space: nowrap;
|
|
340
|
+
pointer-events: none;
|
|
341
|
+
opacity: 1;
|
|
342
|
+
transition: opacity var(--motion-duration-base) var(--motion-ease-standard);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.ds-app-sidebar--expanded .ds-app-sidebar__btn-corner-badge {
|
|
346
|
+
opacity: 0;
|
|
347
|
+
transition-duration: var(--motion-duration-fast);
|
|
348
|
+
}
|
|
349
|
+
|
|
291
350
|
.ds-app-sidebar__btn-chevron {
|
|
292
351
|
--icon-size: var(--icon-size-600);
|
|
293
352
|
color: var(--color-icon-secondary);
|
|
@@ -400,15 +459,6 @@
|
|
|
400
459
|
flex-shrink: 0;
|
|
401
460
|
}
|
|
402
461
|
|
|
403
|
-
/* On a filled row the pill steps back to the page ground, or it would
|
|
404
|
-
share the row's fill and dissolve into it. */
|
|
405
|
-
.ds-app-sidebar__btn--active .ds-app-sidebar__btn-badge,
|
|
406
|
-
.ds-app-sidebar__btn:hover .ds-app-sidebar__btn-badge,
|
|
407
|
-
.ds-app-sidebar__sub-btn--active .ds-app-sidebar__btn-badge,
|
|
408
|
-
.ds-app-sidebar__sub-btn:hover .ds-app-sidebar__btn-badge {
|
|
409
|
-
background-color: var(--color-bg-page-primary);
|
|
410
|
-
}
|
|
411
|
-
|
|
412
462
|
.ds-app-sidebar__sub-chevron {
|
|
413
463
|
--icon-size: var(--icon-size-500);
|
|
414
464
|
flex-shrink: 0;
|
|
@@ -621,13 +671,12 @@
|
|
|
621
671
|
inset-inline-start: calc(var(--ds-sidebar-float-inset, 20px) + 280px + var(--gap-300));
|
|
622
672
|
}
|
|
623
673
|
|
|
624
|
-
/* Inset: the side panel joins the rail on the shell plane,
|
|
625
|
-
between
|
|
626
|
-
|
|
627
|
-
|
|
674
|
+
/* Inset: the side panel joins the rail on the shell plane, one hairline
|
|
675
|
+
divider between the two levels, and the inset content surface starts
|
|
676
|
+
beyond both (AppLayout reserves the panel's width while it shows). The
|
|
677
|
+
trailing edge needs no border: the surface's own edge ends the panel. */
|
|
628
678
|
.ds-app-sidebar__panel--inset {
|
|
629
679
|
background-color: var(--color-bg-app-shell);
|
|
630
|
-
border-inline-start-color: transparent;
|
|
631
680
|
border-inline-end-color: transparent;
|
|
632
681
|
}
|
|
633
682
|
|
|
@@ -638,85 +687,126 @@
|
|
|
638
687
|
widens to 80px and names every destination:
|
|
639
688
|
a pill indicator behind the icon, the label
|
|
640
689
|
beneath (the navigation-rail pattern).
|
|
690
|
+
|
|
691
|
+
Expand/collapse holds one seat, as ThreadPanel
|
|
692
|
+
does: the logo, every icon and the avatar sit
|
|
693
|
+
at the same x and y in both states, so only the
|
|
694
|
+
rail's width, the rows' explicit heights and
|
|
695
|
+
the labels' opacity move. The caption under the
|
|
696
|
+
icon fades out as the inline label fades in.
|
|
641
697
|
============================================ */
|
|
642
698
|
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) {
|
|
643
699
|
width: 80px;
|
|
644
700
|
}
|
|
645
701
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
702
|
+
/* The seat: 12px row margin + 16px row padding puts every 24px icon's
|
|
703
|
+
centre on the 80px rail's centre line (28 + 12 = 40), and the logo,
|
|
704
|
+
the category labels and the profile row share that leading edge. */
|
|
705
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__logo {
|
|
706
|
+
padding-inline-start: calc(var(--padding-500) + var(--padding-200));
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__category {
|
|
710
|
+
padding-inline-start: calc(var(--padding-500) + var(--padding-200));
|
|
649
711
|
}
|
|
650
712
|
|
|
651
|
-
.ds-app-sidebar--panel-mode
|
|
713
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__nav {
|
|
652
714
|
gap: 0;
|
|
715
|
+
transition: gap var(--motion-duration-slow) var(--motion-ease-emphasized);
|
|
653
716
|
}
|
|
654
717
|
|
|
655
|
-
.ds-app-sidebar--panel-mode
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
718
|
+
.ds-app-sidebar--panel-mode.ds-app-sidebar--expanded .ds-app-sidebar__nav {
|
|
719
|
+
gap: var(--gap-100);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
/* The icon is pinned to the row's top in both states, so it holds its
|
|
723
|
+
y while the row's height glides between its two explicit values. */
|
|
724
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__btn {
|
|
725
|
+
position: relative;
|
|
726
|
+
isolation: isolate;
|
|
727
|
+
align-items: flex-start;
|
|
728
|
+
/* Collapsed: the 32px indicator, the caption beneath it, a 4px beat
|
|
729
|
+
above, between and below. */
|
|
730
|
+
height: calc(32px + var(--font-caption-line-height) + var(--padding-100) * 3);
|
|
731
|
+
margin: 0 var(--padding-300);
|
|
732
|
+
padding: var(--padding-200) var(--padding-200) var(--padding-200) var(--padding-400);
|
|
663
733
|
overflow: visible;
|
|
734
|
+
transition:
|
|
735
|
+
background-color var(--motion-duration-fast) var(--motion-ease-standard),
|
|
736
|
+
height var(--motion-duration-slow) var(--motion-ease-emphasized);
|
|
664
737
|
}
|
|
665
738
|
|
|
666
|
-
.ds-app-sidebar--panel-mode
|
|
667
|
-
|
|
668
|
-
background-color: transparent;
|
|
739
|
+
.ds-app-sidebar--panel-mode.ds-app-sidebar--expanded .ds-app-sidebar__btn {
|
|
740
|
+
height: 40px;
|
|
669
741
|
}
|
|
670
742
|
|
|
671
|
-
.ds-app-sidebar--panel-mode
|
|
672
|
-
|
|
673
|
-
gap: var(--gap-100);
|
|
674
|
-
width: 100%;
|
|
743
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__btn-left {
|
|
744
|
+
height: 24px;
|
|
675
745
|
}
|
|
676
746
|
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
the icon and label off centre. Here they leave the layout outright. */
|
|
680
|
-
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn-chevron,
|
|
681
|
-
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn-badge {
|
|
682
|
-
display: none;
|
|
747
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__btn-chevron {
|
|
748
|
+
flex-shrink: 0;
|
|
683
749
|
}
|
|
684
750
|
|
|
685
751
|
/* The indicator: a 56 x 32 pill behind the icon carries hover and the
|
|
686
|
-
selection, so the
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
752
|
+
selection while collapsed, so the caption stays legible on the page
|
|
753
|
+
ground; expanded, the row's own pill takes over and the two crossfade. */
|
|
754
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__btn::before {
|
|
755
|
+
content: '';
|
|
756
|
+
position: absolute;
|
|
757
|
+
top: var(--padding-100);
|
|
758
|
+
inset-inline-start: 0;
|
|
759
|
+
z-index: -1;
|
|
691
760
|
width: 56px;
|
|
692
761
|
height: 32px;
|
|
693
762
|
border-radius: var(--radius-pill);
|
|
763
|
+
background-color: transparent;
|
|
694
764
|
transition: background-color var(--motion-duration-fast) var(--motion-ease-standard);
|
|
695
765
|
}
|
|
696
766
|
|
|
697
|
-
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn:hover
|
|
698
|
-
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn--active
|
|
767
|
+
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn:hover,
|
|
768
|
+
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn--active {
|
|
769
|
+
background-color: transparent;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn:hover::before,
|
|
773
|
+
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn--active::before {
|
|
699
774
|
background-color: var(--color-action-passive-bg-hover);
|
|
700
775
|
}
|
|
701
776
|
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
777
|
+
/* The caption: centred under the indicator, the rail's 72px wide
|
|
778
|
+
(80 less a 4px inset either side), fading out as the rail opens. */
|
|
779
|
+
.ds-app-sidebar__btn-caption {
|
|
780
|
+
position: absolute;
|
|
781
|
+
top: calc(32px + var(--padding-100) * 2);
|
|
782
|
+
inset-inline-start: calc(var(--padding-200) * -1);
|
|
783
|
+
width: 72px;
|
|
705
784
|
font-family: var(--font-caption-family);
|
|
706
785
|
font-size: var(--font-caption-size);
|
|
707
786
|
font-weight: var(--font-caption-weight);
|
|
708
787
|
line-height: var(--font-caption-line-height);
|
|
709
788
|
letter-spacing: var(--font-caption-letter-spacing);
|
|
789
|
+
color: var(--color-text-primary);
|
|
710
790
|
text-align: center;
|
|
791
|
+
white-space: nowrap;
|
|
792
|
+
overflow: hidden;
|
|
711
793
|
text-overflow: ellipsis;
|
|
794
|
+
pointer-events: none;
|
|
795
|
+
opacity: 1;
|
|
796
|
+
transition: opacity var(--motion-duration-base) var(--motion-ease-standard);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
.ds-app-sidebar--expanded .ds-app-sidebar__btn-caption {
|
|
800
|
+
opacity: 0;
|
|
801
|
+
transition-duration: var(--motion-duration-fast);
|
|
712
802
|
}
|
|
713
803
|
|
|
714
|
-
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn--active .ds-app-sidebar__btn-
|
|
804
|
+
.ds-app-sidebar--panel-mode:not(.ds-app-sidebar--expanded) .ds-app-sidebar__btn--active .ds-app-sidebar__btn-caption {
|
|
715
805
|
font-weight: var(--font-paragraph-sm-emphasis-weight);
|
|
716
806
|
}
|
|
717
807
|
|
|
718
|
-
.ds-app-sidebar--panel-mode
|
|
719
|
-
/* Centres the 40px avatar in the 80px rail. */
|
|
808
|
+
.ds-app-sidebar--panel-mode .ds-app-sidebar__profile {
|
|
809
|
+
/* Centres the 40px avatar in the 80px rail, and holds it there open. */
|
|
720
810
|
padding: 0 var(--padding-500);
|
|
721
811
|
}
|
|
722
812
|
|
|
@@ -9,7 +9,7 @@ export interface AppSidebarSubItem {
|
|
|
9
9
|
onClick?: () => void;
|
|
10
10
|
/** Renders the sub-item as a real link to this URL instead of a button. Ignored when the sub-item has children, whose row opens them */
|
|
11
11
|
href?: string;
|
|
12
|
-
/** Trailing
|
|
12
|
+
/** Trailing pill, e.g. unread items. A count takes the count badge colours; a word stays a quiet pill */
|
|
13
13
|
badge?: string | number;
|
|
14
14
|
/** Group heading this entry sits under when it is listed in the panel (see `subNav`); ignored in the accordion */
|
|
15
15
|
group?: string;
|
|
@@ -42,7 +42,7 @@ export interface AppSidebarItem {
|
|
|
42
42
|
onClick?: () => void;
|
|
43
43
|
/** Renders the item as a real link to this URL instead of a button. Ignored when the item has children, whose row is the accordion toggle */
|
|
44
44
|
href?: string;
|
|
45
|
-
/** Trailing
|
|
45
|
+
/** Trailing pill, e.g. unread items. A count takes the count badge colours and, while the rail is collapsed, rides the icon's corner; a word stays a quiet pill, hidden while collapsed */
|
|
46
46
|
badge?: string | number;
|
|
47
47
|
/** Sub-items: an accordion under the row, or the side panel's contents when `subNav="panel"` */
|
|
48
48
|
children?: AppSidebarSubItem[];
|
|
@@ -14,6 +14,9 @@ import "../../behaviors/direction.css";
|
|
|
14
14
|
import "../../fonts/material-symbols.css";
|
|
15
15
|
import { mirrorClass } from "../../behaviors/direction.js";
|
|
16
16
|
import { distinctPixelInks } from "../PixelAvatar/pixelInks.js";
|
|
17
|
+
function isCount(badge) {
|
|
18
|
+
return typeof badge === "number" || /^\d+\+?$/.test(badge.trim());
|
|
19
|
+
}
|
|
17
20
|
function DefaultLogo() {
|
|
18
21
|
return /* @__PURE__ */ jsxs(
|
|
19
22
|
"svg",
|
|
@@ -315,16 +318,20 @@ const AppSidebar = React.forwardRef(function AppSidebar2({
|
|
|
315
318
|
].filter(Boolean).join(" ");
|
|
316
319
|
const itemContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
317
320
|
/* @__PURE__ */ jsxs("span", { className: `${baseClass}__btn-left`, children: [
|
|
318
|
-
|
|
319
|
-
"span",
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
/* @__PURE__ */ jsxs("span", { className: `${baseClass}__btn-seat`, children: [
|
|
322
|
+
item.pixelAvatar ? /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-icon ${baseClass}__btn-icon--avatar`, children: /* @__PURE__ */ jsx(PixelAvatar, { name: avatarSeed(item), ink: avatarInks.get(item.key) }) }) : /* @__PURE__ */ jsx(
|
|
323
|
+
"span",
|
|
324
|
+
{
|
|
325
|
+
className: `${baseClass}__btn-icon${typeof item.icon === "string" ? ` material-symbols-rounded ${mirrorClass(item.icon)}` : ""}`,
|
|
326
|
+
children: item.icon
|
|
327
|
+
}
|
|
328
|
+
),
|
|
329
|
+
item.badge !== void 0 && isCount(item.badge) && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-corner-badge`, "aria-hidden": "true", children: item.badge })
|
|
330
|
+
] }),
|
|
325
331
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-label`, children: item.label })
|
|
326
332
|
] }),
|
|
327
|
-
|
|
333
|
+
isPanelMode && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-caption`, "aria-hidden": "true", children: item.label }),
|
|
334
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-badge${isCount(item.badge) ? ` ${baseClass}__btn-badge--count` : ""}`, children: item.badge }),
|
|
328
335
|
hasChildren && /* @__PURE__ */ jsx(
|
|
329
336
|
"span",
|
|
330
337
|
{
|
|
@@ -390,7 +397,7 @@ const AppSidebar = React.forwardRef(function AppSidebar2({
|
|
|
390
397
|
].filter(Boolean).join(" ");
|
|
391
398
|
const subLabel = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
392
399
|
/* @__PURE__ */ jsx("span", { className: `${baseClass}__sub-label`, children: sub.label }),
|
|
393
|
-
sub.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-badge`, children: sub.badge }),
|
|
400
|
+
sub.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: `${baseClass}__btn-badge${isCount(sub.badge) ? ` ${baseClass}__btn-badge--count` : ""}`, children: sub.badge }),
|
|
394
401
|
subHasChildren && /* @__PURE__ */ jsx(
|
|
395
402
|
"span",
|
|
396
403
|
{
|
|
@@ -100,6 +100,12 @@
|
|
|
100
100
|
position: relative;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
/* A bar is a large filled mass, so it takes a wash of its series colour, the
|
|
104
|
+
way an area fill does; thin marks (lines, dots, swatches) keep the full token. */
|
|
105
|
+
.ds-chart__bar .recharts-rectangle {
|
|
106
|
+
fill-opacity: 0.45;
|
|
107
|
+
}
|
|
108
|
+
|
|
103
109
|
/* ============================================
|
|
104
110
|
BARE MODE — the chart sits inside another
|
|
105
111
|
panel that supplies the surface, so its own
|
|
@@ -70,12 +70,24 @@
|
|
|
70
70
|
padding: 0 var(--padding-200);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/* The compact field's keycaps step down to caption type with no block
|
|
74
|
+
padding, so they sit inside the shorter row with air around them
|
|
75
|
+
instead of filling it. */
|
|
76
|
+
.ds-command-palette-trigger--compact .ds-kbd--compact {
|
|
77
|
+
padding-block: 0;
|
|
78
|
+
font-size: var(--font-caption-size);
|
|
79
|
+
line-height: var(--font-caption-line-height);
|
|
80
|
+
}
|
|
81
|
+
|
|
73
82
|
/* Folded to the icon: a circle the row height across, hovering like the
|
|
74
|
-
theme picker's trigger rather than like a field.
|
|
83
|
+
theme picker's trigger rather than like a field. With no prompt beside it
|
|
84
|
+
the glyph is the control, so it takes the icon colour the family's other
|
|
85
|
+
circles wear rather than the field's placeholder tone. */
|
|
75
86
|
.ds-command-palette-trigger--icon-only {
|
|
76
87
|
justify-content: center;
|
|
77
88
|
width: var(--control-height-default);
|
|
78
89
|
padding: 0;
|
|
90
|
+
color: var(--color-action-icon-default);
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
.ds-command-palette-trigger--compact.ds-command-palette-trigger--icon-only {
|
|
@@ -633,3 +633,75 @@
|
|
|
633
633
|
.ds-composer--disabled.ds-composer--mentions .ds-composer__textarea {
|
|
634
634
|
color: transparent;
|
|
635
635
|
}
|
|
636
|
+
|
|
637
|
+
/* ============================================
|
|
638
|
+
COMPACT: the same shell at the compact density
|
|
639
|
+
============================================ */
|
|
640
|
+
.ds-composer--compact {
|
|
641
|
+
--ds-composer-send-size: var(--control-height-compact);
|
|
642
|
+
--ds-composer-text-inset: var(--padding-300);
|
|
643
|
+
/* Concentric on this density's tighter ring. */
|
|
644
|
+
--ds-composer-radius: calc(
|
|
645
|
+
min(var(--radius-pill), var(--ds-composer-send-size) / 2) + var(--padding-100) + var(--border-025)
|
|
646
|
+
);
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
.ds-composer--compact .ds-composer__content {
|
|
650
|
+
padding-block: var(--padding-200) var(--padding-100);
|
|
651
|
+
height: calc(var(--ds-composer-text-height, var(--font-paragraph-sm-line-height)) + var(--padding-200) + var(--padding-100));
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
.ds-composer--compact .ds-composer__textarea {
|
|
655
|
+
font-size: var(--font-paragraph-sm-size);
|
|
656
|
+
line-height: var(--font-paragraph-sm-line-height);
|
|
657
|
+
letter-spacing: var(--font-paragraph-sm-letter-spacing);
|
|
658
|
+
max-height: calc(var(--ds-composer-max-rows, 8) * var(--font-paragraph-sm-line-height));
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.ds-composer--compact .ds-composer__footer {
|
|
662
|
+
padding: var(--padding-100);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
/* ============================================
|
|
666
|
+
INLINE: one row at the control height, the send button on the text's line.
|
|
667
|
+
The shell is an input here, so it does not float, and the button sits
|
|
668
|
+
inside the height, concentric on a thinner ring.
|
|
669
|
+
============================================ */
|
|
670
|
+
.ds-composer--inline {
|
|
671
|
+
--ds-composer-control: var(--control-height-default);
|
|
672
|
+
--ds-composer-line: var(--font-paragraph-line-height);
|
|
673
|
+
--ds-composer-send-size: calc(var(--ds-composer-control) - var(--padding-050) * 2 - var(--border-025) * 2);
|
|
674
|
+
--ds-composer-radius: calc(
|
|
675
|
+
min(var(--radius-pill), var(--ds-composer-send-size) / 2) + var(--padding-050) + var(--border-025)
|
|
676
|
+
);
|
|
677
|
+
flex-direction: row;
|
|
678
|
+
align-items: center;
|
|
679
|
+
box-shadow: none;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.ds-composer--inline.ds-composer--compact {
|
|
683
|
+
--ds-composer-control: var(--control-height-compact);
|
|
684
|
+
--ds-composer-line: var(--font-paragraph-sm-line-height);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.ds-composer--inline .ds-composer__content,
|
|
688
|
+
.ds-composer--inline.ds-composer--compact .ds-composer__content {
|
|
689
|
+
--ds-composer-text-block: calc((var(--ds-composer-control) - var(--ds-composer-line)) / 2 - var(--border-025));
|
|
690
|
+
flex: 1;
|
|
691
|
+
min-width: 0;
|
|
692
|
+
width: auto;
|
|
693
|
+
padding-block: var(--ds-composer-text-block);
|
|
694
|
+
padding-inline: var(--ds-composer-text-inset) var(--padding-100);
|
|
695
|
+
height: calc(var(--ds-composer-text-height, var(--ds-composer-line)) + var(--ds-composer-text-block) * 2);
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
.ds-composer--inline .ds-composer__footer,
|
|
699
|
+
.ds-composer--inline.ds-composer--compact .ds-composer__footer {
|
|
700
|
+
flex-shrink: 0;
|
|
701
|
+
padding: var(--padding-050);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.ds-composer--inline .ds-composer__footer .ds-circular-button {
|
|
705
|
+
width: var(--ds-composer-send-size);
|
|
706
|
+
height: var(--ds-composer-send-size);
|
|
707
|
+
}
|
|
@@ -32,7 +32,11 @@ type ComposerOwnProps = {
|
|
|
32
32
|
streaming?: boolean;
|
|
33
33
|
/** Fires when the stop button is pressed while `streaming`. */
|
|
34
34
|
onStop?: () => void;
|
|
35
|
-
/**
|
|
35
|
+
/** The density, matching a table's or a bar's: `compact` tightens the padding and takes the smaller text and buttons. */
|
|
36
|
+
size?: 'default' | 'compact';
|
|
37
|
+
/** One row with the send button on the text's line, the shell exactly `size`'s control height, so it lines up with an Input or a table's toolbar. For a popover, a sheet or a tight bar. `maxRows` defaults to 1. */
|
|
38
|
+
inline?: boolean;
|
|
39
|
+
/** Growth cap in text rows before the textarea scrolls internally. Defaults to 8, or 1 when `inline`. */
|
|
36
40
|
maxRows?: number;
|
|
37
41
|
/**
|
|
38
42
|
* While focused, the shell wears AiButton's slowly rotating gradient ring
|
|
@@ -34,7 +34,9 @@ const Composer = React.forwardRef(
|
|
|
34
34
|
onSubmit,
|
|
35
35
|
streaming = false,
|
|
36
36
|
onStop,
|
|
37
|
-
|
|
37
|
+
size = "default",
|
|
38
|
+
inline = false,
|
|
39
|
+
maxRows = inline ? 1 : 8,
|
|
38
40
|
aiGlow = false,
|
|
39
41
|
context,
|
|
40
42
|
contextIcon,
|
|
@@ -362,6 +364,8 @@ const Composer = React.forwardRef(
|
|
|
362
364
|
const classes = [
|
|
363
365
|
baseClass,
|
|
364
366
|
aiGlow ? `${baseClass}--ai-glow` : "",
|
|
367
|
+
size === "compact" ? `${baseClass}--compact` : "",
|
|
368
|
+
inline ? `${baseClass}--inline` : "",
|
|
365
369
|
streaming ? `${baseClass}--streaming` : "",
|
|
366
370
|
disabled ? `${baseClass}--disabled` : "",
|
|
367
371
|
dragging ? `${baseClass}--dragging` : "",
|
|
@@ -469,6 +473,7 @@ const Composer = React.forwardRef(
|
|
|
469
473
|
{
|
|
470
474
|
icon: "add",
|
|
471
475
|
variant: "tertiary",
|
|
476
|
+
size,
|
|
472
477
|
ariaLabel: attachLabel,
|
|
473
478
|
disabled,
|
|
474
479
|
onClick: () => fileInputRef.current?.click()
|
|
@@ -483,6 +488,7 @@ const Composer = React.forwardRef(
|
|
|
483
488
|
{
|
|
484
489
|
icon: "stop",
|
|
485
490
|
variant: "primary",
|
|
491
|
+
size,
|
|
486
492
|
ariaLabel: stopLabel,
|
|
487
493
|
disabled,
|
|
488
494
|
onClick: onStop
|
|
@@ -492,6 +498,7 @@ const Composer = React.forwardRef(
|
|
|
492
498
|
{
|
|
493
499
|
icon: "arrow_upward",
|
|
494
500
|
variant: "primary",
|
|
501
|
+
size,
|
|
495
502
|
ariaLabel: sendLabel,
|
|
496
503
|
disabled: !canSend,
|
|
497
504
|
onClick: submit
|
|
@@ -848,7 +848,10 @@
|
|
|
848
848
|
read, from a visually hidden thead.
|
|
849
849
|
============================================ */
|
|
850
850
|
|
|
851
|
+
/* The wrapper qualifier outranks Table's phone rule, which holds a
|
|
852
|
+
column table at max-content so it scrolls: cards fit the frame. */
|
|
851
853
|
.ds-data-table__grid--stacked,
|
|
854
|
+
.ds-table__wrapper .ds-data-table__grid--stacked,
|
|
852
855
|
.ds-data-table__grid--stacked > tbody {
|
|
853
856
|
display: block;
|
|
854
857
|
width: 100%;
|
|
@@ -901,8 +904,10 @@
|
|
|
901
904
|
width: auto;
|
|
902
905
|
}
|
|
903
906
|
|
|
907
|
+
/* The actions close the title line, at its end, with or without a row header beside them. */
|
|
904
908
|
.ds-data-table__grid--stacked .ds-data-table__actions {
|
|
905
909
|
order: 1;
|
|
910
|
+
margin-inline-start: auto;
|
|
906
911
|
}
|
|
907
912
|
|
|
908
913
|
/* A row has no drag on a card, and no filler column. */
|
|
@@ -922,11 +927,10 @@
|
|
|
922
927
|
gap: var(--gap-200);
|
|
923
928
|
}
|
|
924
929
|
|
|
930
|
+
/* A long header wraps in its quarter rather than losing its end. */
|
|
925
931
|
.ds-data-table__stack-label {
|
|
926
932
|
min-width: 0;
|
|
927
|
-
overflow:
|
|
928
|
-
text-overflow: ellipsis;
|
|
929
|
-
white-space: nowrap;
|
|
933
|
+
overflow-wrap: break-word;
|
|
930
934
|
font-family: var(--font-caption-family);
|
|
931
935
|
font-size: var(--font-caption-size);
|
|
932
936
|
font-weight: var(--font-caption-weight);
|
|
@@ -19,6 +19,8 @@ type PopoverOwnProps = {
|
|
|
19
19
|
surface?: 'panel' | 'menu';
|
|
20
20
|
/** Preferred position. `left` and `right` are screen sides; `start` and `end` follow the reading direction, so `end` opens to the right in English and to the left in Arabic. */
|
|
21
21
|
position?: 'top' | 'bottom' | 'left' | 'right' | 'start' | 'end';
|
|
22
|
+
/** Which edge of the trigger the panel lines up with, on the top and bottom sides. `start` and `end` follow the reading direction. Defaults to `start`. */
|
|
23
|
+
align?: 'start' | 'end';
|
|
22
24
|
/** Trigger mode */
|
|
23
25
|
trigger?: 'click' | 'hover';
|
|
24
26
|
/** Whether the popover is open (controlled mode) */
|
|
@@ -14,6 +14,7 @@ const Popover = React.forwardRef(
|
|
|
14
14
|
size = "default",
|
|
15
15
|
surface = "panel",
|
|
16
16
|
position = "bottom",
|
|
17
|
+
align = "start",
|
|
17
18
|
trigger = "click",
|
|
18
19
|
open: controlledOpen,
|
|
19
20
|
defaultOpen = false,
|
|
@@ -77,7 +78,7 @@ const Popover = React.forwardRef(
|
|
|
77
78
|
anchorRef: triggerRef,
|
|
78
79
|
panelRef,
|
|
79
80
|
side: position,
|
|
80
|
-
align
|
|
81
|
+
align,
|
|
81
82
|
gapProperty: "--gap-050"
|
|
82
83
|
});
|
|
83
84
|
const baseClass = "ds-popover";
|
|
@@ -247,7 +247,9 @@
|
|
|
247
247
|
============================================ */
|
|
248
248
|
|
|
249
249
|
.ds-segmented-control__label--tip {
|
|
250
|
-
/* Out of flow at rest; the behaviour makes it fixed once it shows
|
|
250
|
+
/* Out of flow at rest; the behaviour makes it fixed once it shows, and
|
|
251
|
+
lifts it into the top layer (src/behaviors/useTopLayer), above every
|
|
252
|
+
z-index on the page. */
|
|
251
253
|
position: absolute;
|
|
252
254
|
z-index: var(--layer-floating);
|
|
253
255
|
padding: var(--padding-150) var(--padding-200);
|
|
@@ -6,6 +6,7 @@ import "../../behaviors/visually-hidden.css";
|
|
|
6
6
|
import "../../fonts/material-symbols.css";
|
|
7
7
|
import { mirrorClass, logicalArrowKey } from "../../behaviors/direction.js";
|
|
8
8
|
import { useAnchoredPosition } from "../../behaviors/useAnchoredPosition.js";
|
|
9
|
+
import { useTopLayer } from "../../behaviors/useTopLayer.js";
|
|
9
10
|
const SegmentedControl = React.forwardRef(
|
|
10
11
|
({
|
|
11
12
|
segments,
|
|
@@ -197,6 +198,7 @@ const SegmentedControl = React.forwardRef(
|
|
|
197
198
|
tipLabelRef.current = label;
|
|
198
199
|
setTip([...strip.querySelectorAll(`.${baseClass}__segment`)].indexOf(segment));
|
|
199
200
|
};
|
|
201
|
+
useTopLayer({ open: tip !== null, panelRef: tipLabelRef, target: tip });
|
|
200
202
|
useAnchoredPosition({
|
|
201
203
|
open: tip !== null,
|
|
202
204
|
target: tip,
|
|
@@ -223,11 +223,19 @@
|
|
|
223
223
|
|
|
224
224
|
/* On a filled row the pill steps back to the page ground, or it would
|
|
225
225
|
share the row's fill and dissolve into it. */
|
|
226
|
-
.ds-sidebar-panel__row--active .ds-sidebar-panel__badge,
|
|
227
|
-
.ds-sidebar-panel__row:hover .ds-sidebar-panel__badge {
|
|
226
|
+
.ds-sidebar-panel__row--active .ds-sidebar-panel__badge:not(.ds-sidebar-panel__badge--count),
|
|
227
|
+
.ds-sidebar-panel__row:hover .ds-sidebar-panel__badge:not(.ds-sidebar-panel__badge--count) {
|
|
228
228
|
background-color: var(--color-bg-page-primary);
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
+
/* A count: a solid pill on the count badge pair, the "how many" mark the
|
|
232
|
+
rail beside it, BottomNav and TableToolbar share, which reads on any
|
|
233
|
+
row fill. A word such as "New" keeps the quiet pill above. */
|
|
234
|
+
.ds-sidebar-panel__badge--count {
|
|
235
|
+
color: var(--color-count-badge-text);
|
|
236
|
+
background-color: var(--color-count-badge-bg);
|
|
237
|
+
}
|
|
238
|
+
|
|
231
239
|
.ds-sidebar-panel__chevron {
|
|
232
240
|
--icon-size: var(--icon-size-500);
|
|
233
241
|
flex-shrink: 0;
|