@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,93 @@
|
|
|
1
|
+
<!-- sds-toast — ported from kdls-design-system v2.5.1 (0f3edf8) components/Toast/Toast.tsx.
|
|
2
|
+
|
|
3
|
+
One message on an inverted surface: dark in the light theme, light in the dark one.
|
|
4
|
+
It knows nothing about timing or stacking — that is sds-toaster and the store behind
|
|
5
|
+
it, which is what lets toast(...) be called from a catch block that is nowhere near a
|
|
6
|
+
component.
|
|
7
|
+
|
|
8
|
+
`leaving` is the exit animation, set by the toaster. It is in the public attribute
|
|
9
|
+
surface because KDLS put it there, marked internal for the same reason: nothing else
|
|
10
|
+
should set it.
|
|
11
|
+
|
|
12
|
+
Divergence: none in behaviour. The four hover and active overlays were rgba literals
|
|
13
|
+
in KDLS's stylesheet, which is what --color-opacity-inverse-* now holds — the regular
|
|
14
|
+
opacity family follows the theme and is backwards on a surface that runs against it. -->
|
|
15
|
+
|
|
16
|
+
import { assertPlacement } from "../Floating/floating-position.js";
|
|
17
|
+
import { assertToastFeedback, TOAST_FEEDBACK } from "./toast-variants.js";
|
|
18
|
+
import dismissIcon from "../../icons/generated/fluent-dismiss-regular.marko";
|
|
19
|
+
import successIcon from "../../icons/generated/fluent-checkmark-circle-filled.marko";
|
|
20
|
+
import alertIcon from "../../icons/generated/fluent-warning-filled.marko";
|
|
21
|
+
import errorIcon from "../../icons/generated/fluent-dismiss-circle-filled.marko";
|
|
22
|
+
|
|
23
|
+
$ {
|
|
24
|
+
const {
|
|
25
|
+
message,
|
|
26
|
+
feedback = "neutral",
|
|
27
|
+
actionLabel,
|
|
28
|
+
onAction,
|
|
29
|
+
actionDisabled = false,
|
|
30
|
+
actionDisabledTooltip,
|
|
31
|
+
actionDisabledTooltipPosition = "top",
|
|
32
|
+
showDismiss = true,
|
|
33
|
+
onDismiss,
|
|
34
|
+
leaving = false,
|
|
35
|
+
dismissLabel = "Fechar",
|
|
36
|
+
class: extraClass = "",
|
|
37
|
+
} = input;
|
|
38
|
+
|
|
39
|
+
assertPlacement(actionDisabledTooltipPosition);
|
|
40
|
+
|
|
41
|
+
if (!message) throw new Error("sds-toast needs a `message`.");
|
|
42
|
+
assertToastFeedback(feedback);
|
|
43
|
+
|
|
44
|
+
// neutral carries no icon at all: a message with nothing to report should not borrow a
|
|
45
|
+
// symbol that says something happened.
|
|
46
|
+
const icons = { neutral: null, success: successIcon, alert: alertIcon, error: errorIcon };
|
|
47
|
+
const icon = icons[feedback];
|
|
48
|
+
|
|
49
|
+
const classes = [
|
|
50
|
+
"sds-toast",
|
|
51
|
+
`sds-toast--${feedback}`,
|
|
52
|
+
leaving ? "sds-toast--leaving" : "",
|
|
53
|
+
extraClass,
|
|
54
|
+
].filter(Boolean).join(" ");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
<div
|
|
58
|
+
class=classes
|
|
59
|
+
role="status"
|
|
60
|
+
aria-live=(feedback === "error" ? "assertive" : "polite")
|
|
61
|
+
>
|
|
62
|
+
<if(icon)>
|
|
63
|
+
<span class="sds-toast__icon" aria-hidden="true">
|
|
64
|
+
<sds-icon color=feedback><${icon}/></sds-icon>
|
|
65
|
+
</span>
|
|
66
|
+
</if>
|
|
67
|
+
|
|
68
|
+
<span class="sds-toast__message">${message}</span>
|
|
69
|
+
|
|
70
|
+
<if(actionLabel)>
|
|
71
|
+
<sds-button
|
|
72
|
+
variant="link"
|
|
73
|
+
label=actionLabel
|
|
74
|
+
onClick=onAction
|
|
75
|
+
disabled=actionDisabled
|
|
76
|
+
disabledTooltip=actionDisabledTooltip
|
|
77
|
+
disabledTooltipPosition=actionDisabledTooltipPosition
|
|
78
|
+
class="sds-toast__action"
|
|
79
|
+
/>
|
|
80
|
+
</if>
|
|
81
|
+
|
|
82
|
+
<if(showDismiss)>
|
|
83
|
+
<sds-icon-button
|
|
84
|
+
variant="neutral"
|
|
85
|
+
size="sm"
|
|
86
|
+
class="sds-toast__dismiss"
|
|
87
|
+
aria-label=dismissLabel
|
|
88
|
+
onClick=onDismiss
|
|
89
|
+
>
|
|
90
|
+
<@icon><${dismissIcon}/></@icon>
|
|
91
|
+
</sds-icon-button>
|
|
92
|
+
</if>
|
|
93
|
+
</div>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<!-- sds-toaster — ported from kdls-design-system v2.5.1 (0f3edf8) components/Toast/Toaster.tsx.
|
|
2
|
+
|
|
3
|
+
Mount once at the root of the page. It subscribes to the store and renders whatever
|
|
4
|
+
toast(...) has fired, stacked in the corner. No attributes: the position is fixed and
|
|
5
|
+
the timing belongs to the store.
|
|
6
|
+
|
|
7
|
+
Hovering the stack pauses every timer. A toast that vanishes while someone is reaching
|
|
8
|
+
for its action has wasted their time, and KDLS gets this right — it is carried as is.
|
|
9
|
+
|
|
10
|
+
Divergences:
|
|
11
|
+
|
|
12
|
+
No portal. KDLS renders through createPortal into <body>; Marko 5 has none, and a node
|
|
13
|
+
moved there returns on the next re-render (measured — see components/Floating).
|
|
14
|
+
The container is position:fixed, so it covers the viewport from wherever it sits, and
|
|
15
|
+
the only thing lost is escaping an ancestor with a transform. Mounted at the root of
|
|
16
|
+
the page, as it is meant to be, there is no such ancestor.
|
|
17
|
+
|
|
18
|
+
It renders nothing at all until the store has something, rather than an empty
|
|
19
|
+
container: an empty <div role="region" aria-label="Notificações"> is a landmark a
|
|
20
|
+
screen reader offers to navigate to and finds nothing inside. -->
|
|
21
|
+
|
|
22
|
+
import { subscribe, dismissToast, pauseAll, resumeAll } from "./toast-store.js";
|
|
23
|
+
|
|
24
|
+
class {
|
|
25
|
+
onCreate() {
|
|
26
|
+
this.state = { items: [] };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
onMount() {
|
|
30
|
+
// The store calls back immediately with what it already holds, so a toaster mounted
|
|
31
|
+
// after a toast was fired still shows it.
|
|
32
|
+
this.unsubscribe = subscribe((items) => { this.state.items = items; });
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
onDestroy() {
|
|
36
|
+
this.unsubscribe?.();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
pause() { pauseAll(); }
|
|
40
|
+
resume() { resumeAll(); }
|
|
41
|
+
dismiss(id) { dismissToast(id); }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
<if(state.items.length)>
|
|
45
|
+
<div
|
|
46
|
+
class="sds-toaster"
|
|
47
|
+
role="region"
|
|
48
|
+
aria-label="Notificações"
|
|
49
|
+
on-mouseenter("pause")
|
|
50
|
+
on-mouseleave("resume")
|
|
51
|
+
>
|
|
52
|
+
<!-- `key` on each toast, so a dismissal removes the right node rather than shifting
|
|
53
|
+
the list up underneath the animation. -->
|
|
54
|
+
<for|item| of=state.items>
|
|
55
|
+
<sds-toast
|
|
56
|
+
key=item.id
|
|
57
|
+
message=item.message
|
|
58
|
+
feedback=item.feedback
|
|
59
|
+
actionLabel=item.actionLabel
|
|
60
|
+
onAction=item.onAction
|
|
61
|
+
actionDisabled=item.actionDisabled
|
|
62
|
+
actionDisabledTooltip=item.actionDisabledTooltip
|
|
63
|
+
actionDisabledTooltipPosition=item.actionDisabledTooltipPosition
|
|
64
|
+
showDismiss=item.showDismiss
|
|
65
|
+
leaving=item.leaving
|
|
66
|
+
onDismiss=() => component.dismiss(item.id)
|
|
67
|
+
/>
|
|
68
|
+
</for>
|
|
69
|
+
</div>
|
|
70
|
+
</if>
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/* SDS Toggle.
|
|
2
|
+
Ported from kdls-design-system v2.5.1 (0f3edf8) components/Toggle/Toggle.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-toggle__item--active
|
|
7
|
+
[data-color-scheme="lya"] .sds-toggle__item--active:hover:not(:disabled)
|
|
8
|
+
[data-color-scheme="lya"] .sds-toggle:hover:not(.sds-toggle--disabled)
|
|
9
|
+
*//* ── Toggle — Segmented control ──────────────────────────────────
|
|
10
|
+
Container: gray track with pill radius
|
|
11
|
+
Items: no individual borders; active = blue filled pill
|
|
12
|
+
─────────────────────────────────────────────────────────────── */
|
|
13
|
+
|
|
14
|
+
.sds-toggle {
|
|
15
|
+
display: inline-flex;
|
|
16
|
+
align-items: center;
|
|
17
|
+
gap: var(--spacing-0-5);
|
|
18
|
+
height: 40px;
|
|
19
|
+
padding: var(--spacing-1);
|
|
20
|
+
background: var(--component-bg-color);
|
|
21
|
+
border: 1px solid var(--border-interactive-color);
|
|
22
|
+
/* soft, the install default — see the note by the scheme overrides below */
|
|
23
|
+
border-radius: 11px;
|
|
24
|
+
transition: border-color 120ms ease, background-color 120ms ease;
|
|
25
|
+
}
|
|
26
|
+
.sds-toggle--fill { width: 100%; }
|
|
27
|
+
.sds-toggle--fill .sds-toggle__item { flex: 1; }
|
|
28
|
+
.sds-toggle:hover:not(.sds-toggle--disabled) {
|
|
29
|
+
border-color: var(--color-primary-50-solid);
|
|
30
|
+
}
|
|
31
|
+
.sds-toggle--disabled {
|
|
32
|
+
background: var(--color-neutral-20);
|
|
33
|
+
border-color: var(--border-static-color);
|
|
34
|
+
cursor: not-allowed;
|
|
35
|
+
}
|
|
36
|
+
.sds-toggle--disabled .sds-toggle__item {
|
|
37
|
+
color: var(--color-neutral-40);
|
|
38
|
+
}
|
|
39
|
+
[data-theme="dark"] .sds-toggle--disabled {
|
|
40
|
+
background: var(--color-neutral-30);
|
|
41
|
+
border-color: var(--border-interactive-color);
|
|
42
|
+
}
|
|
43
|
+
[data-theme="dark"] .sds-toggle--disabled .sds-toggle__item--active {
|
|
44
|
+
background: var(--color-neutral-40);
|
|
45
|
+
color: var(--component-bg-color);
|
|
46
|
+
}
|
|
47
|
+
/* ── Item (default = 40px track height) ────────────────────────── */
|
|
48
|
+
.sds-toggle__item {
|
|
49
|
+
display: inline-flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
gap: 6px;
|
|
53
|
+
height: 32px;
|
|
54
|
+
padding: 0 var(--spacing-3);
|
|
55
|
+
border: none;
|
|
56
|
+
background: transparent;
|
|
57
|
+
/* soft, the install default — see the note by the scheme overrides below */
|
|
58
|
+
border-radius: 9px;
|
|
59
|
+
font-family: var(--font-family-base);
|
|
60
|
+
font-size: var(--font-size-body-md); /* 16px */
|
|
61
|
+
font-weight: var(--font-weight-regular);
|
|
62
|
+
color: var(--color-neutral-80);
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
transition: background 120ms ease, color 120ms ease;
|
|
65
|
+
white-space: nowrap;
|
|
66
|
+
user-select: none;
|
|
67
|
+
outline: none;
|
|
68
|
+
}
|
|
69
|
+
.sds-toggle__item:hover:not(:disabled) {
|
|
70
|
+
background: var(--color-neutral-10);
|
|
71
|
+
color: var(--color-neutral-10-on);
|
|
72
|
+
}
|
|
73
|
+
/* ── Active item ────────────────────────────────────────────────── */
|
|
74
|
+
.sds-toggle__item--active {
|
|
75
|
+
background: var(--color-primary-50);
|
|
76
|
+
color: var(--color-on-primary);
|
|
77
|
+
}
|
|
78
|
+
.sds-toggle__item--active:hover:not(:disabled) {
|
|
79
|
+
background: var(--color-primary-60);
|
|
80
|
+
color: var(--color-on-primary);
|
|
81
|
+
box-shadow: none;
|
|
82
|
+
}
|
|
83
|
+
/* ── Disabled individual item (item.disabled in an enabled group) ── */
|
|
84
|
+
.sds-toggle__item:disabled {
|
|
85
|
+
cursor: not-allowed;
|
|
86
|
+
color: var(--color-neutral-40);
|
|
87
|
+
}
|
|
88
|
+
/* ── Active item in disabled state — neutral instead of primary ─── */
|
|
89
|
+
.sds-toggle--disabled .sds-toggle__item--active {
|
|
90
|
+
background: var(--color-neutral-40);
|
|
91
|
+
color: var(--color-white);
|
|
92
|
+
}
|
|
93
|
+
/* ── Focus ring ─────────────────────────────────────────────────── */
|
|
94
|
+
.sds-toggle__item:focus-visible {
|
|
95
|
+
outline: none;
|
|
96
|
+
box-shadow: var(--focus-ring);
|
|
97
|
+
}
|
|
98
|
+
/* ── Icon slot ──────────────────────────────────────────────────── */
|
|
99
|
+
.sds-toggle__icon {
|
|
100
|
+
display: inline-flex;
|
|
101
|
+
align-items: center;
|
|
102
|
+
justify-content: center;
|
|
103
|
+
flex-shrink: 0;
|
|
104
|
+
font-size: 24px;
|
|
105
|
+
}
|
|
106
|
+
/* ── Icon-only: square padding ──────────────────────────────────── */
|
|
107
|
+
.sds-toggle--icon-only .sds-toggle__item {
|
|
108
|
+
padding: 0 var(--spacing-2);
|
|
109
|
+
min-width: 32px;
|
|
110
|
+
}
|
|
111
|
+
/* ── Corner Radius Scheme overrides ──
|
|
112
|
+
Carried from KDLS unchanged. The numbers are a proportion of each element's own height,
|
|
113
|
+
which is what holds the container and the item to the same shape at every tier:
|
|
114
|
+
|
|
115
|
+
container 40px soft 11px (0.275) medium 15px (0.375)
|
|
116
|
+
item 32px soft 9px (0.28) medium 12px (0.375)
|
|
117
|
+
|
|
118
|
+
See Pill.css — the container is the same 40px as a pill and takes the same numbers, and
|
|
119
|
+
the note there explains why the base values below are soft's rather than a capsule's:
|
|
120
|
+
an install with no data-radius attribute gets the default scheme, and SDS's default is
|
|
121
|
+
soft. `rounded` is explicit for the same reason — it can no longer fall through. */
|
|
122
|
+
[data-radius="flat"] .sds-toggle { border-radius: 0; }
|
|
123
|
+
[data-radius="flat"] .sds-toggle__item { border-radius: 0; }
|
|
124
|
+
[data-radius="soft"] .sds-toggle { border-radius: 11px; }
|
|
125
|
+
[data-radius="soft"] .sds-toggle__item { border-radius: 9px; }
|
|
126
|
+
[data-radius="medium"] .sds-toggle { border-radius: 15px; }
|
|
127
|
+
[data-radius="rounded"] .sds-toggle { border-radius: var(--radius-full); }
|
|
128
|
+
/* Item is 32px tall — 16px would clamp to a full pill on its own, erasing the softened look */
|
|
129
|
+
[data-radius="medium"] .sds-toggle__item { border-radius: 12px; }
|
|
130
|
+
[data-radius="rounded"] .sds-toggle__item { border-radius: var(--radius-full); }
|
|
131
|
+
/* ── Dark mode ──────────────────────────────────────────────────── */
|
|
132
|
+
/* ── The native radios ─────────────────────────────────────────────────────────
|
|
133
|
+
A segmented control is a radio group. KDLS built it from divs with a click handler, so
|
|
134
|
+
arrow keys did nothing, the value never reached a form, and a screen reader read three
|
|
135
|
+
unrelated words instead of "Mapa, 2 de 3".
|
|
136
|
+
|
|
137
|
+
The inputs are hidden with opacity, not display:none — a hidden input cannot be focused,
|
|
138
|
+
and the whole point of using radios is the keyboard. */
|
|
139
|
+
/* A fieldset needs its browser chrome reset before it can be laid out — but only the
|
|
140
|
+
chrome. `padding: 0` here also erased the 4px inset the base rule gives the track, and
|
|
141
|
+
the segments ran into the container's own border. */
|
|
142
|
+
.sds-toggle {
|
|
143
|
+
border: 1px solid var(--border-interactive-color);
|
|
144
|
+
margin: 0;
|
|
145
|
+
min-inline-size: 0;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.sds-toggle__legend {
|
|
149
|
+
position: absolute;
|
|
150
|
+
width: 1px;
|
|
151
|
+
height: 1px;
|
|
152
|
+
overflow: hidden;
|
|
153
|
+
clip-path: inset(50%);
|
|
154
|
+
white-space: nowrap;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.sds-toggle__input {
|
|
158
|
+
position: absolute;
|
|
159
|
+
width: 1px;
|
|
160
|
+
height: 1px;
|
|
161
|
+
margin: 0;
|
|
162
|
+
opacity: 0;
|
|
163
|
+
pointer-events: none;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.sds-toggle__item:has(.sds-toggle__input:focus-visible) {
|
|
167
|
+
box-shadow: var(--focus-ring);
|
|
168
|
+
}
|
|
169
|
+
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<!-- sds-toggle — ported from kdls-design-system v2.5.1 (0f3edf8) components/Toggle/Toggle.tsx.
|
|
2
|
+
|
|
3
|
+
A segmented control: several options, one chosen. That is a radio group, and it is built
|
|
4
|
+
as one — an <input type="radio"> per segment inside a <fieldset>.
|
|
5
|
+
|
|
6
|
+
KDLS built it from divs with useState and a click handler. The radios give what that could
|
|
7
|
+
not: arrow keys move between the segments, the browser enforces one-of-N, the value goes
|
|
8
|
+
into a form on its own, and a screen reader announces "Mapa, 2 de 3" instead of reading
|
|
9
|
+
three unrelated words. None of it needs JavaScript, so the component holds no state.
|
|
10
|
+
|
|
11
|
+
The fieldset needs a name. KDLS had none — a segmented control with no legend is three
|
|
12
|
+
buttons a screen reader cannot connect to each other. -->
|
|
13
|
+
|
|
14
|
+
class {
|
|
15
|
+
/** The radios are native, so the change event already bubbles — this names it. */
|
|
16
|
+
handleChange(event) {
|
|
17
|
+
if (event.target.type !== "radio") return;
|
|
18
|
+
this.input.onChange?.(event.target.value);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
$ {
|
|
23
|
+
const {
|
|
24
|
+
items = [],
|
|
25
|
+
// `component.id`, not a random string. Marko gives every component an id that is the
|
|
26
|
+
// same on the server and in the browser; a random one drawn inside the render block is
|
|
27
|
+
// a different value on each side, so every `for` and `aria-*` pointing at it resolved
|
|
28
|
+
// to nothing after hydration — and changed again on every re-render.
|
|
29
|
+
name = `sds-toggle-${component.id}`,
|
|
30
|
+
value,
|
|
31
|
+
defaultValue,
|
|
32
|
+
label,
|
|
33
|
+
width = "hug",
|
|
34
|
+
disabled = false,
|
|
35
|
+
class: extraClass = "",
|
|
36
|
+
} = input;
|
|
37
|
+
|
|
38
|
+
if (items.length < 2) {
|
|
39
|
+
throw new Error("sds-toggle needs at least two items — one option is not a choice.");
|
|
40
|
+
}
|
|
41
|
+
if (!label) {
|
|
42
|
+
throw new Error("sds-toggle needs a `label` naming what is being chosen.");
|
|
43
|
+
}
|
|
44
|
+
if (width !== "hug" && width !== "fill") {
|
|
45
|
+
throw new Error(`Unknown toggle width: "${width}". Allowed: hug, fill`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const renderable = (v) => (v && v.renderBody) || v;
|
|
49
|
+
const selected = value ?? defaultValue ?? items[0].value;
|
|
50
|
+
const iconOnly = items.every((item) => !item.label);
|
|
51
|
+
|
|
52
|
+
const classes = [
|
|
53
|
+
"sds-toggle",
|
|
54
|
+
`sds-toggle--${width}`,
|
|
55
|
+
disabled ? "sds-toggle--disabled" : "",
|
|
56
|
+
iconOnly ? "sds-toggle--icon-only" : "",
|
|
57
|
+
extraClass,
|
|
58
|
+
].filter(Boolean).join(" ");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
<fieldset class=classes on-change("handleChange")>
|
|
62
|
+
<legend class="sds-toggle__legend">${label}</legend>
|
|
63
|
+
|
|
64
|
+
<for|item| of=items>
|
|
65
|
+
<label class=`sds-toggle__item ${item.value === selected ? "sds-toggle__item--active" : ""}`.trim()>
|
|
66
|
+
<input
|
|
67
|
+
class="sds-toggle__input"
|
|
68
|
+
type="radio"
|
|
69
|
+
name=name
|
|
70
|
+
value=item.value
|
|
71
|
+
checked=(item.value === selected || null)
|
|
72
|
+
disabled=((disabled || item.disabled) || null)
|
|
73
|
+
/>
|
|
74
|
+
<if(item.iconLeft)>
|
|
75
|
+
<span class="sds-toggle__icon" aria-hidden="true">
|
|
76
|
+
<sds-icon size="sm"><${renderable(item.iconLeft)}/></sds-icon>
|
|
77
|
+
</span>
|
|
78
|
+
</if>
|
|
79
|
+
<if(item.label)>
|
|
80
|
+
${item.label}
|
|
81
|
+
</if>
|
|
82
|
+
<else>
|
|
83
|
+
<!-- Icon-only segments still need a name; the label is visually hidden. -->
|
|
84
|
+
<span class="sds-visually-hidden">${item.ariaLabel ?? item.value}</span>
|
|
85
|
+
</else>
|
|
86
|
+
<if(item.iconRight)>
|
|
87
|
+
<span class="sds-toggle__icon" aria-hidden="true">
|
|
88
|
+
<sds-icon size="sm"><${renderable(item.iconRight)}/></sds-icon>
|
|
89
|
+
</span>
|
|
90
|
+
</if>
|
|
91
|
+
</label>
|
|
92
|
+
</for>
|
|
93
|
+
</fieldset>
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* SDS Tooltip.
|
|
2
|
+
Ported from kdls-design-system v2.5.1 (0f3edf8) components/Tooltip/Tooltip.css.
|
|
3
|
+
|
|
4
|
+
The arrow is keyed off the panel's data-placement rather than a class built from the
|
|
5
|
+
placement name, for the same reason as Popover: KDLS spells the placement twice, once in
|
|
6
|
+
JavaScript and once in CSS, and the two can drift. Here sds-floating writes the placement
|
|
7
|
+
it actually settled on and the rules read that. */
|
|
8
|
+
|
|
9
|
+
.sds-tooltip-wrapper {
|
|
10
|
+
position: relative;
|
|
11
|
+
display: inline-flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
cursor: help;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.sds-tooltip {
|
|
17
|
+
width: max-content;
|
|
18
|
+
max-width: 240px;
|
|
19
|
+
padding: var(--spacing-1-5) var(--spacing-2-5);
|
|
20
|
+
background: var(--color-neutral-90);
|
|
21
|
+
color: var(--color-neutral-90-on);
|
|
22
|
+
border-radius: var(--radius-sm);
|
|
23
|
+
font-family: var(--font-family-base);
|
|
24
|
+
font-size: var(--font-size-label-sm);
|
|
25
|
+
line-height: var(--lh-label-sm);
|
|
26
|
+
/* The tooltip must never be the thing the pointer is over: a tooltip that can be hovered
|
|
27
|
+
keeps itself open and blocks what is underneath it. */
|
|
28
|
+
pointer-events: none;
|
|
29
|
+
white-space: normal;
|
|
30
|
+
animation: sds-tooltip-fade-in 120ms ease;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@keyframes sds-tooltip-fade-in {
|
|
34
|
+
from { opacity: 0; }
|
|
35
|
+
to { opacity: 1; }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* ── Arrow ──
|
|
39
|
+
A CSS triangle: a zero-size box with one border side coloured. Which side depends on
|
|
40
|
+
where the panel ended up, which is what data-placement carries. */
|
|
41
|
+
.sds-tooltip::before {
|
|
42
|
+
content: '';
|
|
43
|
+
position: absolute;
|
|
44
|
+
width: 0;
|
|
45
|
+
height: 0;
|
|
46
|
+
border-style: solid;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* Panel above the trigger → the arrow points down, from the panel's bottom edge. */
|
|
50
|
+
[data-placement^="top"] .sds-tooltip::before {
|
|
51
|
+
bottom: -6px;
|
|
52
|
+
border-width: 6px 6px 0 6px;
|
|
53
|
+
border-color: var(--color-neutral-90) transparent transparent transparent;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Panel below → points up. */
|
|
57
|
+
[data-placement^="bottom"] .sds-tooltip::before {
|
|
58
|
+
top: -6px;
|
|
59
|
+
border-width: 0 6px 6px 6px;
|
|
60
|
+
border-color: transparent transparent var(--color-neutral-90) transparent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Panel to the left → points right. */
|
|
64
|
+
[data-placement^="left"] .sds-tooltip::before {
|
|
65
|
+
right: -6px;
|
|
66
|
+
border-width: 6px 0 6px 6px;
|
|
67
|
+
border-color: transparent transparent transparent var(--color-neutral-90);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Panel to the right → points left. */
|
|
71
|
+
[data-placement^="right"] .sds-tooltip::before {
|
|
72
|
+
left: -6px;
|
|
73
|
+
border-width: 6px 6px 6px 0;
|
|
74
|
+
border-color: transparent var(--color-neutral-90) transparent transparent;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Where along that edge the arrow sits. Exact matches, so the centred case — the one with
|
|
78
|
+
no corner word — does not also catch the cornered ones. */
|
|
79
|
+
[data-placement="top"] .sds-tooltip::before,
|
|
80
|
+
[data-placement="bottom"] .sds-tooltip::before { left: 50%; transform: translateX(-50%); }
|
|
81
|
+
|
|
82
|
+
[data-placement="topLeft"] .sds-tooltip::before,
|
|
83
|
+
[data-placement="bottomLeft"] .sds-tooltip::before { left: var(--spacing-2); }
|
|
84
|
+
|
|
85
|
+
[data-placement="topRight"] .sds-tooltip::before,
|
|
86
|
+
[data-placement="bottomRight"] .sds-tooltip::before { right: var(--spacing-2); }
|
|
87
|
+
|
|
88
|
+
[data-placement="left"] .sds-tooltip::before,
|
|
89
|
+
[data-placement="right"] .sds-tooltip::before { top: 50%; transform: translateY(-50%); }
|
|
90
|
+
|
|
91
|
+
[data-placement="leftTop"] .sds-tooltip::before,
|
|
92
|
+
[data-placement="rightTop"] .sds-tooltip::before { top: var(--spacing-2); }
|
|
93
|
+
|
|
94
|
+
[data-placement="leftBottom"] .sds-tooltip::before,
|
|
95
|
+
[data-placement="rightBottom"] .sds-tooltip::before { bottom: var(--spacing-2); }
|
|
96
|
+
|
|
97
|
+
/* The default trigger: the design system's own info affordance. KDLS renders a bare Icon
|
|
98
|
+
here, which no keyboard can reach — so a tooltip with no custom trigger was mouse-only.
|
|
99
|
+
This is a real button with the browser's chrome taken off. */
|
|
100
|
+
.sds-tooltip-wrapper__trigger {
|
|
101
|
+
appearance: none;
|
|
102
|
+
border: 0;
|
|
103
|
+
background: none;
|
|
104
|
+
padding: 0;
|
|
105
|
+
display: inline-flex;
|
|
106
|
+
align-items: center;
|
|
107
|
+
color: var(--color-neutral-60);
|
|
108
|
+
cursor: help;
|
|
109
|
+
border-radius: var(--radius-xs);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.sds-tooltip-wrapper__trigger:focus-visible {
|
|
113
|
+
outline: var(--focus-ring-width) solid var(--focus-stroke-color);
|
|
114
|
+
outline-offset: 2px;
|
|
115
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
<!-- sds-tooltip — ported from kdls-design-system v2.5.1 (0f3edf8) components/Tooltip/Tooltip.tsx.
|
|
2
|
+
|
|
3
|
+
A short label that appears on hover or focus. It is sds-floating with a dark panel and
|
|
4
|
+
an arrow, opened by hover and focus together — KDLS wrote the same show/hide, the same
|
|
5
|
+
100ms delays and the same positioning maths inline, before Floating existed to hold it.
|
|
6
|
+
|
|
7
|
+
Three divergences, all of them defects rather than choices:
|
|
8
|
+
|
|
9
|
+
KDLS's default trigger is a bare <Icon> — a <span> with no tabindex. A tooltip with no
|
|
10
|
+
custom trigger is therefore unreachable by keyboard, which is most of the tooltips in a
|
|
11
|
+
product. Here it is a real <button>.
|
|
12
|
+
|
|
13
|
+
The panel carries role="tooltip" and nothing points at it, so a screen reader never
|
|
14
|
+
reads it: role="tooltip" describes what an element is, it does not announce it. The
|
|
15
|
+
trigger now carries aria-describedby, and the text is also in a permanently rendered
|
|
16
|
+
visually-hidden node so it is in the accessibility tree whether or not the panel is
|
|
17
|
+
open. When the trigger is the caller's own markup, put aria-describedby on the
|
|
18
|
+
focusable thing inside it — the id is `${id}-text`, and the component exposes `id`
|
|
19
|
+
for exactly that.
|
|
20
|
+
|
|
21
|
+
Touch is still open, and it is not a small gap: there is no hover on a phone, so a
|
|
22
|
+
tooltip whose only triggers are hover and focus does not exist for 62% of this
|
|
23
|
+
product's traffic. Tapping the default trigger does open it, because a tap focuses a
|
|
24
|
+
button — but a custom trigger that is not focusable stays silent. The real answer is
|
|
25
|
+
probably a press-and-hold or a bottom sheet, and that is Rafael's decision, recorded
|
|
26
|
+
here rather than guessed. -->
|
|
27
|
+
|
|
28
|
+
import { assertPlacement } from "../Floating/floating-position.js";
|
|
29
|
+
import infoIcon from "../../icons/generated/fluent-info-regular.marko";
|
|
30
|
+
|
|
31
|
+
$ {
|
|
32
|
+
const {
|
|
33
|
+
content,
|
|
34
|
+
placement = "top",
|
|
35
|
+
// `component.id`, not a random string. Marko gives every component an id that is the
|
|
36
|
+
// same on the server and in the browser; a random one drawn inside the render block is
|
|
37
|
+
// a different value on each side, so every `for` and `aria-*` pointing at it resolved
|
|
38
|
+
// to nothing after hydration — and changed again on every re-render.
|
|
39
|
+
id = `sds-tooltip-${component.id}`,
|
|
40
|
+
class: extraClass = "",
|
|
41
|
+
} = input;
|
|
42
|
+
|
|
43
|
+
if (!content) throw new Error("sds-tooltip needs `content` — the text it shows.");
|
|
44
|
+
assertPlacement(placement);
|
|
45
|
+
|
|
46
|
+
const textId = `${id}-text`;
|
|
47
|
+
const GAP = 8;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
<span class=`sds-tooltip-wrapper ${extraClass}`.trim()>
|
|
51
|
+
<sds-floating
|
|
52
|
+
placement=placement
|
|
53
|
+
trigger=["hover", "focus"]
|
|
54
|
+
gap=GAP
|
|
55
|
+
zIndex="var(--z-notice)"
|
|
56
|
+
mouseEnterDelay=100
|
|
57
|
+
mouseLeaveDelay=100
|
|
58
|
+
>
|
|
59
|
+
<@content>
|
|
60
|
+
<span class="sds-tooltip" role="tooltip">${content}</span>
|
|
61
|
+
</@content>
|
|
62
|
+
|
|
63
|
+
<if(input.renderBody)>
|
|
64
|
+
<${input.renderBody}/>
|
|
65
|
+
</if>
|
|
66
|
+
<else>
|
|
67
|
+
<button type="button" class="sds-tooltip-wrapper__trigger" aria-describedby=textId>
|
|
68
|
+
<sds-icon size="sm"><${infoIcon}/></sds-icon>
|
|
69
|
+
</button>
|
|
70
|
+
</else>
|
|
71
|
+
</sds-floating>
|
|
72
|
+
|
|
73
|
+
<!-- The description lives here, always, not in the panel: a node that appears at the
|
|
74
|
+
same moment it is referenced is one a screen reader has already read past. The panel
|
|
75
|
+
is the visual half of the same text. -->
|
|
76
|
+
<span class="sds-visually-hidden" id=textId>${content}</span>
|
|
77
|
+
</span>
|