@studiocms/ui 0.4.17 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/components/Accordion/Accordion.astro +1 -0
  2. package/dist/components/Accordion/Item.astro +8 -6
  3. package/dist/components/Accordion/accordion.css +35 -21
  4. package/dist/components/Accordion/accordion.d.ts +46 -1
  5. package/dist/components/Accordion/accordion.js +95 -70
  6. package/dist/components/Badge/Badge.astro +2 -2
  7. package/dist/components/Badge/badge.css +32 -32
  8. package/dist/components/Breadcrumbs/breadcrumbs.css +1 -1
  9. package/dist/components/Button/button.css +93 -93
  10. package/dist/components/Card/card.css +4 -4
  11. package/dist/components/Checkbox/checkbox.css +26 -26
  12. package/dist/components/Divider/Divider.astro +1 -1
  13. package/dist/components/Divider/divider.css +2 -2
  14. package/dist/components/Dropdown/Dropdown.astro +2 -2
  15. package/dist/components/Dropdown/dropdown.css +26 -26
  16. package/dist/components/Footer/footer.css +4 -4
  17. package/dist/components/Group/group.css +12 -6
  18. package/dist/components/Icon/Icon.astro +114 -6
  19. package/dist/components/Icon/IconBase.astro +108 -7
  20. package/dist/components/Icon/errors.d.ts +29 -0
  21. package/dist/components/Icon/errors.js +25 -0
  22. package/dist/components/Input/Input.astro +43 -1
  23. package/dist/components/Input/input.css +39 -9
  24. package/dist/components/Modal/Modal.astro +1 -1
  25. package/dist/components/Modal/modal.css +4 -4
  26. package/dist/components/Progress/progress.css +7 -7
  27. package/dist/components/RadioGroup/radiogroup.css +21 -21
  28. package/dist/components/SearchSelect/SearchSelect.astro +2 -2
  29. package/dist/components/SearchSelect/searchselect.css +28 -22
  30. package/dist/components/Select/Select.astro +2 -2
  31. package/dist/components/Select/select.css +36 -30
  32. package/dist/components/Sidebar/Double.astro +4 -4
  33. package/dist/components/Sidebar/Single.astro +2 -2
  34. package/dist/components/Skeleton/Skeleton.astro +61 -0
  35. package/dist/components/Skeleton/skeleton.css +111 -0
  36. package/dist/components/Skeleton/skeleton.d.ts +161 -0
  37. package/dist/components/Skeleton/skeleton.js +71 -0
  38. package/dist/components/Tabs/TabItem.astro +14 -9
  39. package/dist/components/Tabs/Tabs.astro +91 -54
  40. package/dist/components/Tabs/tabs.css +14 -14
  41. package/dist/components/Tabs/tabs.d.ts +17 -1
  42. package/dist/components/Tabs/tabs.js +99 -76
  43. package/dist/components/Textarea/textarea.css +8 -8
  44. package/dist/components/Toast/toaster.css +26 -23
  45. package/dist/components/Toast/toaster.js +4 -0
  46. package/dist/components/Toggle/toggle.css +13 -13
  47. package/dist/components/Tooltip/Tooltip.astro +119 -0
  48. package/dist/components/Tooltip/tooltip.css +187 -0
  49. package/dist/components/Tooltip/tooltip.d.ts +46 -0
  50. package/dist/components/Tooltip/tooltip.js +330 -0
  51. package/dist/components/User/User.astro +1 -1
  52. package/dist/components/User/user.css +3 -3
  53. package/dist/css/colors.css +85 -83
  54. package/dist/css/prose.css +360 -0
  55. package/dist/css/resets.css +3 -3
  56. package/dist/events.d.ts +104 -0
  57. package/dist/index.d.ts +25 -0
  58. package/dist/index.js +120 -313
  59. package/dist/toolbar/index.js +5 -5
  60. package/dist/types/index.d.ts +2 -0
  61. package/dist/utils/iconifyUtils.d.ts +1 -1
  62. package/dist/virtuals.d.js +0 -0
  63. package/dist/virtuals.d.ts +564 -0
  64. package/package.json +5 -1
  65. package/dist/components/Icon/iconType.d.ts +0 -2
  66. package/dist/components/ThemeToggle/ThemeToggle.astro +0 -21
  67. package/dist/components/ThemeToggle/themetoggle.css +0 -17
  68. package/dist/components/ThemeToggle/themetoggle.d.ts +0 -1
  69. package/dist/components/ThemeToggle/themetoggle.js +0 -4
  70. /package/dist/{components/Icon/iconType.js → events.d.js} +0 -0
@@ -1,85 +1,108 @@
1
- function loadTabs() {
2
- const allTabContainers = document.querySelectorAll(".sui-tabs-container");
3
- for (const tabContainer of allTabContainers) {
4
- const storage = tabContainer.dataset.storageStrategy;
5
- const syncKey = tabContainer.dataset.syncKey;
1
+ const switchTab = (tabContainer, newActiveHeader, originatedFromSync = false) => {
2
+ const tabHeaders = Array.from(
3
+ tabContainer.querySelectorAll(":scope > .sui-tabs-list > .sui-tab-header")
4
+ );
5
+ const tabPanels = Array.from(
6
+ tabContainer.querySelectorAll(":scope > .sui-tabs-content > sui-tab-item")
7
+ );
8
+ if (!newActiveHeader || !tabHeaders.includes(newActiveHeader)) return;
9
+ for (const header of tabHeaders) {
10
+ header.classList.remove("active");
11
+ header.tabIndex = -1;
12
+ header.setAttribute("aria-selected", "false");
13
+ }
14
+ for (const panel of tabPanels) {
15
+ panel.classList.remove("active");
16
+ }
17
+ newActiveHeader.classList.add("active");
18
+ newActiveHeader.tabIndex = 0;
19
+ newActiveHeader.setAttribute("aria-selected", "true");
20
+ const activePanel = tabPanels.find((p) => p.id === newActiveHeader.getAttribute("aria-controls"));
21
+ if (activePanel) {
22
+ activePanel.classList.add("active");
23
+ }
24
+ const syncKey = tabContainer.dataset.syncKey;
25
+ if (syncKey && !originatedFromSync) {
26
+ const storage = tabContainer.dataset.storageStrategy ?? "session";
6
27
  const storageLayer = storage === "session" ? sessionStorage : localStorage;
7
- const constructCustomEvent = (tabIndex, uniqueId) => {
8
- return new CustomEvent(`sui-tab-switch:${syncKey}`, {
28
+ const tabIndex = tabHeaders.indexOf(newActiveHeader);
29
+ storageLayer.setItem(syncKey, tabIndex.toString());
30
+ document.dispatchEvent(
31
+ new CustomEvent(`sui-tab-switch:${syncKey}`, {
9
32
  detail: {
10
33
  tabIndex,
11
- uniqueId
12
- }
13
- });
14
- };
15
- const switchTab = (target, container, originatedFromSync = false) => {
16
- const activeChildren = container.querySelectorAll(".active");
17
- for (const child of activeChildren) {
18
- child.tabIndex = -1;
19
- child.classList.remove("active");
20
- }
21
- const newActiveTab = target;
22
- newActiveTab.classList.add("active");
23
- newActiveTab.tabIndex = 0;
24
- const newActiveTabContentId = newActiveTab.dataset.tabChild;
25
- const newActiveTabContent = container.querySelector(
26
- `sui-tab-item[data-tab-id="${newActiveTabContentId}"]`
27
- );
28
- newActiveTabContent.classList.add("active");
29
- if (syncKey && !originatedFromSync) {
30
- const tabIndex = Array.prototype.indexOf.call(
31
- newActiveTab.parentElement.children,
32
- newActiveTab
33
- );
34
- storageLayer.setItem(syncKey, tabIndex.toString());
35
- document.dispatchEvent(constructCustomEvent(tabIndex, container.dataset.uniqueId));
36
- }
37
- };
38
- const tabHeaders = tabContainer.querySelectorAll(".sui-tab-header");
39
- for (const tab of tabHeaders) {
40
- tab.addEventListener("click", (e) => switchTab(e.target, tabContainer));
41
- tab.addEventListener("keydown", (e) => {
42
- if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
43
- const activeTabIndex = Array.prototype.indexOf.call(tab.parentElement.children, tab);
44
- const nextTabIndex = e.key === "ArrowLeft" ? activeTabIndex - 1 : activeTabIndex + 1;
45
- if (nextTabIndex >= 0 && nextTabIndex < tab.parentElement.children.length) {
46
- tab.tabIndex = -1;
47
- const nextTab = tab.parentElement.children[nextTabIndex];
48
- nextTab.tabIndex = 0;
49
- nextTab.click();
50
- nextTab.focus();
51
- } else if (nextTabIndex < 0) {
52
- tab.tabIndex = -1;
53
- const lastTab = tab.parentElement.children[tab.parentElement.children.length - 1];
54
- lastTab.tabIndex = 0;
55
- lastTab.click();
56
- lastTab.focus();
57
- } else {
58
- tab.tabIndex = -1;
59
- const firstTab = tab.parentElement.children[0];
60
- firstTab.tabIndex = 0;
61
- firstTab.click();
62
- firstTab.focus();
63
- }
34
+ uniqueId: tabContainer.dataset.uniqueId
64
35
  }
65
- });
36
+ })
37
+ );
38
+ }
39
+ };
40
+ const setupTabContainer = (tabContainer) => {
41
+ const tabHeaders = Array.from(
42
+ tabContainer.querySelectorAll(":scope > .sui-tabs-list > .sui-tab-header")
43
+ );
44
+ const tabPanels = Array.from(
45
+ tabContainer.querySelectorAll(":scope > .sui-tabs-content > sui-tab-item")
46
+ );
47
+ const tabList = tabContainer.querySelector(":scope > .sui-tabs-list");
48
+ if (!tabHeaders.length || !tabPanels.length || !tabList) return;
49
+ tabHeaders.forEach((header, index) => {
50
+ const panel = tabPanels[index];
51
+ if (!panel) return;
52
+ const panelId = panel.dataset.tabId ?? `sui-panel-${crypto.randomUUID()}`;
53
+ const headerId = header.id || `sui-header-${crypto.randomUUID()}`;
54
+ header.id = headerId;
55
+ panel.id = panelId;
56
+ panel.setAttribute("role", "tabpanel");
57
+ panel.setAttribute("aria-labelledby", headerId);
58
+ header.setAttribute("aria-controls", panelId);
59
+ });
60
+ tabList.addEventListener("click", (e) => {
61
+ const header = e.target.closest(".sui-tab-header");
62
+ if (header && tabHeaders.includes(header)) {
63
+ switchTab(tabContainer, header);
66
64
  }
67
- if (syncKey) {
68
- const activeTabIndex = storageLayer.getItem(syncKey);
69
- if (activeTabIndex) {
70
- const activeTab = tabContainer.querySelector(`#${syncKey}-${activeTabIndex}`);
71
- if (activeTab) {
72
- activeTab.click();
73
- }
65
+ });
66
+ tabList.addEventListener("keydown", (e) => {
67
+ if (e.key !== "ArrowLeft" && e.key !== "ArrowRight") return;
68
+ const currentHeader = e.target.closest(".sui-tab-header");
69
+ if (!currentHeader || !tabHeaders.includes(currentHeader)) return;
70
+ e.preventDefault();
71
+ const currentIndex = tabHeaders.indexOf(currentHeader);
72
+ const newIndex = e.key === "ArrowLeft" ? (currentIndex - 1 + tabHeaders.length) % tabHeaders.length : (currentIndex + 1) % tabHeaders.length;
73
+ const nextTab = tabHeaders[newIndex];
74
+ nextTab.focus();
75
+ switchTab(tabContainer, nextTab);
76
+ });
77
+ const syncKey = tabContainer.dataset.syncKey;
78
+ const initiallyActiveTab = tabHeaders.find((h) => h.classList.contains("active")) ?? tabHeaders[0];
79
+ if (syncKey) {
80
+ const storage = tabContainer.dataset.storageStrategy ?? "session";
81
+ const storageLayer = storage === "session" ? sessionStorage : localStorage;
82
+ const activeTabIndex = storageLayer.getItem(syncKey);
83
+ if (activeTabIndex) {
84
+ const activeTab = tabHeaders[Number.parseInt(activeTabIndex, 10)];
85
+ if (activeTab) {
86
+ switchTab(tabContainer, activeTab);
74
87
  }
75
- document.addEventListener(`sui-tab-switch:${syncKey}`, (e) => {
76
- const event = e;
77
- const { tabIndex, uniqueId } = event.detail;
78
- if (uniqueId === tabContainer.dataset.uniqueId) return;
79
- const newTab = tabContainer.querySelector(`#${syncKey}-${tabIndex}`);
80
- switchTab(newTab, tabContainer, true);
81
- });
88
+ } else {
89
+ switchTab(tabContainer, initiallyActiveTab);
82
90
  }
91
+ document.addEventListener(`sui-tab-switch:${syncKey}`, (e) => {
92
+ const { tabIndex, uniqueId } = e.detail;
93
+ if (uniqueId === tabContainer.dataset.uniqueId) return;
94
+ const newTab = tabHeaders[tabIndex];
95
+ if (newTab) {
96
+ switchTab(tabContainer, newTab, true);
97
+ }
98
+ });
99
+ } else {
100
+ switchTab(tabContainer, initiallyActiveTab);
101
+ }
102
+ };
103
+ const loadTabs = () => {
104
+ for (const tabContainer of document.querySelectorAll(".sui-tabs-container")) {
105
+ setupTabContainer(tabContainer);
83
106
  }
84
- }
107
+ };
85
108
  document.addEventListener("astro:page-load", loadTabs);
@@ -7,7 +7,7 @@
7
7
  .sui-textarea-label.disabled {
8
8
  opacity: 0.5;
9
9
  pointer-events: none;
10
- color: hsl(var(--text-muted));
10
+ color: var(--text-muted);
11
11
  }
12
12
  .sui-textarea-label.full-width {
13
13
  width: 100%;
@@ -22,9 +22,9 @@
22
22
  .sui-textarea {
23
23
  padding: .65rem;
24
24
  border-radius: var(--radius-md);
25
- border: 1px solid hsl(var(--border));
26
- background: hsl(var(--background-step-2));
27
- color: hsl(var(--text-normal));
25
+ border: 1px solid var(--border);
26
+ background: var(--background-step-2);
27
+ color: var(--text-normal);
28
28
  transition: all .15s ease;
29
29
  resize: none;
30
30
  min-height: 12ch;
@@ -32,18 +32,18 @@
32
32
  height: 100%;
33
33
  }
34
34
  .sui-textarea:hover {
35
- background: hsl(var(--background-step-3));
35
+ background: var(--background-step-3);
36
36
  }
37
37
  .resize .sui-textarea {
38
38
  resize: both;
39
39
  }
40
40
  .sui-textarea:active,
41
41
  .sui-textarea:focus {
42
- border: 1px solid hsl(var(--primary-base));
42
+ border: 1px solid var(--primary-base);
43
43
  outline: none;
44
- background: hsl(var(--background-step-2));
44
+ background: var(--background-step-2);
45
45
  }
46
46
  .req-star {
47
- color: hsl(var(--danger-base));
47
+ color: var(--danger-base);
48
48
  font-weight: 700;
49
49
  }
@@ -6,7 +6,7 @@
6
6
  left: 0;
7
7
  z-index: 100;
8
8
  pointer-events: none;
9
- color: hsl(var(--text-normal));
9
+ color: var(--text-normal);
10
10
  }
11
11
  #sui-toast-drawer {
12
12
  max-width: 420px;
@@ -25,9 +25,9 @@
25
25
  pointer-events: all;
26
26
  padding: 1rem;
27
27
  border-radius: var(--radius-md);
28
- border: 1px solid hsl(var(--border));
29
- background-color: hsl(var(--background-base));
30
- box-shadow: 0px 4px 8px hsl(var(--shadow), 0.5);
28
+ border: 1px solid var(--border);
29
+ background-color: var(--background-base);
30
+ box-shadow: 0px 4px 8px var(--shadow);
31
31
  display: flex;
32
32
  flex-direction: column;
33
33
  gap: .5rem;
@@ -52,22 +52,22 @@
52
52
  font-size: 1.125em;
53
53
  }
54
54
  .sui-toast-header-left-side svg {
55
- color: hsl(var(--primary-base));
55
+ color: var(--primary-base);
56
56
  }
57
57
  .sui-toast-container.success .sui-toast-header-left-side svg {
58
- color: hsl(var(--success-base));
58
+ color: var(--success-base);
59
59
  }
60
60
  .sui-toast-container.warning .sui-toast-header-left-side svg {
61
- color: hsl(var(--warning-base));
61
+ color: var(--warning-base);
62
62
  }
63
63
  .sui-toast-container.danger .sui-toast-header-left-side svg {
64
- color: hsl(var(--danger-base));
64
+ color: var(--danger-base);
65
65
  }
66
66
  .sui-toast-container.info .sui-toast-header-left-side svg {
67
- color: hsl(var(--info-base));
67
+ color: var(--info-base);
68
68
  }
69
69
  .sui-toast-container.mono .sui-toast-header-left-side svg {
70
- color: hsl(var(--mono-base));
70
+ color: var(--mono-base);
71
71
  }
72
72
  .sui-toast-progress-bar {
73
73
  position: absolute;
@@ -75,20 +75,23 @@
75
75
  width: 100%;
76
76
  bottom: 0;
77
77
  left: 0%;
78
- background-color: hsl(var(--primary-base));
78
+ background-color: var(--primary-base);
79
79
  animation: toast-progress forwards linear;
80
80
  }
81
81
  .sui-toast-container.paused .sui-toast-progress-bar {
82
82
  animation-play-state: paused;
83
83
  }
84
84
  .sui-toast-container.success .sui-toast-progress-bar {
85
- background-color: hsl(var(--success-base));
85
+ background-color: var(--success-base);
86
86
  }
87
87
  .sui-toast-container.warning .sui-toast-progress-bar {
88
- background-color: hsl(var(--warning-base));
88
+ background-color: var(--warning-base);
89
89
  }
90
90
  .sui-toast-container.danger .sui-toast-progress-bar {
91
- background-color: hsl(var(--danger-base));
91
+ background-color: var(--danger-base);
92
+ }
93
+ .sui-toast-container.info .sui-toast-progress-bar {
94
+ background-color: var(--info-base);
92
95
  }
93
96
  .close-icon-container {
94
97
  cursor: pointer;
@@ -101,26 +104,26 @@
101
104
  border-radius: var(--radius-sm);
102
105
  }
103
106
  .close-icon-container:hover {
104
- background-color: hsl(var(--default-base));
107
+ background-color: var(--default-base);
105
108
  }
106
109
  .close-icon-container:focus-visible {
107
- outline: 2px solid hsl(var(--text-normal));
110
+ outline: 2px solid var(--text-normal);
108
111
  outline-offset: 2px;
109
112
  }
110
113
  .sui-toast-container.closing {
111
114
  animation: toast-closing .25s ease forwards;
112
115
  }
113
116
  .sui-toast-container.persistent {
114
- border: 1px solid hsl(var(--primary-base));
117
+ border: 1px solid var(--primary-base);
115
118
  }
116
119
  .sui-toast-container.persistent.success {
117
- border: 1px solid hsl(var(--success-base));
120
+ border: 1px solid var(--success-base);
118
121
  }
119
122
  .sui-toast-container.persistent.warning {
120
- border: 1px solid hsl(var(--warning-base));
123
+ border: 1px solid var(--warning-base);
121
124
  }
122
125
  .sui-toast-container.persistent.danger {
123
- border: 1px solid hsl(var(--danger-base));
126
+ border: 1px solid var(--danger-base);
124
127
  }
125
128
  @keyframes toast-pop-in {
126
129
  0% {
@@ -139,7 +142,7 @@
139
142
  max-height: 500px;
140
143
  margin-bottom: var(--gap);
141
144
  padding: 1rem;
142
- border: 1px solid hsl(var(--border));
145
+ border: 1px solid var(--border);
143
146
  }
144
147
  62.5% {
145
148
  scale: 0.75;
@@ -147,7 +150,7 @@
147
150
  max-height: 500px;
148
151
  margin-bottom: var(--gap);
149
152
  padding: 1rem;
150
- border: 1px solid hsl(var(--border));
153
+ border: 1px solid var(--border);
151
154
  }
152
155
  100% {
153
156
  scale: 0.75;
@@ -155,7 +158,7 @@
155
158
  max-height: 0px;
156
159
  margin-bottom: 0;
157
160
  padding: 0;
158
- border: 0px solid hsl(var(--border));
161
+ border: 0px solid var(--border);
159
162
  }
160
163
  }
161
164
  @keyframes toast-progress {
@@ -75,12 +75,16 @@ function createToast(props) {
75
75
  let iconString;
76
76
  if (props.type === "success") {
77
77
  iconString = "check-circle";
78
+ toastContainer.classList.add("success");
78
79
  } else if (props.type === "danger") {
79
80
  iconString = "exclamation-circle";
81
+ toastContainer.classList.add("danger");
80
82
  } else if (props.type === "warning") {
81
83
  iconString = "exclamation-triangle";
84
+ toastContainer.classList.add("warning");
82
85
  } else {
83
86
  iconString = "information-circle";
87
+ toastContainer.classList.add("info");
84
88
  }
85
89
  const toastIcon = getIconString(iconString, "toast-icon", 24, 24);
86
90
  toastHeaderLeftSide.innerHTML = toastIcon;
@@ -9,7 +9,7 @@
9
9
  .sui-toggle-label.disabled {
10
10
  opacity: 0.5;
11
11
  pointer-events: none;
12
- color: hsl(var(--text-muted));
12
+ color: var(--text-muted);
13
13
  }
14
14
  .sui-toggle-label:active .sui-toggle-switch {
15
15
  transform: scale(0.85);
@@ -21,7 +21,7 @@
21
21
  align-items: center;
22
22
  cursor: pointer;
23
23
  transition: all .15s ease;
24
- background-color: hsl(var(--default-base));
24
+ background-color: var(--default-base);
25
25
  width: var(--toggle-width);
26
26
  height: var(--toggle-height);
27
27
  border-radius: var(--radius-full);
@@ -30,7 +30,7 @@
30
30
  --switch: calc(var(--toggle-height) * 1.75);
31
31
  height: var(--switch);
32
32
  width: var(--switch);
33
- background-color: hsl(var(--text-muted));
33
+ background-color: var(--text-muted);
34
34
  border-radius: var(--radius-full);
35
35
  position: relative;
36
36
  left: 0;
@@ -38,12 +38,12 @@
38
38
  will-change: transform;
39
39
  }
40
40
  .sui-toggle-switch:focus-visible {
41
- outline: 2px solid hsl(var(--text-normal));
41
+ outline: 2px solid var(--text-normal);
42
42
  outline-offset: 2px;
43
43
  }
44
44
  .sui-toggle-container:has(.sui-toggle-checkbox:checked) .sui-toggle-switch {
45
45
  left: calc(100% - var(--switch));
46
- background-color: hsl(var(--text-normal));
46
+ background-color: var(--text-normal);
47
47
  }
48
48
  .sui-toggle-label.sm .sui-toggle-container {
49
49
  --toggle-height: 10px;
@@ -60,28 +60,28 @@
60
60
  --switch: calc(var(--toggle-height) * 1.65);
61
61
  }
62
62
  .sui-toggle-label.primary .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
63
- background-color: hsl(var(--primary-base));
63
+ background-color: var(--primary-base);
64
64
  }
65
65
  .sui-toggle-label.success .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
66
- background-color: hsl(var(--success-base));
66
+ background-color: var(--success-base);
67
67
  }
68
68
  .sui-toggle-label.warning .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
69
- background-color: hsl(var(--warning-base));
69
+ background-color: var(--warning-base);
70
70
  }
71
71
  .sui-toggle-label.danger .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
72
- background-color: hsl(var(--danger-base));
72
+ background-color: var(--danger-base);
73
73
  }
74
74
  .sui-toggle-label.info .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
75
- background-color: hsl(var(--info-base));
75
+ background-color: var(--info-base);
76
76
  }
77
77
  .sui-toggle-label.mono .sui-toggle-container:has(.sui-toggle-checkbox:checked) {
78
- background-color: hsl(var(--mono-base));
78
+ background-color: var(--mono-base);
79
79
  }
80
80
  .sui-toggle-label.mono .sui-toggle-switch {
81
- border: 1px solid hsl(var(--text-inverted));
81
+ border: 1px solid var(--text-inverted);
82
82
  }
83
83
  .req-star {
84
- color: hsl(var(--danger-base));
84
+ color: var(--danger-base);
85
85
  font-weight: 700;
86
86
  }
87
87
  .sui-toggle-checkbox {
@@ -0,0 +1,119 @@
1
+ ---
2
+ import './tooltip.css';
3
+ import type { HTMLAttributes } from 'astro/types';
4
+
5
+ interface Props extends Omit<HTMLAttributes<'div'>, 'class:list'> {
6
+ /**
7
+ * The position of the tooltip. Defaults to 'auto'.
8
+ *
9
+ * 'auto' will try to position below, then above, then right, then left.
10
+ */
11
+ position?: 'auto' | 'top' | 'bottom' | 'left' | 'right';
12
+
13
+ /**
14
+ * Whether the tooltip should be opened by default. Defaults to false.
15
+ */
16
+ defaultOpen?: boolean;
17
+
18
+ /**
19
+ * Whether the tooltip should be inline with the anchor element. Defaults to false.
20
+ *
21
+ * @todo This is not fully working, due to an Astro bug: https://github.com/withastro/astro/issues/13970
22
+ *
23
+ * USE AT YOUR OWN RISK!
24
+ */
25
+ inline?: boolean;
26
+
27
+ /**
28
+ * The variant of the tooltip. Defaults to 'default'.
29
+ */
30
+ variant?: 'default' | 'outlined';
31
+
32
+ /**
33
+ * The color of the tooltip. Defaults to 'default'.
34
+ */
35
+ color?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error' | 'mono';
36
+
37
+ /**
38
+ * The gap between the tooltip and the anchor element in pixels. Defaults to 8.
39
+ */
40
+ gap?: number;
41
+
42
+ /**
43
+ * The delay before the tooltip appears in milliseconds. Defaults to 0.
44
+ */
45
+ enterDelay?: number;
46
+
47
+ /**
48
+ * The delay before the tooltip disappears in milliseconds. Defaults to 0.
49
+ */
50
+ exitDelay?: number;
51
+
52
+ /**
53
+ * Whether the tooltip should be hover only. Defaults to false.
54
+ *
55
+ * By default, the tooltip will show on mouse hover and click (for mobile support).
56
+ */
57
+ hoverOnly?: boolean;
58
+
59
+ /**
60
+ * Whether the tooltip should animate a fade in and out. Defaults to true.
61
+ */
62
+ animate?: boolean;
63
+
64
+ /**
65
+ * Render a triangle pointer on the tooltip. Defaults to true.
66
+ */
67
+ pointer?: boolean;
68
+ }
69
+
70
+ const {
71
+ position = 'auto',
72
+ defaultOpen = false,
73
+ inline = false,
74
+ variant = 'default',
75
+ color = 'default',
76
+ gap = 8,
77
+ enterDelay = 0,
78
+ exitDelay = 0,
79
+ hoverOnly = false,
80
+ animate = true,
81
+ pointer = true,
82
+ ...others
83
+ } = Astro.props;
84
+ ---
85
+
86
+ <div
87
+ class:list={["sui-tooltip-container", inline && "inline"]}
88
+ data-sui-tooltip
89
+ data-sui-tooltip-options={JSON.stringify({
90
+ position,
91
+ defaultOpen,
92
+ gap,
93
+ enterDelay,
94
+ exitDelay,
95
+ hoverOnly,
96
+ animate,
97
+ pointer,
98
+ })}
99
+ {...others}
100
+ >
101
+ <div class="sui-tooltip-anchor-wrapper" data-sui-tooltip-anchor>
102
+ <slot />
103
+ </div>
104
+ <div
105
+ class={`sui-tooltip-popup color-${color} variant-${variant}`}
106
+ class:list={[animate && "animate"]}
107
+ data-sui-tooltip-popup
108
+ role="tooltip"
109
+ >
110
+ {pointer && <div class="sui-tooltip-pointer" />}
111
+ <slot name="tooltip">
112
+ <p>Warning: slot 'tooltip' was not found</p>
113
+ </slot>
114
+ </div>
115
+ </div>
116
+
117
+ <script>
118
+ import "studiocms:ui/scripts/tooltip";
119
+ </script>