@nubisco/ui 3.2.0 → 3.4.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/dist/components/Board.d.ts +23 -0
- package/dist/components/Board.vue.d.ts +16 -8
- package/dist/components/Board.vue.d.ts.map +1 -1
- package/dist/components/Button.vue.d.ts.map +1 -1
- package/dist/components/Charts/GanttChart.vue.d.ts.map +1 -1
- package/dist/components/Charts/InterpolationChart.vue.d.ts.map +1 -1
- package/dist/components/Charts/shared/palette.d.ts +76 -1
- package/dist/components/Charts/shared/palette.d.ts.map +1 -1
- package/dist/components/CommandPalette.vue.d.ts.map +1 -1
- package/dist/components/Confirm.d.ts +199 -0
- package/dist/components/Confirm.env.d.ts +52 -0
- package/dist/components/Confirm.env.d.ts.map +1 -0
- package/dist/components/Confirm.vue.d.ts +61 -0
- package/dist/components/Confirm.vue.d.ts.map +1 -0
- package/dist/components/DatePicker.vue.d.ts +1 -1
- package/dist/components/InlineEdit.d.ts +24 -0
- package/dist/components/InlineEdit.vue.d.ts +20 -0
- package/dist/components/InlineEdit.vue.d.ts.map +1 -0
- package/dist/components/InlineLoading.d.ts +37 -0
- package/dist/components/InlineLoading.vue.d.ts +30 -0
- package/dist/components/InlineLoading.vue.d.ts.map +1 -0
- package/dist/components/MenuItem.vue.d.ts +1 -1
- package/dist/components/Modal.d.ts +35 -1
- package/dist/components/Modal.vue.d.ts +10 -1
- package/dist/components/Modal.vue.d.ts.map +1 -1
- package/dist/components/NotificationCenter.d.ts +184 -0
- package/dist/components/NotificationCenter.vue.d.ts +130 -0
- package/dist/components/NotificationCenter.vue.d.ts.map +1 -0
- package/dist/components/NotificationCenterItem.d.ts +53 -0
- package/dist/components/NotificationCenterItem.vue.d.ts +36 -0
- package/dist/components/NotificationCenterItem.vue.d.ts.map +1 -0
- package/dist/components/ProgressBar.vue.d.ts.map +1 -1
- package/dist/components/Shell.d.ts +138 -8
- package/dist/components/Shell.vue.d.ts +30 -3
- package/dist/components/Shell.vue.d.ts.map +1 -1
- package/dist/components/ShellPanel.d.ts +16 -0
- package/dist/components/ShellPanel.vue.d.ts +1 -0
- package/dist/components/ShellPanel.vue.d.ts.map +1 -1
- package/dist/components/SidebarLink.d.ts +14 -1
- package/dist/components/Skeleton.d.ts +87 -0
- package/dist/components/Skeleton.vue.d.ts +17 -0
- package/dist/components/Skeleton.vue.d.ts.map +1 -0
- package/dist/components/Spinner.d.ts +80 -0
- package/dist/components/Spinner.overlay.d.ts +56 -0
- package/dist/components/Spinner.overlay.d.ts.map +1 -0
- package/dist/components/Spinner.vue.d.ts +25 -0
- package/dist/components/Spinner.vue.d.ts.map +1 -0
- package/dist/components/Stepper.context.d.ts +48 -0
- package/dist/components/Stepper.context.d.ts.map +1 -0
- package/dist/components/Stepper.d.ts +101 -0
- package/dist/components/Stepper.vue.d.ts +31 -0
- package/dist/components/Stepper.vue.d.ts.map +1 -0
- package/dist/components/StepperStep.vue.d.ts +24 -0
- package/dist/components/StepperStep.vue.d.ts.map +1 -0
- package/dist/components/TextInput.vue.d.ts +2 -2
- package/dist/components/TextInput.vue.d.ts.map +1 -1
- package/dist/components/Toast.vue.d.ts +43 -0
- package/dist/components/Toast.vue.d.ts.map +1 -1
- package/dist/components/Toaster.d.ts +93 -0
- package/dist/components/Toaster.vue.d.ts +30 -0
- package/dist/components/Toaster.vue.d.ts.map +1 -0
- package/dist/components/UserMenu.vue.d.ts.map +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/composables/useConfirm.composable.d.ts +45 -0
- package/dist/composables/useConfirm.composable.d.ts.map +1 -0
- package/dist/composables/useInlineLoading.composable.d.ts +43 -0
- package/dist/composables/useInlineLoading.composable.d.ts.map +1 -0
- package/dist/composables/useLoadingAnnouncer.composable.d.ts +63 -0
- package/dist/composables/useLoadingAnnouncer.composable.d.ts.map +1 -0
- package/dist/composables/useScrollLock.composable.d.ts +47 -0
- package/dist/composables/useScrollLock.composable.d.ts.map +1 -0
- package/dist/composables/useShellSlot.composable.d.ts +193 -0
- package/dist/composables/useShellSlot.composable.d.ts.map +1 -0
- package/dist/composables/useToast.composable.d.ts +325 -0
- package/dist/composables/useToast.composable.d.ts.map +1 -0
- package/dist/directives/ToolTip.content.d.ts +20 -0
- package/dist/directives/ToolTip.content.d.ts.map +1 -0
- package/dist/directives/ToolTip.directive.d.ts +94 -8
- package/dist/directives/ToolTip.directive.d.ts.map +1 -1
- package/dist/global.d.ts +20 -0
- package/dist/index.cjs +8 -9
- package/dist/index.mjs +13970 -10511
- package/dist/main.d.ts +46 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/ui.css +1 -1
- package/package.json +1 -1
- package/src/styles/_reset.scss +5 -0
- package/src/styles/_theme.scss +171 -0
- package/src/styles/directives/_tooltip.scss +143 -21
package/package.json
CHANGED
package/src/styles/_reset.scss
CHANGED
|
@@ -84,6 +84,11 @@
|
|
|
84
84
|
a {
|
|
85
85
|
background-color: transparent;
|
|
86
86
|
all: unset;
|
|
87
|
+
/* `all: unset` resets box-sizing to content-box, and the element
|
|
88
|
+
* selector outranks the `*` border-box rule above, so every anchor
|
|
89
|
+
* (including link-rendered components like NbCard) would overflow the
|
|
90
|
+
* box its layout gave it by its own padding and border. */
|
|
91
|
+
box-sizing: border-box;
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
/**
|
package/src/styles/_theme.scss
CHANGED
|
@@ -146,6 +146,23 @@
|
|
|
146
146
|
--nb-c-primary-hover-a11y: var(--nb-c-grape-hyacinth-600-a11y);
|
|
147
147
|
--nb-c-primary-active: var(--nb-c-grape-hyacinth-700);
|
|
148
148
|
--nb-c-primary-active-a11y: var(--nb-c-grape-hyacinth-700-a11y);
|
|
149
|
+
// A pale wash of the brand, for an edge drawn ON a primary fill (the
|
|
150
|
+
// ghost button's hover border is the only consumer today). It was
|
|
151
|
+
// var(--nb-c-grape-hyacinth-200) at the call site, which forced a
|
|
152
|
+
// white-label product to name the vendor's ramp in its own stylesheet.
|
|
153
|
+
//
|
|
154
|
+
// Derived, not aliased: an alias would still be violet after a product
|
|
155
|
+
// sets --nb-c-primary, which is the exact leak this token exists to
|
|
156
|
+
// close. 39% of the brand on white measures dE2000 0.71 from the tint
|
|
157
|
+
// it replaced, under the ~1.0 just-noticeable threshold, so no shipped
|
|
158
|
+
// hover border visibly moves. The dark theme repeats the mix at 50%
|
|
159
|
+
// because its --nb-c-primary is already a lighter step of the same ramp
|
|
160
|
+
// and needs less white to land on the same wash (dE2000 0.00 there).
|
|
161
|
+
--nb-c-primary-subtle: color-mix(
|
|
162
|
+
in srgb,
|
|
163
|
+
var(--nb-c-primary) 39%,
|
|
164
|
+
var(--nb-c-white)
|
|
165
|
+
);
|
|
149
166
|
|
|
150
167
|
--nb-c-secondary: var(--nb-c-plain-black-700);
|
|
151
168
|
--nb-c-secondary-a11y: var(--nb-c-plain-black-700-a11y);
|
|
@@ -249,6 +266,59 @@
|
|
|
249
266
|
--nb-c-status-warning: var(--nb-c-phoenix-flames-700);
|
|
250
267
|
--nb-c-status-error: var(--nb-c-chicken-comb-600);
|
|
251
268
|
|
|
269
|
+
// == Data visualisation roles ==========================================
|
|
270
|
+
// Charts address colour by ROLE, never by ramp: a series is "chart-3",
|
|
271
|
+
// not "emerald". The eight defaults below alias exactly the ramps that
|
|
272
|
+
// Charts/shared/palette.ts used to name inline, so this theme repaints
|
|
273
|
+
// nothing, but a white-label product now retints every chart in the
|
|
274
|
+
// product by redefining eight custom properties in one place instead of
|
|
275
|
+
// hardcoding hex per app. (A green-branded white-label product did the
|
|
276
|
+
// hardcoding and shipped a violet placeholder series.)
|
|
277
|
+
//
|
|
278
|
+
// Order is part of the contract. colorAt() walks 1, 2, 3 ... and wraps
|
|
279
|
+
// at 8, so the sequence has to degrade gracefully: the low roles are the
|
|
280
|
+
// best separated pair we have. Minimum CIEDE2000 across the first five
|
|
281
|
+
// roles is 16.0 under normal vision; across all eight it falls to 6.5,
|
|
282
|
+
// because roles 1 and 7 are both violet-blues. Under simulated
|
|
283
|
+
// deuteranopia the same numbers are 5.2 and 0.8. That is a property of
|
|
284
|
+
// the brand ramps, not of this indirection, and it is why the docs cap
|
|
285
|
+
// colour-only encoding at five series. See charts/color.md.
|
|
286
|
+
//
|
|
287
|
+
// Contrast against layer-1, in order: 7.28, 5.25, 3.16, 2.06, 4.62,
|
|
288
|
+
// 5.68, 7.04, 4.63. Two roles miss WCAG 1.4.11 at 3:1 here: role 4
|
|
289
|
+
// (amber) on every layer, and role 3 on layer-0 and layer-2 (2.85 and
|
|
290
|
+
// 2.69, it only clears on layer-1). Both stay because raising them
|
|
291
|
+
// would repaint charts already in production, and both are documented
|
|
292
|
+
// as fill-only, never a 1px line or a legend dot on its own.
|
|
293
|
+
// Re-measure any change with tests/chartRoles.test.ts.
|
|
294
|
+
--nb-c-chart-1: var(--nb-c-grape-hyacinth-500);
|
|
295
|
+
--nb-c-chart-2: var(--nb-c-the-blues-brothers-500);
|
|
296
|
+
--nb-c-chart-3: var(--nb-c-emerald-reflection-600);
|
|
297
|
+
--nb-c-chart-4: var(--nb-c-phoenix-flames-500);
|
|
298
|
+
--nb-c-chart-5: var(--nb-c-chicken-comb-500);
|
|
299
|
+
--nb-c-chart-6: var(--nb-c-liberty-blue-500);
|
|
300
|
+
--nb-c-chart-7: var(--nb-c-powder-blue-500);
|
|
301
|
+
--nb-c-chart-8: var(--nb-c-nouveau-gray-500);
|
|
302
|
+
|
|
303
|
+
// Sequential ramp anchors: one hue, lightness carries the magnitude.
|
|
304
|
+
// Interpolated at paint time by sequentialAt() in the chart palette
|
|
305
|
+
// module, so a retint of these two ends retints the whole ramp. In this
|
|
306
|
+
// theme the largest value is the darkest end (L* 87.4 down to 21.2),
|
|
307
|
+
// which inverts under .dark.
|
|
308
|
+
--nb-c-chart-sequential-from: var(--nb-c-grape-hyacinth-100);
|
|
309
|
+
--nb-c-chart-sequential-to: var(--nb-c-grape-hyacinth-700);
|
|
310
|
+
|
|
311
|
+
// Diverging ramp anchors: two hues meeting at a neutral zero point.
|
|
312
|
+
// Cool to warm rather than green to red, because a green/red pair is
|
|
313
|
+
// the one axis a deuteranope cannot read at all, and a diverging scale
|
|
314
|
+
// has no legend position to fall back on. The two ends are matched in
|
|
315
|
+
// lightness (L* 44.4 and 47.9) so neither pole looks heavier than the
|
|
316
|
+
// other, and the midpoint is near the page ground so zero reads as
|
|
317
|
+
// "nothing here".
|
|
318
|
+
--nb-c-chart-diverging-low: var(--nb-c-the-blues-brothers-500);
|
|
319
|
+
--nb-c-chart-diverging-mid: var(--nb-c-nouveau-gray-150);
|
|
320
|
+
--nb-c-chart-diverging-high: var(--nb-c-chicken-comb-500);
|
|
321
|
+
|
|
252
322
|
// ── Node graph (NbBlueprint) ──────────────────────────────────────────
|
|
253
323
|
// A port is a control, and it sits OUTSIDE the card on the canvas
|
|
254
324
|
// ground, so its outline is measured against layer-0 rather than the
|
|
@@ -454,6 +524,10 @@
|
|
|
454
524
|
var(--nb-c-black)
|
|
455
525
|
);
|
|
456
526
|
--nb-shell-sidebar-width: calc(var(--nb-base-unit) * 7); // 56px
|
|
527
|
+
// The verbose variant's rail width. A token rather than a literal inside
|
|
528
|
+
// Shell.vue's variant rule, so a product with long navigation labels can
|
|
529
|
+
// widen the rail without re-declaring the variant.
|
|
530
|
+
--nb-shell-sidebar-width-verbose: calc(var(--nb-base-unit) * 30); // 240px
|
|
457
531
|
--nb-shell-sidebar-link-color: color-mix(
|
|
458
532
|
in srgb,
|
|
459
533
|
var(--nb-c-white) 55%,
|
|
@@ -483,15 +557,70 @@
|
|
|
483
557
|
var(--nb-c-white)
|
|
484
558
|
);
|
|
485
559
|
--nb-shell-topbar-height: calc(var(--nb-base-unit) * 6.25); // 50px
|
|
560
|
+
|
|
561
|
+
// Shell chrome. Every rule that paints the frame reads one of these, so a
|
|
562
|
+
// dark or white-label product retints the shell by setting a token on
|
|
563
|
+
// :root instead of out-specifying Shell.vue's scoped [data-v-] selectors
|
|
564
|
+
// from a built stylesheet. The defaults point at the semantic tokens the
|
|
565
|
+
// chrome already used, so the pixels are unchanged, and because var()
|
|
566
|
+
// resolves where it is used they follow the .dark theme with no dark-mode
|
|
567
|
+
// duplicate of this block.
|
|
568
|
+
//
|
|
569
|
+
// Three levels: --nb-shell-bg for the frame ground, --nb-shell-chrome-* as
|
|
570
|
+
// the one place to retint every strip at once, and the per-region tokens
|
|
571
|
+
// that default to the chrome ones for when only the topbar should differ.
|
|
572
|
+
--nb-shell-bg: var(--nb-c-surface-raised);
|
|
573
|
+
--nb-shell-chrome-bg: var(--nb-c-surface);
|
|
574
|
+
--nb-shell-chrome-color: var(--nb-c-text);
|
|
575
|
+
--nb-shell-chrome-border: 1px solid var(--nb-c-border);
|
|
576
|
+
--nb-shell-chrome-padding-x: calc(var(--nb-base-unit) * 3); // 24px
|
|
577
|
+
--nb-shell-topbar-bg: var(--nb-shell-chrome-bg);
|
|
578
|
+
--nb-shell-topbar-color: var(--nb-shell-chrome-color);
|
|
579
|
+
--nb-shell-topbar-border: var(--nb-shell-chrome-border);
|
|
580
|
+
--nb-shell-fixedbar-bg: var(--nb-shell-chrome-bg);
|
|
581
|
+
--nb-shell-fixedbar-color: var(--nb-shell-chrome-color);
|
|
582
|
+
--nb-shell-fixedbar-border: var(--nb-shell-chrome-border);
|
|
583
|
+
// Shared by the outer menu, the inner menu and the legacy menubar: they
|
|
584
|
+
// are one visual family and no application has ever wanted them to differ.
|
|
585
|
+
--nb-shell-menu-bg: var(--nb-shell-chrome-bg);
|
|
586
|
+
--nb-shell-menu-color: var(--nb-shell-chrome-color);
|
|
587
|
+
--nb-shell-menu-border: var(--nb-shell-chrome-border);
|
|
588
|
+
--nb-shell-body-bg: var(--nb-shell-chrome-bg);
|
|
589
|
+
// The page ground behind the main region. Kept separate from the chrome:
|
|
590
|
+
// a branded topbar usually sits above an unbranded page.
|
|
591
|
+
--nb-shell-main-bg: var(--nb-c-surface);
|
|
486
592
|
--nb-shell-inspector-width: calc(var(--nb-base-unit) * 70); // 560px
|
|
487
593
|
--nb-shell-inspector-expanded-width: 50vw;
|
|
594
|
+
// Ceiling for a visible inspector, whatever set its width (a size preset,
|
|
595
|
+
// the expanded flag, or a dragged width). Half the viewport is the point
|
|
596
|
+
// at which the inspector stops being a side panel and starts being the
|
|
597
|
+
// page. Set it to `none` to opt out.
|
|
598
|
+
// `max()` with the resize floor is load-bearing: half a 560px-wide window
|
|
599
|
+
// is 280px, below the 288px floor the resize handle announces and clamps
|
|
600
|
+
// to, so a bare 50vw made the announced value, the clamped value and the
|
|
601
|
+
// rendered width disagree on a narrow viewport. The floor wins there.
|
|
602
|
+
--nb-shell-inspector-max-width: max(calc(var(--nb-base-unit) * 36), 50vw);
|
|
488
603
|
--nb-shell-inspector-border: 1px solid var(--nb-c-border);
|
|
489
604
|
--nb-shell-inspector-bg: var(--nb-c-surface);
|
|
605
|
+
// The grab-line on the inspector's resize handle. A token, not a literal
|
|
606
|
+
// brand hex: a white-label product should never have to name the vendor's
|
|
607
|
+
// ramp to restyle the frame.
|
|
608
|
+
--nb-shell-inspector-resize-color: var(--nb-c-primary);
|
|
609
|
+
// The dimmer behind the navigation drawer at collapsed widths. Black at
|
|
610
|
+
// 45% reads on both themes because it darkens whatever is under it rather
|
|
611
|
+
// than painting a colour of its own.
|
|
612
|
+
--nb-shell-scrim-bg: color-mix(in srgb, var(--nb-c-black) 45%, transparent);
|
|
490
613
|
|
|
491
614
|
// Panels — emitted at :root so consumer apps can override on :root without
|
|
492
615
|
// fighting the components' scoped-style specificity.
|
|
493
616
|
--nb-shell-panel-header-height: calc(var(--nb-base-unit) * 3.5); // 28px
|
|
494
617
|
--nb-shell-panel-gap: 1px; // hairline separator, not a spacing step
|
|
618
|
+
--nb-shell-panel-bg: var(--nb-c-surface);
|
|
619
|
+
--nb-shell-panel-border: 1px solid var(--nb-c-border);
|
|
620
|
+
// Transparent by default so the header reads as part of the panel; set it
|
|
621
|
+
// when a product wants the header bar tinted against its own content.
|
|
622
|
+
--nb-shell-panel-header-bg: transparent;
|
|
623
|
+
--nb-shell-panel-header-border: 1px solid var(--nb-c-border);
|
|
495
624
|
--nb-bottom-panel-header-height: calc(var(--nb-base-unit) * 3.5); // 28px
|
|
496
625
|
--nb-bottom-panel-bg: var(--nb-c-layer-0, var(--nb-c-bg));
|
|
497
626
|
--nb-bottom-panel-border: var(--nb-c-border);
|
|
@@ -506,6 +635,13 @@
|
|
|
506
635
|
.dark {
|
|
507
636
|
// Status colors — lighter tints for dark backgrounds
|
|
508
637
|
--nb-c-primary: #{colors.get-color('grape-hyacinth', 400)};
|
|
638
|
+
// Same wash, re-mixed: the dark --nb-c-primary is a 400, so it takes less
|
|
639
|
+
// white than the light 500 does to reach the tint this token used to alias.
|
|
640
|
+
--nb-c-primary-subtle: color-mix(
|
|
641
|
+
in srgb,
|
|
642
|
+
var(--nb-c-primary) 50%,
|
|
643
|
+
var(--nb-c-white)
|
|
644
|
+
);
|
|
509
645
|
--nb-c-primary-a11y: #{colors.color-contrast(
|
|
510
646
|
colors.get-color('grape-hyacinth', 400)
|
|
511
647
|
)};
|
|
@@ -634,6 +770,41 @@
|
|
|
634
770
|
--nb-c-status-warning: #{colors.get-color('phoenix-flames', 400)};
|
|
635
771
|
--nb-c-status-error: #{colors.get-color('chicken-comb', 300)};
|
|
636
772
|
|
|
773
|
+
// Data visualisation roles, dark. Same eight hues, stepped up their
|
|
774
|
+
// ramps, exactly as --nb-c-primary and the status colours are stepped
|
|
775
|
+
// here. The light values are mid-ramp fills chosen against a white
|
|
776
|
+
// page: three of them (roles 1, 6 and 7 at 2.17, 2.78 and 2.25 against
|
|
777
|
+
// layer-1) sink into a dark one and were failing WCAG 1.4.11 in every
|
|
778
|
+
// dark-mode chart the fleet renders. The tints below measure 5.48,
|
|
779
|
+
// 4.42, 7.69, 8.89, 4.32, 4.30, 4.49 and 5.56 against layer-1, and all
|
|
780
|
+
// eight clear 3:1 on layer-0 through layer-2, which the light set does
|
|
781
|
+
// not manage. They do NOT clear it on layer-3, the lightest dark
|
|
782
|
+
// surface (roles 2, 5, 6 and 7 land between 2.79 and 2.92), so do not
|
|
783
|
+
// paint a chart on layer-3 in dark without overriding these. Role 7 is
|
|
784
|
+
// a 350 rather than the 400 its neighbours use: at 400 it measured
|
|
785
|
+
// 2.95 on layer-2, and contrast wins over separation on the role that
|
|
786
|
+
// is already the weakest of the eight. Minimum CIEDE2000 is 15.4 over
|
|
787
|
+
// the first five roles and 5.5 over all eight.
|
|
788
|
+
--nb-c-chart-1: var(--nb-c-grape-hyacinth-300);
|
|
789
|
+
--nb-c-chart-2: var(--nb-c-the-blues-brothers-400);
|
|
790
|
+
--nb-c-chart-3: var(--nb-c-emerald-reflection-500);
|
|
791
|
+
--nb-c-chart-4: var(--nb-c-phoenix-flames-400);
|
|
792
|
+
--nb-c-chart-5: var(--nb-c-chicken-comb-400);
|
|
793
|
+
--nb-c-chart-6: var(--nb-c-liberty-blue-400);
|
|
794
|
+
--nb-c-chart-7: var(--nb-c-powder-blue-350);
|
|
795
|
+
--nb-c-chart-8: var(--nb-c-nouveau-gray-400);
|
|
796
|
+
|
|
797
|
+
// Sequential runs the other way on a dark page: the largest value is
|
|
798
|
+
// the brightest end, so "from" is the tint nearest the background.
|
|
799
|
+
--nb-c-chart-sequential-from: var(--nb-c-grape-hyacinth-800);
|
|
800
|
+
--nb-c-chart-sequential-to: var(--nb-c-grape-hyacinth-200);
|
|
801
|
+
|
|
802
|
+
// Diverging keeps its two hues and moves the zero point to a dark
|
|
803
|
+
// neutral. Ends stepped one tint lighter to hold 4.3:1 on layer-1.
|
|
804
|
+
--nb-c-chart-diverging-low: var(--nb-c-the-blues-brothers-400);
|
|
805
|
+
--nb-c-chart-diverging-mid: var(--nb-c-nouveau-gray-800);
|
|
806
|
+
--nb-c-chart-diverging-high: var(--nb-c-chicken-comb-400);
|
|
807
|
+
|
|
637
808
|
// Discrete
|
|
638
809
|
--nb-c-discrete: #{colors.get-color('nouveau-gray', 700)};
|
|
639
810
|
--nb-c-component-discrete-text: #{colors.get-color('nouveau-gray', 300)};
|
|
@@ -1,24 +1,101 @@
|
|
|
1
1
|
@mixin tooltip {
|
|
2
|
+
// The description node. Not a chip: it is the text of the tooltip as
|
|
3
|
+
// assistive technology sees it, present from the moment the binding mounts,
|
|
4
|
+
// referenced by the anchor's `aria-describedby` the whole time.
|
|
5
|
+
//
|
|
6
|
+
// Visually hidden, never `display: none` and never the `hidden` attribute.
|
|
7
|
+
// Both of those remove it from the accessibility tree, which is the one
|
|
8
|
+
// place it has to be; the whole reason it exists is that a description
|
|
9
|
+
// computed at focus time cannot be waiting on a hover-intent timer.
|
|
10
|
+
.nb-tooltip-description {
|
|
11
|
+
position: absolute;
|
|
12
|
+
inset-block-start: 0;
|
|
13
|
+
inset-inline-start: 0;
|
|
14
|
+
inline-size: 1px;
|
|
15
|
+
block-size: 1px;
|
|
16
|
+
padding: 0;
|
|
17
|
+
margin: 0;
|
|
18
|
+
border: 0;
|
|
19
|
+
overflow: hidden;
|
|
20
|
+
// `clip-path` rather than the legacy `clip`: it is not deprecated and it
|
|
21
|
+
// does not force the element out of the flow in a way that some engines
|
|
22
|
+
// use to skip it entirely.
|
|
23
|
+
clip-path: inset(50%);
|
|
24
|
+
white-space: nowrap;
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
2
28
|
.nb-tooltip {
|
|
3
29
|
position: fixed;
|
|
4
30
|
overflow: visible;
|
|
5
|
-
padding
|
|
31
|
+
// Logical, so a chip in an Arabic or Hebrew build gets its padding on the
|
|
32
|
+
// sides the text actually starts and ends on. The arrow offsets further
|
|
33
|
+
// down stay physical on purpose: placement is computed from geometry in
|
|
34
|
+
// the directive (which side has room), and geometry has no direction.
|
|
35
|
+
padding-block: var(--nb-base-unit);
|
|
36
|
+
padding-inline: var(--nb-base-unit);
|
|
6
37
|
border-radius: calc(var(--nb-base-unit) / 1.333);
|
|
7
|
-
|
|
8
|
-
|
|
38
|
+
// Inverted surface, not the discrete grey pair. Two reasons: the grey
|
|
39
|
+
// pair only flips its background between themes (its -a11y foreground
|
|
40
|
+
// stays the light-theme value, so a dark-theme chip was dark text on a
|
|
41
|
+
// dark chip), and every hand-rolled tooltip in the fleet, including the
|
|
42
|
+
// two inside this library, independently chose an inverted chip. The two
|
|
43
|
+
// vars let a consumer retint one chip without touching the theme.
|
|
44
|
+
background: var(--nb-tooltip-bg, var(--nb-c-contrast));
|
|
45
|
+
color: var(--nb-tooltip-fg, var(--nb-c-surface));
|
|
9
46
|
z-index: var(--nb-zindex-tooltip);
|
|
10
47
|
text-transform: none;
|
|
11
48
|
font-size: var(--nb-font-size-13);
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
49
|
+
// A chip has no width of its own: it shrink-wraps its text. Without a
|
|
50
|
+
// ceiling, a 400-character body renders as ONE line wider than the
|
|
51
|
+
// viewport, and the directive's clamp cannot rescue it (the maximum left
|
|
52
|
+
// goes negative, so the chip is pushed back to the inset and runs off the
|
|
53
|
+
// right edge). 34 base units is about 55 characters at this size, a
|
|
54
|
+
// comfortable measure. `--nb-tooltip-max-width` widens or narrows it for
|
|
55
|
+
// one chip; the answer for anything that needs much more is not a
|
|
56
|
+
// tooltip.
|
|
57
|
+
max-inline-size: var(
|
|
58
|
+
--nb-tooltip-max-width,
|
|
59
|
+
calc(var(--nb-base-unit) * 34)
|
|
60
|
+
);
|
|
61
|
+
// Now that the text can wrap, it needs leading. At `line-height: 1` a
|
|
62
|
+
// wrapped body, a documented `<br>` and an embedded newline all render as
|
|
63
|
+
// touching lines.
|
|
64
|
+
line-height: var(--nb-line-height-snug);
|
|
65
|
+
// A single unbroken token (a URL, a hash, a file path) would otherwise
|
|
66
|
+
// blow straight through the max-width.
|
|
67
|
+
overflow-wrap: anywhere;
|
|
68
|
+
// The chip is reachable by the pointer. WCAG 2.1 AA 1.4.13 ("Hoverable")
|
|
69
|
+
// requires that content revealed on hover can be hovered without
|
|
70
|
+
// disappearing, and `pointer-events: none` makes that impossible by
|
|
71
|
+
// construction: nothing the user does with the mouse can ever land on the
|
|
72
|
+
// chip. That is not a defensible default for the one affordance in this
|
|
73
|
+
// library whose whole purpose is labelling controls, and it is the
|
|
74
|
+
// difference between readable and unreadable for anyone at 200% zoom, who
|
|
75
|
+
// has to pan onto a clamped chip to finish the sentence.
|
|
76
|
+
//
|
|
77
|
+
// The directive supplies the other half: entering the chip cancels the
|
|
78
|
+
// pending hide, leaving it restarts it. The chip stays out of the tab
|
|
79
|
+
// order and holds nothing operable, so it is still not a container.
|
|
80
|
+
pointer-events: auto;
|
|
81
|
+
// Text in a chip is often the thing worth copying: an error code, a full
|
|
82
|
+
// path, a signature. There is no reason to forbid selecting it now that
|
|
83
|
+
// the pointer can reach it.
|
|
84
|
+
user-select: text;
|
|
85
|
+
// Structural containment, defence in depth for caller-supplied content.
|
|
86
|
+
// `contain: layout` makes the chip the containing block for any
|
|
87
|
+
// absolutely or fixed-positioned descendant, so a class or a style that
|
|
88
|
+
// reached the chip from a CMS field or an API payload cannot escape the
|
|
89
|
+
// chip's box to become a full-viewport overlay. The content sanitiser
|
|
90
|
+
// already refuses `position`; this is the belt to that pair of braces,
|
|
91
|
+
// and it does not clip (the arrow pseudo-elements still overflow).
|
|
92
|
+
contain: layout;
|
|
15
93
|
opacity: 0;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
transform 0.2s ease;
|
|
94
|
+
// `start`, not `center`. A one-line chip shrink-wraps its text so the two
|
|
95
|
+
// are indistinguishable, and a wrapped chip is far easier to read ragged
|
|
96
|
+
// right than centred.
|
|
97
|
+
text-align: start;
|
|
98
|
+
--tooltip-arrow-border-color: var(--nb-tooltip-bg, var(--nb-c-contrast));
|
|
22
99
|
&:before,
|
|
23
100
|
&:after {
|
|
24
101
|
position: absolute;
|
|
@@ -47,32 +124,64 @@
|
|
|
47
124
|
}
|
|
48
125
|
&-tip {
|
|
49
126
|
font-weight: var(--nb-font-weight-regular);
|
|
50
|
-
|
|
127
|
+
// Demoted by transparency rather than by a second colour token: on an
|
|
128
|
+
// inverted chip any fixed grey is right in one theme and wrong in the
|
|
129
|
+
// other, while 78% of an already-contrasting foreground stays legible
|
|
130
|
+
// in both.
|
|
131
|
+
opacity: 0.78;
|
|
51
132
|
}
|
|
52
133
|
|
|
134
|
+
// Every flavour foreground is the theme's auto-contrast companion for its
|
|
135
|
+
// own background, never a literal. `--nb-c-danger` and friends are not the
|
|
136
|
+
// same colour in both themes (the dark theme uses a lighter step of the
|
|
137
|
+
// same ramp), so a hardcoded white is correct in at most one of them and
|
|
138
|
+
// is the WORST available choice in the other. The `-a11y` companions are
|
|
139
|
+
// computed from the background they sit on, which is why the rest of the
|
|
140
|
+
// library uses them.
|
|
53
141
|
&-flavor {
|
|
54
142
|
&-primary {
|
|
55
143
|
background: var(--nb-c-primary);
|
|
56
|
-
color: var(--nb-c-
|
|
144
|
+
color: var(--nb-c-primary-a11y);
|
|
57
145
|
--tooltip-arrow-border-color: var(--nb-c-primary);
|
|
58
146
|
.nb-tooltip-tip {
|
|
59
|
-
color: var(--nb-c-
|
|
147
|
+
color: var(--nb-c-primary-a11y);
|
|
60
148
|
}
|
|
61
149
|
}
|
|
62
150
|
&-danger {
|
|
63
151
|
background: var(--nb-c-danger);
|
|
64
|
-
color: var(--nb-c-
|
|
152
|
+
color: var(--nb-c-danger-a11y);
|
|
65
153
|
--tooltip-arrow-border-color: var(--nb-c-danger);
|
|
66
154
|
.nb-tooltip-tip {
|
|
67
|
-
color: var(--nb-c-
|
|
155
|
+
color: var(--nb-c-danger-a11y);
|
|
68
156
|
}
|
|
69
157
|
}
|
|
70
158
|
&-info {
|
|
71
159
|
background: var(--nb-c-info);
|
|
72
|
-
color: var(--nb-c-
|
|
160
|
+
color: var(--nb-c-info-a11y);
|
|
73
161
|
--tooltip-arrow-border-color: var(--nb-c-info);
|
|
74
162
|
.nb-tooltip-tip {
|
|
75
|
-
color: var(--nb-c-
|
|
163
|
+
color: var(--nb-c-info-a11y);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// `success` and `warning` exist because the library's status vocabulary
|
|
167
|
+
// has them (NbBanner.status, EVariant) and the tooltip was the one place
|
|
168
|
+
// that silently did not: `flavor: 'warning'` used to compile and emit an
|
|
169
|
+
// unstyled chip. Same construction as the three above, so a themed build
|
|
170
|
+
// that moves the ramp moves these with it.
|
|
171
|
+
&-success {
|
|
172
|
+
background: var(--nb-c-success);
|
|
173
|
+
color: var(--nb-c-success-a11y);
|
|
174
|
+
--tooltip-arrow-border-color: var(--nb-c-success);
|
|
175
|
+
.nb-tooltip-tip {
|
|
176
|
+
color: var(--nb-c-success-a11y);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
&-warning {
|
|
180
|
+
background: var(--nb-c-warning);
|
|
181
|
+
color: var(--nb-c-warning-a11y);
|
|
182
|
+
--tooltip-arrow-border-color: var(--nb-c-warning);
|
|
183
|
+
.nb-tooltip-tip {
|
|
184
|
+
color: var(--nb-c-warning-a11y);
|
|
76
185
|
}
|
|
77
186
|
}
|
|
78
187
|
}
|
|
@@ -164,23 +273,36 @@
|
|
|
164
273
|
}
|
|
165
274
|
}
|
|
166
275
|
|
|
167
|
-
|
|
276
|
+
@media (prefers-reduced-motion: reduce) {
|
|
277
|
+
.nb-tooltip {
|
|
278
|
+
animation: none !important;
|
|
279
|
+
transform: none;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Entrance and exit. Both the fade and the small rise live in the keyframes
|
|
284
|
+
// rather than in a base `transform` plus a `transition`: the directive only
|
|
285
|
+
// ever sets `animation`, so a base transform had nothing to transition back
|
|
286
|
+
// from and every chip rendered permanently scaled down.
|
|
168
287
|
@keyframes tooltipAppear {
|
|
169
288
|
0% {
|
|
170
289
|
opacity: 0;
|
|
290
|
+
transform: scale(0.96);
|
|
171
291
|
}
|
|
172
292
|
100% {
|
|
173
293
|
opacity: 1;
|
|
294
|
+
transform: scale(1);
|
|
174
295
|
}
|
|
175
296
|
}
|
|
176
297
|
|
|
177
|
-
// Animation for disappearing
|
|
178
298
|
@keyframes tooltipDisappear {
|
|
179
299
|
0% {
|
|
180
300
|
opacity: 1;
|
|
301
|
+
transform: scale(1);
|
|
181
302
|
}
|
|
182
303
|
100% {
|
|
183
304
|
opacity: 0;
|
|
305
|
+
transform: scale(0.98);
|
|
184
306
|
}
|
|
185
307
|
}
|
|
186
308
|
}
|