@flux-ui/components 3.0.0 → 3.1.2

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.
Files changed (45) hide show
  1. package/dist/component/FluxBreadcrumb.vue.d.ts +15 -0
  2. package/dist/component/FluxBreadcrumbItem.vue.d.ts +23 -0
  3. package/dist/component/{FluxCheckbox.vue.d.ts → FluxFormCheckbox.vue.d.ts} +3 -0
  4. package/dist/component/FluxFormCheckboxGroup.vue.d.ts +26 -0
  5. package/dist/component/FluxFormField.vue.d.ts +1 -0
  6. package/dist/component/FluxFormNumberInput.vue.d.ts +26 -0
  7. package/dist/component/FluxFormRadio.vue.d.ts +18 -0
  8. package/dist/component/FluxFormRadioGroup.vue.d.ts +27 -0
  9. package/dist/component/FluxSkeleton.vue.d.ts +9 -0
  10. package/dist/component/index.d.ts +8 -1
  11. package/dist/composable/index.d.ts +2 -0
  12. package/dist/composable/useFormCheckboxGroupInjection.d.ts +2 -0
  13. package/dist/composable/useFormFieldInjection.d.ts +3 -2
  14. package/dist/composable/useFormRadioGroupInjection.d.ts +2 -0
  15. package/dist/data/di.d.ts +23 -0
  16. package/dist/index.css +1374 -1012
  17. package/dist/index.js +893 -399
  18. package/dist/index.js.map +1 -1
  19. package/package.json +9 -9
  20. package/src/component/FluxBreadcrumb.vue +24 -0
  21. package/src/component/FluxBreadcrumbItem.vue +72 -0
  22. package/src/component/FluxDataTable.vue +3 -3
  23. package/src/component/FluxFormCheckbox.vue +123 -0
  24. package/src/component/FluxFormCheckboxGroup.vue +57 -0
  25. package/src/component/FluxFormField.vue +23 -7
  26. package/src/component/FluxFormNumberInput.vue +180 -0
  27. package/src/component/FluxFormPinInput.vue +2 -2
  28. package/src/component/FluxFormRadio.vue +76 -0
  29. package/src/component/FluxFormRadioGroup.vue +53 -0
  30. package/src/component/FluxQuantitySelector.vue +4 -4
  31. package/src/component/FluxSkeleton.vue +46 -0
  32. package/src/component/FluxToggle.vue +4 -4
  33. package/src/component/index.ts +8 -1
  34. package/src/composable/index.ts +2 -0
  35. package/src/composable/useFormCheckboxGroupInjection.ts +6 -0
  36. package/src/composable/useFormFieldInjection.ts +7 -3
  37. package/src/composable/useFormRadioGroupInjection.ts +13 -0
  38. package/src/css/component/BorderBeam.module.scss +51 -22
  39. package/src/css/component/Breadcrumb.module.scss +86 -0
  40. package/src/css/component/Divider.module.scss +1 -0
  41. package/src/css/component/Form.module.scss +251 -45
  42. package/src/css/component/SegmentedControl.module.scss +18 -18
  43. package/src/css/component/Skeleton.module.scss +67 -0
  44. package/src/data/di.ts +30 -0
  45. package/src/component/FluxCheckbox.vue +0 -87
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <div
3
+ :class="clsx(
4
+ $style.formRadioGroup,
5
+ isInline && $style.isInline
6
+ )"
7
+ role="radiogroup"
8
+ :aria-label="ariaLabel">
9
+ <slot/>
10
+ </div>
11
+ </template>
12
+
13
+ <script
14
+ lang="ts"
15
+ setup>
16
+ import type { FluxFormInputBaseProps } from '@flux-ui/types';
17
+ import { clsx } from 'clsx';
18
+ import { provide, toRef, useId, type VNode } from 'vue';
19
+ import { useDisabled } from '~flux/components/composable';
20
+ import { FluxFormRadioGroupInjectionKey, type FluxFormRadioGroupValue } from '~flux/components/data';
21
+ import $style from '~flux/components/css/component/Form.module.scss';
22
+
23
+ const modelValue = defineModel<FluxFormRadioGroupValue>();
24
+
25
+ const {
26
+ disabled: componentDisabled,
27
+ error,
28
+ isReadonly,
29
+ name
30
+ } = defineProps<Pick<FluxFormInputBaseProps, 'disabled' | 'error' | 'isReadonly'> & {
31
+ readonly ariaLabel?: string;
32
+ readonly isInline?: boolean;
33
+ readonly name?: string;
34
+ }>();
35
+
36
+ defineSlots<{
37
+ default(): VNode[];
38
+ }>();
39
+
40
+ const disabled = useDisabled(toRef(() => componentDisabled));
41
+ const generatedName = useId();
42
+
43
+ provide(FluxFormRadioGroupInjectionKey, {
44
+ name: name ?? generatedName,
45
+ modelValue,
46
+ disabled,
47
+ isReadonly: toRef(() => isReadonly ?? false),
48
+ error: toRef(() => error),
49
+ select(value) {
50
+ modelValue.value = value;
51
+ }
52
+ });
53
+ </script>
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <FluxButtonGroup
3
- :class="$style.quantitySelector"
3
+ :class="$style.formQuantitySelector"
4
4
  :aria-disabled="disabled ? true : undefined">
5
5
  <FluxSecondaryButton
6
- :class="$style.quantitySelectorButton"
6
+ :class="$style.formQuantitySelectorButton"
7
7
  :disabled="disabled || modelValue <= min"
8
8
  icon-leading="minus"
9
9
  tabindex="-1"
@@ -12,7 +12,7 @@
12
12
  <input
13
13
  ref="input"
14
14
  v-model="modelValue"
15
- :class="$style.quantitySelectorInput"
15
+ :class="$style.formQuantitySelectorInput"
16
16
  :style="{
17
17
  width: `${width}px`
18
18
  }"
@@ -24,7 +24,7 @@
24
24
  :step="step"/>
25
25
 
26
26
  <FluxSecondaryButton
27
- :class="$style.quantitySelectorButton"
27
+ :class="$style.formQuantitySelectorButton"
28
28
  :disabled="disabled || modelValue >= max"
29
29
  icon-leading="plus"
30
30
  tabindex="-1"
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <component
3
+ :is="is"
4
+ :class="clsx(
5
+ $style.skeleton,
6
+ variant === 'circle' && $style.isCircle,
7
+ variant === 'rectangle' && $style.isRectangle,
8
+ variant === 'rounded' && $style.isRounded,
9
+ variant === 'text' && $style.isText
10
+ )"
11
+ :style="style"
12
+ aria-hidden="true"/>
13
+ </template>
14
+
15
+ <script
16
+ lang="ts"
17
+ setup>
18
+ import { clsx } from 'clsx';
19
+ import { computed, type CSSProperties } from 'vue';
20
+ import $style from '~flux/components/css/component/Skeleton.module.scss';
21
+
22
+ const {
23
+ height,
24
+ is = 'div',
25
+ variant = 'text',
26
+ width
27
+ } = defineProps<{
28
+ readonly height?: string | number;
29
+ readonly is?: string;
30
+ readonly variant?: 'text' | 'circle' | 'rectangle' | 'rounded';
31
+ readonly width?: string | number;
32
+ }>();
33
+
34
+ const style = computed<CSSProperties>(() => ({
35
+ height: toSize(height),
36
+ width: toSize(width)
37
+ }));
38
+
39
+ function toSize(value: string | number | undefined): string | undefined {
40
+ if (value === undefined) {
41
+ return undefined;
42
+ }
43
+
44
+ return typeof value === 'number' ? `${value}px` : value;
45
+ }
46
+ </script>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <label
3
3
  :class="clsx(
4
- $style.toggle,
4
+ $style.formToggle,
5
5
  modelValue && $style.isChecked,
6
6
  disabled && $style.isDisabled,
7
7
  isReadonly && $style.isReadonly,
@@ -14,18 +14,18 @@
14
14
  :aria-invalid="error ? true : undefined">
15
15
  <FluxIcon
16
16
  v-if="iconOff"
17
- :class="$style.toggleIconOff"
17
+ :class="$style.formToggleIconOff"
18
18
  :name="iconOff"
19
19
  :size="14"/>
20
20
 
21
21
  <FluxIcon
22
22
  v-if="iconOn"
23
- :class="$style.toggleIconOn"
23
+ :class="$style.formToggleIconOn"
24
24
  :name="iconOn"
25
25
  :size="14"/>
26
26
 
27
27
  <input
28
- :class="$style.toggleInput"
28
+ :class="$style.formToggleInput"
29
29
  :id="id"
30
30
  :disabled="disabled"
31
31
  type="checkbox"
@@ -12,12 +12,13 @@ export { default as FluxBadgeStack } from './FluxBadgeStack.vue';
12
12
  export { default as FluxBorderBeam } from './FluxBorderBeam.vue';
13
13
  export { default as FluxBorderShine } from './FluxBorderShine.vue';
14
14
  export { default as FluxBoxedIcon } from './FluxBoxedIcon.vue';
15
+ export { default as FluxBreadcrumb } from './FluxBreadcrumb.vue';
16
+ export { default as FluxBreadcrumbItem } from './FluxBreadcrumbItem.vue';
15
17
  export { default as FluxButton } from './FluxButton.vue';
16
18
  export { default as FluxButtonGroup } from './FluxButtonGroup.vue';
17
19
  export { default as FluxButtonStack } from './FluxButtonStack.vue';
18
20
  export { default as FluxCalendar } from './FluxCalendar.vue';
19
21
  export { default as FluxCalendarItem } from './FluxCalendarItem.vue';
20
- export { default as FluxCheckbox } from './FluxCheckbox.vue';
21
22
  export { default as FluxChip } from './FluxChip.vue';
22
23
  export { default as FluxClickablePane } from './FluxClickablePane.vue';
23
24
  export { default as FluxCommandPalette } from './FluxCommandPalette.vue';
@@ -55,6 +56,8 @@ export { default as FluxFlyout } from './FluxFlyout.vue';
55
56
  export { default as FluxFocalPointEditor } from './FluxFocalPointEditor.vue';
56
57
  export { default as FluxFocalPointImage } from './FluxFocalPointImage.vue';
57
58
  export { default as FluxForm } from './FluxForm.vue';
59
+ export { default as FluxFormCheckbox } from './FluxFormCheckbox.vue';
60
+ export { default as FluxFormCheckboxGroup } from './FluxFormCheckboxGroup.vue';
58
61
  export { default as FluxFormColumn } from './FluxFormColumn.vue';
59
62
  export { default as FluxFormDateInput } from './FluxFormDateInput.vue';
60
63
  export { default as FluxFormDateRangeInput } from './FluxFormDateRangeInput.vue';
@@ -65,7 +68,10 @@ export { default as FluxFormGrid } from './FluxFormGrid.vue';
65
68
  export { default as FluxFormInput } from './FluxFormInput.vue';
66
69
  export { default as FluxFormInputAddition } from './FluxFormInputAddition.vue';
67
70
  export { default as FluxFormInputGroup } from './FluxFormInputGroup.vue';
71
+ export { default as FluxFormNumberInput } from './FluxFormNumberInput.vue';
68
72
  export { default as FluxFormPinInput } from './FluxFormPinInput.vue';
73
+ export { default as FluxFormRadio } from './FluxFormRadio.vue';
74
+ export { default as FluxFormRadioGroup } from './FluxFormRadioGroup.vue';
69
75
  export { default as FluxFormRangeSlider } from './FluxFormRangeSlider.vue';
70
76
  export { default as FluxFormRow } from './FluxFormRow.vue';
71
77
  export { default as FluxFormSection } from './FluxFormSection.vue';
@@ -131,6 +137,7 @@ export { default as FluxSecondaryLinkButton } from './FluxSecondaryLinkButton.vu
131
137
  export { default as FluxSegmentedControl } from './FluxSegmentedControl.vue';
132
138
  export { default as FluxSegmentedControlItem } from './FluxSegmentedControlItem.vue';
133
139
  export { default as FluxSeparator } from './FluxSeparator.vue';
140
+ export { default as FluxSkeleton } from './FluxSkeleton.vue';
134
141
  export { default as FluxSlideOver } from './FluxSlideOver.vue';
135
142
  export { default as FluxSnackbar } from './FluxSnackbar.vue';
136
143
  export { default as FluxSnackbarProvider } from './FluxSnackbarProvider.vue';
@@ -7,7 +7,9 @@ export { default as useDisabledInjection } from './useDisabledInjection';
7
7
  export { default as useExpandableGroupInjection } from './useExpandableGroupInjection';
8
8
  export { default as useFilterInjection } from './useFilterInjection';
9
9
  export { default as useFlyoutInjection } from './useFlyoutInjection';
10
+ export { default as useFormCheckboxGroupInjection } from './useFormCheckboxGroupInjection';
10
11
  export { default as useFormFieldInjection } from './useFormFieldInjection';
12
+ export { default as useFormRadioGroupInjection } from './useFormRadioGroupInjection';
11
13
  export { default as useKanbanInjection } from './useKanbanInjection';
12
14
  export { default as useSegmentedControlInjection } from './useSegmentedControlInjection';
13
15
  export { default as useTabBarInjection } from './useTabBarInjection';
@@ -0,0 +1,6 @@
1
+ import { inject } from 'vue';
2
+ import { FluxFormCheckboxGroupInjectionKey } from '~flux/components/data';
3
+
4
+ export default function () {
5
+ return inject(FluxFormCheckboxGroupInjectionKey, null);
6
+ }
@@ -2,7 +2,11 @@ import { inject, useId } from 'vue';
2
2
  import { FluxFormFieldInjectionKey } from '~flux/components/data';
3
3
 
4
4
  export default function () {
5
- return inject(FluxFormFieldInjectionKey, {
6
- id: useId()
7
- });
5
+ const field = inject(FluxFormFieldInjectionKey, null);
6
+
7
+ if (field?.registerControl) {
8
+ return {id: field.registerControl()};
9
+ }
10
+
11
+ return {id: field?.id ?? useId()};
8
12
  }
@@ -0,0 +1,13 @@
1
+ import { inject, ref } from 'vue';
2
+ import { FluxFormRadioGroupInjectionKey, type FluxFormRadioGroupValue } from '~flux/components/data';
3
+
4
+ export default function () {
5
+ return inject(FluxFormRadioGroupInjectionKey, {
6
+ name: '',
7
+ modelValue: ref<FluxFormRadioGroupValue | undefined>(undefined),
8
+ disabled: ref(false),
9
+ isReadonly: ref(false),
10
+ error: ref<string | null | undefined>(undefined),
11
+ select: () => undefined
12
+ });
13
+ }
@@ -425,6 +425,11 @@ $pulse-outer-bloom: (
425
425
  $thin-w2: 14px;
426
426
  $thin-w3: 12px;
427
427
  $thin-w4: 10px;
428
+
429
+ // The light theme widens the last thin spike further for mono.
430
+ @if not $is-dark {
431
+ $thin-w4: 12px;
432
+ }
428
433
  $thin-h1: 42px;
429
434
  $thin-h2: 38px;
430
435
  $thin-h3: 40px;
@@ -487,6 +492,17 @@ $pulse-outer-bloom: (
487
492
  @return $grads;
488
493
  }
489
494
 
495
+ // Gradients that reference animated custom properties (--beam-angle, --beam-x,
496
+ // --beam-w, ...) must be declared directly on the layer that paints them.
497
+ // Routing them through an intermediate custom property breaks per-frame
498
+ // updates of the dependent value in Chromium and WebKit, which makes the
499
+ // animation stutter.
500
+ $rotate-highlight-light: string.unquote('conic-gradient(from var(--beam-angle), transparent 0%, transparent 54%, rgba(0, 0, 0, 0.08) 57%, rgba(0, 0, 0, 0.2) 60%, rgba(0, 0, 0, 0.4) 63%, rgba(0, 0, 0, 0.55) 66%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.2) 72%, rgba(0, 0, 0, 0.08) 75%, transparent 78%, transparent 100%)');
501
+ $rotate-highlight-dark: string.unquote('conic-gradient(from var(--beam-angle), transparent 0%, transparent 54%, rgba(255, 255, 255, 0.1) 57%, rgba(255, 255, 255, 0.3) 60%, rgba(255, 255, 255, 0.6) 63%, rgba(255, 255, 255, 0.75) 66%, rgba(255, 255, 255, 0.6) 69%, rgba(255, 255, 255, 0.3) 72%, rgba(255, 255, 255, 0.1) 75%, transparent 78%, transparent 100%)');
502
+ $rotate-bloom-light: string.unquote('conic-gradient(from var(--beam-angle), transparent 0%, transparent 58%, rgba(0, 0, 0, 0.02) 62%, rgba(0, 0, 0, 0.08) 65%, rgba(0, 0, 0, 0.2) 67%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.6) 70%, rgba(0, 0, 0, 0.6) 70.5%, rgba(0, 0, 0, 0.4) 71.5%, rgba(0, 0, 0, 0.2) 73%, rgba(0, 0, 0, 0.08) 75%, rgba(0, 0, 0, 0.02) 78%, transparent 82%)');
503
+ $rotate-bloom-dark: string.unquote('conic-gradient(from var(--beam-angle), transparent 0%, transparent 58%, rgba(255, 255, 255, 0.03) 62%, rgba(255, 255, 255, 0.08) 65%, rgba(255, 255, 255, 0.2) 67%, rgba(255, 255, 255, 0.45) 69%, rgba(255, 255, 255, 0.85) 70%, rgba(255, 255, 255, 0.85) 70.5%, rgba(255, 255, 255, 0.45) 71.5%, rgba(255, 255, 255, 0.2) 73%, rgba(255, 255, 255, 0.08) 75%, rgba(255, 255, 255, 0.03) 78%, transparent 82%)');
504
+ $line-highlight-light: string.unquote('radial-gradient(ellipse calc(35px * var(--beam-w)) calc(28px * var(--beam-h)) at calc(var(--beam-x) * 100%) calc(100% + 2px), rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.25) 35%, transparent 70%)');
505
+ $line-highlight-dark: string.unquote('radial-gradient(ellipse calc(24px * var(--beam-w)) calc(28px * var(--beam-h)) at calc(var(--beam-x) * 100%) calc(100% + 2px), rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0.12) 30%, transparent 65%)');
490
506
  $ring-mask: string.unquote('linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)');
491
507
  $edge-fade-y: string.unquote('linear-gradient(white, transparent 28px, transparent calc(100% - 28px), white)');
492
508
  $edge-fade-x: string.unquote('linear-gradient(to right, white, transparent 28px, transparent calc(100% - 28px), white)');
@@ -532,18 +548,30 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
532
548
  --beam-rotate-inner: #{blobs(map.get($ring-colors, $palette), $ring-geometry, $inner-alpha, .9)};
533
549
  --beam-sm-blobs: #{blobs(map.get($sm-colors, $palette), $sm-geometry)};
534
550
  --beam-sm-inner: #{blobs(map.get($sm-colors, $palette), $sm-geometry, map.get($sm-inner-alphas, $palette))};
535
- --beam-line-blobs: #{line-blobs(map.get($line-colors, $palette, light), $line-geometry-light)};
536
- --beam-line-inner: #{line-blobs(map.get($line-inner-colors, $palette), $line-inner-geometry, $line-inner-alphas)};
537
- --beam-line-bloom: #{line-bloom($palette, light)};
538
551
  --beam-pulse-ring: #{pulse-blobs(pulse-ring($palette))};
539
552
  --beam-pulse-inner-ring: #{pulse-blobs(pulse-ring-resized($palette))};
540
553
  --beam-pulse-inner-bloom: #{pulse-blobs-frozen(pulse-table($palette, $pulse-inner-bloom))};
541
554
  --beam-pulse-outer-core: #{pulse-blobs(pulse-table($palette, $pulse-outer-core))};
542
555
  --beam-pulse-outer-bloom: #{pulse-blobs-frozen(pulse-table($palette, $pulse-outer-bloom))};
543
556
 
544
- [dark] & {
545
- --beam-line-blobs: #{line-blobs(map.get($line-colors, $palette, dark), $line-geometry-dark)};
546
- --beam-line-bloom: #{line-bloom($palette, dark)};
557
+ &.line::after {
558
+ background: #{$line-highlight-light}, #{line-blobs(map.get($line-colors, $palette, light), $line-geometry-light)};
559
+ }
560
+
561
+ &.line::before {
562
+ background: #{line-blobs(map.get($line-inner-colors, $palette), $line-inner-geometry, $line-inner-alphas)};
563
+ }
564
+
565
+ &.line > .bloom {
566
+ background: #{line-bloom($palette, light)};
567
+ }
568
+
569
+ [dark] &.line::after {
570
+ background: #{$line-highlight-dark}, #{line-blobs(map.get($line-colors, $palette, dark), $line-geometry-dark)};
571
+ }
572
+
573
+ [dark] &.line > .bloom {
574
+ background: #{line-bloom($palette, dark)};
547
575
  }
548
576
  }
549
577
  }
@@ -557,14 +585,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
557
585
  .sm {
558
586
  overflow: hidden;
559
587
 
560
- --beam-rotate-highlight: conic-gradient(from var(--beam-angle), transparent 0%, transparent 54%, rgba(0, 0, 0, 0.08) 57%, rgba(0, 0, 0, 0.2) 60%, rgba(0, 0, 0, 0.4) 63%, rgba(0, 0, 0, 0.55) 66%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.2) 72%, rgba(0, 0, 0, 0.08) 75%, transparent 78%, transparent 100%);
561
- --beam-rotate-bloom: conic-gradient(from var(--beam-angle), transparent 0%, transparent 58%, rgba(0, 0, 0, 0.02) 62%, rgba(0, 0, 0, 0.08) 65%, rgba(0, 0, 0, 0.2) 67%, rgba(0, 0, 0, 0.4) 69%, rgba(0, 0, 0, 0.6) 70%, rgba(0, 0, 0, 0.6) 70.5%, rgba(0, 0, 0, 0.4) 71.5%, rgba(0, 0, 0, 0.2) 73%, rgba(0, 0, 0, 0.08) 75%, rgba(0, 0, 0, 0.02) 78%, transparent 82%);
562
-
563
- [dark] & {
564
- --beam-rotate-highlight: conic-gradient(from var(--beam-angle), transparent 0%, transparent 54%, rgba(255, 255, 255, 0.1) 57%, rgba(255, 255, 255, 0.3) 60%, rgba(255, 255, 255, 0.6) 63%, rgba(255, 255, 255, 0.75) 66%, rgba(255, 255, 255, 0.6) 69%, rgba(255, 255, 255, 0.3) 72%, rgba(255, 255, 255, 0.1) 75%, transparent 78%, transparent 100%);
565
- --beam-rotate-bloom: conic-gradient(from var(--beam-angle), transparent 0%, transparent 58%, rgba(255, 255, 255, 0.03) 62%, rgba(255, 255, 255, 0.08) 65%, rgba(255, 255, 255, 0.2) 67%, rgba(255, 255, 255, 0.45) 69%, rgba(255, 255, 255, 0.85) 70%, rgba(255, 255, 255, 0.85) 70.5%, rgba(255, 255, 255, 0.45) 71.5%, rgba(255, 255, 255, 0.2) 73%, rgba(255, 255, 255, 0.08) 75%, rgba(255, 255, 255, 0.03) 78%, transparent 82%);
566
- }
567
-
568
588
  &.isActive {
569
589
  animation: borderBeamSpin calc(var(--beam-duration) * 1s) linear infinite, borderBeamFadeIn .6s ease forwards;
570
590
  }
@@ -606,7 +626,7 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
606
626
  z-index: 3;
607
627
  inset: 0;
608
628
  padding: 1px;
609
- background: var(--beam-rotate-bloom);
629
+ background: #{$rotate-bloom-light};
610
630
  border-radius: calc(var(--beam-radius) - 1px);
611
631
  opacity: 0;
612
632
  filter: blur(8px) brightness(var(--beam-brightness)) saturate(var(--beam-saturation));
@@ -615,6 +635,10 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
615
635
  mask-composite: exclude;
616
636
  }
617
637
 
638
+ [dark] & > .bloom {
639
+ background: #{$rotate-bloom-dark};
640
+ }
641
+
618
642
  &.isActive > .bloom,
619
643
  &.isFading > .bloom {
620
644
  display: block;
@@ -640,11 +664,16 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
640
664
 
641
665
  &.isActive::after,
642
666
  &.isFading::after {
643
- background: var(--beam-rotate-highlight), var(--beam-rotate-blobs);
667
+ background: #{$rotate-highlight-light}, var(--beam-rotate-blobs);
644
668
  mask: #{$md-window}, #{$ring-mask};
645
669
  mask-composite: intersect, exclude;
646
670
  }
647
671
 
672
+ [dark] &.isActive::after,
673
+ [dark] &.isFading::after {
674
+ background: #{$rotate-highlight-dark}, var(--beam-rotate-blobs);
675
+ }
676
+
648
677
  &.isActive::before,
649
678
  &.isFading::before {
650
679
  background: var(--beam-rotate-inner);
@@ -673,11 +702,16 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
673
702
 
674
703
  &.isActive::after,
675
704
  &.isFading::after {
676
- background: var(--beam-rotate-highlight), var(--beam-sm-blobs);
705
+ background: #{$rotate-highlight-light}, var(--beam-sm-blobs);
677
706
  mask: #{$sm-window}, #{$ring-mask};
678
707
  mask-composite: intersect, exclude;
679
708
  }
680
709
 
710
+ [dark] &.isActive::after,
711
+ [dark] &.isFading::after {
712
+ background: #{$rotate-highlight-dark}, var(--beam-sm-blobs);
713
+ }
714
+
681
715
  &.isActive::before,
682
716
  &.isFading::before {
683
717
  background: var(--beam-sm-inner);
@@ -700,7 +734,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
700
734
  --beam-brightness: 1.3;
701
735
  --beam-inner-opacity: .32;
702
736
  --beam-inner-shadow: rgba(0, 0, 0, .14);
703
- --beam-line-highlight: radial-gradient(ellipse calc(35px * var(--beam-w)) calc(28px * var(--beam-h)) at calc(var(--beam-x) * 100%) calc(100% + 2px), rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.25) 35%, transparent 70%);
704
737
  --beam-saturation: 1.95;
705
738
  --beam-stroke-opacity: .16;
706
739
 
@@ -708,7 +741,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
708
741
  --beam-bloom-opacity: .8;
709
742
  --beam-inner-opacity: .7;
710
743
  --beam-inner-shadow: rgba(255, 255, 255, .1);
711
- --beam-line-highlight: radial-gradient(ellipse calc(24px * var(--beam-w)) calc(28px * var(--beam-h)) at calc(var(--beam-x) * 100%) calc(100% + 2px), rgba(255, 255, 255, 0.38) 0%, rgba(255, 255, 255, 0.12) 30%, transparent 65%);
712
744
  --beam-saturation: 1.2;
713
745
  --beam-stroke-opacity: 1.14;
714
746
  }
@@ -728,7 +760,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
728
760
  inset: 0;
729
761
  padding: 1px;
730
762
  content: '';
731
- background: var(--beam-line-highlight), var(--beam-line-blobs);
732
763
  border-radius: calc(var(--beam-radius) - 1px);
733
764
  opacity: calc(var(--beam-opacity) * var(--beam-edge) * var(--beam-stroke-opacity) * var(--beam-strength));
734
765
  animation: borderBeamHueShift 12s ease-in-out infinite;
@@ -743,7 +774,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
743
774
  z-index: 1;
744
775
  inset: 0;
745
776
  content: '';
746
- background: var(--beam-line-inner);
747
777
  border-radius: var(--beam-radius);
748
778
  box-shadow: inset 0 0 9px 1px var(--beam-inner-shadow);
749
779
  opacity: calc(var(--beam-opacity) * var(--beam-edge) * var(--beam-inner-opacity) * var(--beam-strength));
@@ -761,7 +791,6 @@ $line-bloom-window: string.unquote('radial-gradient(ellipse calc(84px * var(--be
761
791
  > .bloom {
762
792
  z-index: 3;
763
793
  inset: 0;
764
- background: var(--beam-line-bloom);
765
794
  border-radius: calc(var(--beam-radius) - 1px);
766
795
  opacity: 0;
767
796
  clip-path: inset(0 round var(--beam-radius));
@@ -0,0 +1,86 @@
1
+ @use '~flux/components/css/mixin';
2
+
3
+ .breadcrumb {
4
+ display: block;
5
+ max-width: 100%;
6
+ }
7
+
8
+ .breadcrumbList {
9
+ display: flex;
10
+ flex-wrap: wrap;
11
+ margin: 0;
12
+ padding: 0;
13
+ align-items: center;
14
+ gap: 3px;
15
+ list-style: none;
16
+
17
+ .breadcrumbItem {
18
+ margin: 0;
19
+ }
20
+ }
21
+
22
+ .breadcrumbItem {
23
+ display: inline-flex;
24
+ min-width: 0;
25
+ align-items: center;
26
+ gap: 3px;
27
+
28
+ &:last-child .breadcrumbSeparator {
29
+ display: none;
30
+ }
31
+ }
32
+
33
+ .breadcrumbLink {
34
+ display: inline-flex;
35
+ height: 30px;
36
+ max-width: 100%;
37
+ padding: 0 9px;
38
+ align-items: center;
39
+ gap: 9px;
40
+ background: transparent;
41
+ border: 0;
42
+ border-radius: var(--radius);
43
+ color: var(--foreground-secondary);
44
+ font-size: 14px;
45
+ line-height: 1;
46
+ text-decoration: none;
47
+ white-space: nowrap;
48
+ cursor: pointer;
49
+ transition: var(--transition-default);
50
+ transition-property: background, color, mixin.focus-ring-transition-properties();
51
+
52
+ @include mixin.focus-ring(2px, true);
53
+
54
+ &:not(.isCurrent) {
55
+ @include mixin.hover {
56
+ background: var(--surface-hover);
57
+ color: var(--foreground);
58
+ }
59
+ }
60
+
61
+ &.isCurrent {
62
+ color: var(--foreground-prominent);
63
+ font-weight: 600;
64
+ cursor: default;
65
+ pointer-events: none;
66
+ }
67
+ }
68
+
69
+ .breadcrumbIcon {
70
+ margin-top: -1px;
71
+ margin-bottom: -1px;
72
+ flex-shrink: 0;
73
+ }
74
+
75
+ .breadcrumbLabel {
76
+ overflow: hidden;
77
+ text-overflow: ellipsis;
78
+ white-space: nowrap;
79
+ }
80
+
81
+ .breadcrumbSeparator {
82
+ flex-shrink: 0;
83
+ color: var(--foreground-secondary);
84
+ opacity: .5;
85
+ pointer-events: none;
86
+ }
@@ -63,6 +63,7 @@
63
63
  }
64
64
 
65
65
  .separator {
66
+ flex-shrink: 0;
66
67
  background: var(--gray-200);
67
68
  }
68
69