@eunomia/elements 1.0.0-beta.7 → 1.0.0-beta.8

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 (177) hide show
  1. package/dist/cdn/components/chunks/{chunk-3PNGQEG4.js → chunk-32L2QYWQ.js} +2 -2
  2. package/dist/cdn/components/chunks/{chunk-Z3OFIE7S.js → chunk-3UUZM7X2.js} +1 -1
  3. package/dist/cdn/components/chunks/{chunk-BVASCT2V.js → chunk-55PUDL7D.js} +13 -13
  4. package/dist/cdn/components/chunks/chunk-5LA5DQMP.js +1 -0
  5. package/dist/cdn/components/chunks/chunk-5LXGJVJR.js +1 -0
  6. package/dist/cdn/components/chunks/chunk-6TIEBY34.js +1 -0
  7. package/dist/cdn/components/chunks/{chunk-LVKMAHMU.js → chunk-AH2SKZ7T.js} +4 -1
  8. package/dist/cdn/components/chunks/chunk-JAGZL7JH.js +1 -0
  9. package/dist/cdn/components/chunks/{chunk-DGI7TKCU.js → chunk-LD35BFNK.js} +5 -9
  10. package/dist/cdn/components/chunks/chunk-P6LGU3FT.js +1 -0
  11. package/dist/cdn/components/chunks/{chunk-UYZR4JXZ.js → chunk-QSZO4GIH.js} +45 -9
  12. package/dist/cdn/components/chunks/{chunk-PXF554MD.js → chunk-QYB6Z6FG.js} +5 -5
  13. package/dist/cdn/components/chunks/{chunk-RIFF2D2F.js → chunk-RGC3I6MK.js} +1 -1
  14. package/dist/cdn/components/chunks/{chunk-N6ZW5CDN.js → chunk-TCSB2MLU.js} +1 -1
  15. package/dist/cdn/components/chunks/chunk-WIUERJII.js +1 -0
  16. package/dist/cdn/components/eun-animate.js +4 -4
  17. package/dist/cdn/components/eun-button.js +1 -1
  18. package/dist/cdn/components/eun-carousel.js +10 -9
  19. package/dist/cdn/components/eun-chip.js +17 -11
  20. package/dist/cdn/components/eun-collapse.js +1 -1
  21. package/dist/cdn/components/eun-color-picker.js +18 -5
  22. package/dist/cdn/components/eun-counter.js +10 -8
  23. package/dist/cdn/components/eun-date-picker.js +46 -43
  24. package/dist/cdn/components/eun-drawer.js +19 -20
  25. package/dist/cdn/components/eun-dropdown-button.js +1 -1
  26. package/dist/cdn/components/eun-dropdown-item.js +3 -3
  27. package/dist/cdn/components/eun-fab.js +1 -1
  28. package/dist/cdn/components/eun-image-carousel.js +4 -4
  29. package/dist/cdn/components/eun-input-phone.js +11 -8
  30. package/dist/cdn/components/eun-input.js +1 -1
  31. package/dist/cdn/components/eun-link.js +59 -13
  32. package/dist/cdn/components/eun-modal.js +23 -13
  33. package/dist/cdn/components/eun-scheduler-event-editor.js +1 -1
  34. package/dist/cdn/components/eun-search.js +34 -28
  35. package/dist/cdn/components/eun-select.js +3 -3
  36. package/dist/cdn/components/eun-sidebar.js +66 -21
  37. package/dist/cdn/components/eun-sliding-card.js +1 -1
  38. package/dist/cdn/components/eun-stepper.js +16 -16
  39. package/dist/cdn/components/eun-tab-panel.js +1 -1
  40. package/dist/cdn/components/eun-table-action-bar.js +1 -1
  41. package/dist/cdn/components/eun-table.js +2 -2
  42. package/dist/cdn/components/eun-textarea.js +16 -13
  43. package/dist/cdn/components/eun-time-picker.js +25 -23
  44. package/dist/cdn/components/eun-toast.js +8 -8
  45. package/dist/cdn/components/eun-toggle-group.js +71 -35
  46. package/dist/cdn/components/eun-toggle-item.js +8 -8
  47. package/dist/cdn/components/eun-toolbar.js +20 -20
  48. package/dist/cdn/components/eun-tooltip.js +6 -6
  49. package/dist/cdn/styles/eunomia-themes.css +1 -1
  50. package/dist/cdn/styles/themes/mixins/eunomia-neutrals.mixin.scss +6 -2
  51. package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +6 -2
  52. package/dist/cdn/styles/themes/prebuilt-themes/eunomia/eunomia.theme.css +1 -1
  53. package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +6 -2
  54. package/dist/cdn/styles/themes/prebuilt-themes/fire/eunomia-fire.theme.css +1 -1
  55. package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +6 -2
  56. package/dist/cdn/styles/themes/prebuilt-themes/forest/eunomia-forest.theme.css +1 -1
  57. package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +6 -2
  58. package/dist/cdn/styles/themes/prebuilt-themes/gold/eunomia-gold.theme.css +1 -1
  59. package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +6 -2
  60. package/dist/cdn/styles/themes/prebuilt-themes/ocean/eunomia-ocean.theme.css +1 -1
  61. package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +6 -2
  62. package/dist/cdn/styles/themes/prebuilt-themes/salmon/eunomia-salmon.theme.css +1 -1
  63. package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +6 -2
  64. package/dist/cdn/styles/themes/prebuilt-themes/violet/eunomia-violet.theme.css +1 -1
  65. package/dist/components/action/button/button.d.ts +2 -2
  66. package/dist/components/action/button/button.js +3 -7
  67. package/dist/components/action/button/button.styles.js +3 -3
  68. package/dist/components/action/dropdown-button/dropdown-button.d.ts +4 -6
  69. package/dist/components/action/dropdown-button/dropdown-button.js +6 -8
  70. package/dist/components/action/dropdown-button/dropdown-item.d.ts +10 -2
  71. package/dist/components/action/dropdown-button/dropdown-item.js +24 -9
  72. package/dist/components/action/link/link.d.ts +10 -1
  73. package/dist/components/action/link/link.js +13 -1
  74. package/dist/components/action/link/link.styles.js +50 -3
  75. package/dist/components/action/toggle/toggle-group.d.ts +12 -2
  76. package/dist/components/action/toggle/toggle-group.js +17 -2
  77. package/dist/components/action/toggle/toggle-group.styles.js +54 -18
  78. package/dist/components/action/toggle/toggle-item.js +1 -3
  79. package/dist/components/action/toggle/toggle-item.styles.js +7 -7
  80. package/dist/components/alert/drawer/drawer.d.ts +25 -0
  81. package/dist/components/alert/drawer/drawer.js +42 -3
  82. package/dist/components/alert/drawer/drawer.styles.js +6 -6
  83. package/dist/components/alert/modal/modal.d.ts +25 -0
  84. package/dist/components/alert/modal/modal.js +42 -3
  85. package/dist/components/alert/modal/modal.styles.js +17 -6
  86. package/dist/components/alert/toast/toast.js +3 -2
  87. package/dist/components/alert/toast/toast.styles.js +3 -3
  88. package/dist/components/content/chip/chip.js +3 -2
  89. package/dist/components/content/chip/chip.styles.js +9 -3
  90. package/dist/components/content/image-carousel/image-carousel.js +5 -4
  91. package/dist/components/content/tooltip/tooltip.d.ts +16 -9
  92. package/dist/components/content/tooltip/tooltip.js +28 -12
  93. package/dist/components/content/tooltip/tooltip.styles.js +1 -1
  94. package/dist/components/form/color-picker/color-picker.d.ts +7 -1
  95. package/dist/components/form/color-picker/color-picker.js +8 -2
  96. package/dist/components/form/color-picker/color-picker.styles.js +13 -0
  97. package/dist/components/form/counter/counter.d.ts +3 -1
  98. package/dist/components/form/counter/counter.js +3 -1
  99. package/dist/components/form/counter/counter.styles.js +6 -4
  100. package/dist/components/form/date-picker/date-picker.d.ts +6 -1
  101. package/dist/components/form/date-picker/date-picker.js +7 -2
  102. package/dist/components/form/date-picker/date-picker.styles.js +9 -6
  103. package/dist/components/form/input/input.d.ts +6 -1
  104. package/dist/components/form/input/input.js +7 -2
  105. package/dist/components/form/input-phone/input-phone.d.ts +7 -1
  106. package/dist/components/form/input-phone/input-phone.js +7 -1
  107. package/dist/components/form/input-phone/input-phone.styles.js +6 -3
  108. package/dist/components/form/search/search.d.ts +64 -10
  109. package/dist/components/form/search/search.js +112 -31
  110. package/dist/components/form/search/search.styles.js +2 -0
  111. package/dist/components/form/select/select.d.ts +7 -1
  112. package/dist/components/form/select/select.js +7 -1
  113. package/dist/components/form/shared-styles/field.styles.js +45 -8
  114. package/dist/components/form/shared-styles/listbox.styles.js +5 -1
  115. package/dist/components/form/textarea/textarea.d.ts +1 -0
  116. package/dist/components/form/textarea/textarea.js +2 -1
  117. package/dist/components/form/textarea/textarea.styles.js +3 -0
  118. package/dist/components/form/time-picker/time-picker.d.ts +6 -1
  119. package/dist/components/form/time-picker/time-picker.js +7 -2
  120. package/dist/components/form/time-picker/time-picker.styles.js +7 -5
  121. package/dist/components/layout/animate/animate.js +2 -1
  122. package/dist/components/navigation/carousel/carousel.d.ts +1 -2
  123. package/dist/components/navigation/carousel/carousel.js +14 -6
  124. package/dist/components/navigation/carousel/carousel.styles.js +5 -4
  125. package/dist/components/navigation/sidebar/sidebar.d.ts +98 -52
  126. package/dist/components/navigation/sidebar/sidebar.js +140 -85
  127. package/dist/components/navigation/sidebar/sidebar.styles.d.ts +1 -1
  128. package/dist/components/navigation/sidebar/sidebar.styles.js +69 -21
  129. package/dist/components/navigation/stepper/stepper.d.ts +1 -3
  130. package/dist/components/navigation/stepper/stepper.js +3 -21
  131. package/dist/components/navigation/toolbar/toolbar.d.ts +10 -0
  132. package/dist/components/navigation/toolbar/toolbar.js +8 -1
  133. package/dist/components/navigation/toolbar/toolbar.styles.js +18 -17
  134. package/dist/events/select.event.d.ts +3 -2
  135. package/dist/events/select.event.js +2 -1
  136. package/dist/features/scheduler/scheduler-event-editor/scheduler-event-editor.js +1 -1
  137. package/dist/features/table/table/table.js +1 -1
  138. package/dist/features/table/table-action-bar/table-action-bar.js +2 -2
  139. package/dist/index.d.ts +1 -0
  140. package/dist/mixins/button.mixin.d.ts +1 -1
  141. package/dist/mixins/button.mixin.js +6 -4
  142. package/dist/mixins/dialog-surface.mixin.d.ts +8 -0
  143. package/dist/mixins/field-size.mixin.d.ts +19 -0
  144. package/dist/mixins/field-size.mixin.js +33 -0
  145. package/dist/mixins/rounded.mixin.d.ts +18 -0
  146. package/dist/mixins/rounded.mixin.js +32 -0
  147. package/dist/ssr/button-ssr.css +5 -5
  148. package/dist/ssr/carousel-ssr.css +9 -0
  149. package/dist/ssr/chip-ssr.css +8 -0
  150. package/dist/ssr/collapse-ssr.css +29 -0
  151. package/dist/ssr/field-ssr.css +43 -4
  152. package/dist/ssr/image-carousel-ssr.css +10 -0
  153. package/dist/ssr/links-ssr.css +38 -1
  154. package/dist/ssr/sidebar-ssr.css +95 -4
  155. package/dist/ssr/toggle-group-ssr.css +64 -13
  156. package/dist/ssr/toolbar-ssr.css +50 -0
  157. package/dist/types/variant.type.d.ts +4 -1
  158. package/dist/utils/boolean.utils.d.ts +14 -0
  159. package/dist/utils/boolean.utils.js +20 -0
  160. package/dist/utils/dropdown-menu.utils.d.ts +1 -1
  161. package/dist/utils/focusable-elements.utils.d.ts +12 -0
  162. package/dist/utils/focusable-elements.utils.js +26 -0
  163. package/dist/utils/input-modality.utils.d.ts +13 -0
  164. package/dist/utils/input-modality.utils.js +34 -0
  165. package/dist/utils/theme-generator.utils.d.ts +8 -2
  166. package/dist/utils/theme-generator.utils.js +30 -9
  167. package/package.json +1 -1
  168. package/styles/themes/mixins/eunomia-neutrals.mixin.scss +6 -2
  169. package/styles/themes/prebuilt-themes/eunomia/eunomia-dark.mixin.scss +6 -2
  170. package/styles/themes/prebuilt-themes/fire/eunomia-fire-dark.mixin.scss +6 -2
  171. package/styles/themes/prebuilt-themes/forest/eunomia-forest-dark.mixin.scss +6 -2
  172. package/styles/themes/prebuilt-themes/gold/eunomia-gold-dark.mixin.scss +6 -2
  173. package/styles/themes/prebuilt-themes/ocean/eunomia-ocean-dark.mixin.scss +6 -2
  174. package/styles/themes/prebuilt-themes/salmon/eunomia-salmon-dark.mixin.scss +6 -2
  175. package/styles/themes/prebuilt-themes/violet/eunomia-violet-dark.mixin.scss +6 -2
  176. package/dist/cdn/components/chunks/chunk-6VK6SHCG.js +0 -1
  177. package/dist/cdn/components/chunks/chunk-UDOZRIJZ.js +0 -1
@@ -1,7 +1,44 @@
1
- /* Once upgraded, a link wraps as one piece, never inside its text. */
2
1
  eun-link:not(:defined) {
3
2
  display: inline-flex;
4
3
  align-items: center;
4
+ gap: var(--eun-space-s, 8px);
5
+ padding: var(
6
+ --link-padding,
7
+ var(--link-padding-block, 0) var(--link-padding-inline, 0)
8
+ );
9
+ color: var(--link-color, var(--eun-text-color, #071621));
10
+ }
11
+
12
+ eun-link[theme="dark"]:not(:defined) {
13
+ color: var(
14
+ --link-color,
15
+ var(--eun-text-on-inverse-secondary, rgba(255, 255, 255, 0.7))
16
+ );
17
+ }
18
+
19
+ eun-link[current]:not(:defined) {
20
+ color: var(--link-color-current, var(--eun-color-primary-500, #3d6fff));
21
+ }
22
+
23
+ eun-link:not(:defined) > [slot="icon"] {
24
+ display: inline-flex;
25
+ flex-shrink: 0;
26
+ color: var(--link-icon-color, inherit);
27
+ font-size: var(--link-icon-size, inherit);
28
+ }
29
+
30
+ eun-link[block]:not(:defined) {
31
+ display: flex;
32
+ width: 100%;
33
+ min-width: 0;
34
+ white-space: nowrap;
35
+ }
36
+
37
+ eun-link[block]:not(:defined) > a {
38
+ min-width: 0;
39
+ overflow: hidden;
40
+ text-overflow: ellipsis;
41
+ white-space: nowrap;
5
42
  }
6
43
 
7
44
  :where(:is(eun-link, eun-button, eun-card):not(:defined) > a) {
@@ -1,5 +1,6 @@
1
1
  eun-sidebar:not(:defined) {
2
2
  display: flex;
3
+ flex-direction: column;
3
4
  position: sticky;
4
5
  top: 0;
5
6
  flex-shrink: 0;
@@ -7,12 +8,47 @@ eun-sidebar:not(:defined) {
7
8
  box-sizing: border-box;
8
9
  overflow: hidden;
9
10
  width: var(--sidebar-width, 280px);
10
- border-inline-end: var(--eun-border-width-s, 1px) solid transparent;
11
+ padding-block: var(--sidebar-gap, var(--eun-space-m, 16px));
12
+ padding-inline: var(
13
+ --sidebar-padding,
14
+ var(--sidebar-padding-inline, var(--eun-space-m, 16px))
15
+ );
16
+ background: var(--sidebar-background, var(--eun-surface-color, #ffffff));
17
+ color: var(--sidebar-color, var(--eun-text-color, #071621));
18
+ font-family: var(--eun-font-family, "Mulish", sans-serif);
19
+ font-size: var(--eun-font-size-s, 14px);
20
+ border-inline-end: var(--eun-border-width-s, 1px) solid
21
+ var(--sidebar-border-color, var(--eun-border-color, #dee0e7));
22
+ }
23
+
24
+ eun-sidebar[theme="dark"]:not(:defined) {
25
+ background: var(--sidebar-background, var(--eun-surface-inverse, #0b1620));
26
+ color: var(--sidebar-color, var(--eun-text-on-inverse, #f5f7fa));
27
+ border-color: var(
28
+ --sidebar-border-color,
29
+ color-mix(
30
+ in srgb,
31
+ var(--sidebar-color, var(--eun-text-on-inverse, #f5f7fa)) 16%,
32
+ transparent
33
+ )
34
+ );
11
35
  }
12
36
 
13
37
  eun-sidebar[position="end"]:not(:defined) {
14
38
  border-inline-end: none;
15
- border-inline-start: var(--eun-border-width-s, 1px) solid transparent;
39
+ border-inline-start: var(--eun-border-width-s, 1px) solid
40
+ var(--sidebar-border-color, var(--eun-border-color, #dee0e7));
41
+ }
42
+
43
+ eun-sidebar[theme="dark"][position="end"]:not(:defined) {
44
+ border-inline-start-color: var(
45
+ --sidebar-border-color,
46
+ color-mix(
47
+ in srgb,
48
+ var(--sidebar-color, var(--eun-text-on-inverse, #f5f7fa)) 16%,
49
+ transparent
50
+ )
51
+ );
16
52
  }
17
53
 
18
54
  eun-sidebar[collapsed]:is([collapse-mode="mini"], :not([collapse-mode])):not(
@@ -21,7 +57,62 @@ eun-sidebar[collapsed]:is([collapse-mode="mini"], :not([collapse-mode])):not(
21
57
  width: var(--sidebar-mini-width, 64px);
22
58
  }
23
59
 
24
- eun-sidebar[collapsed][collapse-mode="hidden"]:not(:defined),
25
- eun-sidebar[dragged-hidden]:not(:defined) {
60
+ eun-sidebar[collapsed][collapse-mode="hidden"]:not(:defined) {
26
61
  width: 0px;
62
+ padding: 0;
63
+ border-color: transparent;
64
+ }
65
+
66
+ eun-sidebar:not(:defined):has(> [slot="header"]) {
67
+ padding-block-start: var(
68
+ --sidebar-padding,
69
+ var(--sidebar-padding-block, var(--eun-space-m, 16px))
70
+ );
71
+ }
72
+
73
+ eun-sidebar:not(:defined):has(> [slot="footer"]) {
74
+ padding-block-end: var(
75
+ --sidebar-padding,
76
+ var(--sidebar-padding-block, var(--eun-space-m, 16px))
77
+ );
78
+ }
79
+
80
+ eun-sidebar:not(:defined) > [slot="header"] {
81
+ order: -1;
82
+ }
83
+
84
+ eun-sidebar:not(:defined) > :nth-last-child(1 of [slot="header"]) {
85
+ margin-block-end: var(--sidebar-gap, var(--eun-space-m, 16px));
86
+ }
87
+
88
+ eun-sidebar:not(:defined) > [slot="footer"] {
89
+ order: 1;
90
+ }
91
+
92
+ eun-sidebar:not(:defined) > :nth-child(1 of [slot="footer"]) {
93
+ margin-block-start: auto;
94
+ }
95
+
96
+ @media (width < 600px) {
97
+ eun-sidebar[hide-below="mobile"] {
98
+ display: none;
99
+ }
100
+ }
101
+
102
+ @media (width < 768px) {
103
+ eun-sidebar[hide-below="tablet"] {
104
+ display: none;
105
+ }
106
+ }
107
+
108
+ @media (width < 1024px) {
109
+ eun-sidebar[hide-below="laptop"] {
110
+ display: none;
111
+ }
112
+ }
113
+
114
+ @media (width < 1280px) {
115
+ eun-sidebar[hide-below="desktop"] {
116
+ display: none;
117
+ }
27
118
  }
@@ -1,16 +1,32 @@
1
1
  eun-toggle-group:not(:defined) {
2
+ --_toggleRadius: var(
3
+ --toggle-group-border-radius,
4
+ var(--eun-border-radius-m, 8px)
5
+ );
6
+ --_toggleFontSize: var(--eun-font-size-s, 14px);
7
+ --_toggleButtonPaddingBlock: var(--eun-space-s, 8px);
8
+ --_toggleOptionPaddingInline: calc(var(--eun-space-l, 32px) / 2);
9
+ --_toggleLineHeight: 1rem;
10
+ --_trackPaddingBlock: var(
11
+ --toggle-group-padding,
12
+ var(
13
+ --toggle-group-padding-block,
14
+ calc(var(--_toggleButtonPaddingBlock) / 2)
15
+ )
16
+ );
17
+ --_toggleOptionPaddingBlock: max(
18
+ 0px,
19
+ calc(var(--_toggleButtonPaddingBlock) - var(--_trackPaddingBlock))
20
+ );
2
21
  display: inline-flex;
3
22
  box-sizing: border-box;
4
23
  width: fit-content;
5
24
  max-width: 100%;
6
25
  gap: var(--toggle-group-gap, var(--eun-space-xs, 4px));
7
- padding: var(--toggle-group-padding, var(--toggle-group-padding-block, 4px))
26
+ padding: var(--_trackPaddingBlock)
8
27
  var(--toggle-group-padding, var(--toggle-group-padding-inline, 4px));
9
28
  overflow: hidden;
10
- border-radius: var(
11
- --toggle-group-border-radius,
12
- var(--eun-border-radius-m, 8px)
13
- );
29
+ border-radius: var(--_toggleRadius);
14
30
  background: var(
15
31
  --toggle-group-background,
16
32
  var(--eun-surface-sunken, #f7f8fa)
@@ -19,10 +35,46 @@ eun-toggle-group:not(:defined) {
19
35
  var(--toggle-group-border-color, var(--eun-color-grey-300, #dee0e7));
20
36
  box-shadow: var(--toggle-group-box-shadow, none);
21
37
  font-family: var(--eun-font-family, "Mulish", sans-serif);
22
- font-size: var(--eun-font-size-s, 14px);
38
+ font-size: var(--_toggleFontSize);
39
+ }
40
+
41
+ eun-toggle-group[rounded]:not(:defined) {
42
+ --_toggleRadius: var(
43
+ --toggle-group-border-radius,
44
+ var(--eun-border-radius-xl, 999px)
45
+ );
46
+ }
47
+
48
+ eun-toggle-group[size="xs"]:not(:defined) {
49
+ --_toggleFontSize: var(--eun-font-size-xs, 10px);
50
+ --_toggleButtonPaddingBlock: var(--eun-space-xxs, 1.6px);
51
+ --_toggleOptionPaddingInline: var(--eun-space-xs, 4px);
52
+ --_toggleLineHeight: 10px;
53
+ }
54
+
55
+ eun-toggle-group[size="s"]:not(:defined) {
56
+ --_toggleFontSize: var(--eun-font-size-xs, 10px);
57
+ --_toggleButtonPaddingBlock: calc(var(--eun-space-s, 8px) / 2);
58
+ --_toggleOptionPaddingInline: var(--eun-space-s, 8px);
59
+ --_toggleLineHeight: 10px;
60
+ }
61
+
62
+ eun-toggle-group[size="l"]:not(:defined) {
63
+ --_toggleFontSize: var(--eun-font-size-m, 16px);
64
+ --_toggleButtonPaddingBlock: calc(var(--eun-space-s, 8px) * 1.25);
65
+ --_toggleOptionPaddingInline: calc(var(--eun-space-m, 16px) * 1.25);
66
+ --_toggleLineHeight: 1.1rem;
67
+ }
68
+
69
+ eun-toggle-group[size="xl"]:not(:defined) {
70
+ --_toggleFontSize: var(--eun-font-size-l, 1.3rem);
71
+ --_toggleButtonPaddingBlock: calc(var(--eun-space-s, 8px) * 1.5);
72
+ --_toggleOptionPaddingInline: calc(var(--eun-space-m, 16px) * 1.5);
73
+ --_toggleLineHeight: 1.3rem;
23
74
  }
24
75
 
25
76
  eun-toggle-group:is([appearance="outline"], [appearance="flat"]):not(:defined) {
77
+ --_toggleOptionPaddingBlock: var(--_toggleButtonPaddingBlock);
26
78
  padding: 0;
27
79
  overflow: visible;
28
80
  background: var(--toggle-group-background, transparent);
@@ -45,13 +97,15 @@ eun-toggle-item:not(:defined) {
45
97
  align-items: center;
46
98
  gap: var(--eun-space-xs, 4px);
47
99
  box-sizing: border-box;
48
- padding: 6px 14px;
100
+ padding: var(--_toggleOptionPaddingBlock, calc(var(--eun-space-s, 8px) / 2))
101
+ var(--_toggleOptionPaddingInline, calc(var(--eun-space-l, 32px) / 2));
49
102
  border-radius: calc(
50
- var(--toggle-group-border-radius, var(--eun-border-radius-m, 8px)) - 3px
103
+ var(--_toggleRadius, var(--eun-border-radius-m, 8px)) - 3px
51
104
  );
52
105
  color: var(--toggle-group-color, var(--eun-color-grey-600, #666e8a));
53
106
  font-family: var(--eun-font-family, "Mulish", sans-serif);
54
- font-size: var(--eun-font-size-s, 14px);
107
+ font-size: var(--_toggleFontSize, var(--eun-font-size-s, 14px));
108
+ line-height: var(--_toggleLineHeight, 1rem);
55
109
  font-weight: var(--eun-font-weight-m, 500);
56
110
  white-space: nowrap;
57
111
  --_customTint: color-mix(
@@ -72,10 +126,7 @@ eun-toggle-item:not(:defined) > [slot="icon"] {
72
126
  ):not(:defined) {
73
127
  border: var(--eun-border-width-s, 1px) solid
74
128
  var(--toggle-group-border-color, transparent);
75
- border-radius: var(
76
- --toggle-group-border-radius,
77
- var(--eun-border-radius-m, 8px)
78
- );
129
+ border-radius: var(--_toggleRadius, var(--eun-border-radius-m, 8px));
79
130
  }
80
131
 
81
132
  :is(
@@ -106,3 +106,53 @@ eun-toolbar:not(:defined):where(
106
106
  align-items: center;
107
107
  justify-content: flex-end;
108
108
  }
109
+
110
+ @media (width < 600px) {
111
+ eun-toolbar[mobile-breakpoint="600"][mobile-hide~="start"]:not(:defined)
112
+ > [slot="start"],
113
+ eun-toolbar[mobile-breakpoint="600"][mobile-hide~="center"]:not(:defined)
114
+ > [slot="center"],
115
+ eun-toolbar[mobile-breakpoint="600"][mobile-hide~="end"]:not(:defined)
116
+ > [slot="end"] {
117
+ display: none;
118
+ }
119
+ }
120
+
121
+ @media (width < 768px) {
122
+ eun-toolbar:not([mobile-breakpoint])[mobile-hide~="start"]:not(:defined)
123
+ > [slot="start"],
124
+ eun-toolbar:not([mobile-breakpoint])[mobile-hide~="center"]:not(:defined)
125
+ > [slot="center"],
126
+ eun-toolbar:not([mobile-breakpoint])[mobile-hide~="end"]:not(:defined)
127
+ > [slot="end"],
128
+ eun-toolbar[mobile-breakpoint="768"][mobile-hide~="start"]:not(:defined)
129
+ > [slot="start"],
130
+ eun-toolbar[mobile-breakpoint="768"][mobile-hide~="center"]:not(:defined)
131
+ > [slot="center"],
132
+ eun-toolbar[mobile-breakpoint="768"][mobile-hide~="end"]:not(:defined)
133
+ > [slot="end"] {
134
+ display: none;
135
+ }
136
+ }
137
+
138
+ @media (width < 1024px) {
139
+ eun-toolbar[mobile-breakpoint="1024"][mobile-hide~="start"]:not(:defined)
140
+ > [slot="start"],
141
+ eun-toolbar[mobile-breakpoint="1024"][mobile-hide~="center"]:not(:defined)
142
+ > [slot="center"],
143
+ eun-toolbar[mobile-breakpoint="1024"][mobile-hide~="end"]:not(:defined)
144
+ > [slot="end"] {
145
+ display: none;
146
+ }
147
+ }
148
+
149
+ @media (width < 1280px) {
150
+ eun-toolbar[mobile-breakpoint="1280"][mobile-hide~="start"]:not(:defined)
151
+ > [slot="start"],
152
+ eun-toolbar[mobile-breakpoint="1280"][mobile-hide~="center"]:not(:defined)
153
+ > [slot="center"],
154
+ eun-toolbar[mobile-breakpoint="1280"][mobile-hide~="end"]:not(:defined)
155
+ > [slot="end"] {
156
+ display: none;
157
+ }
158
+ }
@@ -55,6 +55,9 @@ export type EunomiaModalConfirmColor = Extract<EunomiaActionColor, "primary" | "
55
55
  * (elevated, drop shadow) doesn't share that constraint : it's a static
56
56
  * effect, not one gated behind interaction, so `eun-card` also exposes it
57
57
  * (see {@link EunomiaCardAppearance}) despite being a passive container.
58
+ * Button-family components spell that pale tinted wash `soft` instead of
59
+ * `default`, since their own default is `fill` : `appearance="default"`
60
+ * on a button would otherwise not render the default.
58
61
  * `underline` (a bottom border only) is a form field's own look, and
59
62
  * `transparent` (the pale tint, see-through instead of opaque) a scheduler
60
63
  * event chip's : each belongs to a single family, like `ghost`.
@@ -64,7 +67,7 @@ export type EunomiaModalConfirmColor = Extract<EunomiaActionColor, "primary" | "
64
67
  * (a loader's dots or bar, a skeleton's shape) is a `variant` instead,
65
68
  * with values of its own that mean nothing outside that component.
66
69
  */
67
- export type EunomiaAppearance = "default" | "fill" | "outline" | "flat" | "raised" | "ghost" | "underline" | "transparent";
70
+ export type EunomiaAppearance = "default" | "soft" | "fill" | "outline" | "flat" | "raised" | "ghost" | "underline" | "transparent";
68
71
  /**
69
72
  * The four-value {@link EunomiaAppearance} subset feedback/display components
70
73
  * (alert, toast, chip, tag, tooltip) actually use — no `raised`/`ghost`,
@@ -0,0 +1,14 @@
1
+ import type { ComplexAttributeConverter } from "lit";
2
+ /**
3
+ * Converter for the boolean attributes that default to `true`. Lit's
4
+ * standard boolean converter only looks at the attribute's presence, the
5
+ * same way native HTML boolean attributes work, so `closeable="false"`
6
+ * would still read as `true`, and nothing declarative (HTML, SSR, JSX)
7
+ * could turn these off. Here the literal `"false"` really means `false`.
8
+ *
9
+ * When reflected, `true` writes an empty attribute and `false` writes
10
+ * `"false"`, rather than removing it : a missing attribute would read back
11
+ * as the `true` default on the next upgrade (SSR output, `cloneNode`), and
12
+ * stylesheets can target the off state with `[attr="false"]`.
13
+ */
14
+ export declare const defaultTrueConverter: ComplexAttributeConverter<boolean>;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Converter for the boolean attributes that default to `true`. Lit's
3
+ * standard boolean converter only looks at the attribute's presence, the
4
+ * same way native HTML boolean attributes work, so `closeable="false"`
5
+ * would still read as `true`, and nothing declarative (HTML, SSR, JSX)
6
+ * could turn these off. Here the literal `"false"` really means `false`.
7
+ *
8
+ * When reflected, `true` writes an empty attribute and `false` writes
9
+ * `"false"`, rather than removing it : a missing attribute would read back
10
+ * as the `true` default on the next upgrade (SSR output, `cloneNode`), and
11
+ * stylesheets can target the off state with `[attr="false"]`.
12
+ */
13
+ export const defaultTrueConverter = {
14
+ fromAttribute(value) {
15
+ return value !== null && value !== "false";
16
+ },
17
+ toAttribute(value) {
18
+ return value ? "" : "false";
19
+ },
20
+ };
@@ -38,7 +38,7 @@ export interface DropdownMenuContainer extends HTMLElement {
38
38
  * an open submenu without knowing its concrete class.
39
39
  */
40
40
  export interface DropdownMenuEntry extends HTMLElement {
41
- readonly key: string;
41
+ readonly value: string;
42
42
  closeSubmenu(): void;
43
43
  repositionSubmenu(): void;
44
44
  }
@@ -36,6 +36,18 @@ export interface FocusableElementsOptions {
36
36
  * @returns every focusable descendant, in traversal order.
37
37
  */
38
38
  export declare function getFocusableElements(root: Element | ShadowRoot, options?: FocusableElementsOptions): HTMLElement[];
39
+ /**
40
+ * The element that actually receives focus for `element` : `element`
41
+ * itself when it's a tab stop, otherwise its first focusable descendant
42
+ * (crossing slots and nested shadow roots, see {@link walkFlatTree}), e.g.
43
+ * the `<a>` slotted into an `eun-link` or the native control rendered
44
+ * inside a component's shadow root. Falls back to `element` when nothing
45
+ * inside it is focusable. Rendering isn't required, so a visually hidden
46
+ * (`sr-only`) control still counts.
47
+ *
48
+ * @param element the element to resolve.
49
+ */
50
+ export declare function resolveFocusTarget(element: HTMLElement): HTMLElement;
39
51
  /**
40
52
  * Whether `root` has *any* focusable descendant (see {@link
41
53
  * walkFlatTree}), stopping at the first match rather than collecting them
@@ -106,6 +106,32 @@ export function getFocusableElements(root, options = {}) {
106
106
  });
107
107
  return results;
108
108
  }
109
+ /**
110
+ * The element that actually receives focus for `element` : `element`
111
+ * itself when it's a tab stop, otherwise its first focusable descendant
112
+ * (crossing slots and nested shadow roots, see {@link walkFlatTree}), e.g.
113
+ * the `<a>` slotted into an `eun-link` or the native control rendered
114
+ * inside a component's shadow root. Falls back to `element` when nothing
115
+ * inside it is focusable. Rendering isn't required, so a visually hidden
116
+ * (`sr-only`) control still counts.
117
+ *
118
+ * @param element the element to resolve.
119
+ */
120
+ export function resolveFocusTarget(element) {
121
+ const options = { requireRendered: false };
122
+ if (isFocusable(element, options)) {
123
+ return element;
124
+ }
125
+ let target;
126
+ walkFlatTree(element.shadowRoot ?? element, (descendant) => {
127
+ if (isFocusable(descendant, options)) {
128
+ target = descendant;
129
+ return true;
130
+ }
131
+ return false;
132
+ });
133
+ return target ?? element;
134
+ }
109
135
  /**
110
136
  * Whether `root` has *any* focusable descendant (see {@link
111
137
  * walkFlatTree}), stopping at the first match rather than collecting them
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Starts recording, once per page, whether the latest interaction came from
3
+ * the keyboard or a pointer. Listens in the capture phase, so a handler
4
+ * stopping propagation further down can't hide an interaction. Safe to call
5
+ * from every instance's `connectedCallback`, and a no-op outside a browser.
6
+ */
7
+ export declare function trackInputModality(): void;
8
+ /**
9
+ * Whether the latest interaction recorded by {@link trackInputModality}
10
+ * came from the keyboard. `false` before any interaction, so a surface
11
+ * opened by script on page load keeps its pointer behavior.
12
+ */
13
+ export declare function isKeyboardModality(): boolean;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Whether the user's latest interaction with the page came from the
3
+ * keyboard, as opposed to a mouse, pen, or touch.
4
+ */
5
+ let keyboardModality = false;
6
+ let tracking = false;
7
+ const handleKeydown = () => {
8
+ keyboardModality = true;
9
+ };
10
+ const handlePointerdown = () => {
11
+ keyboardModality = false;
12
+ };
13
+ /**
14
+ * Starts recording, once per page, whether the latest interaction came from
15
+ * the keyboard or a pointer. Listens in the capture phase, so a handler
16
+ * stopping propagation further down can't hide an interaction. Safe to call
17
+ * from every instance's `connectedCallback`, and a no-op outside a browser.
18
+ */
19
+ export function trackInputModality() {
20
+ if (tracking || typeof document === "undefined") {
21
+ return;
22
+ }
23
+ tracking = true;
24
+ document.addEventListener("keydown", handleKeydown, true);
25
+ document.addEventListener("pointerdown", handlePointerdown, true);
26
+ }
27
+ /**
28
+ * Whether the latest interaction recorded by {@link trackInputModality}
29
+ * came from the keyboard. `false` before any interaction, so a surface
30
+ * opened by script on page load keeps its pointer behavior.
31
+ */
32
+ export function isKeyboardModality() {
33
+ return keyboardModality;
34
+ }
@@ -41,8 +41,12 @@ export interface EunomiaThemeTints {
41
41
  * secondary seed separately, a full theme is two of these.
42
42
  */
43
43
  export declare function buildPalette(baseHex: EunomiaHexColor, isDark: boolean): EunomiaThemeShadeValue[];
44
- /** The `-tint` counterpart of the surface/border/content-hover/content-pressed neutral tokens. */
45
- export declare function buildTints(primaryHex: EunomiaHexColor, isDark: boolean): EunomiaThemeTints;
44
+ /**
45
+ * The `-tint` counterpart of the surface/border/content-hover/content-pressed
46
+ * neutral tokens. `borderColor` is the border the tint is mixed from, the
47
+ * mode's default border when unset.
48
+ */
49
+ export declare function buildTints(primaryHex: EunomiaHexColor, isDark: boolean, borderColor?: EunomiaHexColor): EunomiaThemeTints;
46
50
  /**
47
51
  * The one non-pure export in this file: generates and applies a full
48
52
  * custom brand from two hex seed colors by composing `buildPalette` and
@@ -75,6 +79,8 @@ export interface EunomiaThemeCssOptions {
75
79
  darkInverseSurfaceColor?: EunomiaHexColor;
76
80
  textColor?: EunomiaHexColor;
77
81
  darkTextColor?: EunomiaHexColor;
82
+ borderColor?: EunomiaHexColor;
83
+ darkBorderColor?: EunomiaHexColor;
78
84
  fontFamily?: string;
79
85
  brand?: string;
80
86
  }
@@ -179,13 +179,30 @@ const LIGHT_TINT_BASE = {
179
179
  contentHover: "#edeff0",
180
180
  contentPressed: "#e4e6e8",
181
181
  };
182
- const DARK_TINT_BASE = { surface: DARK_SURFACE, border: "#666e8a" };
183
- /** The `-tint` counterpart of the surface/border/content-hover/content-pressed neutral tokens. */
184
- export function buildTints(primaryHex, isDark) {
182
+ const DARK_TEXT = "#f7f8fa";
183
+ /**
184
+ * Share of the text mixed into the surface for the dark
185
+ * `--eun-border-color`, mirroring the prebuilt dark neutrals: about 1.4:1
186
+ * against the surface, as discreet as the light border.
187
+ */
188
+ const DARK_BORDER_RATIO = 0.12;
189
+ /**
190
+ * The dark `--eun-border-color` for a given surface and text color, the
191
+ * same mix the prebuilt dark neutrals compute in CSS.
192
+ */
193
+ function darkBorder(surface = DARK_SURFACE, text = DARK_TEXT) {
194
+ return mix(surface, text, DARK_BORDER_RATIO);
195
+ }
196
+ /**
197
+ * The `-tint` counterpart of the surface/border/content-hover/content-pressed
198
+ * neutral tokens. `borderColor` is the border the tint is mixed from, the
199
+ * mode's default border when unset.
200
+ */
201
+ export function buildTints(primaryHex, isDark, borderColor) {
185
202
  const primary500 = isDark ? darkAccessible(primaryHex) : primaryHex;
186
- const base = isDark ? DARK_TINT_BASE : LIGHT_TINT_BASE;
187
- const border = mix(base.border, primary500, TINT_RATIO);
188
- const surfaceTint = mix(base.surface, primary500, TINT_RATIO);
203
+ const baseBorder = borderColor ?? (isDark ? darkBorder() : LIGHT_TINT_BASE.border);
204
+ const border = mix(baseBorder, primary500, TINT_RATIO);
205
+ const surfaceTint = mix(isDark ? DARK_SURFACE : LIGHT_TINT_BASE.surface, primary500, TINT_RATIO);
189
206
  if (isDark) {
190
207
  const hoverBase = mix("#ffffff", primary500, TINT_RATIO);
191
208
  return {
@@ -227,7 +244,7 @@ function secondaryText(text, surface) {
227
244
  * so the inline and the stylesheet output can never drift apart.
228
245
  */
229
246
  function buildThemeTokens(primary, secondary, isDark, options) {
230
- const { surfaceColor, fontFamily, darkSecondaryColor, inverseSurfaceColor, textColor, } = options;
247
+ const { surfaceColor, fontFamily, darkSecondaryColor, inverseSurfaceColor, textColor, borderColor, } = options;
231
248
  const tokens = [];
232
249
  for (const [type, seed, checkDark] of [
233
250
  ["primary", primary, isDark],
@@ -258,7 +275,10 @@ function buildThemeTokens(primary, secondary, isDark, options) {
258
275
  if (fontFamily) {
259
276
  tokens.push(["--eun-font-family", fontFamily]);
260
277
  }
261
- const tints = buildTints(primary, isDark);
278
+ if (borderColor) {
279
+ tokens.push(["--eun-border-color", borderColor], ["--eun-divider-color", borderColor]);
280
+ }
281
+ const tints = buildTints(primary, isDark, borderColor ?? (isDark ? darkBorder(surfaceColor, textColor) : undefined));
262
282
  tokens.push(["--eun-surface-tint", tints.surfaceTint]);
263
283
  tokens.push(["--eun-border-tint", tints.borderTint]);
264
284
  tokens.push(["--eun-divider-tint", tints.dividerTint]);
@@ -311,7 +331,7 @@ export function initializeTheme(primary, secondary, isDark = false, surfaceColor
311
331
  * switching mode is just a `data-theme` change, no regeneration needed.
312
332
  */
313
333
  export function buildThemeCss(primary, secondary, options = {}) {
314
- const { surfaceColor = "#ffffff", darkSurfaceColor = DARK_SURFACE, darkSecondaryColor, inverseSurfaceColor, darkInverseSurfaceColor = inverseSurfaceColor, textColor, darkTextColor, fontFamily, brand = "custom", } = options;
334
+ const { surfaceColor = "#ffffff", darkSurfaceColor = DARK_SURFACE, darkSecondaryColor, inverseSurfaceColor, darkInverseSurfaceColor = inverseSurfaceColor, textColor, darkTextColor, borderColor, darkBorderColor, fontFamily, brand = "custom", } = options;
315
335
  const rule = (selector, isDark) => {
316
336
  const tokens = buildThemeTokens(primary, secondary, isDark, {
317
337
  surfaceColor: isDark ? darkSurfaceColor : surfaceColor,
@@ -321,6 +341,7 @@ export function buildThemeCss(primary, secondary, options = {}) {
321
341
  ? darkInverseSurfaceColor
322
342
  : inverseSurfaceColor,
323
343
  textColor: isDark ? darkTextColor : textColor,
344
+ borderColor: isDark ? darkBorderColor : borderColor,
324
345
  });
325
346
  if (isDark && textColor && !darkTextColor) {
326
347
  tokens.push(["--eun-text-color", "var(--eun-color-grey-800)"], ["--eun-text-secondary", "var(--eun-color-grey-700)"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eunomia/elements",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0-beta.8",
4
4
  "description": "Eunomia the framework-agnostic web component design system",
5
5
  "type": "module",
6
6
  "homepage": "https://eunomia-ds.vercel.app",
@@ -39,9 +39,13 @@
39
39
  @mixin eunomia-dark-neutrals {
40
40
  --eun-content-hover: rgba(255, 255, 255, 0.08);
41
41
  --eun-content-pressed: rgba(255, 255, 255, 0.14);
42
- --eun-divider-color: var(--eun-color-grey-300);
43
- --eun-border-color: var(--eun-color-grey-300);
44
42
  --eun-surface-color: var(--eun-color-grey-0);
43
+ --eun-border-color: color-mix(
44
+ in srgb,
45
+ var(--eun-text-color) 12%,
46
+ var(--eun-surface-color)
47
+ );
48
+ --eun-divider-color: var(--eun-border-color);
45
49
  --eun-surface-sunken: color-mix(
46
50
  in srgb,
47
51
  var(--eun-text-color) 8%,
@@ -63,8 +63,12 @@
63
63
  @include eunomia-dark-neutrals();
64
64
 
65
65
  --eun-surface-tint: #2a3243;
66
- --eun-divider-tint: #667090;
67
- --eun-border-tint: #667090;
66
+ --eun-border-tint: color-mix(
67
+ in srgb,
68
+ var(--eun-color-primary-500) 5%,
69
+ var(--eun-border-color)
70
+ );
71
+ --eun-divider-tint: var(--eun-border-tint);
68
72
  --eun-content-hover-tint: rgba(248, 250, 255, 0.08);
69
73
  --eun-content-pressed-tint: rgba(248, 250, 255, 0.14);
70
74
  }
@@ -63,8 +63,12 @@
63
63
  @include eunomia-dark-neutrals();
64
64
 
65
65
  --eun-surface-tint: #2f2e39;
66
- --eun-divider-tint: #6c6c86;
67
- --eun-border-tint: #6c6c86;
66
+ --eun-border-tint: color-mix(
67
+ in srgb,
68
+ var(--eun-color-primary-500) 5%,
69
+ var(--eun-border-color)
70
+ );
71
+ --eun-divider-tint: var(--eun-border-tint);
68
72
  --eun-content-hover-tint: rgba(253, 245, 245, 0.08);
69
73
  --eun-content-pressed-tint: rgba(253, 245, 245, 0.14);
70
74
  }