@astronox/core 0.3.1 → 0.4.1

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 (39) hide show
  1. package/README.md +2 -2
  2. package/package.json +1 -1
  3. package/src/ads/adsense/AdsenseHead.astro +55 -0
  4. package/src/ads/adsense/AdsenseUnit.astro +45 -0
  5. package/src/ads/adsense/index.ts +3 -1
  6. package/src/ads/adsense/provider.ts +41 -0
  7. package/src/ads/adsense/runtime.ts +284 -0
  8. package/src/ads/contracts.ts +67 -5
  9. package/src/components/content/CardHeader/CardHeader.astro +20 -0
  10. package/src/components/content/CardHeader/CardHeader.css +21 -0
  11. package/src/components/feedback/Tooltip/tooltipController.ts +37 -5
  12. package/src/components/monetization/AdSlot/AdSlot.astro +0 -3
  13. package/src/components/monetization/AdSlot/AdSlot.css +5 -28
  14. package/src/components/navigation/Breadcrumbs/Breadcrumbs.astro +2 -0
  15. package/src/components/navigation/Breadcrumbs/Breadcrumbs.css +12 -6
  16. package/src/components/navigation/Footer/Footer.astro +8 -0
  17. package/src/components/navigation/Footer/Footer.css +20 -6
  18. package/src/components/navigation/Footer/contracts.ts +1 -0
  19. package/src/composition/Grid/Grid.css +1 -1
  20. package/src/composition/SurfaceGroup/SurfaceGroup.astro +2 -1
  21. package/src/composition/SurfaceGroup/SurfaceGroup.css +18 -18
  22. package/src/composition/SurfaceGroup/stickySurfaceGroupController.ts +9 -0
  23. package/src/config/environment.ts +66 -2
  24. package/src/layouts/BaseLayout.astro +6 -1
  25. package/src/patterns/Combobox/comboboxController.ts +51 -12
  26. package/src/patterns/Dropdown/dropdownController.ts +17 -6
  27. package/src/patterns/Fullscreen/FullscreenControl.astro +3 -30
  28. package/src/patterns/Fullscreen/fullscreenController.ts +18 -22
  29. package/src/patterns/Table/Table.css +8 -2
  30. package/src/patterns/Table/TableFilterPanel.astro +84 -0
  31. package/src/patterns/Table/TableFilterPanel.css +139 -0
  32. package/src/patterns/Table/TableSkeleton.css +0 -3
  33. package/src/patterns/Table/tableFilterPanelController.ts +91 -0
  34. package/src/patterns/Table/tableProgressiveController.ts +78 -16
  35. package/src/patterns/Table/tableScrollPosition.ts +41 -0
  36. package/src/patterns/Table/tableSortController.ts +6 -3
  37. package/src/patterns/index.ts +2 -0
  38. package/src/styles/style.css +1 -0
  39. package/src/ads/adsense.ts +0 -112
@@ -352,6 +352,7 @@ export function initCombobox(root: HTMLElement): () => void {
352
352
  let activeOption: HTMLButtonElement | null = null;
353
353
  let positionFrame: number | null = null;
354
354
  let viewportListenersAttached = false;
355
+ let openAtPointerDown: boolean | null = null;
355
356
 
356
357
  const isOpen = (): boolean => root.hasAttribute('data-combobox-open');
357
358
 
@@ -391,6 +392,18 @@ export function initCombobox(root: HTMLElement): () => void {
391
392
  }
392
393
  };
393
394
 
395
+ const scrollOptionIntoView = (option: HTMLElement | null): void => {
396
+ if (!option) return;
397
+ const optionsRect = optionsRoot.getBoundingClientRect();
398
+ const optionRect = option.getBoundingClientRect();
399
+
400
+ if (optionRect.top < optionsRect.top) {
401
+ optionsRoot.scrollTop -= optionsRect.top - optionRect.top;
402
+ } else if (optionRect.bottom > optionsRect.bottom) {
403
+ optionsRoot.scrollTop += optionRect.bottom - optionsRect.bottom;
404
+ }
405
+ };
406
+
394
407
  const positionPanel = (): void => {
395
408
  if (!isOpen()) return;
396
409
 
@@ -490,7 +503,13 @@ export function initCombobox(root: HTMLElement): () => void {
490
503
  const target = event.target;
491
504
  if (target instanceof Node && panel.contains(target)) return;
492
505
 
493
- if (window.matchMedia(compactViewportQuery).matches) {
506
+ const siteViewport = document.querySelector<HTMLElement>(
507
+ '[data-site-viewport]',
508
+ );
509
+ const isSiteScroll = siteViewport
510
+ ? target === siteViewport
511
+ : target === document || target === window;
512
+ if (isSiteScroll && window.matchMedia(compactViewportQuery).matches) {
494
513
  close();
495
514
  blurFocusedDescendant();
496
515
  return;
@@ -547,6 +566,10 @@ export function initCombobox(root: HTMLElement): () => void {
547
566
  resetFilter();
548
567
  if (panel.matches(':popover-open')) panel.hidePopover();
549
568
  panel.hidden = true;
569
+ panel.style.removeProperty('--combobox-panel-inline-start');
570
+ panel.style.removeProperty('--combobox-panel-block-start');
571
+ panel.style.removeProperty('--combobox-panel-inline-size');
572
+ panel.style.removeProperty('--combobox-panel-available-block-size');
550
573
 
551
574
  if (restoreFocus) owner.focus();
552
575
  };
@@ -573,7 +596,7 @@ export function initCombobox(root: HTMLElement): () => void {
573
596
  (option) => option.getAttribute('aria-selected') === 'true',
574
597
  ) ?? null;
575
598
  setActiveOption(null);
576
- selectedOption?.scrollIntoView({ block: 'nearest' });
599
+ scrollOptionIntoView(selectedOption);
577
600
 
578
601
  if (focusSearch && search) {
579
602
  window.requestAnimationFrame(() => {
@@ -601,7 +624,7 @@ export function initCombobox(root: HTMLElement): () => void {
601
624
  visibleOptions.length;
602
625
  const nextOption = visibleOptions[nextIndex] ?? null;
603
626
  setActiveOption(nextOption);
604
- nextOption?.scrollIntoView({ block: 'nearest' });
627
+ scrollOptionIntoView(nextOption);
605
628
  };
606
629
 
607
630
  const selectOption = (
@@ -687,13 +710,23 @@ export function initCombobox(root: HTMLElement): () => void {
687
710
  };
688
711
 
689
712
  const toggleControl = (restoreFocus = true): void => {
690
- if (isOpen()) {
713
+ const wasOpen = openAtPointerDown ?? isOpen();
714
+ openAtPointerDown = null;
715
+ if (wasOpen) {
691
716
  close(restoreFocus);
692
717
  } else {
693
718
  open();
694
719
  }
695
720
  };
696
721
 
722
+ const handleOwnerPointerDown = (): void => {
723
+ openAtPointerDown = isOpen();
724
+ };
725
+
726
+ const handleOwnerPointerCancel = (): void => {
727
+ openAtPointerDown = null;
728
+ };
729
+
697
730
  const handleOptionsTriggerClick = (): void => {
698
731
  toggleControl(false);
699
732
  };
@@ -703,6 +736,7 @@ export function initCombobox(root: HTMLElement): () => void {
703
736
  };
704
737
 
705
738
  const handleOwnerKeydown = (event: KeyboardEvent): void => {
739
+ openAtPointerDown = null;
706
740
  if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
707
741
  event.preventDefault();
708
742
  if (!isOpen()) {
@@ -799,12 +833,9 @@ export function initCombobox(root: HTMLElement): () => void {
799
833
  const handleNumberInputClick = (): void => {
800
834
  if (!numberInput) return;
801
835
 
802
- if (isOpen()) {
803
- close();
804
- } else {
805
- open(false);
806
- numberInput.select();
807
- }
836
+ const wasOpen = openAtPointerDown ?? isOpen();
837
+ toggleControl(false);
838
+ if (!wasOpen) numberInput.select();
808
839
  };
809
840
 
810
841
  const handleNumberInput = (): void => {
@@ -825,7 +856,7 @@ export function initCombobox(root: HTMLElement): () => void {
825
856
  });
826
857
  }
827
858
  setActiveOption(matchingOption ?? null);
828
- matchingOption?.scrollIntoView({ block: 'nearest' });
859
+ scrollOptionIntoView(matchingOption ?? null);
829
860
  };
830
861
 
831
862
  const handleNumberInputChange = (): void => {
@@ -851,7 +882,7 @@ export function initCombobox(root: HTMLElement): () => void {
851
882
  (option) => option.getAttribute('aria-selected') === 'true',
852
883
  ) ?? null;
853
884
  setActiveOption(selectedOption);
854
- selectedOption?.scrollIntoView({ block: 'nearest' });
885
+ scrollOptionIntoView(selectedOption);
855
886
  }
856
887
  };
857
888
 
@@ -877,6 +908,8 @@ export function initCombobox(root: HTMLElement): () => void {
877
908
 
878
909
  if (mode === 'options' && trigger && search) {
879
910
  control.addEventListener('click', handleOptionsControlClick);
911
+ trigger.addEventListener('pointerdown', handleOwnerPointerDown);
912
+ trigger.addEventListener('pointercancel', handleOwnerPointerCancel);
880
913
  trigger.addEventListener('click', handleOptionsTriggerClick);
881
914
  trigger.addEventListener('keydown', handleOwnerKeydown);
882
915
  search.addEventListener('input', filterOptions);
@@ -884,6 +917,8 @@ export function initCombobox(root: HTMLElement): () => void {
884
917
  }
885
918
 
886
919
  if (mode === 'number' && numberInput) {
920
+ numberInput.addEventListener('pointerdown', handleOwnerPointerDown);
921
+ numberInput.addEventListener('pointercancel', handleOwnerPointerCancel);
887
922
  numberInput.addEventListener('click', handleNumberInputClick);
888
923
  numberInput.addEventListener('input', handleNumberInput);
889
924
  numberInput.addEventListener('change', handleNumberInputChange);
@@ -908,10 +943,14 @@ export function initCombobox(root: HTMLElement): () => void {
908
943
  detachViewportListeners();
909
944
  controlResizeObserver?.disconnect();
910
945
  control.removeEventListener('click', handleOptionsControlClick);
946
+ trigger?.removeEventListener('pointerdown', handleOwnerPointerDown);
947
+ trigger?.removeEventListener('pointercancel', handleOwnerPointerCancel);
911
948
  trigger?.removeEventListener('click', handleOptionsTriggerClick);
912
949
  trigger?.removeEventListener('keydown', handleOwnerKeydown);
913
950
  search?.removeEventListener('input', filterOptions);
914
951
  search?.removeEventListener('keydown', handleSearchKeydown);
952
+ numberInput?.removeEventListener('pointerdown', handleOwnerPointerDown);
953
+ numberInput?.removeEventListener('pointercancel', handleOwnerPointerCancel);
915
954
  numberInput?.removeEventListener('click', handleNumberInputClick);
916
955
  numberInput?.removeEventListener('input', handleNumberInput);
917
956
  numberInput?.removeEventListener('change', handleNumberInputChange);
@@ -25,6 +25,7 @@ export function initDropdown(root: HTMLElement): () => void {
25
25
  const triggerMode = getTriggerMode(root);
26
26
  const hoverMedia = window.matchMedia('(hover: hover)');
27
27
  let isOpen = !content.hidden;
28
+ let openAtPointerDown: boolean | null = null;
28
29
 
29
30
  const canOpenOnHover = (): boolean =>
30
31
  triggerMode === 'hover' && hoverMedia.matches;
@@ -61,12 +62,17 @@ export function initDropdown(root: HTMLElement): () => void {
61
62
  };
62
63
 
63
64
  const handleTriggerClick = (): void => {
64
- if (canOpenOnHover()) {
65
- setOpen(true);
66
- return;
67
- }
65
+ const wasOpen = openAtPointerDown ?? isOpen;
66
+ openAtPointerDown = null;
67
+ setOpen(!wasOpen);
68
+ };
69
+
70
+ const handleTriggerPointerDown = (): void => {
71
+ openAtPointerDown = isOpen;
72
+ };
68
73
 
69
- setOpen(!isOpen);
74
+ const handleTriggerPointerCancel = (): void => {
75
+ openAtPointerDown = null;
70
76
  };
71
77
 
72
78
  const handleRootPointerEnter = (): void => {
@@ -88,12 +94,13 @@ export function initDropdown(root: HTMLElement): () => void {
88
94
  };
89
95
 
90
96
  const handleTriggerFocus = (): void => {
91
- if (triggerMode === 'hover') {
97
+ if (canOpenOnHover()) {
92
98
  setOpen(true);
93
99
  }
94
100
  };
95
101
 
96
102
  const handleTriggerKeydown = (event: KeyboardEvent): void => {
103
+ openAtPointerDown = null;
97
104
  if (event.key === 'ArrowDown') {
98
105
  event.preventDefault();
99
106
  openAndFocusFirstItem();
@@ -131,6 +138,8 @@ export function initDropdown(root: HTMLElement): () => void {
131
138
 
132
139
  setOpen(isOpen);
133
140
 
141
+ trigger.addEventListener('pointerdown', handleTriggerPointerDown);
142
+ trigger.addEventListener('pointercancel', handleTriggerPointerCancel);
134
143
  trigger.addEventListener('click', handleTriggerClick);
135
144
  trigger.addEventListener('focus', handleTriggerFocus);
136
145
  trigger.addEventListener('keydown', handleTriggerKeydown);
@@ -143,6 +152,8 @@ export function initDropdown(root: HTMLElement): () => void {
143
152
 
144
153
  return () => {
145
154
  close();
155
+ trigger.removeEventListener('pointerdown', handleTriggerPointerDown);
156
+ trigger.removeEventListener('pointercancel', handleTriggerPointerCancel);
146
157
  trigger.removeEventListener('click', handleTriggerClick);
147
158
  trigger.removeEventListener('focus', handleTriggerFocus);
148
159
  trigger.removeEventListener('keydown', handleTriggerKeydown);
@@ -4,13 +4,6 @@ import type { Tone } from '../../theme/contracts';
4
4
  import Button from '../../components/actions/Button/Button.astro';
5
5
  import EnterFullscreenIcon from '../../components/icons/EnterFullscreenIcon.astro';
6
6
  import ExitFullscreenIcon from '../../components/icons/ExitFullscreenIcon.astro';
7
- import ExternalLinkIcon from '../../components/icons/ExternalLinkIcon.astro';
8
-
9
- type FullscreenUnsupportedFallback = {
10
- href: string;
11
- label: string;
12
- target?: '_blank' | '_self';
13
- };
14
7
 
15
8
  type Props = Omit<
16
9
  HTMLAttributes<'button'>,
@@ -21,7 +14,7 @@ type Props = Omit<
21
14
  exitLabel: string;
22
15
  targetId: string;
23
16
  tone?: Tone;
24
- unsupportedFallback?: FullscreenUnsupportedFallback;
17
+ unavailableLabel?: string;
25
18
  };
26
19
 
27
20
  const {
@@ -30,7 +23,7 @@ const {
30
23
  exitLabel,
31
24
  targetId,
32
25
  tone,
33
- unsupportedFallback,
26
+ unavailableLabel = enterLabel,
34
27
  ...attrs
35
28
  }: Props = Astro.props;
36
29
  const resolvedClass = ['fullscreen-control', className]
@@ -54,6 +47,7 @@ const resolvedClass = ['fullscreen-control', className]
54
47
  data-fullscreen-enter-label={enterLabel}
55
48
  data-fullscreen-exit-label={exitLabel}
56
49
  data-fullscreen-target={targetId}
50
+ data-fullscreen-unavailable-label={unavailableLabel}
57
51
  >
58
52
  <span class="fullscreen-control__icon" data-fullscreen-enter-icon>
59
53
  <EnterFullscreenIcon />
@@ -63,27 +57,6 @@ const resolvedClass = ['fullscreen-control', className]
63
57
  </span>
64
58
  </Button>
65
59
 
66
- {
67
- unsupportedFallback ? (
68
- <Button
69
- href={unsupportedFallback.href}
70
- target={unsupportedFallback.target ?? '_blank'}
71
- borderless
72
- full
73
- iconOnly
74
- tone={tone}
75
- aria-label={unsupportedFallback.label}
76
- title={unsupportedFallback.label}
77
- hidden
78
- data-fullscreen-unsupported-fallback
79
- >
80
- <span class="fullscreen-control__icon">
81
- <ExternalLinkIcon />
82
- </span>
83
- </Button>
84
- ) : null
85
- }
86
-
87
60
  <script>
88
61
  import { initFullscreenControl } from './fullscreenController';
89
62
 
@@ -6,32 +6,30 @@ export function initFullscreenControl(control: HTMLButtonElement): () => void {
6
6
 
7
7
  const targetId = control.dataset.fullscreenTarget;
8
8
  const target = targetId ? document.getElementById(targetId) : null;
9
- const fallbackCandidate = control.nextElementSibling;
10
- const fallback =
11
- fallbackCandidate instanceof HTMLAnchorElement &&
12
- fallbackCandidate.hasAttribute('data-fullscreen-unsupported-fallback')
13
- ? fallbackCandidate
14
- : null;
15
- const showUnsupportedFallback = (): void => {
16
- control.hidden = true;
17
- if (fallback instanceof HTMLAnchorElement) fallback.hidden = false;
9
+ const initiallyDisabled = control.disabled;
10
+ const enterLabel = control.dataset.fullscreenEnterLabel ?? '';
11
+ const exitLabel = control.dataset.fullscreenExitLabel ?? '';
12
+ const unavailableLabel =
13
+ control.dataset.fullscreenUnavailableLabel ?? enterLabel;
14
+ const setUnavailable = (): void => {
15
+ control.disabled = true;
16
+ control.setAttribute('aria-disabled', 'true');
17
+ control.setAttribute('aria-label', unavailableLabel);
18
+ control.setAttribute('aria-pressed', 'false');
19
+ control.title = unavailableLabel;
20
+ control.setAttribute('data-fullscreen-unavailable', '');
18
21
  };
19
22
  if (
20
23
  document.fullscreenEnabled !== true ||
21
24
  !target ||
22
25
  typeof target.requestFullscreen !== 'function'
23
26
  ) {
24
- showUnsupportedFallback();
27
+ setUnavailable();
25
28
  return noop;
26
29
  }
27
30
 
28
- control.hidden = false;
29
- if (fallback instanceof HTMLAnchorElement) fallback.hidden = true;
30
31
  control.setAttribute(initializedAttribute, 'true');
31
32
 
32
- const enterLabel = control.dataset.fullscreenEnterLabel ?? '';
33
- const exitLabel = control.dataset.fullscreenExitLabel ?? '';
34
-
35
33
  const sync = (): void => {
36
34
  const active = document.fullscreenElement === target;
37
35
  const label = active ? exitLabel : enterLabel;
@@ -49,11 +47,7 @@ export function initFullscreenControl(control: HTMLButtonElement): () => void {
49
47
  await target.requestFullscreen();
50
48
  }
51
49
  } catch {
52
- if (fallback instanceof HTMLAnchorElement) {
53
- showUnsupportedFallback();
54
- } else {
55
- sync();
56
- }
50
+ setUnavailable();
57
51
  }
58
52
  };
59
53
 
@@ -65,7 +59,9 @@ export function initFullscreenControl(control: HTMLButtonElement): () => void {
65
59
  control.removeEventListener('click', toggle);
66
60
  document.removeEventListener('fullscreenchange', sync);
67
61
  control.removeAttribute(initializedAttribute);
68
- control.hidden = false;
69
- if (fallback instanceof HTMLAnchorElement) fallback.hidden = true;
62
+ control.removeAttribute('data-fullscreen-unavailable');
63
+ control.removeAttribute('aria-disabled');
64
+ control.disabled = initiallyDisabled;
65
+ sync();
70
66
  };
71
67
  }
@@ -49,7 +49,10 @@
49
49
 
50
50
  .table[data-table-sticky-header]:has([data-sticky-surface])
51
51
  [data-table-header] {
52
- top: calc(var(--nox-layout-gap) + var(--nox-section-responsive-block-size));
52
+ top: var(
53
+ --surface-group-sticky-occlusion-size,
54
+ calc(var(--nox-layout-gap) + var(--nox-section-responsive-block-size))
55
+ );
53
56
  }
54
57
 
55
58
  @container nox-table (width < 32rem) {
@@ -60,7 +63,10 @@
60
63
 
61
64
  .table[data-table-sticky-header]:has([data-sticky-surface])
62
65
  [data-table-header] {
63
- top: calc(var(--nox-layout-gap) + var(--nox-section-compact-block-size));
66
+ top: var(
67
+ --surface-group-sticky-occlusion-size,
68
+ calc(var(--nox-layout-gap) + var(--nox-section-compact-block-size))
69
+ );
64
70
  }
65
71
  }
66
72
 
@@ -0,0 +1,84 @@
1
+ ---
2
+ import type { HTMLAttributes } from 'astro/types';
3
+ import type { DisplayMedia } from '../../display/contracts';
4
+ import type { Tone } from '../../theme/contracts';
5
+ import type {
6
+ AstroComponent,
7
+ HeadingLevel,
8
+ } from '../../components/widgetTypes';
9
+ import ArrowDownIcon from '../../components/icons/ArrowDownIcon.astro';
10
+ import CardBody from '../../components/content/CardBody/CardBody.astro';
11
+ import CardHeader from '../../components/content/CardHeader/CardHeader.astro';
12
+ import SurfaceGroup from '../../composition/SurfaceGroup/SurfaceGroup.astro';
13
+
14
+ type HeaderVisual =
15
+ | { icon?: AstroComponent; media?: never }
16
+ | { icon?: never; media: DisplayMedia };
17
+
18
+ type Props = Omit<HTMLAttributes<'div'>, 'id'> &
19
+ HeaderVisual & {
20
+ id: string;
21
+ title: string;
22
+ collapseAt?: 'sm' | 'md' | 'lg' | 'xl';
23
+ headingLevel?: HeadingLevel;
24
+ tone?: Tone;
25
+ };
26
+
27
+ const {
28
+ class: className,
29
+ collapseAt = 'lg',
30
+ headingLevel = 2,
31
+ icon,
32
+ id,
33
+ media,
34
+ title,
35
+ tone,
36
+ ...attrs
37
+ }: Props = Astro.props;
38
+ const contentId = `${id}-content`;
39
+ const hasAction = Astro.slots.has('action');
40
+ const headerVisual: HeaderVisual = media ? { media } : { icon };
41
+ ---
42
+
43
+ <SurfaceGroup
44
+ {...attrs}
45
+ id={id}
46
+ class:list={['table-filter-panel', className]}
47
+ data-table-filter-panel
48
+ data-table-filter-panel-collapse-at={collapseAt}
49
+ tone={tone}
50
+ >
51
+ <CardHeader
52
+ {...headerVisual}
53
+ title={title}
54
+ headingLevel={headingLevel}
55
+ tone={tone}
56
+ trigger={{
57
+ controls: contentId,
58
+ expanded: false,
59
+ label: title,
60
+ }}
61
+ >
62
+ <span slot="end" class="table-filter-panel__indicator" aria-hidden="true">
63
+ <ArrowDownIcon />
64
+ </span>
65
+ {
66
+ hasAction ? (
67
+ <Fragment slot="action">
68
+ <slot name="action" />
69
+ </Fragment>
70
+ ) : null
71
+ }
72
+ </CardHeader>
73
+ <CardBody id={contentId} overlayBoundary data-table-filter-panel-content>
74
+ <slot />
75
+ </CardBody>
76
+ </SurfaceGroup>
77
+
78
+ <script>
79
+ import { initTableFilterPanel } from './tableFilterPanelController';
80
+
81
+ for (const root of document.querySelectorAll('[data-table-filter-panel]')) {
82
+ if (root instanceof HTMLElement) initTableFilterPanel(root);
83
+ }
84
+ </script>
@@ -0,0 +1,139 @@
1
+ .table-filter-panel__indicator {
2
+ display: none;
3
+ inline-size: 1.25rem;
4
+ block-size: 1.25rem;
5
+ flex: none;
6
+ transition: transform var(--nox-motion-duration-sm)
7
+ var(--nox-motion-easing-standard);
8
+ }
9
+
10
+ .table-filter-panel .card-header__trigger {
11
+ display: none;
12
+ }
13
+
14
+ .table-filter-panel__indicator > svg {
15
+ display: block;
16
+ inline-size: 100%;
17
+ block-size: 100%;
18
+ }
19
+
20
+ .table-filter-panel[data-table-filter-panel-compact]
21
+ .table-filter-panel__indicator {
22
+ display: block;
23
+ }
24
+
25
+ .table-filter-panel[data-table-filter-panel-compact] .card-header__trigger {
26
+ display: block;
27
+ }
28
+
29
+ .table-filter-panel[data-table-filter-panel-compact]:not(
30
+ [data-table-filter-panel-open]
31
+ ) {
32
+ --surface-group-connected-border-end-radius: var(--nox-radius-md);
33
+ }
34
+
35
+ .table-filter-panel[data-table-filter-panel-compact]:not(
36
+ [data-table-filter-panel-open]
37
+ )
38
+ > [data-table-filter-panel-content] {
39
+ display: none;
40
+ }
41
+
42
+ .table-filter-panel[data-table-filter-panel-compact][data-table-filter-panel-open]
43
+ .table-filter-panel__indicator {
44
+ transform: rotate(180deg);
45
+ }
46
+
47
+ @container nox-grid (width < 24rem) {
48
+ .table-filter-panel[data-table-filter-panel-collapse-at='sm']:not(
49
+ [data-table-filter-panel-open]
50
+ ) {
51
+ --surface-group-connected-border-end-radius: var(--nox-radius-md);
52
+ }
53
+
54
+ .table-filter-panel[data-table-filter-panel-collapse-at='sm']
55
+ .table-filter-panel__indicator,
56
+ .table-filter-panel[data-table-filter-panel-collapse-at='sm']
57
+ .card-header__trigger {
58
+ display: block;
59
+ }
60
+
61
+ .table-filter-panel[data-table-filter-panel-collapse-at='sm']:not(
62
+ [data-table-filter-panel-open]
63
+ )
64
+ > [data-table-filter-panel-content] {
65
+ display: none;
66
+ }
67
+ }
68
+
69
+ @container nox-grid (width < 36rem) {
70
+ .table-filter-panel[data-table-filter-panel-collapse-at='md']:not(
71
+ [data-table-filter-panel-open]
72
+ ) {
73
+ --surface-group-connected-border-end-radius: var(--nox-radius-md);
74
+ }
75
+
76
+ .table-filter-panel[data-table-filter-panel-collapse-at='md']
77
+ .table-filter-panel__indicator,
78
+ .table-filter-panel[data-table-filter-panel-collapse-at='md']
79
+ .card-header__trigger {
80
+ display: block;
81
+ }
82
+
83
+ .table-filter-panel[data-table-filter-panel-collapse-at='md']:not(
84
+ [data-table-filter-panel-open]
85
+ )
86
+ > [data-table-filter-panel-content] {
87
+ display: none;
88
+ }
89
+ }
90
+
91
+ @container nox-grid (width < 44rem) {
92
+ .table-filter-panel[data-table-filter-panel-collapse-at='lg']:not(
93
+ [data-table-filter-panel-open]
94
+ ) {
95
+ --surface-group-connected-border-end-radius: var(--nox-radius-md);
96
+ }
97
+
98
+ .table-filter-panel[data-table-filter-panel-collapse-at='lg']
99
+ .table-filter-panel__indicator,
100
+ .table-filter-panel[data-table-filter-panel-collapse-at='lg']
101
+ .card-header__trigger {
102
+ display: block;
103
+ }
104
+
105
+ .table-filter-panel[data-table-filter-panel-collapse-at='lg']:not(
106
+ [data-table-filter-panel-open]
107
+ )
108
+ > [data-table-filter-panel-content] {
109
+ display: none;
110
+ }
111
+ }
112
+
113
+ @container nox-grid (width < 54rem) {
114
+ .table-filter-panel[data-table-filter-panel-collapse-at='xl']:not(
115
+ [data-table-filter-panel-open]
116
+ ) {
117
+ --surface-group-connected-border-end-radius: var(--nox-radius-md);
118
+ }
119
+
120
+ .table-filter-panel[data-table-filter-panel-collapse-at='xl']
121
+ .table-filter-panel__indicator,
122
+ .table-filter-panel[data-table-filter-panel-collapse-at='xl']
123
+ .card-header__trigger {
124
+ display: block;
125
+ }
126
+
127
+ .table-filter-panel[data-table-filter-panel-collapse-at='xl']:not(
128
+ [data-table-filter-panel-open]
129
+ )
130
+ > [data-table-filter-panel-content] {
131
+ display: none;
132
+ }
133
+ }
134
+
135
+ @media (prefers-reduced-motion: reduce) {
136
+ .table-filter-panel__indicator {
137
+ transition: none;
138
+ }
139
+ }
@@ -17,9 +17,6 @@
17
17
 
18
18
  [data-nox-table-enhanced]
19
19
  .table[data-table-loading-state='pending']
20
- .table-body__row[data-table-row],
21
- [data-nox-table-enhanced]
22
- .table[data-table-loading-state='refreshing']
23
20
  .table-body__row[data-table-row] {
24
21
  display: none;
25
22
  }