@kenlo/sds-design-system 0.9.9
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/README.md +129 -0
- package/components/Accordion/Accordion.css +186 -0
- package/components/Accordion/accordion-variants.js +17 -0
- package/components/Accordion/accordion.marko +264 -0
- package/components/AccordionGroup/AccordionGroup.css +35 -0
- package/components/AccordionGroup/accordion-group.marko +17 -0
- package/components/Alert/Alert.css +104 -0
- package/components/Alert/alert-variants.js +35 -0
- package/components/Alert/alert.marko +94 -0
- package/components/AttachmentList/AttachmentList.css +92 -0
- package/components/AttachmentList/attachment-list.marko +51 -0
- package/components/AttachmentList/attachment-row.marko +167 -0
- package/components/Avatar/Avatar.css +110 -0
- package/components/Avatar/avatar-variants.js +12 -0
- package/components/Avatar/avatar.marko +71 -0
- package/components/Badge/Badge.css +381 -0
- package/components/Badge/badge-dismissible.marko +143 -0
- package/components/Badge/badge-variants.js +35 -0
- package/components/Badge/badge.marko +134 -0
- package/components/BottomSheet/BottomSheet.css +300 -0
- package/components/BottomSheet/bottom-sheet.marko +340 -0
- package/components/BulkActionBar/BulkActionBar.css +88 -0
- package/components/BulkActionBar/bulk-action-bar.marko +186 -0
- package/components/Button/Button.css +340 -0
- package/components/Button/button-variants.js +25 -0
- package/components/Button/button.marko +139 -0
- package/components/Card/Card.css +391 -0
- package/components/Card/card-body.marko +5 -0
- package/components/Card/card-collapsible.marko +94 -0
- package/components/Card/card-footer.marko +12 -0
- package/components/Card/card-header.marko +30 -0
- package/components/Card/card-info-pair.marko +17 -0
- package/components/Card/card-info-row.marko +12 -0
- package/components/Card/card-section.marko +14 -0
- package/components/Card/card-variants.js +24 -0
- package/components/Card/card.marko +124 -0
- package/components/Checkbox/Checkbox.css +249 -0
- package/components/Checkbox/checkbox-variants.js +21 -0
- package/components/Checkbox/checkbox.marko +128 -0
- package/components/ColorPicker/ColorPicker.css +253 -0
- package/components/ColorPicker/color-maths.js +104 -0
- package/components/ColorPicker/color-picker.marko +474 -0
- package/components/DatePicker/DatePicker.css +429 -0
- package/components/DatePicker/date-logic.js +225 -0
- package/components/DatePicker/date-picker.marko +492 -0
- package/components/Drawer/Drawer.css +174 -0
- package/components/Drawer/drawer.marko +262 -0
- package/components/Floating/Floating.css +28 -0
- package/components/Floating/floating-position.js +251 -0
- package/components/Floating/floating.marko +291 -0
- package/components/Form/Form.css +15 -0
- package/components/Form/form-context.js +69 -0
- package/components/Form/form.marko +73 -0
- package/components/GradientPicker/GradientPicker.css +179 -0
- package/components/GradientPicker/gradient-picker.marko +398 -0
- package/components/Grid/Grid.css +161 -0
- package/components/Grid/col.marko +36 -0
- package/components/Grid/grid-variants.js +43 -0
- package/components/Grid/grid.marko +25 -0
- package/components/Header/Header.css +457 -0
- package/components/Header/header.marko +523 -0
- package/components/Icon/Icon.css +44 -0
- package/components/Icon/icon-colors.js +31 -0
- package/components/Icon/icon.marko +56 -0
- package/components/IconButton/IconButton.css +85 -0
- package/components/IconButton/icon-button-variants.js +18 -0
- package/components/IconButton/icon-button.marko +103 -0
- package/components/Incrementer/Incrementer.css +94 -0
- package/components/Incrementer/incrementer.marko +70 -0
- package/components/Input/Input.css +547 -0
- package/components/Input/input-countries.js +109 -0
- package/components/Input/input-masks.js +218 -0
- package/components/Input/input-types.js +194 -0
- package/components/Input/input.marko +530 -0
- package/components/Menu/Menu.css +651 -0
- package/components/Menu/menu-variants.js +89 -0
- package/components/Menu/menu.marko +560 -0
- package/components/Modal/Modal.css +160 -0
- package/components/Modal/modal.marko +296 -0
- package/components/Nav/Nav.css +298 -0
- package/components/Nav/nav-variants.js +23 -0
- package/components/Nav/nav.marko +164 -0
- package/components/Notification/Notification.css +78 -0
- package/components/Notification/notification-variants.js +30 -0
- package/components/Notification/notification.marko +55 -0
- package/components/Pagination/Pagination.css +78 -0
- package/components/Pagination/pagination-pages.js +66 -0
- package/components/Pagination/pagination.marko +141 -0
- package/components/Pill/Pill.css +193 -0
- package/components/Pill/pill-variants.js +16 -0
- package/components/Pill/pill.marko +165 -0
- package/components/Popover/Popover.css +121 -0
- package/components/Popover/popover.marko +96 -0
- package/components/Radio/Radio.css +230 -0
- package/components/Radio/radio-variants.js +16 -0
- package/components/Radio/radio.marko +93 -0
- package/components/RadioGroup/RadioGroup.css +32 -0
- package/components/RadioGroup/radio-group.marko +93 -0
- package/components/SearchBar/SearchBar.css +181 -0
- package/components/SearchBar/search-bar-variants.js +24 -0
- package/components/SearchBar/search-bar.marko +157 -0
- package/components/Select/Select.css +427 -0
- package/components/Select/select-options.js +163 -0
- package/components/Select/select.marko +449 -0
- package/components/Separator/Separator.css +22 -0
- package/components/Separator/separator.marko +14 -0
- package/components/Skeleton/Skeleton.css +100 -0
- package/components/Skeleton/skeleton-avatar.marko +28 -0
- package/components/Skeleton/skeleton-button.marko +22 -0
- package/components/Skeleton/skeleton-image.marko +20 -0
- package/components/Skeleton/skeleton-input.marko +22 -0
- package/components/Skeleton/skeleton-variants.js +16 -0
- package/components/Skeleton/skeleton.marko +53 -0
- package/components/Spinner/Spinner.css +173 -0
- package/components/Spinner/spinner-geometry.js +39 -0
- package/components/Spinner/spinner-overlay.marko +97 -0
- package/components/Spinner/spinner.marko +88 -0
- package/components/StatCard/StatCard.css +90 -0
- package/components/StatCard/stat-card-group.marko +5 -0
- package/components/StatCard/stat-card.marko +57 -0
- package/components/Switch/Switch.css +209 -0
- package/components/Switch/switch.marko +99 -0
- package/components/Table/Table.css +270 -0
- package/components/Table/table-cell.marko +28 -0
- package/components/Table/table-header.marko +27 -0
- package/components/Table/table-logic.js +129 -0
- package/components/Table/table.marko +372 -0
- package/components/Text/Text.css +79 -0
- package/components/Text/text-variants.js +25 -0
- package/components/Text/text.marko +48 -0
- package/components/TextEditor/TextEditor.css +78 -0
- package/components/TextEditor/safe-url.js +50 -0
- package/components/TextEditor/text-editor-commands.js +22 -0
- package/components/TextEditor/text-editor.marko +253 -0
- package/components/Toast/Toast.css +88 -0
- package/components/Toast/toast-api.js +19 -0
- package/components/Toast/toast-store.js +118 -0
- package/components/Toast/toast-variants.js +16 -0
- package/components/Toast/toast.marko +93 -0
- package/components/Toast/toaster.marko +70 -0
- package/components/Toggle/Toggle.css +169 -0
- package/components/Toggle/toggle.marko +93 -0
- package/components/Tooltip/Tooltip.css +115 -0
- package/components/Tooltip/tooltip.marko +77 -0
- package/components/Uploader/Uploader.css +180 -0
- package/components/Uploader/crop-geometry.js +161 -0
- package/components/Uploader/uploader.marko +269 -0
- package/foundations/Scrollbar/Scrollbar.css +26 -0
- package/foundations/attrs.js +27 -0
- package/foundations/breakpoints.js +27 -0
- package/foundations/contrast.js +74 -0
- package/foundations/custom-scheme.js +222 -0
- package/foundations/overlay.js +108 -0
- package/foundations/styles.css +284 -0
- package/foundations/text.js +22 -0
- package/foundations/theme-server.js +81 -0
- package/foundations/theme.js +42 -0
- package/foundations/tokens.css +1656 -0
- package/icons/custom/custom-video-horizontal-filled.marko +6 -0
- package/icons/custom/custom-video-horizontal-regular.marko +6 -0
- package/icons/custom/custom-video-tour-3d-filled.marko +7 -0
- package/icons/custom/custom-video-tour-3d-regular.marko +9 -0
- package/icons/custom/custom-video-vertical-filled.marko +6 -0
- package/icons/custom/custom-video-vertical-regular.marko +6 -0
- package/icons/generated/fluent-add-regular.marko +3 -0
- package/icons/generated/fluent-alert-regular.marko +3 -0
- package/icons/generated/fluent-apps-regular.marko +3 -0
- package/icons/generated/fluent-arrow-download-regular.marko +3 -0
- package/icons/generated/fluent-arrow-left-regular.marko +3 -0
- package/icons/generated/fluent-arrow-right-regular.marko +3 -0
- package/icons/generated/fluent-arrow-rotate-clockwise-regular.marko +3 -0
- package/icons/generated/fluent-arrow-rotate-counterclockwise-regular.marko +3 -0
- package/icons/generated/fluent-border-all-regular.marko +3 -0
- package/icons/generated/fluent-calendar-regular.marko +3 -0
- package/icons/generated/fluent-checkmark-circle-filled.marko +3 -0
- package/icons/generated/fluent-checkmark-regular.marko +3 -0
- package/icons/generated/fluent-chevron-down-regular.marko +3 -0
- package/icons/generated/fluent-chevron-left-regular.marko +3 -0
- package/icons/generated/fluent-chevron-right-regular.marko +3 -0
- package/icons/generated/fluent-chevron-up-regular.marko +3 -0
- package/icons/generated/fluent-circle-half-fill-regular.marko +3 -0
- package/icons/generated/fluent-clock-regular.marko +3 -0
- package/icons/generated/fluent-color-regular.marko +3 -0
- package/icons/generated/fluent-crop-regular.marko +3 -0
- package/icons/generated/fluent-dark-theme-regular.marko +3 -0
- package/icons/generated/fluent-delete-regular.marko +3 -0
- package/icons/generated/fluent-desktop-regular.marko +3 -0
- package/icons/generated/fluent-dismiss-circle-filled.marko +3 -0
- package/icons/generated/fluent-dismiss-regular.marko +3 -0
- package/icons/generated/fluent-document-pdf-regular.marko +3 -0
- package/icons/generated/fluent-document-regular.marko +3 -0
- package/icons/generated/fluent-eye-off-regular.marko +3 -0
- package/icons/generated/fluent-eye-regular.marko +3 -0
- package/icons/generated/fluent-eyedropper-regular.marko +3 -0
- package/icons/generated/fluent-grid-regular.marko +3 -0
- package/icons/generated/fluent-history-regular.marko +3 -0
- package/icons/generated/fluent-home-regular.marko +3 -0
- package/icons/generated/fluent-image-regular.marko +3 -0
- package/icons/generated/fluent-info-regular.marko +3 -0
- package/icons/generated/fluent-link-regular.marko +3 -0
- package/icons/generated/fluent-more-horizontal-regular.marko +3 -0
- package/icons/generated/fluent-navigation-regular.marko +3 -0
- package/icons/generated/fluent-paint-brush-regular.marko +3 -0
- package/icons/generated/fluent-question-circle-regular.marko +3 -0
- package/icons/generated/fluent-search-regular.marko +3 -0
- package/icons/generated/fluent-settings-regular.marko +3 -0
- package/icons/generated/fluent-square-hint-regular.marko +3 -0
- package/icons/generated/fluent-subtract-regular.marko +3 -0
- package/icons/generated/fluent-text-align-center-regular.marko +3 -0
- package/icons/generated/fluent-text-align-left-regular.marko +3 -0
- package/icons/generated/fluent-text-align-right-regular.marko +3 -0
- package/icons/generated/fluent-text-bold-regular.marko +3 -0
- package/icons/generated/fluent-text-bullet-list-regular.marko +3 -0
- package/icons/generated/fluent-text-font-regular.marko +3 -0
- package/icons/generated/fluent-text-font-size-regular.marko +3 -0
- package/icons/generated/fluent-text-italic-regular.marko +3 -0
- package/icons/generated/fluent-text-number-list-ltr-regular.marko +3 -0
- package/icons/generated/fluent-video-regular.marko +3 -0
- package/icons/generated/fluent-warning-filled.marko +3 -0
- package/icons/generated/fluent-weather-moon-regular.marko +3 -0
- package/icons/generated/fluent-weather-sunny-regular.marko +3 -0
- package/icons/generated/fluent-zoom-in-regular.marko +3 -0
- package/icons/generated/fluent-zoom-out-regular.marko +3 -0
- package/icons/manifest.json +61 -0
- package/icons/social/social-facebook-color.marko +7 -0
- package/icons/social/social-facebook.marko +6 -0
- package/icons/social/social-google-color.marko +20 -0
- package/icons/social/social-google.marko +6 -0
- package/icons/social/social-instagram-color.marko +16 -0
- package/icons/social/social-instagram.marko +6 -0
- package/icons/social/social-linkedin-color.marko +8 -0
- package/icons/social/social-linkedin.marko +8 -0
- package/icons/social/social-messenger-color.marko +15 -0
- package/icons/social/social-messenger.marko +6 -0
- package/icons/social/social-pinterest-color.marko +6 -0
- package/icons/social/social-pinterest.marko +6 -0
- package/icons/social/social-telegram-color.marko +7 -0
- package/icons/social/social-telegram.marko +6 -0
- package/icons/social/social-whatsapp-color.marko +8 -0
- package/icons/social/social-whatsapp.marko +7 -0
- package/icons/social/social-x-color.marko +7 -0
- package/icons/social/social-x.marko +6 -0
- package/icons/social/social-youtube-color.marko +7 -0
- package/icons/social/social-youtube.marko +6 -0
- package/marko.json +203 -0
- package/package.json +55 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<!-- sds-badge — ported from kdls-design-system v2.5.1 (0f3edf8) components/Badge/Badge.tsx.
|
|
2
|
+
|
|
3
|
+
Divergences:
|
|
4
|
+
|
|
5
|
+
1. Colours. `primary`, `secondary`, `tertiary` and `lya` are gone; fourteen remain.
|
|
6
|
+
`scheme-color` follows the site's own colour and is the one to reach for.
|
|
7
|
+
|
|
8
|
+
2. No state, and therefore no click. KDLS's Badge holds useState for one thing:
|
|
9
|
+
when onClickIconRight returns a Promise it shows a spinner until it settles.
|
|
10
|
+
|
|
11
|
+
Measured, not assumed: rendering this template on the server with an on-click
|
|
12
|
+
handler produces HTML with no hydration script and no handler at all — Marko 5
|
|
13
|
+
drops the listener silently on a component that does not hydrate. A clickable
|
|
14
|
+
badge is therefore not free; it must hydrate, and hydrating serialises the whole
|
|
15
|
+
input, once per instance. Twenty property cards on a listing page would pay it
|
|
16
|
+
twenty times. That is the mechanism behind the 492 KB payload and the
|
|
17
|
+
2026-06-12 production OOM.
|
|
18
|
+
|
|
19
|
+
So the two are separate tags. <sds-badge> is markup: it renders a right icon as
|
|
20
|
+
decoration and never listens. <sds-badge-dismissible> hydrates knowingly and
|
|
21
|
+
carries the full KDLS behaviour, automatic promise spinner included. The
|
|
22
|
+
consumer chooses, and the choice is visible at the call site.
|
|
23
|
+
|
|
24
|
+
This is the precedent for Alert, Avatar, Card and every other component holding
|
|
25
|
+
state for one small thing.
|
|
26
|
+
|
|
27
|
+
3. Icons arrive as attribute tags rather than as props holding instantiated
|
|
28
|
+
elements — <@icon-left> and <@icon-right> — because Marko passes markup, not
|
|
29
|
+
element values.
|
|
30
|
+
|
|
31
|
+
4. An unknown variant, appearance, size or width throws instead of rendering an
|
|
32
|
+
unstyled badge. -->
|
|
33
|
+
|
|
34
|
+
import { assertVariant, assertAppearance, assertSize, assertWidth } from "./badge-variants.js";
|
|
35
|
+
|
|
36
|
+
$ {
|
|
37
|
+
const {
|
|
38
|
+
label,
|
|
39
|
+
variant = "neutral",
|
|
40
|
+
appearance = "tone-30",
|
|
41
|
+
size = "sm",
|
|
42
|
+
width = "hug",
|
|
43
|
+
iconLeft,
|
|
44
|
+
iconRight,
|
|
45
|
+
iconRightLoading = false,
|
|
46
|
+
iconRightDisabled = false,
|
|
47
|
+
class: extraClass = "",
|
|
48
|
+
} = input;
|
|
49
|
+
|
|
50
|
+
// A KDLS Badge always renders its right icon as a dismiss control. Here the split is
|
|
51
|
+
// deliberate — sds-badge is markup and does not hydrate, sds-badge-dismissible does, and
|
|
52
|
+
// a listing with forty badges pays that difference forty times. But a straight port of a
|
|
53
|
+
// KDLS call site landed here, lost its handler, and said nothing: the ✕ rendered, looked
|
|
54
|
+
// clickable and did nothing. Say so instead, and name the tag that does the job.
|
|
55
|
+
if (input.onClickIconRight) {
|
|
56
|
+
throw new Error("sds-badge takes no `onClickIconRight` — it is markup and never hydrates. Use <sds-badge-dismissible>, which does.");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
assertVariant(variant);
|
|
60
|
+
assertAppearance(appearance);
|
|
61
|
+
assertSize(size);
|
|
62
|
+
assertWidth(width);
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
// An icon may arrive two ways: as an attribute tag (<@icon-left>…</@icon-left>, which
|
|
66
|
+
// is the Marko idiom and what a page writes) or as a template value (which is what a
|
|
67
|
+
// test or a loop passes). Normalising here means callers never have to care.
|
|
68
|
+
const renderable = (value) => (value && value.renderBody) || value;
|
|
69
|
+
|
|
70
|
+
const showSpinner = iconRightLoading && !iconRightDisabled;
|
|
71
|
+
|
|
72
|
+
// The label's typography is the Text scale: label-sm at sm, body-sm at md, body-md at
|
|
73
|
+
// lg. It renders through <sds-text> so that scale lives in one place, and passes
|
|
74
|
+
// color="inherit" because the badge decides the colour — that is where the contrast
|
|
75
|
+
// tokens are applied.
|
|
76
|
+
const labelVariant = { sm: "labelRegular", md: "bodySm", lg: "bodyMd" }[size];
|
|
77
|
+
|
|
78
|
+
const badgeClass = [
|
|
79
|
+
"sds-badge",
|
|
80
|
+
`sds-badge--${variant}`,
|
|
81
|
+
`sds-badge--${appearance}`,
|
|
82
|
+
`sds-badge--${size}`,
|
|
83
|
+
width === "fill" ? "sds-badge--fill" : "",
|
|
84
|
+
iconRight ? "sds-badge--has-icon-right" : "",
|
|
85
|
+
extraClass,
|
|
86
|
+
].filter(Boolean).join(" ");
|
|
87
|
+
|
|
88
|
+
const contentClass = ["sds-badge__content", iconRight ? "sds-badge__content--has-icon-right" : ""]
|
|
89
|
+
.filter(Boolean).join(" ");
|
|
90
|
+
|
|
91
|
+
const iconRightClass = [
|
|
92
|
+
"sds-badge__icon",
|
|
93
|
+
"sds-badge__icon--right",
|
|
94
|
+
iconRightDisabled ? "sds-badge__icon--right--disabled" : "",
|
|
95
|
+
showSpinner ? "sds-badge__icon--right--loading" : "",
|
|
96
|
+
].filter(Boolean).join(" ");
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
<span class=badgeClass>
|
|
100
|
+
<span class=contentClass>
|
|
101
|
+
<if(iconLeft)>
|
|
102
|
+
<span class="sds-badge__icon sds-badge__icon--left" aria-hidden="true">
|
|
103
|
+
<sds-icon size="sm">
|
|
104
|
+
<${renderable(iconLeft)}/>
|
|
105
|
+
</sds-icon>
|
|
106
|
+
</span>
|
|
107
|
+
</if>
|
|
108
|
+
<sds-text as="span" variant=labelVariant color="inherit" class="sds-badge__label">
|
|
109
|
+
${label}
|
|
110
|
+
</sds-text>
|
|
111
|
+
</span>
|
|
112
|
+
|
|
113
|
+
<if(iconRight)>
|
|
114
|
+
<span class="sds-badge__icon-right-wrap">
|
|
115
|
+
<span
|
|
116
|
+
class=iconRightClass
|
|
117
|
+
aria-busy=(showSpinner ? "true" : null)
|
|
118
|
+
aria-disabled=(iconRightDisabled ? "true" : null)
|
|
119
|
+
>
|
|
120
|
+
// `showSpinner` was computed and then used only to set a wait cursor: the icon
|
|
121
|
+
// stayed painted, so a loading badge looked exactly like an idle one. The
|
|
122
|
+
// dismissible sibling has had this branch all along.
|
|
123
|
+
<if(showSpinner)>
|
|
124
|
+
<sds-spinner size="sm"/>
|
|
125
|
+
</if>
|
|
126
|
+
<else>
|
|
127
|
+
<sds-icon size="sm">
|
|
128
|
+
<${renderable(iconRight)}/>
|
|
129
|
+
</sds-icon>
|
|
130
|
+
</else>
|
|
131
|
+
</span>
|
|
132
|
+
</span>
|
|
133
|
+
</if>
|
|
134
|
+
</span>
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/* SDS BottomSheet.
|
|
2
|
+
Ported from kdls-design-system v2.5.1 (0f3edf8) components/BottomSheet/BottomSheet.css
|
|
3
|
+
by scripts/port-css.mjs. Divergences beyond the mechanical rename are noted inline.
|
|
4
|
+
|
|
5
|
+
Rules removed with the brand families they targeted:
|
|
6
|
+
[data-color-scheme="lya"] .sds-bottomsheet__searchable-input
|
|
7
|
+
*//* ============================================================
|
|
8
|
+
SDS BottomSheet
|
|
9
|
+
Standalone mobile overlay panel — slides up from bottom
|
|
10
|
+
BEM root: .sds-bottomsheet / .sds-bottomsheet__list / .sds-bottomsheet__item
|
|
11
|
+
z-index: 400 (overlay) / 401 (panel)
|
|
12
|
+
============================================================ */
|
|
13
|
+
|
|
14
|
+
/* ── Overlay ── */
|
|
15
|
+
.sds-bottomsheet__overlay {
|
|
16
|
+
position: fixed;
|
|
17
|
+
inset: 0;
|
|
18
|
+
/* Black in both themes. --color-opacity-* inverts, so it would light the screen up in
|
|
19
|
+
dark mode — which is why KDLS wrote a literal here. */
|
|
20
|
+
background: var(--color-scrim);
|
|
21
|
+
z-index: var(--z-overlay);
|
|
22
|
+
animation: sds-bs-fade 180ms ease;
|
|
23
|
+
}
|
|
24
|
+
/* ── Panel ── */
|
|
25
|
+
.sds-bottomsheet {
|
|
26
|
+
position: fixed;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
left: 0;
|
|
29
|
+
right: 0;
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
max-height: 80vh;
|
|
32
|
+
background: var(--component-bg-color);
|
|
33
|
+
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
|
34
|
+
padding: var(--spacing-3) 0;
|
|
35
|
+
z-index: calc(var(--z-overlay) + 1);
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-direction: column;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
animation: sds-bs-slide 240ms cubic-bezier(0.32, 0.72, 0, 1);
|
|
40
|
+
}
|
|
41
|
+
/* ── Title row — title + close button, always present ── */
|
|
42
|
+
.sds-bottomsheet__title-row {
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
gap: var(--spacing-4);
|
|
46
|
+
flex-shrink: 0;
|
|
47
|
+
padding: 0 var(--spacing-4);
|
|
48
|
+
}
|
|
49
|
+
.sds-bottomsheet__close {
|
|
50
|
+
margin-left: auto;
|
|
51
|
+
flex-shrink: 0;
|
|
52
|
+
}
|
|
53
|
+
/* ── Search (sticky slot — does not scroll with body) ── */
|
|
54
|
+
.sds-bottomsheet__search {
|
|
55
|
+
flex-shrink: 0;
|
|
56
|
+
padding: var(--spacing-2) var(--spacing-4);
|
|
57
|
+
border-bottom: 1px solid var(--border-static-color);
|
|
58
|
+
/* Allow focus rings on inputs inside to overflow visually */
|
|
59
|
+
overflow: visible;
|
|
60
|
+
}
|
|
61
|
+
/* ── Header (searchable + select-all — same wrapper/spacing as Select's) ── */
|
|
62
|
+
.sds-bottomsheet__header {
|
|
63
|
+
flex-shrink: 0;
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-direction: column;
|
|
66
|
+
gap: var(--spacing-4);
|
|
67
|
+
padding: var(--spacing-4);
|
|
68
|
+
border-bottom: 1px solid var(--border-static-color);
|
|
69
|
+
}
|
|
70
|
+
.sds-bottomsheet__searchable-field {
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
gap: var(--spacing-2);
|
|
74
|
+
height: 40px;
|
|
75
|
+
padding: 0 var(--spacing-3);
|
|
76
|
+
border: 1px solid var(--border-interactive-color);
|
|
77
|
+
border-radius: var(--radius-md);
|
|
78
|
+
background: var(--component-bg-color);
|
|
79
|
+
transition: border-color 120ms ease, box-shadow 120ms ease;
|
|
80
|
+
}
|
|
81
|
+
.sds-bottomsheet__searchable-field:hover {
|
|
82
|
+
border-color: var(--color-primary-50-solid);
|
|
83
|
+
}
|
|
84
|
+
.sds-bottomsheet__searchable-field:focus-within {
|
|
85
|
+
border-color: var(--color-primary-50-solid);
|
|
86
|
+
box-shadow: var(--focus-ring);
|
|
87
|
+
}
|
|
88
|
+
.sds-bottomsheet__searchable-icon {
|
|
89
|
+
display: inline-flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
font-size: 24px;
|
|
92
|
+
flex-shrink: 0;
|
|
93
|
+
}
|
|
94
|
+
.sds-bottomsheet__searchable-input {
|
|
95
|
+
flex: 1;
|
|
96
|
+
border: none;
|
|
97
|
+
outline: none;
|
|
98
|
+
background: transparent;
|
|
99
|
+
font-family: var(--font-family-base);
|
|
100
|
+
font-size: var(--font-size-body-md);
|
|
101
|
+
color: var(--color-neutral-90);
|
|
102
|
+
caret-color: var(--color-primary-50-solid);
|
|
103
|
+
min-width: 0;
|
|
104
|
+
}
|
|
105
|
+
.sds-bottomsheet__searchable-input::placeholder { color: var(--placeholder-color); }
|
|
106
|
+
/* ── Empty state (searchable, no results) ── */
|
|
107
|
+
.sds-bottomsheet__empty {
|
|
108
|
+
padding: var(--spacing-2) var(--spacing-4);
|
|
109
|
+
font-family: var(--font-family-base);
|
|
110
|
+
font-size: var(--font-size-body-md);
|
|
111
|
+
color: var(--color-neutral-50);
|
|
112
|
+
list-style: none;
|
|
113
|
+
box-sizing: border-box;
|
|
114
|
+
}
|
|
115
|
+
/* ── Body ── */
|
|
116
|
+
.sds-bottomsheet__body {
|
|
117
|
+
flex: 1;
|
|
118
|
+
min-height: 0;
|
|
119
|
+
overflow-y: auto;
|
|
120
|
+
/* Small vertical padding so focus rings on first/last items aren't clipped */
|
|
121
|
+
padding: var(--spacing-1) 0;
|
|
122
|
+
}
|
|
123
|
+
/* ── Footer ── */
|
|
124
|
+
.sds-bottomsheet__footer {
|
|
125
|
+
flex-shrink: 0;
|
|
126
|
+
border-top: 1px solid var(--border-static-color);
|
|
127
|
+
padding: var(--spacing-3) var(--spacing-4);
|
|
128
|
+
}
|
|
129
|
+
/* Limpar + Aplicar, when the footer is the automatic one (clearable/multiple) — Limpar on the left, Aplicar on the right */
|
|
130
|
+
.sds-bottomsheet__footer-actions {
|
|
131
|
+
display: flex;
|
|
132
|
+
align-items: center;
|
|
133
|
+
justify-content: space-between;
|
|
134
|
+
gap: var(--spacing-3);
|
|
135
|
+
}
|
|
136
|
+
/* The panel already reserves its own padding-bottom (spacing-4) — when the automatic footer
|
|
137
|
+
is present, the footer's own padding-bottom becomes duplicated space below the buttons */
|
|
138
|
+
.sds-bottomsheet__footer:has(.sds-bottomsheet__footer-actions) {
|
|
139
|
+
padding-bottom: 0;
|
|
140
|
+
}
|
|
141
|
+
/* ── List ── */
|
|
142
|
+
.sds-bottomsheet__list {
|
|
143
|
+
list-style: none;
|
|
144
|
+
margin: 0;
|
|
145
|
+
padding: 0;
|
|
146
|
+
}
|
|
147
|
+
/* ── Item ── */
|
|
148
|
+
.sds-bottomsheet__item {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
gap: var(--spacing-3);
|
|
152
|
+
padding: var(--spacing-2) var(--spacing-3);
|
|
153
|
+
min-height: 40px;
|
|
154
|
+
cursor: pointer;
|
|
155
|
+
color: var(--color-neutral-80);
|
|
156
|
+
font-family: var(--font-family-base);
|
|
157
|
+
font-size: var(--font-size-body-md);
|
|
158
|
+
font-weight: var(--font-weight-regular);
|
|
159
|
+
line-height: var(--lh-body-md);
|
|
160
|
+
border-radius: 11px; /* soft, the install default — schemes at the end */
|
|
161
|
+
margin: 0 var(--spacing-1);
|
|
162
|
+
transition: background-color 120ms ease, color 120ms ease;
|
|
163
|
+
user-select: none;
|
|
164
|
+
box-sizing: border-box;
|
|
165
|
+
}
|
|
166
|
+
.sds-bottomsheet__item:hover {
|
|
167
|
+
background-color: var(--color-opacity-05);
|
|
168
|
+
}
|
|
169
|
+
.sds-bottomsheet__item:focus {
|
|
170
|
+
outline: none;
|
|
171
|
+
}
|
|
172
|
+
.sds-bottomsheet__item:focus-visible {
|
|
173
|
+
outline: none;
|
|
174
|
+
background-color: var(--color-opacity-08);
|
|
175
|
+
box-shadow: var(--focus-ring-inset);
|
|
176
|
+
}
|
|
177
|
+
.sds-bottomsheet__item:active {
|
|
178
|
+
background-color: var(--color-opacity-10);
|
|
179
|
+
}
|
|
180
|
+
.sds-bottomsheet__item--active {
|
|
181
|
+
background-color: transparent;
|
|
182
|
+
color: var(--color-neutral-90);
|
|
183
|
+
font-weight: var(--font-weight-bold);
|
|
184
|
+
}
|
|
185
|
+
.sds-bottomsheet__item--active:hover {
|
|
186
|
+
background-color: var(--color-opacity-05);
|
|
187
|
+
}
|
|
188
|
+
.sds-bottomsheet__item--disabled {
|
|
189
|
+
opacity: 0.4;
|
|
190
|
+
cursor: not-allowed;
|
|
191
|
+
}
|
|
192
|
+
/* ── Item slots ── */
|
|
193
|
+
.sds-bottomsheet__item-label {
|
|
194
|
+
flex: 1;
|
|
195
|
+
white-space: nowrap;
|
|
196
|
+
}
|
|
197
|
+
.sds-bottomsheet__item-checkbox {
|
|
198
|
+
display: inline-flex;
|
|
199
|
+
align-items: center;
|
|
200
|
+
flex-shrink: 0;
|
|
201
|
+
}
|
|
202
|
+
.sds-bottomsheet__item-icon-left {
|
|
203
|
+
display: inline-flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
flex-shrink: 0;
|
|
206
|
+
color: inherit;
|
|
207
|
+
}
|
|
208
|
+
.sds-bottomsheet__item-check {
|
|
209
|
+
display: inline-flex;
|
|
210
|
+
align-items: center;
|
|
211
|
+
flex-shrink: 0;
|
|
212
|
+
color: var(--color-neutral-90);
|
|
213
|
+
margin-left: auto;
|
|
214
|
+
}
|
|
215
|
+
/* ── Animations ── */
|
|
216
|
+
@keyframes sds-bs-fade {
|
|
217
|
+
from { opacity: 0; }
|
|
218
|
+
to { opacity: 1; }
|
|
219
|
+
}
|
|
220
|
+
@keyframes sds-bs-slide {
|
|
221
|
+
from { transform: translateY(100%); }
|
|
222
|
+
to { transform: translateY(0); }
|
|
223
|
+
}
|
|
224
|
+
/* ── Dark mode ── */
|
|
225
|
+
[data-theme="dark"] .sds-bottomsheet__search {
|
|
226
|
+
border-bottom-color: var(--border-interactive-color);
|
|
227
|
+
}
|
|
228
|
+
[data-theme="dark"] .sds-bottomsheet__header {
|
|
229
|
+
border-bottom-color: var(--border-interactive-color);
|
|
230
|
+
}
|
|
231
|
+
[data-theme="dark"] .sds-bottomsheet__searchable-field {
|
|
232
|
+
border-color: var(--border-interactive-color);
|
|
233
|
+
}
|
|
234
|
+
[data-theme="dark"] .sds-bottomsheet__footer {
|
|
235
|
+
border-top-color: var(--border-interactive-color);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
/* Native chrome reset for the option rows.
|
|
240
|
+
KDLS draws each option as an <li> with a mousedown handler: not focusable, not
|
|
241
|
+
activatable by keyboard, and invisible to anything that looks for controls. SDS renders
|
|
242
|
+
a real <button> inside the <li>, and this is what takes the browser's own styling off —
|
|
243
|
+
without it the list renders as a column of OS push-buttons, which is measured and
|
|
244
|
+
documented in Select.css. */
|
|
245
|
+
.sds-bottomsheet__item-button {
|
|
246
|
+
appearance: none;
|
|
247
|
+
border: 0;
|
|
248
|
+
background: none;
|
|
249
|
+
text-align: left;
|
|
250
|
+
font: inherit;
|
|
251
|
+
color: inherit;
|
|
252
|
+
cursor: pointer;
|
|
253
|
+
display: flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
gap: var(--spacing-3);
|
|
256
|
+
width: 100%;
|
|
257
|
+
padding: 0;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
.sds-bottomsheet__item-button:disabled {
|
|
261
|
+
cursor: not-allowed;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* "Selecionar todos". It used to borrow `__header`, which is the sheet's title bar — 16px
|
|
265
|
+
all round, laid out for a title and a close button. Its own rule now, so the two can
|
|
266
|
+
change independently. */
|
|
267
|
+
.sds-bottomsheet__select-all {
|
|
268
|
+
padding: var(--spacing-2) var(--spacing-4);
|
|
269
|
+
border-bottom: 1px solid var(--border-static-color);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
/* A section heading inside the list. It used to borrow `__header`, which is a 16px-padded
|
|
273
|
+
flex column with a bottom border — the container the search box sits in, not a label. */
|
|
274
|
+
.sds-bottomsheet__section {
|
|
275
|
+
padding: var(--spacing-3) var(--spacing-4) var(--spacing-1);
|
|
276
|
+
font-size: var(--font-size-label-sm);
|
|
277
|
+
font-weight: var(--font-weight-medium);
|
|
278
|
+
color: var(--color-neutral-60);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/* ── Corner radius: the 40px family ───────────────────────────────────────────
|
|
282
|
+
A row in a menu, a select or a dropdown is 40px tall, which makes it the same control
|
|
283
|
+
as the Pill and the navButton — so it takes the same four values. Rafael, pointing at
|
|
284
|
+
the theme bar's own menu: these are reactive, but not in the right way; they should be
|
|
285
|
+
40px like the navButton and have the radius resolved here.
|
|
286
|
+
|
|
287
|
+
height 40px flat 0 soft 11px medium 15px rounded 20px (a capsule)
|
|
288
|
+
as a fraction 0 0.275 0.375 0.5
|
|
289
|
+
|
|
290
|
+
`--radius-sm` was what they had, and it tops out at 16px — so `rounded` drew a rounded
|
|
291
|
+
rectangle where every other 40px control in the system drew a capsule. See Pill.css for
|
|
292
|
+
the arithmetic; the numbers are a fraction of the control's own height, which is what
|
|
293
|
+
keeps the family reading as one thing.
|
|
294
|
+
|
|
295
|
+
The bare value is `soft`'s, because an install that never picks a scheme has no
|
|
296
|
+
attribute at all and falls through to it. */
|
|
297
|
+
[data-radius="flat"] .sds-bottomsheet__item { border-radius: 0; }
|
|
298
|
+
[data-radius="soft"] .sds-bottomsheet__item { border-radius: 11px; }
|
|
299
|
+
[data-radius="medium"] .sds-bottomsheet__item { border-radius: 15px; }
|
|
300
|
+
[data-radius="rounded"] .sds-bottomsheet__item { border-radius: var(--radius-full); }
|