@slotted/styles 0.0.0-stage → 0.1.0-beta.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/LICENSE +21 -0
- package/README.md +10 -2
- package/package.json +276 -3
- package/src/accordion/accordion.css +96 -0
- package/src/accordion/accordion.tokens.json +14 -0
- package/src/action-bar/action-bar.css +455 -0
- package/src/action-bar/action-bar.tokens.json +50 -0
- package/src/action-sheet/action-sheet.css +462 -0
- package/src/action-sheet/action-sheet.tokens.json +59 -0
- package/src/alert/alert.css +764 -0
- package/src/alert/alert.tokens.json +77 -0
- package/src/app-shell/app-shell.css +1899 -0
- package/src/app-shell/app-shell.tokens.json +88 -0
- package/src/aspect-ratio/aspect-ratio.css +131 -0
- package/src/aspect-ratio/aspect-ratio.tokens.json +1 -0
- package/src/attachment/attachment.css +906 -0
- package/src/attachment/attachment.tokens.json +85 -0
- package/src/avatar/avatar.css +598 -0
- package/src/avatar/avatar.tokens.json +64 -0
- package/src/avatar-group/avatar-group.css +268 -0
- package/src/avatar-group/avatar-group.tokens.json +16 -0
- package/src/badge/badge.css +462 -0
- package/src/badge/badge.tokens.json +58 -0
- package/src/breadcrumb/breadcrumb.css +441 -0
- package/src/breadcrumb/breadcrumb.tokens.json +50 -0
- package/src/button/button.css +754 -0
- package/src/button/button.tokens.json +72 -0
- package/src/button-group/button-group.css +455 -0
- package/src/button-group/button-group.tokens.json +11 -0
- package/src/calendar/calendar.css +846 -0
- package/src/calendar/calendar.tokens.json +67 -0
- package/src/card/card.css +602 -0
- package/src/card/card.tokens.json +68 -0
- package/src/carousel/carousel.css +860 -0
- package/src/carousel/carousel.tokens.json +62 -0
- package/src/cascader/cascader.css +1320 -0
- package/src/cascader/cascader.tokens.json +103 -0
- package/src/chart/chart.css +1473 -0
- package/src/chart/chart.tokens.json +107 -0
- package/src/checkbox/checkbox.css +1011 -0
- package/src/checkbox/checkbox.tokens.json +102 -0
- package/src/checkbox-group/checkbox-group.css +70 -0
- package/src/checkbox-group/checkbox-group.tokens.json +6 -0
- package/src/code-block/code-block.css +555 -0
- package/src/code-block/code-block.tokens.json +69 -0
- package/src/collapsible/collapsible.css +546 -0
- package/src/collapsible/collapsible.tokens.json +55 -0
- package/src/color-picker/color-picker.css +607 -0
- package/src/color-picker/color-picker.tokens.json +58 -0
- package/src/column-manager/column-manager.css +452 -0
- package/src/column-manager/column-manager.tokens.json +43 -0
- package/src/combobox/combobox.css +1048 -0
- package/src/combobox/combobox.tokens.json +112 -0
- package/src/command-palette/command-palette.css +1000 -0
- package/src/command-palette/command-palette.tokens.json +75 -0
- package/src/container/container.css +198 -0
- package/src/container/container.tokens.json +18 -0
- package/src/context-menu/context-menu.css +104 -0
- package/src/context-menu/context-menu.tokens.json +11 -0
- package/src/currency-field/currency-field.css +787 -0
- package/src/currency-field/currency-field.tokens.json +80 -0
- package/src/dashboard-grid/dashboard-grid.css +748 -0
- package/src/dashboard-grid/dashboard-grid.tokens.json +67 -0
- package/src/data-grid/data-grid.css +2484 -0
- package/src/data-grid/data-grid.tokens.json +100 -0
- package/src/data-list/data-list.css +455 -0
- package/src/data-list/data-list.tokens.json +35 -0
- package/src/date-field/date-field.css +560 -0
- package/src/date-field/date-field.tokens.json +80 -0
- package/src/date-picker/date-picker.css +420 -0
- package/src/date-picker/date-picker.tokens.json +49 -0
- package/src/date-range-picker/date-range-picker.css +983 -0
- package/src/date-range-picker/date-range-picker.tokens.json +109 -0
- package/src/datetime-field/datetime-field.css +850 -0
- package/src/datetime-field/datetime-field.tokens.json +91 -0
- package/src/datetime-picker/datetime-picker.css +843 -0
- package/src/datetime-picker/datetime-picker.tokens.json +78 -0
- package/src/datetime-range-picker/datetime-range-picker.css +1375 -0
- package/src/datetime-range-picker/datetime-range-picker.tokens.json +135 -0
- package/src/description-list/description-list.css +675 -0
- package/src/description-list/description-list.tokens.json +66 -0
- package/src/detail-panel/detail-panel.css +329 -0
- package/src/detail-panel/detail-panel.tokens.json +33 -0
- package/src/dialog/dialog.css +968 -0
- package/src/dialog/dialog.tokens.json +66 -0
- package/src/divider/divider.css +131 -0
- package/src/divider/divider.tokens.json +18 -0
- package/src/drawer/drawer.css +1303 -0
- package/src/drawer/drawer.tokens.json +75 -0
- package/src/entity-picker/entity-picker.css +1367 -0
- package/src/entity-picker/entity-picker.tokens.json +118 -0
- package/src/event-calendar/event-calendar.css +2148 -0
- package/src/event-calendar/event-calendar.tokens.json +87 -0
- package/src/field/field.css +707 -0
- package/src/field/field.tokens.json +58 -0
- package/src/field-group/field-group.css +226 -0
- package/src/field-group/field-group.tokens.json +33 -0
- package/src/filter-bar/filter-bar.css +1306 -0
- package/src/filter-bar/filter-bar.tokens.json +78 -0
- package/src/form/form.css +218 -0
- package/src/form/form.tokens.json +32 -0
- package/src/fullscreen/fullscreen.css +376 -0
- package/src/fullscreen/fullscreen.tokens.json +50 -0
- package/src/grid/grid.css +173 -0
- package/src/grid/grid.tokens.json +20 -0
- package/src/highlight/highlight.css +135 -0
- package/src/highlight/highlight.tokens.json +16 -0
- package/src/hover-card/hover-card.css +93 -0
- package/src/hover-card/hover-card.tokens.json +17 -0
- package/src/icon/icon.css +136 -0
- package/src/icon/icon.tokens.json +14 -0
- package/src/image/image.css +449 -0
- package/src/image/image.tokens.json +27 -0
- package/src/import-export-center/import-export-center.css +1175 -0
- package/src/import-export-center/import-export-center.tokens.json +84 -0
- package/src/inline/inline.css +149 -0
- package/src/inline/inline.tokens.json +14 -0
- package/src/inline-message/inline-message.css +396 -0
- package/src/inline-message/inline-message.tokens.json +19 -0
- package/src/kbd/kbd.css +490 -0
- package/src/kbd/kbd.tokens.json +40 -0
- package/src/link/link.css +237 -0
- package/src/link/link.tokens.json +25 -0
- package/src/list/list.css +240 -0
- package/src/list/list.tokens.json +42 -0
- package/src/list-item/list-item.css +937 -0
- package/src/list-item/list-item.tokens.json +114 -0
- package/src/listbox/listbox.css +674 -0
- package/src/listbox/listbox.tokens.json +72 -0
- package/src/loading-overlay/loading-overlay.css +730 -0
- package/src/loading-overlay/loading-overlay.tokens.json +48 -0
- package/src/markdown/markdown.css +168 -0
- package/src/markdown/markdown.tokens.json +18 -0
- package/src/menu/menu.css +817 -0
- package/src/menu/menu.tokens.json +78 -0
- package/src/menubar/menubar.css +170 -0
- package/src/menubar/menubar.tokens.json +32 -0
- package/src/message/message.css +1453 -0
- package/src/message/message.tokens.json +85 -0
- package/src/message-scroller/message-scroller.css +371 -0
- package/src/message-scroller/message-scroller.tokens.json +47 -0
- package/src/multi-select/multi-select.css +1427 -0
- package/src/multi-select/multi-select.tokens.json +114 -0
- package/src/navigation-menu/navigation-menu.css +1029 -0
- package/src/navigation-menu/navigation-menu.tokens.json +70 -0
- package/src/notification-center/notification-center.css +856 -0
- package/src/notification-center/notification-center.tokens.json +84 -0
- package/src/number-field/number-field.css +794 -0
- package/src/number-field/number-field.tokens.json +80 -0
- package/src/otp-input/otp-input.css +525 -0
- package/src/otp-input/otp-input.tokens.json +69 -0
- package/src/page/page.css +179 -0
- package/src/page/page.tokens.json +20 -0
- package/src/page-header/page-header.css +1181 -0
- package/src/page-header/page-header.tokens.json +71 -0
- package/src/pagination/pagination.css +500 -0
- package/src/pagination/pagination.tokens.json +56 -0
- package/src/popover/popover.css +526 -0
- package/src/popover/popover.tokens.json +60 -0
- package/src/progress-indicator/progress-indicator.css +1584 -0
- package/src/progress-indicator/progress-indicator.tokens.json +50 -0
- package/src/prompt-composer/prompt-composer.css +680 -0
- package/src/prompt-composer/prompt-composer.tokens.json +99 -0
- package/src/prose/prose.css +733 -0
- package/src/prose/prose.tokens.json +79 -0
- package/src/radio-group/radio-group.css +778 -0
- package/src/radio-group/radio-group.tokens.json +103 -0
- package/src/rating/rating.css +1071 -0
- package/src/rating/rating.tokens.json +88 -0
- package/src/result-state/result-state.css +980 -0
- package/src/result-state/result-state.tokens.json +63 -0
- package/src/runtime-properties.mjs +321 -0
- package/src/saved-views/saved-views.css +394 -0
- package/src/saved-views/saved-views.tokens.json +41 -0
- package/src/scroll-area/scroll-area.css +481 -0
- package/src/scroll-area/scroll-area.tokens.json +15 -0
- package/src/section/section.css +177 -0
- package/src/section/section.tokens.json +39 -0
- package/src/segmented-control/segmented-control.css +564 -0
- package/src/segmented-control/segmented-control.tokens.json +67 -0
- package/src/select/select.css +1593 -0
- package/src/select/select.tokens.json +110 -0
- package/src/side-navigation/side-navigation.css +1096 -0
- package/src/side-navigation/side-navigation.tokens.json +87 -0
- package/src/skeleton/skeleton.css +431 -0
- package/src/skeleton/skeleton.tokens.json +29 -0
- package/src/slider/slider.css +792 -0
- package/src/slider/slider.tokens.json +75 -0
- package/src/sparkline/sparkline.css +282 -0
- package/src/sparkline/sparkline.tokens.json +45 -0
- package/src/spinner/spinner.css +224 -0
- package/src/spinner/spinner.tokens.json +8 -0
- package/src/split-button/split-button.css +253 -0
- package/src/split-button/split-button.tokens.json +12 -0
- package/src/splitter/splitter.css +336 -0
- package/src/splitter/splitter.tokens.json +24 -0
- package/src/stack/stack.css +128 -0
- package/src/stack/stack.tokens.json +14 -0
- package/src/stat-card/stat-card.css +641 -0
- package/src/stat-card/stat-card.tokens.json +95 -0
- package/src/status-indicator/status-indicator.css +481 -0
- package/src/status-indicator/status-indicator.tokens.json +38 -0
- package/src/stepper/stepper.css +629 -0
- package/src/stepper/stepper.tokens.json +72 -0
- package/src/switch/switch.css +703 -0
- package/src/switch/switch.tokens.json +75 -0
- package/src/table/table.css +1482 -0
- package/src/table/table.tokens.json +69 -0
- package/src/table-of-contents/table-of-contents.css +533 -0
- package/src/table-of-contents/table-of-contents.tokens.json +53 -0
- package/src/tabs/tabs.css +998 -0
- package/src/tabs/tabs.tokens.json +82 -0
- package/src/tag/tag.css +768 -0
- package/src/tag/tag.tokens.json +85 -0
- package/src/tags-input/tags-input.css +757 -0
- package/src/tags-input/tags-input.tokens.json +84 -0
- package/src/text-field/text-field.css +900 -0
- package/src/text-field/text-field.tokens.json +87 -0
- package/src/textarea/textarea.css +365 -0
- package/src/textarea/textarea.tokens.json +59 -0
- package/src/time-field/time-field.css +719 -0
- package/src/time-field/time-field.tokens.json +86 -0
- package/src/time-picker/time-picker.css +665 -0
- package/src/time-picker/time-picker.tokens.json +66 -0
- package/src/time-range-picker/time-range-picker.css +1287 -0
- package/src/time-range-picker/time-range-picker.tokens.json +134 -0
- package/src/timeline/timeline.css +1596 -0
- package/src/timeline/timeline.tokens.json +96 -0
- package/src/toast/toast.css +943 -0
- package/src/toast/toast.tokens.json +90 -0
- package/src/toggle/toggle.css +290 -0
- package/src/toggle/toggle.tokens.json +54 -0
- package/src/toggle-group/toggle-group.css +463 -0
- package/src/toggle-group/toggle-group.tokens.json +54 -0
- package/src/toolbar/toolbar.css +434 -0
- package/src/toolbar/toolbar.tokens.json +49 -0
- package/src/tooltip/tooltip.css +368 -0
- package/src/tooltip/tooltip.tokens.json +39 -0
- package/src/top-navigation/top-navigation.css +1287 -0
- package/src/top-navigation/top-navigation.tokens.json +91 -0
- package/src/tour/tour.css +680 -0
- package/src/tour/tour.tokens.json +67 -0
- package/src/transfer/transfer.css +571 -0
- package/src/transfer/transfer.tokens.json +49 -0
- package/src/tree/tree.css +1000 -0
- package/src/tree/tree.tokens.json +80 -0
- package/src/typography/typography.css +211 -0
- package/src/typography/typography.tokens.json +31 -0
- package/src/upload/upload.css +1706 -0
- package/src/upload/upload.tokens.json +123 -0
- package/src/visually-hidden/visually-hidden.css +52 -0
- package/src/visually-hidden/visually-hidden.tokens.json +1 -0
- package/src/wizard/wizard.css +740 -0
- package/src/wizard/wizard.tokens.json +63 -0
|
@@ -0,0 +1,1306 @@
|
|
|
1
|
+
@layer slotted.components {
|
|
2
|
+
/**
|
|
3
|
+
* A bar above a listing that edits one value: a tree of conditions over the
|
|
4
|
+
* listing's fields, whose leaves are the descriptor `table` edits in a
|
|
5
|
+
* column header. The bar draws the tree's first level — a search field, a
|
|
6
|
+
* pill per pinned field still waiting for a condition, a chip per condition
|
|
7
|
+
* — and opens a drawer on the whole tree.
|
|
8
|
+
*
|
|
9
|
+
* Two tab stops however many fields a product declares: the search, and the
|
|
10
|
+
* toolbar that holds everything else. The root is a `search` landmark and
|
|
11
|
+
* not a toolbar, because the search field needs the arrow keys a toolbar
|
|
12
|
+
* takes.
|
|
13
|
+
*
|
|
14
|
+
* Every control reads the control scale — height, inline padding, glyph,
|
|
15
|
+
* gap — so a theme that retunes a text field retunes this bar with it, and
|
|
16
|
+
* the three densities move every control together.
|
|
17
|
+
*/
|
|
18
|
+
[data-ui='filter-bar'] {
|
|
19
|
+
--_gap: var(--slotted-filter-bar-gap, var(--slotted-control-gap-md, 8px));
|
|
20
|
+
--_gap-sm: var(--slotted-control-gap-sm, 6px);
|
|
21
|
+
--_height: var(--slotted-control-height-md, 34px);
|
|
22
|
+
--_font-size: var(--slotted-control-font-size-md, 13px);
|
|
23
|
+
--_pad: var(--slotted-control-padding-inline-md, 13px);
|
|
24
|
+
/* A chip segment sits between two others, so it takes the smaller inset of the scale. */
|
|
25
|
+
--_seg-pad: var(--slotted-control-padding-inline-sm, 10px);
|
|
26
|
+
--_icon: var(--slotted-control-icon-size-md, 16px);
|
|
27
|
+
--_radius: var(--slotted-filter-bar-pill-radius, var(--slotted-radius-full, 9999px));
|
|
28
|
+
--_control-radius: var(--slotted-control-radius, var(--slotted-radius-sm, 4px));
|
|
29
|
+
--_border-width: var(--slotted-control-border-width, 1px);
|
|
30
|
+
--_ink: var(--slotted-filter-bar-color, var(--slotted-text, CanvasText));
|
|
31
|
+
--_muted: var(--slotted-filter-bar-color-muted, var(--slotted-text-muted, GrayText));
|
|
32
|
+
--_edge: var(
|
|
33
|
+
--slotted-filter-bar-pill-border,
|
|
34
|
+
var(--slotted-control-border-color, ButtonBorder)
|
|
35
|
+
);
|
|
36
|
+
/* The line between two segments of a chip: the chip's own edge carries the outline, the seam only divides. */
|
|
37
|
+
--_seam: var(--slotted-filter-bar-chip-seam, var(--slotted-border-subtle, ButtonBorder));
|
|
38
|
+
--_surface: var(--slotted-filter-bar-surface, var(--slotted-surface, Canvas));
|
|
39
|
+
--_hover: var(--slotted-tone-secondary-subtle-hover, ButtonFace);
|
|
40
|
+
--_active: var(--slotted-tone-secondary-subtle-active, ButtonFace);
|
|
41
|
+
--_invalid: var(--slotted-tone-danger-border, GrayText);
|
|
42
|
+
/* Width as well as colour (WCAG 1.4.1): in `high-contrast` the danger edge is the resting edge's black, so every invalid box adds the edge `text-field` draws, inside its border, where nothing moves. */
|
|
43
|
+
--_invalid-edge-width: var(--slotted-control-invalid-edge-width, 1px);
|
|
44
|
+
--_invalid-edge: inset 0 0 0 var(--_invalid-edge-width) var(--_invalid);
|
|
45
|
+
--_duration: var(--slotted-control-transition-duration, var(--slotted-duration-short));
|
|
46
|
+
--_easing: var(--slotted-control-transition-easing, var(--slotted-easing-standard));
|
|
47
|
+
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
color: var(--_ink);
|
|
50
|
+
font-family: var(--slotted-filter-bar-font-family, var(--slotted-font-family-sans, inherit));
|
|
51
|
+
font-size: var(--_font-size);
|
|
52
|
+
line-height: var(--slotted-line-height-md, 1.5);
|
|
53
|
+
min-inline-size: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The builder is a part that leaves the root: it renders inside a drawer,
|
|
58
|
+
* which `portal` moves to the end of the document, so it carries `data-ui`
|
|
59
|
+
* of its own and the block above gives it the same locals. The value
|
|
60
|
+
* popover a chip opens does the same.
|
|
61
|
+
*
|
|
62
|
+
* The root is the query container and the frame is the grid, because a
|
|
63
|
+
* container query cannot restyle the element it measures — the split
|
|
64
|
+
* `stepper` and `description-list` already carry, recorded in the briefing.
|
|
65
|
+
*
|
|
66
|
+
* A bar spans the listing it filters, so its inline size is its parent's:
|
|
67
|
+
* inline-size containment gives a container no intrinsic width, and a
|
|
68
|
+
* start-justified grid or flex parent measured the root at zero pixels and
|
|
69
|
+
* drew every pill and chip outside it.
|
|
70
|
+
*/
|
|
71
|
+
[data-ui='filter-bar'][data-part='root'] {
|
|
72
|
+
container-name: slotted-filter-bar;
|
|
73
|
+
container-type: inline-size;
|
|
74
|
+
display: block;
|
|
75
|
+
inline-size: 100%;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The editor a pill or a chip's value opens: one rule alone in a popover,
|
|
80
|
+
* so it carries the family's `data-ui` like the builder does. A column — the
|
|
81
|
+
* operator when a pill opened it, the operand or the pair, then Clear and
|
|
82
|
+
* Done at the end — at a width of its own, because a popover shrink-wraps
|
|
83
|
+
* and a select shrink-wrapped to its value is a control that changes width
|
|
84
|
+
* when the value does.
|
|
85
|
+
*/
|
|
86
|
+
[data-ui='filter-bar'][data-part='rule'] {
|
|
87
|
+
display: grid;
|
|
88
|
+
gap: var(--_gap);
|
|
89
|
+
inline-size: var(--slotted-filter-bar-editor-size, 18rem);
|
|
90
|
+
max-inline-size: 100%;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/*
|
|
94
|
+
* The operator and the operand are reached as descendants and not as
|
|
95
|
+
* children: a binding may render the condition inside one element of its
|
|
96
|
+
* own at `display: contents`, which leaves the two parts as grid items of
|
|
97
|
+
* the rule and out of reach of a child combinator.
|
|
98
|
+
*/
|
|
99
|
+
[data-ui='filter-bar'][data-part='rule'] [data-part='operand'] {
|
|
100
|
+
display: grid;
|
|
101
|
+
gap: var(--_gap-sm);
|
|
102
|
+
min-inline-size: 0;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
[data-ui='filter-bar'][data-part='rule'][data-kind='boolean'] [data-part='operand']:empty {
|
|
106
|
+
display: none;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
[data-ui='filter-bar'][data-part='rule'] > [data-part='actions'] {
|
|
110
|
+
align-items: center;
|
|
111
|
+
display: flex;
|
|
112
|
+
gap: var(--_gap-sm);
|
|
113
|
+
justify-content: flex-end;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* ── Composition ──────────────────────────────────────────────────────
|
|
117
|
+
*
|
|
118
|
+
* Two lines at every width from 36rem: the search, the consumer's controls
|
|
119
|
+
* and the count, then the toolbar, which wraps. The toolbar holds the chips,
|
|
120
|
+
* so it grows with the filter and has a line of its own to grow in; a
|
|
121
|
+
* composition that put it beside the search at a wide width had to measure
|
|
122
|
+
* when it wrapped, and fell back to this one whenever it did.
|
|
123
|
+
*
|
|
124
|
+
* Under 36rem: the search alone, then one control that says how many
|
|
125
|
+
* conditions are applied beside the consumer's controls, then the count.
|
|
126
|
+
* The pills and chips fold behind that control, which opens the builder. The
|
|
127
|
+
* line sits at 36rem and not at 40rem because a reference page's stage is
|
|
128
|
+
* 39rem wide: at 40rem every demonstration on the page showed the fold and
|
|
129
|
+
* none showed a chip.
|
|
130
|
+
*
|
|
131
|
+
* Every member of the first line starts at its top and is a control tall,
|
|
132
|
+
* so the count centres its text against the search whatever wraps.
|
|
133
|
+
*/
|
|
134
|
+
[data-ui='filter-bar'] > [data-part='frame'] {
|
|
135
|
+
align-items: start;
|
|
136
|
+
column-gap: var(--_gap);
|
|
137
|
+
display: grid;
|
|
138
|
+
grid-template-areas:
|
|
139
|
+
'search end count'
|
|
140
|
+
'bar bar bar';
|
|
141
|
+
grid-template-columns: minmax(0, 1fr) auto auto;
|
|
142
|
+
row-gap: var(--_gap);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='search'] {
|
|
146
|
+
grid-area: search;
|
|
147
|
+
max-inline-size: var(--slotted-filter-bar-search-max, 28rem);
|
|
148
|
+
min-inline-size: 0;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='bar'] {
|
|
152
|
+
grid-area: bar;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='end'] {
|
|
156
|
+
grid-area: end;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='count'] {
|
|
160
|
+
grid-area: count;
|
|
161
|
+
justify-self: end;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** A member that is absent collapses: the grid's gap is what would remain, and it is taken away. */
|
|
165
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='end']:empty {
|
|
166
|
+
display: none;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
[data-ui='filter-bar'][data-size='sm'] {
|
|
170
|
+
--_height: var(--slotted-control-height-sm, 30px);
|
|
171
|
+
--_font-size: var(--slotted-control-font-size-sm, 12px);
|
|
172
|
+
--_pad: var(--slotted-control-padding-inline-sm, 10px);
|
|
173
|
+
--_seg-pad: var(--slotted-control-gap-md, 8px);
|
|
174
|
+
--_icon: var(--slotted-control-icon-size-sm, 14px);
|
|
175
|
+
--_gap: var(--slotted-filter-bar-gap, var(--slotted-control-gap-sm, 6px));
|
|
176
|
+
--_gap-sm: var(--slotted-control-gap-sm, 4px);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
[data-ui='filter-bar'][data-size='lg'] {
|
|
180
|
+
--_height: var(--slotted-control-height-lg, 38px);
|
|
181
|
+
--_font-size: var(--slotted-control-font-size-lg, 14px);
|
|
182
|
+
--_pad: var(--slotted-control-padding-inline-lg, 16px);
|
|
183
|
+
--_seg-pad: var(--slotted-control-padding-inline-md, 13px);
|
|
184
|
+
--_icon: var(--slotted-control-icon-size-lg, 18px);
|
|
185
|
+
--_gap: var(--slotted-filter-bar-gap, var(--slotted-control-gap-lg, 8px));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* The search, the preset, a rule's field and operator are other families'
|
|
190
|
+
* roots — `text-field` and `select` select their own root part — so each
|
|
191
|
+
* one sits inside a part of this family's and fills it. The magnifier before
|
|
192
|
+
* the query is an `icon` in the field's start adornment, which the field
|
|
193
|
+
* sizes as it sizes every adornment.
|
|
194
|
+
*/
|
|
195
|
+
[data-ui='filter-bar'] [data-part='search'] > [data-ui='text-field'],
|
|
196
|
+
[data-ui='filter-bar'] [data-part='preset'] > [data-ui='select'],
|
|
197
|
+
[data-ui='filter-bar'] :is([data-part='field'], [data-part='operator']) > [data-ui='select'] {
|
|
198
|
+
inline-size: 100%;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* One toolbar, which wraps: the arrows walk its controls in order from line
|
|
203
|
+
* to line, which the toolbar pattern allows for a toolbar of several rows.
|
|
204
|
+
* The row gap is the column gap, so two lines of chips read as one set.
|
|
205
|
+
*/
|
|
206
|
+
[data-ui='filter-bar'] [data-part='bar'] {
|
|
207
|
+
align-items: center;
|
|
208
|
+
display: flex;
|
|
209
|
+
flex-wrap: wrap;
|
|
210
|
+
gap: var(--_gap);
|
|
211
|
+
min-inline-size: 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
[data-ui='filter-bar'] [data-part='end'] {
|
|
215
|
+
align-items: center;
|
|
216
|
+
display: flex;
|
|
217
|
+
gap: var(--_gap);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/** The count is the answer to the filters, and it takes the far end of its line — PatternFly's rule for an item count. */
|
|
221
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='count'] {
|
|
222
|
+
color: var(--_muted);
|
|
223
|
+
font-variant-numeric: tabular-nums;
|
|
224
|
+
margin: 0;
|
|
225
|
+
/* A line of its own type whatever it holds: before the first answer it holds only the
|
|
226
|
+
spinner, shorter than the text that replaces it, and the rows under the bar moved. */
|
|
227
|
+
min-block-size: 1lh;
|
|
228
|
+
/* The line in the middle of a control's height, which is the line it shares with the
|
|
229
|
+
search: the frame starts every member at the top of its line. */
|
|
230
|
+
padding-block: max(0px, calc((var(--_height) - 1lh) / 2));
|
|
231
|
+
white-space: nowrap;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/* ── The pill ───────────────────────────────────────────────────────────
|
|
235
|
+
*
|
|
236
|
+
* A pinned field with no condition: a place in the bar waiting to be
|
|
237
|
+
* filled. Its edge is dashed — the edge `upload` gives a file not yet sent,
|
|
238
|
+
* which already means *waiting for something* in this library — and it has
|
|
239
|
+
* no ground and no lift, so it reads as a slot rather than as a control
|
|
240
|
+
* that holds something. The plus before the name says what pressing it
|
|
241
|
+
* does. Given a condition, the same place in the bar becomes a chip.
|
|
242
|
+
*/
|
|
243
|
+
[data-ui='filter-bar'] [data-part='pill'] {
|
|
244
|
+
align-items: center;
|
|
245
|
+
appearance: none;
|
|
246
|
+
background-color: transparent;
|
|
247
|
+
block-size: var(--_height);
|
|
248
|
+
border: var(--_border-width) dashed var(--_edge);
|
|
249
|
+
border-radius: var(--_radius);
|
|
250
|
+
box-sizing: border-box;
|
|
251
|
+
color: var(--_muted);
|
|
252
|
+
cursor: pointer;
|
|
253
|
+
display: inline-flex;
|
|
254
|
+
font: inherit;
|
|
255
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
256
|
+
gap: var(--_gap-sm);
|
|
257
|
+
line-height: var(--slotted-control-line-height, 1);
|
|
258
|
+
margin: 0;
|
|
259
|
+
/* The plus carries its own air, so the start inset is one step short. */
|
|
260
|
+
padding-block: 0;
|
|
261
|
+
padding-inline: calc(var(--_pad) - var(--_gap-sm)) var(--_pad);
|
|
262
|
+
transition:
|
|
263
|
+
background-color var(--_duration) var(--_easing),
|
|
264
|
+
border-color var(--_duration) var(--_easing),
|
|
265
|
+
color var(--_duration) var(--_easing),
|
|
266
|
+
opacity var(--slotted-duration-medium) var(--slotted-easing-enter),
|
|
267
|
+
translate var(--slotted-duration-medium) var(--slotted-easing-enter);
|
|
268
|
+
white-space: nowrap;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
[data-ui='filter-bar'] [data-part='pill'] > span:not([data-ui='icon']) {
|
|
272
|
+
min-inline-size: 0;
|
|
273
|
+
overflow: hidden;
|
|
274
|
+
text-overflow: ellipsis;
|
|
275
|
+
unicode-bidi: isolate;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
[data-ui='filter-bar'] [data-part='pill'] > [data-ui='icon'] {
|
|
279
|
+
--slotted-icon-size: var(--_icon);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
[data-ui='filter-bar'] [data-part='pill'][data-invalid] {
|
|
283
|
+
border-color: var(--_invalid);
|
|
284
|
+
box-shadow: var(--_invalid-edge);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
[data-ui='filter-bar'] [data-part='pill']:enabled:hover {
|
|
288
|
+
background-color: var(--_hover);
|
|
289
|
+
border-color: var(--slotted-border-strong, ButtonBorder);
|
|
290
|
+
color: var(--_ink);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
[data-ui='filter-bar'] [data-part='pill']:enabled:active,
|
|
294
|
+
[data-ui='filter-bar'] [data-part='pill']:enabled[aria-expanded='true'] {
|
|
295
|
+
background-color: var(--_active);
|
|
296
|
+
border-color: var(--slotted-border-strong, ButtonBorder);
|
|
297
|
+
color: var(--_ink);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
[data-ui='filter-bar'] [data-part='pill']:focus-visible {
|
|
301
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
302
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/* ── The chip ───────────────────────────────────────────────────────────
|
|
306
|
+
*
|
|
307
|
+
* One condition, written as the sentence it is: the field, the operator,
|
|
308
|
+
* the value, the remove control, each a segment of one capsule divided by a
|
|
309
|
+
* seam. Each segment answers one question — the operator opens a menu of
|
|
310
|
+
* operators, the value a popover with the operand — so changing how two
|
|
311
|
+
* values compare no longer reopens the values.
|
|
312
|
+
*
|
|
313
|
+
* The field is read and never pressed: a condition keeps its field for its
|
|
314
|
+
* life. It carries the weight, the operator reads quieter as the connective
|
|
315
|
+
* between two things, and the value is back at the weight of the field.
|
|
316
|
+
*
|
|
317
|
+
* The capsule owns the edge, the ground and the lift, and the segments own
|
|
318
|
+
* hover and press. The first and last segments take the capsule's corners,
|
|
319
|
+
* so a hover ground and a focus ring follow its curve rather than being
|
|
320
|
+
* clipped by it.
|
|
321
|
+
*/
|
|
322
|
+
[data-ui='filter-bar'] [data-part='chip'] {
|
|
323
|
+
align-items: stretch;
|
|
324
|
+
background-color: var(--_surface);
|
|
325
|
+
block-size: var(--_height);
|
|
326
|
+
border: var(--_border-width) solid var(--_edge);
|
|
327
|
+
border-radius: var(--_radius);
|
|
328
|
+
box-shadow: var(--slotted-control-shadow, none);
|
|
329
|
+
box-sizing: border-box;
|
|
330
|
+
display: inline-flex;
|
|
331
|
+
max-inline-size: 100%;
|
|
332
|
+
min-inline-size: 0;
|
|
333
|
+
transition:
|
|
334
|
+
border-color var(--_duration) var(--_easing),
|
|
335
|
+
opacity var(--slotted-duration-medium) var(--slotted-easing-enter),
|
|
336
|
+
translate var(--slotted-duration-medium) var(--slotted-easing-enter);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* A chip or a pill arrives: it fades in from a step above its place — the
|
|
341
|
+
* arrival `upload` gives a file — so a condition added from the menu is seen
|
|
342
|
+
* landing in the bar. It does not scale: a box of text that scales redraws
|
|
343
|
+
* its letters at every frame. It
|
|
344
|
+
* starts from the style below only on the frame it is first rendered — a
|
|
345
|
+
* chip whose value changes does not arrive again. A chip that leaves does
|
|
346
|
+
* not animate: focus moves to its neighbour in the same gesture, and a chip
|
|
347
|
+
* held for an exit would be a stop of the arrows that no longer exists.
|
|
348
|
+
*/
|
|
349
|
+
@starting-style {
|
|
350
|
+
[data-ui='filter-bar'] :is([data-part='chip'], [data-part='pill']) {
|
|
351
|
+
opacity: 0;
|
|
352
|
+
translate: 0 calc(-1 * var(--slotted-space-2, 0.25rem));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
[data-ui='filter-bar'] [data-part='chip'] > * {
|
|
357
|
+
align-items: center;
|
|
358
|
+
background-color: transparent;
|
|
359
|
+
border: 0;
|
|
360
|
+
box-sizing: border-box;
|
|
361
|
+
color: inherit;
|
|
362
|
+
display: inline-flex;
|
|
363
|
+
flex: none;
|
|
364
|
+
font: inherit;
|
|
365
|
+
gap: var(--_gap-sm);
|
|
366
|
+
line-height: var(--slotted-control-line-height, 1);
|
|
367
|
+
margin: 0;
|
|
368
|
+
min-inline-size: 0;
|
|
369
|
+
padding-block: 0;
|
|
370
|
+
padding-inline: var(--_seg-pad);
|
|
371
|
+
white-space: nowrap;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
[data-ui='filter-bar'] [data-part='chip'] > * + * {
|
|
375
|
+
border-inline-start: var(--_border-width) solid var(--_seam);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
[data-ui='filter-bar'] [data-part='chip'] > :first-child {
|
|
379
|
+
border-end-start-radius: var(--_radius);
|
|
380
|
+
border-start-start-radius: var(--_radius);
|
|
381
|
+
/* The capsule's curve takes air from the first letter, so the start inset is the control's, not the segment's. */
|
|
382
|
+
padding-inline-start: var(--_pad);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
[data-ui='filter-bar'] [data-part='chip'] > :last-child {
|
|
386
|
+
border-end-end-radius: var(--_radius);
|
|
387
|
+
border-start-end-radius: var(--_radius);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
[data-ui='filter-bar'] [data-part='chip'] [data-ui='icon'] {
|
|
391
|
+
--slotted-icon-size: var(--_icon);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
[data-ui='filter-bar'] [data-part='chip-field'] {
|
|
395
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
[data-ui='filter-bar'] [data-part='chip-field'] > [data-ui='icon'] {
|
|
399
|
+
color: var(--_muted);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/** The field's name, the operator and the value are isolated runs, so a right-to-left name beside an ISO date reorders nothing. */
|
|
403
|
+
[data-ui='filter-bar'] [data-part='chip'] > * > span:not([data-ui]),
|
|
404
|
+
[data-ui='filter-bar'] [data-part='chip-operator'] {
|
|
405
|
+
unicode-bidi: isolate;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
[data-ui='filter-bar'] [data-part='chip-operator'] {
|
|
409
|
+
color: var(--_muted);
|
|
410
|
+
font-weight: var(--slotted-font-weight-regular, 400);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
[data-ui='filter-bar'] [data-part='chip-value'] {
|
|
414
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
415
|
+
min-inline-size: 0;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* The value truncates and the whole list stays in the segment's name and title. */
|
|
419
|
+
[data-ui='filter-bar'] [data-part='chip-value'] > [data-value] {
|
|
420
|
+
max-inline-size: var(--slotted-filter-bar-value-max, 12rem);
|
|
421
|
+
min-inline-size: 0;
|
|
422
|
+
overflow: hidden;
|
|
423
|
+
text-overflow: ellipsis;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* The operator's words inside the value segment are drawn only where the
|
|
428
|
+
* operator segment is not — under the narrow breakpoint, below.
|
|
429
|
+
*/
|
|
430
|
+
[data-ui='filter-bar'] [data-part='chip-value'] > [data-operator] {
|
|
431
|
+
color: var(--_muted);
|
|
432
|
+
display: none;
|
|
433
|
+
font-weight: var(--slotted-font-weight-regular, 400);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/** The remove control is square in the capsule's height, and its glyph reads quiet until it is aimed at. */
|
|
437
|
+
[data-ui='filter-bar'] [data-part='chip-remove'] {
|
|
438
|
+
aspect-ratio: 1;
|
|
439
|
+
color: var(--_muted);
|
|
440
|
+
justify-content: center;
|
|
441
|
+
padding-inline: 0;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
[data-ui='filter-bar'] [data-part='chip'] > :is(button, [role='button']) {
|
|
445
|
+
cursor: pointer;
|
|
446
|
+
transition:
|
|
447
|
+
background-color var(--_duration) var(--_easing),
|
|
448
|
+
color var(--_duration) var(--_easing);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/*
|
|
452
|
+
* Hover and press are the segment's own. Press is a step past hover, and an
|
|
453
|
+
* open segment holds the press ground while its surface is up, so the
|
|
454
|
+
* reader sees which segment the menu or the popover belongs to.
|
|
455
|
+
*/
|
|
456
|
+
[data-ui='filter-bar']
|
|
457
|
+
[data-part='chip']
|
|
458
|
+
> :is(button, [role='button']):enabled:not([aria-disabled='true']):hover {
|
|
459
|
+
background-color: var(--_hover);
|
|
460
|
+
color: var(--_ink);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
[data-ui='filter-bar']
|
|
464
|
+
[data-part='chip']
|
|
465
|
+
> :is(button, [role='button']):enabled:not([aria-disabled='true']):active,
|
|
466
|
+
[data-ui='filter-bar'] [data-part='chip'] > :is(button, [role='button'])[aria-expanded='true'] {
|
|
467
|
+
background-color: var(--_active);
|
|
468
|
+
color: var(--_ink);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/*
|
|
472
|
+
* A segment's ring is drawn inward: an outward ring would lie across the
|
|
473
|
+
* neighbouring segments, and inward it stays inside the capsule and follows
|
|
474
|
+
* its curve on the end segments — the rule every inner control follows.
|
|
475
|
+
*/
|
|
476
|
+
[data-ui='filter-bar'] [data-part='chip'] > :focus-visible {
|
|
477
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
478
|
+
outline-offset: calc(var(--slotted-focus-ring-width, 2px) * -1);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* A condition still waiting for its value: the dashed edge of a pill, which
|
|
483
|
+
* says the same thing, and the value segment writes the prompt in the
|
|
484
|
+
* muted ink. The condition is not applied until the value is there.
|
|
485
|
+
*/
|
|
486
|
+
[data-ui='filter-bar'] [data-part='chip'][data-incomplete] {
|
|
487
|
+
border-style: dashed;
|
|
488
|
+
box-shadow: none;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
[data-ui='filter-bar'] [data-part='chip'][data-incomplete] > [data-part='chip-value'] {
|
|
492
|
+
color: var(--_muted);
|
|
493
|
+
font-weight: var(--slotted-font-weight-regular, 400);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
[data-ui='filter-bar'] [data-part='chip'][data-invalid] {
|
|
497
|
+
border-color: var(--_invalid);
|
|
498
|
+
box-shadow: var(--_invalid-edge);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/** The field's glyph and name turn to the danger ink with the edge, so the fault is read on the segment it is about. */
|
|
502
|
+
[data-ui='filter-bar'] [data-part='chip'][data-invalid] > [data-part='chip-field'],
|
|
503
|
+
[data-ui='filter-bar']
|
|
504
|
+
[data-part='chip'][data-invalid]
|
|
505
|
+
> [data-part='chip-field']
|
|
506
|
+
> [data-ui='icon'] {
|
|
507
|
+
color: var(--slotted-tone-danger-text, CanvasText);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
[data-ui='filter-bar'] [data-part='chip'][data-folded] {
|
|
511
|
+
display: none;
|
|
512
|
+
visibility: hidden;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
[data-ui='filter-bar'] [data-part='bar'][data-revealed] [data-part='chip'][data-folded] {
|
|
516
|
+
display: inline-flex;
|
|
517
|
+
visibility: visible;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
/* ── More ───────────────────────────────────────────────────────────── */
|
|
521
|
+
|
|
522
|
+
[data-ui='filter-bar'] [data-part='more'] {
|
|
523
|
+
align-items: center;
|
|
524
|
+
appearance: none;
|
|
525
|
+
background: none;
|
|
526
|
+
block-size: var(--_height);
|
|
527
|
+
border: 0;
|
|
528
|
+
border-radius: var(--_radius);
|
|
529
|
+
color: var(--_muted);
|
|
530
|
+
cursor: pointer;
|
|
531
|
+
display: inline-flex;
|
|
532
|
+
font: inherit;
|
|
533
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
534
|
+
justify-content: center;
|
|
535
|
+
margin: 0;
|
|
536
|
+
padding-inline: var(--_seg-pad);
|
|
537
|
+
transition:
|
|
538
|
+
background-color var(--_duration) var(--_easing),
|
|
539
|
+
color var(--_duration) var(--_easing);
|
|
540
|
+
white-space: nowrap;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
[data-ui='filter-bar'] [data-part='more']:enabled:hover {
|
|
544
|
+
background-color: var(--_hover);
|
|
545
|
+
color: var(--_ink);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
[data-ui='filter-bar'] [data-part='more']:enabled:active {
|
|
549
|
+
background-color: var(--_active);
|
|
550
|
+
color: var(--_ink);
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
[data-ui='filter-bar'] [data-part='more']:focus-visible {
|
|
554
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
555
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/* ── Add and Clear ──────────────────────────────────────────────────────
|
|
559
|
+
*
|
|
560
|
+
* Both are `button`s worn with this family's part name. Add draws its glyph
|
|
561
|
+
* alone once a chip is in the bar, as a circle in the chips' height, so the
|
|
562
|
+
* line of capsules ends in a control of their own shape; it keeps its label
|
|
563
|
+
* as its name and its title. Clear and Reset read at the chips' weight: the
|
|
564
|
+
* conditions are what the bar is about, and a control that empties them is
|
|
565
|
+
* not the loudest word on the line. Apply keeps the weight of a commit.
|
|
566
|
+
*/
|
|
567
|
+
[data-ui='filter-bar'] [data-part='bar'] :is([data-part='clear'], [data-part='reset']) {
|
|
568
|
+
--slotted-control-font-weight: var(--slotted-font-weight-medium, 500);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/* ── The summary, drawn only when the bar is narrow ─────────────────── */
|
|
572
|
+
|
|
573
|
+
[data-ui='filter-bar'] [data-part='summary'] {
|
|
574
|
+
display: none;
|
|
575
|
+
visibility: hidden;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
[data-ui='filter-bar'] [data-part='summary'] > [data-part='label'] > span {
|
|
579
|
+
/* The count in the summary is a figure, and figures line up. */
|
|
580
|
+
font-variant-numeric: tabular-nums;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/* ── The actions under apply=manual ─────────────────────────────────── */
|
|
584
|
+
|
|
585
|
+
/**
|
|
586
|
+
* Apply and Reset close the toolbar line from its end. Clear stays beside
|
|
587
|
+
* Add rather than at the far end: under manual the far end holds Apply,
|
|
588
|
+
* and Clear there would make the control that empties the filter the
|
|
589
|
+
* neighbour of the one that commits it.
|
|
590
|
+
*/
|
|
591
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='bar'] > [data-part='actions'] {
|
|
592
|
+
align-items: center;
|
|
593
|
+
display: flex;
|
|
594
|
+
gap: var(--_gap-sm);
|
|
595
|
+
margin-inline-start: auto;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/* ── States of the whole bar ────────────────────────────────────────── */
|
|
599
|
+
|
|
600
|
+
[data-ui='filter-bar'][data-disabled] {
|
|
601
|
+
--_ink: var(--slotted-disabled-foreground, GrayText);
|
|
602
|
+
--_muted: var(--slotted-disabled-foreground, GrayText);
|
|
603
|
+
--_edge: var(--slotted-disabled-border, GrayText);
|
|
604
|
+
--_seam: var(--slotted-disabled-border, GrayText);
|
|
605
|
+
--_surface: var(--slotted-disabled-background, Canvas);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
[data-ui='filter-bar'][data-disabled] :is([data-part='pill'], [data-part='chip']) {
|
|
609
|
+
box-shadow: none;
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
[data-ui='filter-bar'][data-disabled] :is([data-part='pill'], [data-part='chip'] > *) {
|
|
613
|
+
cursor: not-allowed;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Read-only: every condition stays reachable and readable, and nothing
|
|
618
|
+
* invites a press — the segments keep their stop and lose the pointer, and
|
|
619
|
+
* the binding draws no remove, add or clear control.
|
|
620
|
+
*/
|
|
621
|
+
[data-ui='filter-bar'][data-readonly] [data-part='chip'] > * {
|
|
622
|
+
cursor: default;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
/** A loading bar keeps its width and its controls, and says so in the count's place. */
|
|
626
|
+
[data-ui='filter-bar'][data-loading] > [data-part='frame'] > [data-part='count'] {
|
|
627
|
+
align-items: center;
|
|
628
|
+
display: inline-flex;
|
|
629
|
+
gap: var(--_gap-sm);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
/* ── Sticky ─────────────────────────────────────────────────────────────
|
|
633
|
+
*
|
|
634
|
+
* The bar sticks under the page chrome, reading the property `page`
|
|
635
|
+
* publishes and never measuring the header itself. It then adds its own
|
|
636
|
+
* height to the number for what follows: the binding measures the root and
|
|
637
|
+
* writes the sum as `--slotted-page-sticky-top` on the element that holds
|
|
638
|
+
* the bar and the listing — the rule `section` established for its body —
|
|
639
|
+
* and writes the value it read back on the root itself, so the bar keeps
|
|
640
|
+
* sticking where it did while everything after it stops under the bar.
|
|
641
|
+
*/
|
|
642
|
+
[data-ui='filter-bar'][data-sticky] {
|
|
643
|
+
background-color: var(--_surface);
|
|
644
|
+
inset-block-start: var(--slotted-page-sticky-top, 0px);
|
|
645
|
+
padding-block: var(--slotted-space-3, 0.375rem);
|
|
646
|
+
position: sticky;
|
|
647
|
+
z-index: var(--slotted-z-index-sticky, 100);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/* ── The builder ────────────────────────────────────────────────────────
|
|
651
|
+
*
|
|
652
|
+
* The whole tree, in a drawer, laid out the way Notion, Airtable and AG
|
|
653
|
+
* Grid's advanced filter lay a query out: a group opens with "Match [All |
|
|
654
|
+
* Any] of the following", every row under it starts with the word that
|
|
655
|
+
* joins it to the row above — "Where" on the first, "and" or "or" after —
|
|
656
|
+
* and a group inside a group is a box on a sunken ground with the same
|
|
657
|
+
* header and its own remove. A rule is one row: field, operator, operand,
|
|
658
|
+
* remove; it stacks when the drawer is narrow, and the leading word stays.
|
|
659
|
+
*/
|
|
660
|
+
[data-ui='filter-bar'][data-part='builder'] {
|
|
661
|
+
--_join-col: var(--slotted-filter-bar-join-size, 3.5rem);
|
|
662
|
+
--_group-surface: var(
|
|
663
|
+
--slotted-filter-bar-group-surface,
|
|
664
|
+
var(--slotted-surface-sunken, Canvas)
|
|
665
|
+
);
|
|
666
|
+
--_group-edge: var(--slotted-filter-bar-group-border, var(--slotted-border-subtle, GrayText));
|
|
667
|
+
|
|
668
|
+
container-name: slotted-filter-bar-builder;
|
|
669
|
+
container-type: inline-size;
|
|
670
|
+
display: grid;
|
|
671
|
+
gap: var(--slotted-space-5, 0.75rem);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Every group is a container of its own, so a rule stacks against the width
|
|
676
|
+
* its own group has left, not the drawer's: two levels in, the gutter, the
|
|
677
|
+
* box padding and the border have taken nine rems, and a row measured
|
|
678
|
+
* against the drawer overflowed its box. The name differs from the
|
|
679
|
+
* builder's, because the card form below is the builder's decision and
|
|
680
|
+
* every group in one builder takes the same form.
|
|
681
|
+
*/
|
|
682
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group'] {
|
|
683
|
+
border: 0;
|
|
684
|
+
container-name: slotted-filter-bar-group;
|
|
685
|
+
container-type: inline-size;
|
|
686
|
+
display: grid;
|
|
687
|
+
gap: var(--_gap);
|
|
688
|
+
margin: 0;
|
|
689
|
+
min-inline-size: 0;
|
|
690
|
+
padding: 0;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group']:not([data-depth='0']) {
|
|
694
|
+
background-color: var(--_group-surface);
|
|
695
|
+
border: var(--slotted-border-width-thin, 1px) solid var(--_group-edge);
|
|
696
|
+
border-radius: var(--slotted-radius-md, 6px);
|
|
697
|
+
padding: var(--slotted-space-5, 0.75rem);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/* A box inside a box alternates its ground, so the third level reads as a level and not as a border. */
|
|
701
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
702
|
+
[data-part='group']:is([data-depth='2'], [data-depth='4'], [data-depth='6']) {
|
|
703
|
+
background-color: var(--_surface);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group'] > legend {
|
|
707
|
+
/* The legend names the group to a reader and draws nothing. */
|
|
708
|
+
block-size: 1px;
|
|
709
|
+
clip-path: inset(50%);
|
|
710
|
+
overflow: hidden;
|
|
711
|
+
position: absolute;
|
|
712
|
+
white-space: nowrap;
|
|
713
|
+
inline-size: 1px;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/** The header: the words, the All | Any control between them, and, in a nested group, its remove at the end. */
|
|
717
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='join'] {
|
|
718
|
+
align-items: center;
|
|
719
|
+
color: var(--_ink);
|
|
720
|
+
display: flex;
|
|
721
|
+
flex-wrap: wrap;
|
|
722
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
723
|
+
gap: var(--_gap-sm);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='join'] > [data-part='remove-group'] {
|
|
727
|
+
margin-inline-start: auto;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* The rows: a two-column grid, the joining word then the rule or the group,
|
|
732
|
+
* so every field lines up under the first whatever word stands before it.
|
|
733
|
+
*/
|
|
734
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rules'] {
|
|
735
|
+
align-items: start;
|
|
736
|
+
column-gap: var(--_gap-sm);
|
|
737
|
+
display: grid;
|
|
738
|
+
grid-template-columns: var(--_join-col) minmax(0, 1fr);
|
|
739
|
+
min-inline-size: 0;
|
|
740
|
+
row-gap: var(--_gap);
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='conjunction'] {
|
|
744
|
+
color: var(--_muted);
|
|
745
|
+
/* Centred on the first control of its row, whatever the row stacks to. */
|
|
746
|
+
line-height: var(--_height);
|
|
747
|
+
overflow: hidden;
|
|
748
|
+
text-align: end;
|
|
749
|
+
text-overflow: ellipsis;
|
|
750
|
+
white-space: nowrap;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'] {
|
|
754
|
+
align-items: center;
|
|
755
|
+
display: grid;
|
|
756
|
+
gap: var(--_gap-sm);
|
|
757
|
+
/* Every track may shrink, so a row never pushes its remove control past its
|
|
758
|
+
group's edge; the container query below stacks it before it gets narrow.
|
|
759
|
+
The remove track is the control's own width, so the crosses of one
|
|
760
|
+
group stand in a column whatever each row holds. */
|
|
761
|
+
grid-template-columns:
|
|
762
|
+
minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1.5fr)
|
|
763
|
+
var(--slotted-target-min, 24px);
|
|
764
|
+
min-inline-size: 0;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'] > *,
|
|
768
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
769
|
+
[data-part='rule']
|
|
770
|
+
:is([data-part='operator'], [data-part='operand']) {
|
|
771
|
+
min-inline-size: 0;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
775
|
+
[data-part='rule'][data-operands='0']
|
|
776
|
+
[data-part='operand'] {
|
|
777
|
+
display: none;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-operands='0'] {
|
|
781
|
+
/* The operator takes the operand's tracks too, so the field keeps the width it has on every other row. */
|
|
782
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) var(--slotted-target-min, 24px);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='operand'] {
|
|
786
|
+
display: grid;
|
|
787
|
+
gap: var(--_gap-sm);
|
|
788
|
+
min-inline-size: 0;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
792
|
+
[data-part='rule'][data-operands='2']
|
|
793
|
+
[data-part='operand'] {
|
|
794
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
/** The group's own controls, under its rows and aligned with them. */
|
|
798
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group'] > [data-part='actions'] {
|
|
799
|
+
align-items: center;
|
|
800
|
+
display: flex;
|
|
801
|
+
flex-wrap: wrap;
|
|
802
|
+
gap: var(--_gap-sm);
|
|
803
|
+
padding-inline-start: calc(var(--_join-col) + var(--_gap-sm));
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
/**
|
|
807
|
+
* The builder's Add rule and Add group are outlined: they are what the
|
|
808
|
+
* footer is for, and as ghosts under a column of outlined fields they read
|
|
809
|
+
* as a caption. A nested group's pair is ghost, so the builder's own pair
|
|
810
|
+
* stays the one that reads as the footer. Save
|
|
811
|
+
* as view is a different act — it leaves the builder for the application's
|
|
812
|
+
* dialog — so it stands apart at the far end, at the weight of the words.
|
|
813
|
+
*/
|
|
814
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
815
|
+
[data-part='group']
|
|
816
|
+
> [data-part='actions']
|
|
817
|
+
> :is(
|
|
818
|
+
[data-part='add-rule'],
|
|
819
|
+
[data-part='add-group'],
|
|
820
|
+
[data-part='clear'],
|
|
821
|
+
[data-part='save-preset']
|
|
822
|
+
) {
|
|
823
|
+
--slotted-control-font-weight: var(--slotted-font-weight-medium, 500);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
827
|
+
[data-part='group']
|
|
828
|
+
> [data-part='actions']
|
|
829
|
+
> [data-part='save-preset'] {
|
|
830
|
+
margin-inline-start: auto;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
@container slotted-filter-bar-group (max-width: 30rem) {
|
|
834
|
+
/* The second track is the remove control's own width, not `auto`: the
|
|
835
|
+
operator and the operand span both tracks, and a spanning item hands
|
|
836
|
+
its size to the non-flexible track first — `auto` took the operand's
|
|
837
|
+
whole width and left the field 34 pixels wide, a chevron with no name. */
|
|
838
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'],
|
|
839
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-operands='0'] {
|
|
840
|
+
grid-template-columns: minmax(0, 1fr) var(--slotted-target-min, 24px);
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'] > [data-part='field'] {
|
|
844
|
+
grid-column: 1;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'] > [data-part='remove'] {
|
|
848
|
+
grid-column: 2;
|
|
849
|
+
grid-row: 1;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
853
|
+
[data-part='rule']
|
|
854
|
+
:is([data-part='operator'], [data-part='operand']) {
|
|
855
|
+
grid-column: 1 / -1;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/*
|
|
860
|
+
* The sentence of a rule is the card form's header, and a row that already
|
|
861
|
+
* shows its three controls does not draw it.
|
|
862
|
+
*/
|
|
863
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] {
|
|
864
|
+
display: none;
|
|
865
|
+
visibility: hidden;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
/* ── The builder as cards ───────────────────────────────────────────────
|
|
869
|
+
*
|
|
870
|
+
* Under 30rem of the builder — a phone, where the builder is a sheet — a row
|
|
871
|
+
* of three controls beside a gutter of joining words leaves each control a
|
|
872
|
+
* third of a third of the screen, and every level of nesting takes another
|
|
873
|
+
* eighty pixels. So each rule becomes a card: its sentence, which a reader
|
|
874
|
+
* scans, and its remove control; pressing the sentence expands the card and
|
|
875
|
+
* stacks the field, the operator and the operand under it at the card's
|
|
876
|
+
* full width. A nested group is a rail on its start edge, one step in, and
|
|
877
|
+
* the joining word stands on its own line between two cards.
|
|
878
|
+
*/
|
|
879
|
+
@container slotted-filter-bar-builder (max-width: 30rem) {
|
|
880
|
+
[data-ui='filter-bar'][data-part='builder'] {
|
|
881
|
+
gap: var(--_gap);
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rules'] {
|
|
885
|
+
grid-template-columns: minmax(0, 1fr);
|
|
886
|
+
row-gap: var(--_gap-sm);
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
/* The joining word, small and on a line of its own; "Where" says nothing a list of cards does not. */
|
|
890
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='conjunction'] {
|
|
891
|
+
font-size: var(--slotted-font-size-xs, 12px);
|
|
892
|
+
line-height: var(--slotted-line-height-xs, 1.5);
|
|
893
|
+
padding-inline-start: var(--_seg-pad);
|
|
894
|
+
text-align: start;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
898
|
+
[data-part='rules']
|
|
899
|
+
> [data-part='conjunction']:first-child {
|
|
900
|
+
display: none;
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group']:not([data-depth='0']),
|
|
904
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
905
|
+
[data-part='group']:is([data-depth='2'], [data-depth='4'], [data-depth='6']) {
|
|
906
|
+
background-color: transparent;
|
|
907
|
+
border: 0;
|
|
908
|
+
/* The rail carries the nesting alone here, so it takes the edge the cards have rather than the box's subtler one. */
|
|
909
|
+
border-inline-start: var(--slotted-border-width-medium, 2px) solid var(--_edge);
|
|
910
|
+
border-radius: 0;
|
|
911
|
+
padding-block: 0;
|
|
912
|
+
padding-inline: var(--slotted-space-4, 0.5rem) 0;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'],
|
|
916
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-operands='0'] {
|
|
917
|
+
background-color: var(--_surface);
|
|
918
|
+
border: var(--_border-width) solid var(--_edge);
|
|
919
|
+
border-radius: var(--slotted-radius-md, 6px);
|
|
920
|
+
box-shadow: var(--slotted-control-shadow, none);
|
|
921
|
+
column-gap: 0;
|
|
922
|
+
grid-template-areas: 'summary remove';
|
|
923
|
+
grid-template-columns: minmax(0, 1fr) var(--_height);
|
|
924
|
+
row-gap: var(--_gap-sm);
|
|
925
|
+
transition: border-color var(--_duration) var(--_easing);
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-expanded] {
|
|
929
|
+
border-color: var(--slotted-border-strong, ButtonBorder);
|
|
930
|
+
padding-block-end: var(--_seg-pad);
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-invalid] {
|
|
934
|
+
border-color: var(--_invalid);
|
|
935
|
+
box-shadow: var(--_invalid-edge);
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
/* Forced colours remove the shadow; the edge comes back as an outline. */
|
|
939
|
+
@media (forced-colors: active) {
|
|
940
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'][data-invalid] {
|
|
941
|
+
outline: var(--_invalid-edge-width) solid CanvasText;
|
|
942
|
+
outline-offset: calc(-1 * (var(--_border-width) + var(--_invalid-edge-width)));
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/* The sentence: the field at the weight of a name, the operator quiet, the value back at weight. It wraps rather than truncates — on a phone the sentence is what is read. */
|
|
947
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] {
|
|
948
|
+
/* The chevron stands in the middle of the card's header, whether the sentence takes one line or two. */
|
|
949
|
+
align-items: center;
|
|
950
|
+
appearance: none;
|
|
951
|
+
background: none;
|
|
952
|
+
border: 0;
|
|
953
|
+
border-radius: calc(var(--slotted-radius-md, 6px) - var(--_border-width));
|
|
954
|
+
color: var(--_ink);
|
|
955
|
+
cursor: pointer;
|
|
956
|
+
display: flex;
|
|
957
|
+
font: inherit;
|
|
958
|
+
gap: var(--_gap-sm);
|
|
959
|
+
grid-area: summary;
|
|
960
|
+
margin: 0;
|
|
961
|
+
min-block-size: var(--_height);
|
|
962
|
+
min-inline-size: 0;
|
|
963
|
+
padding-block: max(var(--_gap-sm), calc((var(--_height) - 1lh) / 2));
|
|
964
|
+
padding-inline: var(--_seg-pad) 0;
|
|
965
|
+
text-align: start;
|
|
966
|
+
transition: background-color var(--_duration) var(--_easing);
|
|
967
|
+
visibility: visible;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/* The words wrap inside their own run, so the chevron keeps the end of the first line however long the value is. */
|
|
971
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] > [data-sentence] {
|
|
972
|
+
flex: 1 1 auto;
|
|
973
|
+
min-inline-size: 0;
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] [data-field] {
|
|
977
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] [data-operator] {
|
|
981
|
+
color: var(--_muted);
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] [data-value] {
|
|
985
|
+
font-weight: var(--slotted-font-weight-medium, 500);
|
|
986
|
+
min-inline-size: 0;
|
|
987
|
+
overflow-wrap: anywhere;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary'] > [data-ui='icon'] {
|
|
991
|
+
--slotted-icon-size: var(--_icon);
|
|
992
|
+
|
|
993
|
+
color: var(--_muted);
|
|
994
|
+
flex: none;
|
|
995
|
+
margin-inline-start: auto;
|
|
996
|
+
transition: rotate var(--_duration) var(--_easing);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1000
|
+
[data-part='rule-summary'][aria-expanded='true']
|
|
1001
|
+
> [data-ui='icon'] {
|
|
1002
|
+
rotate: 180deg;
|
|
1003
|
+
}
|
|
1004
|
+
|
|
1005
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary']:enabled:hover {
|
|
1006
|
+
background-color: var(--_hover);
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary']:enabled:active {
|
|
1010
|
+
background-color: var(--_active);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule-summary']:focus-visible {
|
|
1014
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
1015
|
+
outline-offset: calc(var(--slotted-focus-ring-width, 2px) * -1);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/*
|
|
1019
|
+
* The remove control stands level with the chevron, in the middle of the
|
|
1020
|
+
* header: the header's own height is the summary's, so the row it shares
|
|
1021
|
+
* with the summary is centred on it, and an expanded card's controls
|
|
1022
|
+
* below do not pull it down.
|
|
1023
|
+
*/
|
|
1024
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='rule'] > [data-part='remove'] {
|
|
1025
|
+
align-self: center;
|
|
1026
|
+
grid-area: remove;
|
|
1027
|
+
grid-row: 1;
|
|
1028
|
+
justify-self: center;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
/*
|
|
1032
|
+
* A collapsed card holds only its sentence: the controls leave the picture
|
|
1033
|
+
* and the tab order. Expanded, they stack at the card's full width and
|
|
1034
|
+
* arrive from a step above, so the eye follows the card opening; closing
|
|
1035
|
+
* snaps, because the reader has already looked away to the next card.
|
|
1036
|
+
*/
|
|
1037
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1038
|
+
[data-part='rule']:not([data-expanded])
|
|
1039
|
+
:is([data-part='field'], [data-part='operator'], [data-part='operand']) {
|
|
1040
|
+
display: none;
|
|
1041
|
+
visibility: hidden;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1045
|
+
[data-part='rule'][data-expanded]
|
|
1046
|
+
:is([data-part='field'], [data-part='operator'], [data-part='operand']) {
|
|
1047
|
+
grid-column: 1 / -1;
|
|
1048
|
+
margin-inline: var(--_seg-pad);
|
|
1049
|
+
transition:
|
|
1050
|
+
opacity var(--slotted-duration-medium) var(--slotted-easing-enter),
|
|
1051
|
+
translate var(--slotted-duration-medium) var(--slotted-easing-enter);
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
@starting-style {
|
|
1055
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1056
|
+
[data-part='rule'][data-expanded]
|
|
1057
|
+
:is([data-part='field'], [data-part='operator'], [data-part='operand']) {
|
|
1058
|
+
opacity: 0;
|
|
1059
|
+
translate: 0 calc(-1 * var(--slotted-space-2, 0.25rem));
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
[data-ui='filter-bar'][data-part='builder'] [data-part='group'] > [data-part='actions'] {
|
|
1064
|
+
padding-inline-start: 0;
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
/*
|
|
1068
|
+
* The builder's own Add rule and Add group share their line in two equal
|
|
1069
|
+
* halves, and Clear all and Save as view take the line under them. A
|
|
1070
|
+
* nested group's pair stays a quiet line at the start of its rail: three
|
|
1071
|
+
* lines of full-width buttons read as three copies of one control.
|
|
1072
|
+
*/
|
|
1073
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1074
|
+
[data-part='group'][data-depth='0']
|
|
1075
|
+
> [data-part='actions'] {
|
|
1076
|
+
display: grid;
|
|
1077
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1081
|
+
[data-part='group'][data-depth='0']
|
|
1082
|
+
> [data-part='actions']
|
|
1083
|
+
> :is([data-part='add-rule'], [data-part='add-group']) {
|
|
1084
|
+
inline-size: 100%;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
[data-ui='filter-bar'][data-part='builder']
|
|
1088
|
+
[data-part='group']
|
|
1089
|
+
> [data-part='actions']
|
|
1090
|
+
> :is([data-part='clear'], [data-part='save-preset']) {
|
|
1091
|
+
margin-inline-start: 0;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/* ── A builder row's remove control ─────────────────────────────────── */
|
|
1096
|
+
|
|
1097
|
+
[data-ui='filter-bar'] [data-part='rule'] > [data-part='remove'] {
|
|
1098
|
+
align-items: center;
|
|
1099
|
+
appearance: none;
|
|
1100
|
+
background: none;
|
|
1101
|
+
block-size: var(--slotted-target-min, 24px);
|
|
1102
|
+
border: 0;
|
|
1103
|
+
border-radius: var(--_control-radius);
|
|
1104
|
+
color: var(--_muted);
|
|
1105
|
+
cursor: pointer;
|
|
1106
|
+
display: inline-flex;
|
|
1107
|
+
font: inherit;
|
|
1108
|
+
inline-size: var(--slotted-target-min, 24px);
|
|
1109
|
+
justify-content: center;
|
|
1110
|
+
padding: 0;
|
|
1111
|
+
transition:
|
|
1112
|
+
background-color var(--_duration) var(--_easing),
|
|
1113
|
+
color var(--_duration) var(--_easing);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
[data-ui='filter-bar'] [data-part='rule'] > [data-part='remove'] > [data-ui='icon'] {
|
|
1117
|
+
--slotted-icon-size: var(--_icon);
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
[data-ui='filter-bar'] [data-part='rule'] > [data-part='remove']:enabled:hover {
|
|
1121
|
+
background-color: var(--_hover);
|
|
1122
|
+
color: var(--_ink);
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
[data-ui='filter-bar'] [data-part='rule'] > [data-part='remove']:enabled:active {
|
|
1126
|
+
background-color: var(--_active);
|
|
1127
|
+
color: var(--_ink);
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
[data-ui='filter-bar'] [data-part='rule'] > [data-part='remove']:focus-visible {
|
|
1131
|
+
outline: var(--slotted-focus-ring-width, 2px) solid var(--slotted-focus-ring-color, Highlight);
|
|
1132
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
/* ── Narrow ─────────────────────────────────────────────────────────────
|
|
1136
|
+
*
|
|
1137
|
+
* Under the breakpoint — a phone — the bar keeps every condition in sight
|
|
1138
|
+
* on one row that scrolls sideways, instead of folding them away or
|
|
1139
|
+
* wrapping them into a wall of lines above the listing: the summary first,
|
|
1140
|
+
* which opens the builder as a sheet, then every chip, the folded ones too,
|
|
1141
|
+
* then the pinned fields still empty. A chip there is three targets, not
|
|
1142
|
+
* four — the field, the value with the operator's words in it, the remove
|
|
1143
|
+
* control — because every edit on a phone opens the builder, with the
|
|
1144
|
+
* condition's card expanded. The last chip cut by the edge is what says
|
|
1145
|
+
* the row goes on.
|
|
1146
|
+
*
|
|
1147
|
+
* The search stays on top, because a query is the one thing a reader on a
|
|
1148
|
+
* phone types first, and the count stays under the row, because it is the
|
|
1149
|
+
* answer.
|
|
1150
|
+
*/
|
|
1151
|
+
@container slotted-filter-bar (max-width: 36rem) {
|
|
1152
|
+
[data-ui='filter-bar'] > [data-part='frame'] {
|
|
1153
|
+
grid-template-areas:
|
|
1154
|
+
'search'
|
|
1155
|
+
'bar'
|
|
1156
|
+
'count';
|
|
1157
|
+
grid-template-columns: minmax(0, 1fr);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
[data-ui='filter-bar'] > [data-part='frame']:has(> [data-part='end']:not(:empty)) {
|
|
1161
|
+
grid-template-areas:
|
|
1162
|
+
'search'
|
|
1163
|
+
'bar'
|
|
1164
|
+
'end'
|
|
1165
|
+
'count';
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='search'] {
|
|
1169
|
+
max-inline-size: none;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
/*
|
|
1173
|
+
* The row scrolls, so it clips at its padding edge, and a ring drawn
|
|
1174
|
+
* outside a pill or the summary would lose its outer pixels there. Every
|
|
1175
|
+
* member of the row draws its ring one width inside its own box instead —
|
|
1176
|
+
* the chip segments already do, and it is the answer a chip row inside a
|
|
1177
|
+
* control gives (`focus-ring.test.mjs`) — so the row takes no room it
|
|
1178
|
+
* would have to give back as a negative margin.
|
|
1179
|
+
*/
|
|
1180
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='bar'] {
|
|
1181
|
+
flex-wrap: nowrap;
|
|
1182
|
+
overflow-x: auto;
|
|
1183
|
+
overscroll-behavior-inline: contain;
|
|
1184
|
+
scrollbar-width: none;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
[data-ui='filter-bar']
|
|
1188
|
+
> [data-part='frame']
|
|
1189
|
+
> [data-part='bar']
|
|
1190
|
+
> :is([data-part='summary'], [data-part='pill']):focus-visible {
|
|
1191
|
+
outline-offset: calc(var(--slotted-focus-ring-width, 2px) * -1);
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='bar']::-webkit-scrollbar {
|
|
1195
|
+
display: none;
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
[data-ui='filter-bar']
|
|
1199
|
+
> [data-part='frame']
|
|
1200
|
+
> [data-part='bar']
|
|
1201
|
+
> :is([data-part='summary'], [data-part='chip'], [data-part='pill']) {
|
|
1202
|
+
flex: none;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
[data-ui='filter-bar']
|
|
1206
|
+
> [data-part='frame']
|
|
1207
|
+
> [data-part='bar']
|
|
1208
|
+
> :is([data-part='more'], [data-part='add'], [data-part='clear'], [data-part='actions']),
|
|
1209
|
+
[data-ui='filter-bar'] [data-part='chip'] > [data-part='chip-operator'] {
|
|
1210
|
+
display: none;
|
|
1211
|
+
visibility: hidden;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
[data-ui='filter-bar']
|
|
1215
|
+
> [data-part='frame']
|
|
1216
|
+
> [data-part='bar']
|
|
1217
|
+
> [data-part='chip'][data-folded] {
|
|
1218
|
+
display: inline-flex;
|
|
1219
|
+
visibility: visible;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
[data-ui='filter-bar'] [data-part='chip-value'] > [data-operator] {
|
|
1223
|
+
display: inline;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
[data-ui='filter-bar'] [data-part='chip-value'] > [data-value] {
|
|
1227
|
+
max-inline-size: var(--slotted-filter-bar-value-max-narrow, 9rem);
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
[data-ui='filter-bar'] [data-part='summary'] {
|
|
1231
|
+
display: inline-flex;
|
|
1232
|
+
visibility: visible;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/* A line of its own here, with nothing to line up with. */
|
|
1236
|
+
[data-ui='filter-bar'] > [data-part='frame'] > [data-part='count'] {
|
|
1237
|
+
justify-self: start;
|
|
1238
|
+
padding-block: 0;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
/**
|
|
1243
|
+
* A legend for a key the reader has none of. Where the primary input is a
|
|
1244
|
+
* touch screen the shortcut at the end of the search names nothing the
|
|
1245
|
+
* reader can press; the field is tapped. The key still works when a
|
|
1246
|
+
* keyboard is attached.
|
|
1247
|
+
*/
|
|
1248
|
+
@media (hover: none) and (pointer: coarse) {
|
|
1249
|
+
[data-ui='filter-bar'] [data-part='search'] [data-ui='kbd'] {
|
|
1250
|
+
display: none;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1254
|
+
/*
|
|
1255
|
+
* On a finger the remove control of a builder row and `more` are full
|
|
1256
|
+
* targets, and the box is the one a mouse sees: a transparent `::before`
|
|
1257
|
+
* centred on each reaches the comfortable size in both axes, so no row grows
|
|
1258
|
+
* and the builder's remove track keeps its width. A chip's segments take the
|
|
1259
|
+
* control height, which the theme already raises to the comfortable target.
|
|
1260
|
+
*/
|
|
1261
|
+
@media (pointer: coarse) {
|
|
1262
|
+
[data-ui='filter-bar'] :is([data-part='more'], [data-part='rule'] > [data-part='remove']) {
|
|
1263
|
+
position: relative;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
[data-ui='filter-bar']
|
|
1267
|
+
:is([data-part='more'], [data-part='rule'] > [data-part='remove'])::before {
|
|
1268
|
+
content: '';
|
|
1269
|
+
inset: min(0px, calc((100% - var(--slotted-target-comfortable, 44px)) / 2));
|
|
1270
|
+
position: absolute;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
@media (forced-colors: active) {
|
|
1275
|
+
/* Forced colours remove the invalid edge's shadow; it comes back as an
|
|
1276
|
+
outline inside the border, and a focused invalid pill draws its ring
|
|
1277
|
+
double. A chip's ring belongs to a segment and leaves it alone. */
|
|
1278
|
+
[data-ui='filter-bar'] [data-part='pill'][data-invalid],
|
|
1279
|
+
[data-ui='filter-bar'] [data-part='chip'][data-invalid] {
|
|
1280
|
+
outline: var(--_invalid-edge-width) solid CanvasText;
|
|
1281
|
+
outline-offset: calc(-1 * (var(--_border-width) + var(--_invalid-edge-width)));
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
[data-ui='filter-bar'] [data-part='pill'][data-invalid]:focus-visible {
|
|
1285
|
+
outline: calc(var(--slotted-focus-ring-width, 2px) + var(--_invalid-edge-width)) double
|
|
1286
|
+
var(--slotted-focus-ring-color, Highlight);
|
|
1287
|
+
outline-offset: var(--slotted-focus-ring-offset, 2px);
|
|
1288
|
+
}
|
|
1289
|
+
|
|
1290
|
+
/* The seams would read as a second edge in the system palette; the segments keep one line each. */
|
|
1291
|
+
[data-ui='filter-bar'] [data-part='chip'] > * + * {
|
|
1292
|
+
border-inline-start-color: GrayText;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
[data-ui='filter-bar'] [data-part='chip'] > [aria-expanded='true'] {
|
|
1296
|
+
background-color: Highlight;
|
|
1297
|
+
color: HighlightText;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
@media print {
|
|
1302
|
+
[data-ui='filter-bar'][data-sticky] {
|
|
1303
|
+
position: static;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
}
|