@milktop/react-ui 0.1.2 → 0.2.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 (142) hide show
  1. package/README.md +57 -6
  2. package/dist/accordion/Accordion.d.ts +1 -1
  3. package/dist/accordion/Accordion.js +1 -1
  4. package/dist/action-bar/ActionBar.d.ts +1 -1
  5. package/dist/action-bar/ActionBar.js +1 -1
  6. package/dist/alert/Alert.d.ts +1 -1
  7. package/dist/alert/Alert.js +1 -1
  8. package/dist/app-shell/AppShell.d.ts +9 -1
  9. package/dist/app-shell/AppShell.js +46 -5
  10. package/dist/app-shell/Topbar.d.ts +1 -1
  11. package/dist/app-shell/Topbar.js +1 -1
  12. package/dist/app-shell/app-shell.css +5 -0
  13. package/dist/app-shell/shell.d.ts +2 -0
  14. package/dist/appearance-panel/Appearance.d.ts +39 -0
  15. package/dist/appearance-panel/Appearance.js +74 -0
  16. package/dist/appearance-panel/appearance.css +17 -0
  17. package/dist/appearance.d.ts +42 -0
  18. package/dist/appearance.js +157 -0
  19. package/dist/attachments/Attachments.d.ts +1 -1
  20. package/dist/attachments/Attachments.js +1 -1
  21. package/dist/avatar/Avatar.d.ts +1 -1
  22. package/dist/avatar/Avatar.js +1 -1
  23. package/dist/badge/Badge.d.ts +1 -1
  24. package/dist/badge/Badge.js +1 -1
  25. package/dist/banner/Banner.d.ts +1 -1
  26. package/dist/banner/Banner.js +1 -1
  27. package/dist/breadcrumbs/Breadcrumbs.d.ts +1 -1
  28. package/dist/breadcrumbs/Breadcrumbs.js +1 -1
  29. package/dist/button/Button.d.ts +3 -2
  30. package/dist/button/Button.js +1 -1
  31. package/dist/card/Card.d.ts +2 -2
  32. package/dist/card/Card.js +1 -1
  33. package/dist/checkbox/Checkbox.d.ts +1 -1
  34. package/dist/checkbox/Checkbox.js +1 -1
  35. package/dist/checkbox/CheckboxGroup.d.ts +1 -1
  36. package/dist/checkbox/CheckboxGroup.js +1 -1
  37. package/dist/checkbox/checkbox.css +1 -1
  38. package/dist/collapsible/Collapsible.d.ts +1 -1
  39. package/dist/collapsible/Collapsible.js +1 -1
  40. package/dist/command/Command.d.ts +1 -1
  41. package/dist/command/Command.js +1 -1
  42. package/dist/copy-button/CopyButton.d.ts +1 -1
  43. package/dist/copy-button/CopyButton.js +1 -1
  44. package/dist/data-list/DataList.d.ts +1 -1
  45. package/dist/data-list/DataList.js +1 -1
  46. package/dist/date-picker/DatePicker.d.ts +1 -1
  47. package/dist/date-picker/DatePicker.js +1 -1
  48. package/dist/date-picker/date-picker.css +6 -3
  49. package/dist/dialog/Dialog.d.ts +1 -1
  50. package/dist/dialog/Dialog.js +1 -1
  51. package/dist/editable/Editable.d.ts +1 -1
  52. package/dist/editable/Editable.js +1 -1
  53. package/dist/editor/Editor.d.ts +1 -1
  54. package/dist/editor/Editor.js +1 -1
  55. package/dist/editor/editor.css +2 -1
  56. package/dist/empty-state/EmptyState.d.ts +1 -1
  57. package/dist/empty-state/EmptyState.js +1 -1
  58. package/dist/event-calendar/EventCalendar.d.ts +12 -5
  59. package/dist/event-calendar/EventCalendar.js +155 -41
  60. package/dist/event-calendar/event-calendar.css +10 -5
  61. package/dist/file-upload/FileUpload.d.ts +1 -1
  62. package/dist/file-upload/FileUpload.js +1 -1
  63. package/dist/format/messages.d.ts +12 -0
  64. package/dist/format/messages.js +12 -0
  65. package/dist/hover-card/hover-card.css +3 -1
  66. package/dist/icons.d.ts +1 -0
  67. package/dist/icons.js +7 -0
  68. package/dist/index.d.ts +2 -0
  69. package/dist/index.js +2 -0
  70. package/dist/input/Input.d.ts +1 -1
  71. package/dist/input/Input.js +1 -1
  72. package/dist/input/input.css +7 -1
  73. package/dist/menu/Menu.d.ts +1 -1
  74. package/dist/menu/Menu.js +1 -1
  75. package/dist/menu/menu.css +3 -1
  76. package/dist/native-select/NativeSelect.d.ts +1 -1
  77. package/dist/native-select/NativeSelect.js +1 -1
  78. package/dist/native-select/native-select.css +2 -1
  79. package/dist/number-input/NumberInput.d.ts +1 -1
  80. package/dist/number-input/NumberInput.js +1 -1
  81. package/dist/number-input/number-input.css +6 -3
  82. package/dist/page/Page.d.ts +4 -0
  83. package/dist/page/Page.js +4 -2
  84. package/dist/pagination/Pagination.d.ts +1 -1
  85. package/dist/pagination/Pagination.js +1 -1
  86. package/dist/password-input/PasswordInput.d.ts +1 -1
  87. package/dist/password-input/PasswordInput.js +1 -1
  88. package/dist/password-input/password-input.css +6 -3
  89. package/dist/pin-input/pin-input.css +2 -1
  90. package/dist/popover/Popover.d.ts +1 -1
  91. package/dist/popover/Popover.js +1 -1
  92. package/dist/popover/popover.css +3 -1
  93. package/dist/radio-group/RadioGroup.d.ts +1 -1
  94. package/dist/radio-group/RadioGroup.js +1 -1
  95. package/dist/radio-group/radio-group.css +1 -1
  96. package/dist/segment-group/Segmented.d.ts +1 -1
  97. package/dist/segment-group/Segmented.js +1 -1
  98. package/dist/select/ListSelect.d.ts +1 -1
  99. package/dist/select/ListSelect.js +1 -1
  100. package/dist/select/SearchSelect.d.ts +1 -1
  101. package/dist/select/SearchSelect.js +1 -1
  102. package/dist/select/search-select.css +6 -3
  103. package/dist/select/select.css +5 -2
  104. package/dist/sheet/Sheet.d.ts +1 -1
  105. package/dist/sheet/Sheet.js +1 -1
  106. package/dist/sidebar/NavGroup.d.ts +3 -2
  107. package/dist/sidebar/NavGroup.js +14 -4
  108. package/dist/sidebar/NavItem.d.ts +1 -1
  109. package/dist/sidebar/NavItem.js +1 -1
  110. package/dist/sidebar/NavSection.d.ts +1 -1
  111. package/dist/sidebar/NavSection.js +1 -1
  112. package/dist/sidebar/Sidebar.d.ts +1 -1
  113. package/dist/sidebar/Sidebar.js +1 -1
  114. package/dist/sidebar/SidebarUser.d.ts +1 -1
  115. package/dist/sidebar/SidebarUser.js +1 -1
  116. package/dist/sidebar/sidebar.css +75 -14
  117. package/dist/sortable-list/SortableList.d.ts +1 -1
  118. package/dist/sortable-list/SortableList.js +1 -1
  119. package/dist/stat/Stat.d.ts +1 -1
  120. package/dist/stat/Stat.js +1 -1
  121. package/dist/swatch-picker/SwatchPicker.d.ts +1 -1
  122. package/dist/swatch-picker/SwatchPicker.js +1 -1
  123. package/dist/swatch-picker/swatch-picker.css +3 -2
  124. package/dist/table/Table.d.ts +1 -1
  125. package/dist/table/Table.js +1 -1
  126. package/dist/tabs/Tabs.d.ts +1 -1
  127. package/dist/tabs/Tabs.js +1 -1
  128. package/dist/tags-input/TagsInput.d.ts +1 -1
  129. package/dist/tags-input/TagsInput.js +1 -1
  130. package/dist/tags-input/tags-input.css +6 -3
  131. package/dist/textarea/textarea.css +2 -1
  132. package/dist/theme-toggle/ThemeToggle.d.ts +1 -1
  133. package/dist/theme-toggle/ThemeToggle.js +1 -1
  134. package/dist/theme.css +51 -10
  135. package/dist/timeline/Timeline.d.ts +1 -1
  136. package/dist/timeline/Timeline.js +1 -1
  137. package/dist/toast/Toaster.d.ts +1 -1
  138. package/dist/toast/Toaster.js +1 -1
  139. package/dist/tooltip/tooltip.css +3 -1
  140. package/dist/tree-view/TreeView.d.ts +1 -1
  141. package/dist/tree-view/TreeView.js +1 -1
  142. package/package.json +7 -6
@@ -4,10 +4,12 @@
4
4
  [data-scope=input][data-part=control] {
5
5
  display: flex; align-items: center; gap: 0.5rem; min-width: 0; box-sizing: border-box;
6
6
  min-height: var(--ui-control-height); padding: 0 0.75rem;
7
- background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: var(--ui-radius);
7
+ background: var(--ui-field-bg); border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius);
8
8
  color: var(--ui-text); font-family: var(--ui-font); font-size: 14px;
9
9
 
10
+ &:hover { border-color: var(--ui-field-border-hover); }
10
11
  &:focus-within { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
12
+ &:has(input:autofill) { background: var(--ui-field-autofill-bg); }
11
13
  &:has([aria-invalid=true]) { border-color: var(--ui-danger); }
12
14
  &:has(:disabled) { opacity: 0.5; }
13
15
  [data-round] > & { border-radius: 9999px; padding: 0 0.875rem; }
@@ -17,6 +19,10 @@
17
19
  [data-scope=input][data-part=input] { flex: 1; min-width: 0; padding: 0; border: none; background: transparent;
18
20
  outline: none; color: inherit; font: inherit;
19
21
  &::placeholder { color: var(--ui-muted); }
22
+ /* Browsers paint autofilled inputs their own colour, with !important, which
23
+ shows as a patch inside the box. Delaying that change indefinitely keeps
24
+ the input transparent; the box takes --ui-field-autofill-bg instead. */
25
+ &:autofill { transition-property: background-color, color; transition-delay: 600000s; -webkit-text-fill-color: var(--ui-text); caret-color: var(--ui-text); }
20
26
  &[type=number] { appearance: textfield; }
21
27
  &::-webkit-inner-spin-button, &::-webkit-outer-spin-button { appearance: none; margin: 0; } }
22
28
  [data-scope=input]:is([data-part=prefix], [data-part=suffix]) { display: flex; align-items: center; flex-shrink: 0;
@@ -43,7 +43,7 @@
43
43
  */
44
44
  import { type ComponentProps, type ReactElement, type ReactNode } from 'react';
45
45
  import { Menu as Ark } from '@ark-ui/react/menu';
46
- import 'iconify-icon';
46
+ import '../icons.js';
47
47
  import { type Classes } from '../utils.js';
48
48
  import '../theme.css';
49
49
  import './menu.css';
package/dist/menu/Menu.js CHANGED
@@ -44,7 +44,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
44
44
  */
45
45
  import { createContext, useContext, useId, useRef, useState } from 'react';
46
46
  import { Menu as Ark, useMenuContext } from '@ark-ui/react/menu';
47
- import 'iconify-icon';
47
+ import '../icons.js';
48
48
  import { cx, partsOf, withParts } from '../utils.js';
49
49
  import '../theme.css';
50
50
  import './menu.css';
@@ -1,7 +1,9 @@
1
1
  /* Shared by Menu, its child components and submenus. Zag names most parts:
2
2
  item, option-item, trigger-item, separator, item-group-label… */
3
3
  @layer ui {
4
- /* Zag copies the content's z-index onto its positioner. */
4
+ /* The positioner carries the z-index itself. Zag sets it inline as
5
+ var(--z-index) but doesn't always fill in the variable, so set both. */
6
+ [data-scope=menu][data-part=positioner] { z-index: 50; --z-index: 50; }
5
7
  [data-scope=menu][data-part=content] {
6
8
  z-index: 50; font-weight: 400; min-width: 12rem; padding: 0.5rem 0.25rem; box-sizing: border-box; text-align: left; outline: none;
7
9
  background: var(--ui-surface); color: var(--ui-text); font-family: var(--ui-font); font-size: 14px;
@@ -14,7 +14,7 @@
14
14
  * - `name`, `required`, `disabled`: as on a <select>
15
15
  */
16
16
  import { type ReactNode, type SelectHTMLAttributes } from 'react';
17
- import 'iconify-icon';
17
+ import '../icons.js';
18
18
  import { type Classes } from '../utils.js';
19
19
  import '../theme.css';
20
20
  import './native-select.css';
@@ -16,7 +16,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
16
16
  */
17
17
  import { useId } from 'react';
18
18
  import { Field, useFieldContext } from '@ark-ui/react/field';
19
- import 'iconify-icon';
19
+ import '../icons.js';
20
20
  import { cx, partsOf, useControllable } from '../utils.js';
21
21
  import '../theme.css';
22
22
  import './native-select.css';
@@ -3,8 +3,9 @@
3
3
  [data-scope=native-select][data-part=label] { display: block; font-size: 14px; font-weight: 500; margin-bottom: 0.375rem; }
4
4
  [data-scope=native-select][data-part=control] { position: relative; display: flex; align-items: center; min-width: 0; }
5
5
  [data-scope=native-select][data-part=select] { appearance: none; width: 100%; min-width: 0; box-sizing: border-box;
6
- height: var(--ui-control-height); padding: 0 2rem 0 0.75rem; background: var(--ui-surface); border: 1px solid var(--ui-border);
6
+ height: var(--ui-control-height); padding: 0 2rem 0 0.75rem; background: var(--ui-field-bg); border: 1px solid var(--ui-field-border);
7
7
  border-radius: var(--ui-radius); color: var(--ui-text); font-family: var(--ui-font); font-size: 14px; cursor: pointer;
8
+ &:hover { border-color: var(--ui-field-border-hover); }
8
9
  &:focus-visible { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
9
10
  &[aria-invalid=true], &[data-invalid] { border-color: var(--ui-danger); }
10
11
  &:disabled { opacity: 0.5; cursor: not-allowed; }
@@ -25,7 +25,7 @@
25
25
  */
26
26
  import { type ReactNode } from 'react';
27
27
  import { NumberInput as Ark, type NumberInputValueChangeDetails } from '@ark-ui/react/number-input';
28
- import 'iconify-icon';
28
+ import '../icons.js';
29
29
  import { type Classes } from '../utils.js';
30
30
  import '../theme.css';
31
31
  import './number-input.css';
@@ -27,7 +27,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
27
27
  import { useState } from 'react';
28
28
  import { NumberInput as Ark } from '@ark-ui/react/number-input';
29
29
  import { useFieldContext } from '@ark-ui/react/field';
30
- import 'iconify-icon';
30
+ import '../icons.js';
31
31
  import { cx, partsOf, withParts } from '../utils.js';
32
32
  import { useMessages } from '../format/LocaleProvider.js';
33
33
  import '../theme.css';
@@ -2,14 +2,17 @@
2
2
  [data-scope=number-input][data-part=root] { display: inline-block; min-width: 10rem; color: var(--ui-text); font-family: var(--ui-font); }
3
3
  [data-scope=number-input][data-part=label] { display: block; font-size: 14px; font-weight: 500; margin-bottom: 0.375rem; }
4
4
  [data-scope=number-input][data-part=control] { display: flex; align-items: center; gap: 0.5rem; height: var(--ui-control-height);
5
- padding: 0 0.25rem 0 0.75rem; box-sizing: border-box; background: var(--ui-surface);
6
- border: 1px solid var(--ui-border); border-radius: var(--ui-radius); font-size: 14px;
5
+ padding: 0 0.25rem 0 0.75rem; box-sizing: border-box; background: var(--ui-field-bg);
6
+ border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius); font-size: 14px;
7
+ &:hover { border-color: var(--ui-field-border-hover); }
7
8
  &:focus-within { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
9
+ &:has(input:autofill) { background: var(--ui-field-autofill-bg); }
8
10
  &[data-disabled] { opacity: 0.5; }
9
11
  &[data-invalid], &:has([aria-invalid=true]) { border-color: var(--ui-danger); } }
10
12
  [data-scope=number-input][data-part=input] { flex: 1; min-width: 0; padding: 0; border: none; background: transparent; outline: none;
11
13
  color: inherit; font: inherit;
12
- &::placeholder { color: var(--ui-muted); } }
14
+ &::placeholder { color: var(--ui-muted); }
15
+ &:autofill { transition-property: background-color, color; transition-delay: 600000s; -webkit-text-fill-color: var(--ui-text); caret-color: var(--ui-text); } }
13
16
  [data-scope=number-input]:is([data-part=prefix], [data-part=suffix]) { display: flex; align-items: center; flex-shrink: 0;
14
17
  color: var(--ui-muted); white-space: nowrap; }
15
18
  [data-scope=number-input][data-part=icon] { display: block; width: 1em; height: 1em; font-size: 16px; color: var(--ui-muted); flex-shrink: 0; }
@@ -11,6 +11,10 @@
11
11
  * - `align`: 'center' or 'start'
12
12
  * - `actions`, `breadcrumbs`: shown in the header
13
13
  *
14
+ * When the shell scrolls the page rather than the window, the page can take
15
+ * focus (so the keyboard scrolls it) and is marked `scroll-region`, so
16
+ * Inertia resets and restores its scroll on visits as it does the window's.
17
+ *
14
18
  * What's inside a Page isn't the shell's: a Sidebar shown in the page (as an
15
19
  * example, say) doesn't collapse or turn into a drawer with the app's.
16
20
  */
package/dist/page/Page.js CHANGED
@@ -1,9 +1,11 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cx, partsOf } from '../utils.js';
3
- import { ShellContext } from '../app-shell/shell.js';
3
+ import { ShellContext, useShell } from '../app-shell/shell.js';
4
4
  import '../theme.css';
5
5
  import './page.css';
6
6
  export function Page({ heading = null, description = null, width = 'default', align = 'center', actions = null, breadcrumbs = null, className, classes, children, ...rest }) {
7
7
  const part = partsOf('page', classes);
8
- return (_jsx("div", { ...rest, ...part('root'), className: cx(className, classes?.root), "data-width": width, "data-align": align, children: _jsxs("div", { ...part('inner'), children: [(heading || description || actions || breadcrumbs) && (_jsxs("header", { ...part('header'), children: [breadcrumbs && _jsx("div", { ...part('breadcrumbs'), children: breadcrumbs }), _jsxs("div", { ...part('titles'), children: [_jsxs("div", { children: [heading && _jsx("h1", { ...part('heading'), children: heading }), description && _jsx("p", { ...part('description'), children: description })] }), actions && _jsx("div", { ...part('actions'), children: actions })] })] })), _jsx("div", { ...part('content'), children: _jsx(ShellContext, { value: null, children: children }) })] }) }));
8
+ const scrolls = !!useShell()?.pageScroll;
9
+ const scrolling = scrolls ? { tabIndex: -1, 'scroll-region': '' } : {};
10
+ return (_jsx("div", { ...scrolling, ...rest, ...part('root'), className: cx(className, classes?.root), "data-width": width, "data-align": align, children: _jsxs("div", { ...part('inner'), children: [(heading || description || actions || breadcrumbs) && (_jsxs("header", { ...part('header'), children: [breadcrumbs && _jsx("div", { ...part('breadcrumbs'), children: breadcrumbs }), _jsxs("div", { ...part('titles'), children: [_jsxs("div", { children: [heading && _jsx("h1", { ...part('heading'), children: heading }), description && _jsx("p", { ...part('description'), children: description })] }), actions && _jsx("div", { ...part('actions'), children: actions })] })] })), _jsx("div", { ...part('content'), children: _jsx(ShellContext, { value: null, children: children }) })] }) }));
9
11
  }
@@ -1,5 +1,5 @@
1
1
  import { Pagination as Ark } from '@ark-ui/react/pagination';
2
- import 'iconify-icon';
2
+ import '../icons.js';
3
3
  import { type Classes } from '../utils.js';
4
4
  import '../theme.css';
5
5
  import './pagination.css';
@@ -21,7 +21,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
21
21
  */
22
22
  import { useEffect } from 'react';
23
23
  import { Pagination as Ark, usePagination } from '@ark-ui/react/pagination';
24
- import 'iconify-icon';
24
+ import '../icons.js';
25
25
  import { cx, partsOf, useControllable, withParts } from '../utils.js';
26
26
  import { useLocale, useMessages } from '../format/LocaleProvider.js';
27
27
  import { formatNumber } from '../format/format.js';
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import type { ComponentProps, ReactNode } from 'react';
22
22
  import { PasswordInput as Ark, type PasswordInputVisibilityChangeDetails } from '@ark-ui/react/password-input';
23
- import 'iconify-icon';
23
+ import '../icons.js';
24
24
  import { type Classes } from '../utils.js';
25
25
  import '../theme.css';
26
26
  import './password-input.css';
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PasswordInput as Ark, usePasswordInput } from '@ark-ui/react/password-input';
3
3
  import { useFieldContext } from '@ark-ui/react/field';
4
- import 'iconify-icon';
4
+ import '../icons.js';
5
5
  import { cx, partsOf, withParts } from '../utils.js';
6
6
  import { useMessages } from '../format/LocaleProvider.js';
7
7
  import '../theme.css';
@@ -2,14 +2,17 @@
2
2
  [data-scope=password-input][data-part=root] { display: block; min-width: 0; color: var(--ui-text); font-family: var(--ui-font); }
3
3
  [data-scope=password-input][data-part=label] { display: block; font-size: 14px; font-weight: 500; margin-bottom: 0.375rem; }
4
4
  [data-scope=password-input][data-part=control] { display: flex; align-items: center; gap: 0.5rem; height: var(--ui-control-height);
5
- padding: 0 0.25rem 0 0.75rem; box-sizing: border-box; background: var(--ui-surface);
6
- border: 1px solid var(--ui-border); border-radius: var(--ui-radius); font-size: 14px;
5
+ padding: 0 0.25rem 0 0.75rem; box-sizing: border-box; background: var(--ui-field-bg);
6
+ border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius); font-size: 14px;
7
+ &:hover { border-color: var(--ui-field-border-hover); }
7
8
  &:focus-within { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
9
+ &:has(input:autofill) { background: var(--ui-field-autofill-bg); }
8
10
  &[data-invalid], &:has([aria-invalid=true]) { border-color: var(--ui-danger); }
9
11
  &[data-disabled] { opacity: 0.5; } }
10
12
  [data-scope=password-input][data-part=input] { flex: 1; min-width: 0; padding: 0; border: none; background: transparent; outline: none;
11
13
  color: inherit; font: inherit;
12
- &::placeholder { color: var(--ui-muted); } }
14
+ &::placeholder { color: var(--ui-muted); }
15
+ &:autofill { transition-property: background-color, color; transition-delay: 600000s; -webkit-text-fill-color: var(--ui-text); caret-color: var(--ui-text); } }
13
16
  [data-scope=password-input][data-part=icon] { display: block; width: 1em; height: 1em; font-size: 16px; color: var(--ui-muted); flex-shrink: 0; }
14
17
  [data-scope=password-input][data-part=visibility-trigger] { display: grid; place-items: center; flex-shrink: 0; width: 1.75rem; height: 1.75rem;
15
18
  border: none; background: transparent; border-radius: 4px; color: var(--ui-muted); cursor: pointer;
@@ -3,9 +3,10 @@
3
3
  [data-scope=pin-input][data-part=label] { display: block; font-size: 14px; font-weight: 500; margin-bottom: 0.375rem; }
4
4
  [data-scope=pin-input][data-part=control] { display: flex; gap: 0.5rem; }
5
5
  [data-scope=pin-input][data-part=input] { width: var(--ui-control-height); height: var(--ui-control-height); padding: 0; box-sizing: border-box;
6
- text-align: center; background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: var(--ui-radius);
6
+ text-align: center; background: var(--ui-field-bg); border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius);
7
7
  color: inherit; font-family: inherit; font-size: 16px; font-weight: 500; outline: none;
8
8
  &::placeholder { color: var(--ui-muted); }
9
+ &:hover { border-color: var(--ui-field-border-hover); }
9
10
  &:focus { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
10
11
  &:is([data-invalid], [aria-invalid=true]) { border-color: var(--ui-danger); }
11
12
  &[data-complete] { border-color: var(--ui-accent); }
@@ -26,7 +26,7 @@
26
26
  */
27
27
  import type { ReactElement, ReactNode } from 'react';
28
28
  import { Popover as Ark, type PopoverOpenChangeDetails } from '@ark-ui/react/popover';
29
- import 'iconify-icon';
29
+ import '../icons.js';
30
30
  import { type Classes } from '../utils.js';
31
31
  import '../theme.css';
32
32
  import './popover.css';
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Popover as Ark } from '@ark-ui/react/popover';
3
- import 'iconify-icon';
3
+ import '../icons.js';
4
4
  import { cx, on, partOf, partsOf, withParts } from '../utils.js';
5
5
  import { useMessages } from '../format/LocaleProvider.js';
6
6
  import '../theme.css';
@@ -1,5 +1,7 @@
1
1
  @layer ui {
2
- /* Zag copies the content's z-index onto its positioner. */
2
+ /* The positioner carries the z-index itself. Zag sets it inline as
3
+ var(--z-index) but doesn't always fill in the variable, so set both. */
4
+ [data-scope=popover][data-part=positioner] { z-index: 50; --z-index: 50; }
3
5
  [data-scope=popover][data-part=content] { z-index: 50; position: relative; width: 18rem; max-width: calc(100vw - 32px);
4
6
  padding: 1rem; box-sizing: border-box; outline: none; font-weight: 400;
5
7
  background: var(--ui-surface); color: var(--ui-text); font-family: var(--ui-font); font-size: 14px;
@@ -24,7 +24,7 @@
24
24
  */
25
25
  import type { ReactNode } from 'react';
26
26
  import { RadioGroup as Ark, type RadioGroupValueChangeDetails } from '@ark-ui/react/radio-group';
27
- import 'iconify-icon';
27
+ import '../icons.js';
28
28
  import { type Classes } from '../utils.js';
29
29
  import '../theme.css';
30
30
  import './radio-group.css';
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { RadioGroup as Ark } from '@ark-ui/react/radio-group';
3
3
  import { useFieldContext } from '@ark-ui/react/field';
4
- import 'iconify-icon';
4
+ import '../icons.js';
5
5
  import { cx, partOf, partsOf, useControllable, withParts } from '../utils.js';
6
6
  import '../theme.css';
7
7
  import './radio-group.css';
@@ -9,7 +9,7 @@
9
9
  [data-scope=radio-group][data-part=item] { display: flex; align-items: flex-start; gap: 0.5rem; font-size: 14px; cursor: pointer;
10
10
  &[data-disabled] { opacity: 0.5; cursor: not-allowed; } }
11
11
  [data-scope=radio-group][data-part=item-control] { display: grid; place-items: center; flex-shrink: 0; width: 1rem; height: 1rem;
12
- margin-top: 0.125rem; box-sizing: border-box; background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: 9999px;
12
+ margin-top: 0.125rem; box-sizing: border-box; background: var(--ui-field-bg); border: 1px solid var(--ui-field-border); border-radius: 9999px;
13
13
  &[data-state=checked] { border-color: var(--ui-accent); border-width: 5px; }
14
14
  &[data-focus-visible] { outline: 2px solid var(--ui-ring-soft); border-color: var(--ui-ring); }
15
15
  &[data-invalid] { border-color: var(--ui-danger); } }
@@ -28,7 +28,7 @@
28
28
  */
29
29
  import { type ReactNode } from 'react';
30
30
  import { SegmentGroup as Ark, type SegmentGroupValueChangeDetails } from '@ark-ui/react/segment-group';
31
- import 'iconify-icon';
31
+ import '../icons.js';
32
32
  import { type Classes } from '../utils.js';
33
33
  import '../theme.css';
34
34
  import './segment-group.css';
@@ -30,7 +30,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
30
30
  import { useState } from 'react';
31
31
  import { SegmentGroup as Ark } from '@ark-ui/react/segment-group';
32
32
  import { useFieldContext } from '@ark-ui/react/field';
33
- import 'iconify-icon';
33
+ import '../icons.js';
34
34
  import { Tooltip } from '../tooltip/Tooltip.js';
35
35
  import { cx, partOf, partsOf, useControllable, withParts } from '../utils.js';
36
36
  import '../theme.css';
@@ -1,4 +1,4 @@
1
- import 'iconify-icon';
1
+ import '../icons.js';
2
2
  import type { InnerProps } from './Select.js';
3
3
  import '../theme.css';
4
4
  import './select.css';
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
4
  import { Fragment, useMemo, useRef } from 'react';
5
5
  import { Select as Ark, createListCollection, useSelect } from '@ark-ui/react/select';
6
6
  import { useFieldContext } from '@ark-ui/react/field';
7
- import 'iconify-icon';
7
+ import '../icons.js';
8
8
  import { cx, partsOf, slot } from '../utils.js';
9
9
  import { useMessages } from '../format/LocaleProvider.js';
10
10
  import { useItems } from './items.js';
@@ -1,5 +1,5 @@
1
1
  import { Combobox as Ark } from '@ark-ui/react/combobox';
2
- import 'iconify-icon';
2
+ import '../icons.js';
3
3
  import type { InnerProps } from './Select.js';
4
4
  import '../theme.css';
5
5
  import './search-select.css';
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
4
4
  import { useEffect, useMemo, useRef, useState } from 'react';
5
5
  import { Combobox as Ark, createListCollection, useCombobox, } from '@ark-ui/react/combobox';
6
6
  import { useFieldContext } from '@ark-ui/react/field';
7
- import 'iconify-icon';
7
+ import '../icons.js';
8
8
  import { cx, partOf, partsOf, slot } from '../utils.js';
9
9
  import { useMessages } from '../format/LocaleProvider.js';
10
10
  import { useItems } from './items.js';
@@ -5,8 +5,9 @@
5
5
  &[data-variant=outline] { --tag-bg: var(--ui-surface); --tag-border: var(--ui-border); } }
6
6
  [data-scope=combobox][data-part=label] { display: block; font-size: 14px; font-weight: 500; margin-bottom: 0.375rem; }
7
7
  [data-scope=combobox][data-part=control] { display: flex; align-items: center; gap: 0.25rem; min-height: var(--ui-control-height);
8
- padding: 0.125rem 0.25rem 0.125rem 0.5rem; box-sizing: border-box; background: var(--ui-surface);
9
- border: 1px solid var(--ui-border); border-radius: var(--ui-radius);
8
+ padding: 0.125rem 0.25rem 0.125rem 0.5rem; box-sizing: border-box; background: var(--ui-field-bg);
9
+ border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius);
10
+ &:hover { border-color: var(--ui-field-border-hover); }
10
11
  &:focus-within { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
11
12
  &[data-disabled] { opacity: 0.5; }
12
13
  &[data-invalid], &:has([aria-invalid=true]) { border-color: var(--ui-danger); } }
@@ -26,7 +27,9 @@
26
27
  &:hover { background: var(--ui-hover); color: var(--ui-text); } }
27
28
  [data-scope=combobox][data-part=trigger][data-state=open] { rotate: 180deg; }
28
29
 
29
- /* Zag copies the content's z-index onto its positioner. */
30
+ /* The positioner carries the z-index itself. Zag sets it inline as
31
+ var(--z-index) but doesn't always fill in the variable, so set both. */
32
+ [data-scope=combobox][data-part=positioner] { z-index: 50; --z-index: 50; }
30
33
  [data-scope=combobox][data-part=content] { z-index: 50; margin: 0; padding: 0.25rem; list-style: none; box-sizing: border-box; outline: none;
31
34
  max-height: min(300px, var(--available-height)); overflow-y: auto; font-weight: 400;
32
35
  background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: calc(var(--ui-radius) + 2px); box-shadow: var(--ui-shadow); }
@@ -14,8 +14,9 @@
14
14
  [data-scope=select][data-part=control] { display: flex; align-items: center; position: relative; }
15
15
  [data-scope=select][data-part=trigger] { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem;
16
16
  width: 100%; height: var(--ui-control-height); padding: 0 0.75rem; box-sizing: border-box;
17
- background: var(--ui-surface); border: 1px solid var(--ui-border); border-radius: var(--ui-radius);
17
+ background: var(--ui-field-bg); border: 1px solid var(--ui-field-border); border-radius: var(--ui-radius);
18
18
  color: inherit; font-family: var(--ui-font); font-size: 14px; text-align: left; cursor: pointer;
19
+ &:hover { border-color: var(--ui-field-border-hover); }
19
20
  &:focus-visible { border-color: var(--ui-ring); outline: 2px solid var(--ui-ring-soft); }
20
21
  &[data-disabled] { opacity: 0.5; cursor: not-allowed; }
21
22
  &[data-invalid], &[aria-invalid=true] { border-color: var(--ui-danger); }
@@ -30,7 +31,9 @@
30
31
  [data-scope=select][data-part=indicator] { display: inline-flex; color: var(--ui-muted); transition: rotate 150ms;
31
32
  &[data-state=open] { rotate: 180deg; } }
32
33
 
33
- /* Zag copies the content's z-index onto its positioner. */
34
+ /* The positioner carries the z-index itself. Zag sets it inline as
35
+ var(--z-index) but doesn't always fill in the variable, so set both. */
36
+ [data-scope=select][data-part=positioner] { z-index: 50; --z-index: 50; }
34
37
  [data-scope=select][data-part=content] { z-index: 50; margin: 0; padding: 0.25rem; list-style: none; box-sizing: border-box;
35
38
  outline: none; max-height: min(300px, var(--available-height)); overflow-y: auto;
36
39
  background: var(--ui-surface); border: 1px solid var(--ui-border);
@@ -22,7 +22,7 @@
22
22
  */
23
23
  import { type ComponentProps, type ReactElement, type ReactNode } from 'react';
24
24
  import { Dialog as Ark, type DialogOpenChangeDetails } from '@ark-ui/react/dialog';
25
- import 'iconify-icon';
25
+ import '../icons.js';
26
26
  import { type Classes } from '../utils.js';
27
27
  import '../theme.css';
28
28
  import './sheet.css';
@@ -24,7 +24,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
24
24
  import { Children, isValidElement } from 'react';
25
25
  import { Dialog as Ark } from '@ark-ui/react/dialog';
26
26
  import { Portal } from '@ark-ui/react/portal';
27
- import 'iconify-icon';
27
+ import '../icons.js';
28
28
  import { cx, on, partOf, partsOf, withParts } from '../utils.js';
29
29
  import { useMessages } from '../format/LocaleProvider.js';
30
30
  import '../theme.css';
@@ -11,10 +11,11 @@
11
11
  *
12
12
  * In the rail only its icon shows, and its items open beside it as a flyout:
13
13
  * on hover, or on click for keyboard and touch. Escape, leaving it or
14
- * following a link closes it.
14
+ * following a link closes it. It moves up when it would run past the bottom
15
+ * of the window, and scrolls when taller than it.
15
16
  */
16
17
  import { type HTMLAttributes } from 'react';
17
- import 'iconify-icon';
18
+ import '../icons.js';
18
19
  import { type Classes } from '../utils.js';
19
20
  import '../theme.css';
20
21
  import './sidebar.css';
@@ -12,10 +12,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  *
13
13
  * In the rail only its icon shows, and its items open beside it as a flyout:
14
14
  * on hover, or on click for keyboard and touch. Escape, leaving it or
15
- * following a link closes it.
15
+ * following a link closes it. It moves up when it would run past the bottom
16
+ * of the window, and scrolls when taller than it.
16
17
  */
17
- import { useContext, useEffect, useId, useRef, useState } from 'react';
18
- import 'iconify-icon';
18
+ import { useContext, useEffect, useId, useLayoutEffect, useRef, useState } from 'react';
19
+ import '../icons.js';
19
20
  import { useShell } from '../app-shell/shell.js';
20
21
  import { cx, partsOf, useControllable } from '../utils.js';
21
22
  import { FlyoutContext, SectionContext, useSidebar } from './context.js';
@@ -46,7 +47,16 @@ export function NavGroup({ label, icon = null, open: openProp, defaultOpen = fal
46
47
  const [position, setPosition] = useState({ top: 0, left: 0 });
47
48
  const root = useRef(null);
48
49
  const toggleEl = useRef(null);
50
+ const childrenEl = useRef(null);
49
51
  const showing = rail && flyout;
52
+ // Moved up when it would run past the bottom of the window.
53
+ useLayoutEffect(() => {
54
+ if (!showing || !childrenEl.current)
55
+ return;
56
+ const top = Math.max(8, Math.min(position.top, innerHeight - childrenEl.current.offsetHeight - 8));
57
+ if (top !== position.top)
58
+ setPosition({ ...position, top });
59
+ }, [showing, position]);
50
60
  function showFlyout() {
51
61
  if (!rail || !toggleEl.current)
52
62
  return;
@@ -73,6 +83,6 @@ export function NavGroup({ label, icon = null, open: openProp, defaultOpen = fal
73
83
  setFlyout(false);
74
84
  toggleEl.current?.focus();
75
85
  }
76
- return (_jsxs("div", { ...rest, ...part('root'), className: cx(className, classes?.root), ref: root, "data-open": open || undefined, "data-rail": rail || undefined, "data-flyout": showing || undefined, onPointerEnter: showFlyout, onPointerLeave: () => setFlyout(false), onBlur: focusLeft, onKeyDown: escaped, children: [_jsxs("button", { ...part('trigger'), ref: toggleEl, type: "button", "aria-expanded": rail ? showing : open, "aria-controls": `${id}-panel`, "aria-label": rail ? label : undefined, onClick: toggle, children: [icon && _jsx("iconify-icon", { ...part('icon'), icon: icon, "aria-hidden": "true" }), _jsx("span", { ...part('text'), children: label }), _jsx("iconify-icon", { ...part('indicator'), icon: "lucide:chevron-down", "aria-hidden": "true" })] }), (rail ? showing : open) && (_jsx("div", { ...part('children'), id: `${id}-panel`, role: "presentation", style: { '--flyout-top': `${position.top}px`, '--flyout-left': `${position.left}px` }, onClick: (e) => { if (e.target.closest('a'))
86
+ return (_jsxs("div", { ...rest, ...part('root'), className: cx(className, classes?.root), ref: root, "data-open": open || undefined, "data-rail": rail || undefined, "data-flyout": showing || undefined, onPointerEnter: showFlyout, onPointerLeave: () => setFlyout(false), onBlur: focusLeft, onKeyDown: escaped, children: [_jsxs("button", { ...part('trigger'), ref: toggleEl, type: "button", "aria-expanded": rail ? showing : open, "aria-controls": `${id}-panel`, "aria-label": rail ? label : undefined, onClick: toggle, children: [icon && _jsx("iconify-icon", { ...part('icon'), icon: icon, "aria-hidden": "true" }), _jsx("span", { ...part('text'), children: label }), _jsx("iconify-icon", { ...part('indicator'), icon: "lucide:chevron-down", "aria-hidden": "true" })] }), (rail ? showing : open) && (_jsx("div", { ...part('children'), ref: childrenEl, id: `${id}-panel`, role: "presentation", style: { '--flyout-top': `${position.top}px`, '--flyout-left': `${position.left}px` }, onClick: (e) => { if (e.target.closest('a'))
77
87
  setFlyout(false); }, children: _jsxs("div", { ...part('panel'), children: [rail && _jsx("div", { ...part('flyout-heading'), "aria-hidden": "true", children: label }), _jsx(FlyoutContext, { value: true, children: children })] }) }))] }));
78
88
  }
@@ -17,7 +17,7 @@
17
17
  * group's flyout the text stays); in the drawer, following a link closes it.
18
18
  */
19
19
  import { type AnchorHTMLAttributes, type ReactElement, type ReactNode } from 'react';
20
- import 'iconify-icon';
20
+ import '../icons.js';
21
21
  import { type Classes } from '../utils.js';
22
22
  import '../theme.css';
23
23
  import './sidebar.css';
@@ -18,7 +18,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
18
18
  * group's flyout the text stays); in the drawer, following a link closes it.
19
19
  */
20
20
  import { Children, cloneElement, isValidElement, useContext } from 'react';
21
- import 'iconify-icon';
21
+ import '../icons.js';
22
22
  import { Tooltip } from '../tooltip/Tooltip.js';
23
23
  import { useShell } from '../app-shell/shell.js';
24
24
  import { cx, partsOf } from '../utils.js';
@@ -8,7 +8,7 @@
8
8
  * all the section's groups at once
9
9
  */
10
10
  import { type HTMLAttributes, type ReactNode } from 'react';
11
- import 'iconify-icon';
11
+ import '../icons.js';
12
12
  import { type Classes } from '../utils.js';
13
13
  import '../theme.css';
14
14
  import './sidebar.css';
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  * all the section's groups at once
10
10
  */
11
11
  import { useMemo, useRef, useState } from 'react';
12
- import 'iconify-icon';
12
+ import '../icons.js';
13
13
  import { useShell } from '../app-shell/shell.js';
14
14
  import { cx, partsOf } from '../utils.js';
15
15
  import { useMessages } from '../format/LocaleProvider.js';
@@ -25,7 +25,7 @@
25
25
  * Sidebar.User are NavSection, NavGroup, NavItem and SidebarUser.
26
26
  */
27
27
  import { type HTMLAttributes, type ReactNode } from 'react';
28
- import 'iconify-icon';
28
+ import '../icons.js';
29
29
  import { type Classes } from '../utils.js';
30
30
  import { NavSection } from './NavSection.js';
31
31
  import { NavGroup } from './NavGroup.js';
@@ -26,7 +26,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
26
26
  * Sidebar.User are NavSection, NavGroup, NavItem and SidebarUser.
27
27
  */
28
28
  import { useMemo, useState } from 'react';
29
- import 'iconify-icon';
29
+ import '../icons.js';
30
30
  import { Tooltip } from '../tooltip/Tooltip.js';
31
31
  import { useShell } from '../app-shell/shell.js';
32
32
  import { cx, partsOf, withParts } from '../utils.js';
@@ -14,7 +14,7 @@
14
14
  * - `letters`, `color`: passed to the Avatar
15
15
  */
16
16
  import type { ReactNode } from 'react';
17
- import 'iconify-icon';
17
+ import '../icons.js';
18
18
  import { type MenuProps } from '../menu/Menu.js';
19
19
  import { type AvatarColor } from '../avatar/Avatar.js';
20
20
  import { type Classes } from '../utils.js';
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import 'iconify-icon';
2
+ import '../icons.js';
3
3
  import { Menu } from '../menu/Menu.js';
4
4
  import { Avatar } from '../avatar/Avatar.js';
5
5
  import { useShell } from '../app-shell/shell.js';