@remix-run/ui 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -10
- package/dist/animation/animate-layout-mixin.js +66 -66
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/spring.d.ts +6 -35
- package/dist/animation/spring.js +9 -8
- package/dist/animation/spring.js.map +1 -1
- package/dist/components/accordion/accordion.d.ts +7 -7
- package/dist/components/accordion/accordion.js +0 -2
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/demos/card.demo.d.ts +6 -0
- package/dist/components/accordion/demos/card.demo.js +58 -0
- package/dist/components/accordion/demos/card.demo.js.map +1 -0
- package/dist/components/accordion/demos/multiple.demo.d.ts +6 -0
- package/dist/components/accordion/demos/multiple.demo.js +19 -0
- package/dist/components/accordion/demos/multiple.demo.js.map +1 -0
- package/dist/components/accordion/demos/overview.demo.d.ts +6 -0
- package/dist/components/accordion/demos/overview.demo.js +19 -0
- package/dist/components/accordion/demos/overview.demo.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/components/breadcrumbs/breadcrumbs.js +0 -2
- package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/breadcrumbs/demos/basic.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js.map +1 -0
- package/dist/components/breadcrumbs/demos/separator.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js.map +1 -0
- package/dist/components/button/button.d.ts +86 -4
- package/dist/components/button/button.js +63 -3
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/demos/aliases.demo.d.ts +6 -0
- package/dist/components/button/demos/aliases.demo.js +18 -0
- package/dist/components/button/demos/aliases.demo.js.map +1 -0
- package/dist/components/button/demos/basic.demo.d.ts +6 -0
- package/dist/components/button/demos/basic.demo.js +19 -0
- package/dist/components/button/demos/basic.demo.js.map +1 -0
- package/dist/components/button/demos/states.demo.d.ts +6 -0
- package/dist/components/button/demos/states.demo.js +29 -0
- package/dist/components/button/demos/states.demo.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +11 -11
- package/dist/components/combobox/combobox.js +0 -2
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/combobox/demos/overview.demo.d.ts +6 -0
- package/dist/components/combobox/demos/overview.demo.js +153 -0
- package/dist/components/combobox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/demos/overview.demo.d.ts +6 -0
- package/dist/components/listbox/demos/overview.demo.js +64 -0
- package/dist/components/listbox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +4 -9
- package/dist/components/listbox/listbox.js +21 -33
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/menu/demos/bubbling.demo.d.ts +5 -0
- package/dist/components/menu/demos/bubbling.demo.js +15 -0
- package/dist/components/menu/demos/bubbling.demo.js.map +1 -0
- package/dist/components/menu/demos/overview.demo.d.ts +6 -0
- package/dist/components/menu/demos/overview.demo.js +32 -0
- package/dist/components/menu/demos/overview.demo.js.map +1 -0
- package/dist/components/menu/menu.d.ts +15 -24
- package/dist/components/menu/menu.js +23 -38
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/popover/demos/overview.demo.d.ts +6 -0
- package/dist/components/popover/demos/overview.demo.js +64 -0
- package/dist/components/popover/demos/overview.demo.js.map +1 -0
- package/dist/components/popover/popover.d.ts +5 -5
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/select/demos/deconstructed.demo.d.ts +6 -0
- package/dist/components/select/demos/deconstructed.demo.js +53 -0
- package/dist/components/select/demos/deconstructed.demo.js.map +1 -0
- package/dist/components/select/demos/overview.demo.d.ts +5 -0
- package/dist/components/select/demos/overview.demo.js +27 -0
- package/dist/components/select/demos/overview.demo.js.map +1 -0
- package/dist/components/select/select.d.ts +11 -11
- package/dist/components/select/select.js +17 -26
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts +6 -6
- package/dist/components/tabs/tabs.js +0 -2
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interactions/keydown/keydown.d.ts +1 -1
- package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -1
- package/dist/interactions/typeahead/typeahead-mixin.d.ts +3 -1
- package/dist/runtime/component.d.ts +18 -12
- package/dist/runtime/component.js +93 -80
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.d.ts +14 -0
- package/dist/runtime/core/attributes.js +103 -0
- package/dist/runtime/core/attributes.js.map +1 -0
- package/dist/runtime/core/children.d.ts +7 -0
- package/dist/runtime/core/children.js +30 -0
- package/dist/runtime/core/children.js.map +1 -0
- package/dist/runtime/core/props.d.ts +9 -0
- package/dist/runtime/core/props.js +170 -0
- package/dist/runtime/core/props.js.map +1 -0
- package/dist/runtime/core/vnode.d.ts +3 -0
- package/dist/runtime/core/vnode.js +39 -0
- package/dist/runtime/core/vnode.js.map +1 -0
- package/dist/runtime/create-element.js +2 -1
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +47 -14
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.d.ts +1 -2
- package/dist/runtime/diff-props.js +2 -181
- package/dist/runtime/diff-props.js.map +1 -1
- package/dist/runtime/dom.d.ts +20 -9
- package/dist/runtime/frame.d.ts +23 -2
- package/dist/runtime/frame.js +41 -47
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +2 -28
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/mixins/link-mixin.d.ts +5 -1
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +2 -1
- package/dist/runtime/mixins/mixin.js +9 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.d.ts +15 -4
- package/dist/runtime/mixins/on-mixin.js +9 -2
- package/dist/runtime/mixins/on-mixin.js.map +1 -1
- package/dist/runtime/mixins/ref-mixin.d.ts +2 -1
- package/dist/runtime/mixins/ref-mixin.js.map +1 -1
- package/dist/runtime/navigation.js +9 -1
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +1 -1
- package/dist/runtime/reconcile.js +452 -197
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/run.d.ts +17 -2
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.d.ts +10 -10
- package/dist/runtime/scheduler.js +1 -1
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/stream-protocol.d.ts +8 -0
- package/dist/runtime/stream-protocol.js +20 -0
- package/dist/runtime/stream-protocol.js.map +1 -0
- package/dist/runtime/svg-attributes.js +1 -0
- package/dist/runtime/svg-attributes.js.map +1 -1
- package/dist/runtime/to-vnode.js +7 -11
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vnode.d.ts +11 -5
- package/dist/runtime/vnode.js +6 -3
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +154 -114
- package/dist/server/stream.js.map +1 -1
- package/dist/style/css-mixin.d.ts +2 -1
- package/dist/style/css-mixin.js.map +1 -1
- package/dist/style/index.d.ts +1 -1
- package/dist/style/layers.d.ts +2 -0
- package/dist/style/layers.js +3 -0
- package/dist/style/layers.js.map +1 -0
- package/dist/style/stylesheet.d.ts +13 -11
- package/dist/style/stylesheet.js +69 -8
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/theme/contract.d.ts +24 -222
- package/dist/theme/contract.js +2 -2
- package/dist/theme/contract.js.map +1 -1
- package/dist/theme/glyph-contract.d.ts +1 -3
- package/dist/theme/glyph-contract.js.map +1 -1
- package/dist/theme/presets/rmx-01/index.d.ts +4 -2
- package/dist/theme/presets/rmx-01/index.js.map +1 -1
- package/dist/theme/runtime.js +4 -1
- package/dist/theme/runtime.js.map +1 -1
- package/dist/utils/scroll-lock.d.ts +3 -3
- package/dist/utils/scroll-lock.js.map +1 -1
- package/package.json +3 -3
- package/src/animation/README.md +316 -0
- package/src/animation/animate-layout-mixin.ts +79 -71
- package/src/animation/spring.ts +21 -9
- package/src/components/accordion/README.md +166 -0
- package/src/components/accordion/accordion.tsx +14 -14
- package/src/components/accordion/demos/card.demo.tsx +113 -0
- package/src/components/accordion/demos/multiple.demo.tsx +56 -0
- package/src/components/accordion/demos/overview.demo.tsx +56 -0
- package/src/components/anchor/README.md +153 -0
- package/src/components/anchor/anchor.ts +1 -1
- package/src/components/breadcrumbs/README.md +55 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +1 -3
- package/src/components/breadcrumbs/demos/basic.demo.tsx +17 -0
- package/src/components/breadcrumbs/demos/separator.demo.tsx +18 -0
- package/src/components/button/README.md +4 -4
- package/src/components/button/button.tsx +118 -20
- package/src/components/button/demos/aliases.demo.tsx +27 -0
- package/src/components/button/demos/basic.demo.tsx +30 -0
- package/src/components/button/demos/states.demo.tsx +52 -0
- package/src/components/combobox/README.md +1 -1
- package/src/components/combobox/combobox.tsx +37 -21
- package/src/components/combobox/demos/overview.demo.tsx +199 -0
- package/src/components/glyph/README.md +72 -0
- package/src/components/glyph/glyph.tsx +2 -2
- package/src/components/listbox/README.md +115 -0
- package/src/components/listbox/demos/overview.demo.tsx +101 -0
- package/src/components/listbox/listbox.ts +106 -110
- package/src/components/menu/README.md +96 -0
- package/src/components/menu/demos/bubbling.demo.tsx +34 -0
- package/src/components/menu/demos/overview.demo.tsx +76 -0
- package/src/components/menu/menu.tsx +61 -55
- package/src/components/popover/README.md +3 -3
- package/src/components/popover/demos/overview.demo.tsx +143 -0
- package/src/components/popover/popover.ts +90 -79
- package/src/components/select/README.md +107 -0
- package/src/components/select/demos/deconstructed.demo.tsx +95 -0
- package/src/components/select/demos/overview.demo.tsx +51 -0
- package/src/components/select/select.tsx +53 -36
- package/src/components/tabs/tabs.tsx +10 -5
- package/src/index.ts +2 -1
- package/src/runtime/component.ts +122 -88
- package/src/runtime/core/attributes.ts +118 -0
- package/src/runtime/core/children.ts +42 -0
- package/src/runtime/core/props.ts +187 -0
- package/src/runtime/core/vnode.ts +48 -0
- package/src/runtime/create-element.ts +2 -1
- package/src/runtime/diff-dom.ts +59 -12
- package/src/runtime/diff-props.ts +2 -187
- package/src/runtime/dom.ts +20 -9
- package/src/runtime/frame.ts +71 -55
- package/src/runtime/jsx.ts +3 -30
- package/src/runtime/mixins/link-mixin.ts +88 -86
- package/src/runtime/mixins/mixin.ts +18 -5
- package/src/runtime/mixins/on-mixin.ts +20 -12
- package/src/runtime/mixins/ref-mixin.ts +4 -5
- package/src/runtime/navigation.ts +10 -1
- package/src/runtime/reconcile.ts +563 -223
- package/src/runtime/run.ts +17 -1
- package/src/runtime/scheduler.ts +20 -20
- package/src/runtime/stream-protocol.ts +27 -0
- package/src/runtime/svg-attributes.ts +1 -0
- package/src/runtime/to-vnode.ts +7 -10
- package/src/runtime/vnode.ts +16 -9
- package/src/server/README.md +90 -0
- package/src/server/stream.ts +176 -124
- package/src/style/css-mixin.ts +6 -1
- package/src/style/index.ts +1 -2
- package/src/style/layers.ts +2 -0
- package/src/style/stylesheet.ts +88 -11
- package/src/test/README.md +107 -0
- package/src/test/utils.ts +3 -1
- package/src/theme/README.md +103 -0
- package/src/theme/contract.ts +37 -5
- package/src/theme/glyph-contract.ts +3 -1
- package/src/theme/presets/rmx-01/index.ts +4 -2
- package/src/theme/runtime.ts +4 -1
- package/src/utils/scroll-lock/README.md +33 -0
- package/src/utils/scroll-lock.ts +7 -3
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @jsxRuntime classic
|
|
2
|
-
// @jsx createElement
|
|
3
1
|
import { css, createElement } from '@remix-run/ui'
|
|
4
2
|
import type { Handle, Props, RemixNode } from '@remix-run/ui'
|
|
5
3
|
|
|
@@ -74,7 +72,7 @@ const textCss = css({
|
|
|
74
72
|
whiteSpace: 'nowrap',
|
|
75
73
|
})
|
|
76
74
|
|
|
77
|
-
export function Breadcrumbs(handle: Handle<BreadcrumbsProps>) {
|
|
75
|
+
export function Breadcrumbs(handle: Handle<BreadcrumbsProps>): () => RemixNode {
|
|
78
76
|
return () => {
|
|
79
77
|
let { 'aria-label': ariaLabel, items, separator, mix, ...navProps } = handle.props
|
|
80
78
|
let currentIndex = items.findIndex((item) => item.current)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Breadcrumbs } from '@remix-run/ui/breadcrumbs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @name Breadcrumbs Basic
|
|
5
|
+
* @description A basic breadcrumb trail linking back through the page hierarchy.
|
|
6
|
+
*/
|
|
7
|
+
export default function Example() {
|
|
8
|
+
return () => (
|
|
9
|
+
<Breadcrumbs
|
|
10
|
+
items={[
|
|
11
|
+
{ href: '/', label: 'Home' },
|
|
12
|
+
{ href: '/components', label: 'Components' },
|
|
13
|
+
{ label: 'Breadcrumbs' },
|
|
14
|
+
]}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Breadcrumbs } from '@remix-run/ui/breadcrumbs'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @name Breadcrumbs with Separator
|
|
5
|
+
* @description Pass a custom separator string to override the default chevron icon.
|
|
6
|
+
*/
|
|
7
|
+
export default function Example() {
|
|
8
|
+
return () => (
|
|
9
|
+
<Breadcrumbs
|
|
10
|
+
items={[
|
|
11
|
+
{ href: '/', label: 'Workspace' },
|
|
12
|
+
{ href: '/projects', label: 'Projects' },
|
|
13
|
+
{ label: 'RMX_01' },
|
|
14
|
+
]}
|
|
15
|
+
separator="/"
|
|
16
|
+
/>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# button
|
|
2
2
|
|
|
3
|
-
`button` is the shared button styling contract for
|
|
3
|
+
`button` is the shared button styling contract for `remix/ui`. Use `Button` for ordinary action buttons, or compose flat `button.*Style` exports directly when a higher-level control needs button structure without a wrapper.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
```tsx
|
|
8
|
-
import { Button } from '
|
|
9
|
-
import * as button from '
|
|
10
|
-
import { Glyph } from '
|
|
8
|
+
import { Button } from 'remix/ui/button'
|
|
9
|
+
import * as button from 'remix/ui/button'
|
|
10
|
+
import { Glyph } from 'remix/ui/glyph'
|
|
11
11
|
|
|
12
12
|
function Actions() {
|
|
13
13
|
return (
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
// @jsxRuntime classic
|
|
2
|
-
// @jsx createElement
|
|
3
1
|
import { attrs, createElement, createMixin, css } from '@remix-run/ui'
|
|
4
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
CSSMixinDescriptor,
|
|
4
|
+
ElementProps,
|
|
5
|
+
Handle,
|
|
6
|
+
MixinDescriptor,
|
|
7
|
+
MixinFactory,
|
|
8
|
+
Props,
|
|
9
|
+
RemixNode,
|
|
10
|
+
} from '@remix-run/ui'
|
|
5
11
|
|
|
6
12
|
import { theme } from '../../theme/theme.ts'
|
|
7
13
|
|
|
@@ -76,30 +82,83 @@ const buttonIconCss: CSSMixinDescriptor = css({
|
|
|
76
82
|
},
|
|
77
83
|
})
|
|
78
84
|
|
|
79
|
-
const buttonIconAttrsCss = attrs({
|
|
85
|
+
const buttonIconAttrsCss: MixinDescriptor<Element, [Partial<ElementProps>], ElementProps> = attrs({
|
|
86
|
+
'aria-hidden': true,
|
|
87
|
+
})
|
|
80
88
|
|
|
81
|
-
const buttonDefaultsMixin
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
const buttonDefaultsMixin: MixinFactory<Element, [], ElementProps> = createMixin<
|
|
90
|
+
Element,
|
|
91
|
+
[],
|
|
92
|
+
ElementProps
|
|
93
|
+
>((handle, hostType) => (props) => {
|
|
94
|
+
if (hostType !== 'button' || props.type !== undefined) {
|
|
95
|
+
return handle.element
|
|
96
|
+
}
|
|
86
97
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
)
|
|
98
|
+
return createElement(handle.element as unknown as string, {
|
|
99
|
+
...props,
|
|
100
|
+
type: 'button',
|
|
101
|
+
})
|
|
102
|
+
})
|
|
93
103
|
|
|
94
|
-
const buttonDefaultsCss = buttonDefaultsMixin()
|
|
104
|
+
const buttonDefaultsCss: MixinDescriptor<Element, [], ElementProps> = buttonDefaultsMixin()
|
|
95
105
|
|
|
106
|
+
/**
|
|
107
|
+
* Base button styling with the default `type="button"` behavior for `<button>`
|
|
108
|
+
* hosts. Compose with a tone style (e.g. {@link primaryStyle}) when applying
|
|
109
|
+
* button styling without using the {@link Button} component.
|
|
110
|
+
*
|
|
111
|
+
* @category mixin
|
|
112
|
+
*/
|
|
96
113
|
export const baseStyle = [buttonDefaultsCss, buttonBaseStyleCss] as const
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Icon slot sizing and `aria-hidden` defaults for decorative icons rendered
|
|
117
|
+
* inside a button.
|
|
118
|
+
*
|
|
119
|
+
* @category mixin
|
|
120
|
+
*/
|
|
97
121
|
export const iconStyle = [buttonIconAttrsCss, buttonIconCss] as const
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Inline label slot with the standard button label spacing.
|
|
125
|
+
*
|
|
126
|
+
* @category mixin
|
|
127
|
+
*/
|
|
98
128
|
export const labelStyle = buttonLabelCss
|
|
99
|
-
|
|
100
|
-
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Primary visual treatment for buttons. Combine with {@link baseStyle} when
|
|
132
|
+
* styling a non-`Button` host element.
|
|
133
|
+
*
|
|
134
|
+
* @category mixin
|
|
135
|
+
*/
|
|
136
|
+
export const primaryStyle: CSSMixinDescriptor = createButtonCss(theme.colors.action.primary)
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Secondary visual treatment for buttons. Combine with {@link baseStyle} when
|
|
140
|
+
* styling a non-`Button` host element.
|
|
141
|
+
*
|
|
142
|
+
* @category mixin
|
|
143
|
+
*/
|
|
144
|
+
export const secondaryStyle: CSSMixinDescriptor = createButtonCss(theme.colors.action.secondary)
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Ghost visual treatment for buttons — transparent background with a hover
|
|
148
|
+
* surface. Combine with {@link baseStyle} when styling a non-`Button` host
|
|
149
|
+
* element.
|
|
150
|
+
*
|
|
151
|
+
* @category mixin
|
|
152
|
+
*/
|
|
101
153
|
export const ghostStyle = ghostButtonToneCss
|
|
102
|
-
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Danger visual treatment for destructive actions. Combine with
|
|
157
|
+
* {@link baseStyle} when styling a non-`Button` host element.
|
|
158
|
+
*
|
|
159
|
+
* @category mixin
|
|
160
|
+
*/
|
|
161
|
+
export const dangerStyle: CSSMixinDescriptor = createButtonCss(theme.colors.action.danger)
|
|
103
162
|
|
|
104
163
|
const toneStyleByTone = {
|
|
105
164
|
primary: primaryStyle,
|
|
@@ -108,16 +167,55 @@ const toneStyleByTone = {
|
|
|
108
167
|
danger: dangerStyle,
|
|
109
168
|
} as const
|
|
110
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Visual treatment supported by {@link Button} — `'primary'`, `'secondary'`,
|
|
172
|
+
* `'ghost'`, or `'danger'`.
|
|
173
|
+
*/
|
|
111
174
|
export type ButtonTone = keyof typeof toneStyleByTone
|
|
112
175
|
|
|
176
|
+
/**
|
|
177
|
+
* Props accepted by the {@link Button} component.
|
|
178
|
+
*
|
|
179
|
+
* Extends the native `<button>` element props with optional icon slots and a
|
|
180
|
+
* tone variant
|
|
181
|
+
*/
|
|
113
182
|
export type ButtonProps = Omit<Props<'button'>, 'children'> & {
|
|
183
|
+
/**
|
|
184
|
+
* Content rendered inside the button's label slot.
|
|
185
|
+
*/
|
|
114
186
|
readonly children?: RemixNode
|
|
187
|
+
/**
|
|
188
|
+
* Decorative icon rendered after the label, inside the icon slot.
|
|
189
|
+
*/
|
|
115
190
|
readonly endIcon?: RemixNode
|
|
191
|
+
/**
|
|
192
|
+
* Decorative icon rendered before the label, inside the icon slot.
|
|
193
|
+
*/
|
|
116
194
|
readonly startIcon?: RemixNode
|
|
195
|
+
/**
|
|
196
|
+
* Visual treatment to apply to the button (default `'secondary'`).
|
|
197
|
+
*/
|
|
117
198
|
readonly tone?: ButtonTone
|
|
118
199
|
}
|
|
119
200
|
|
|
120
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Renders a `<button>` with `baseStyle` and the resolved tone style, along with
|
|
203
|
+
* optional start and end icons.
|
|
204
|
+
*
|
|
205
|
+
* @param handle Component handle providing the runtime API and the resolved {@link ButtonProps}.
|
|
206
|
+
* @returns A render function for the button element.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```tsx
|
|
210
|
+
* import { Button } from '@remix-run/ui/button'
|
|
211
|
+
* import { Glyph } from '@remix-run/ui/glyph'
|
|
212
|
+
*
|
|
213
|
+
* <Button startIcon={<Glyph name="add" />} tone="primary">
|
|
214
|
+
* Create project
|
|
215
|
+
* </Button>
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
export function Button(handle: Handle<ButtonProps>): () => RemixNode {
|
|
121
219
|
return () => {
|
|
122
220
|
let { children, endIcon, mix, startIcon, tone = 'secondary', ...buttonProps } = handle.props
|
|
123
221
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Button } from '@remix-run/ui/button'
|
|
2
|
+
import { css } from '@remix-run/ui'
|
|
3
|
+
import { theme } from '@remix-run/ui/theme'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @name Button Component
|
|
7
|
+
* @description The Button component wraps the low-level style primitives and accepts a tone prop for quick theming.
|
|
8
|
+
* @order 2
|
|
9
|
+
*/
|
|
10
|
+
export default function Example() {
|
|
11
|
+
return () => (
|
|
12
|
+
<div mix={buttonRowCss}>
|
|
13
|
+
<Button tone="primary" type="submit">
|
|
14
|
+
Save
|
|
15
|
+
</Button>
|
|
16
|
+
<Button tone="secondary">Secondary</Button>
|
|
17
|
+
<Button tone="ghost">Ghost</Button>
|
|
18
|
+
<Button tone="danger">Delete</Button>
|
|
19
|
+
</div>
|
|
20
|
+
)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const buttonRowCss = css({
|
|
24
|
+
display: 'flex',
|
|
25
|
+
alignItems: 'center',
|
|
26
|
+
gap: theme.space.sm,
|
|
27
|
+
})
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { css } from '@remix-run/ui'
|
|
2
|
+
import * as button from '@remix-run/ui/button'
|
|
3
|
+
import { Glyph } from '@remix-run/ui/glyph'
|
|
4
|
+
import { theme } from '@remix-run/ui/theme'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @name Basic Button
|
|
8
|
+
* @description The default button contract supports both ordinary actions and link-shaped navigation.
|
|
9
|
+
* @order 1
|
|
10
|
+
*/
|
|
11
|
+
export default function Example() {
|
|
12
|
+
return () => (
|
|
13
|
+
<div mix={buttonRowCss}>
|
|
14
|
+
<button type="submit" mix={[button.baseStyle, button.primaryStyle]}>
|
|
15
|
+
<Glyph mix={button.iconStyle} name="add" />
|
|
16
|
+
<span mix={button.labelStyle}>Publish</span>
|
|
17
|
+
</button>
|
|
18
|
+
<a href="/api/remix/ui/button/overview/" mix={[button.baseStyle, button.secondaryStyle]}>
|
|
19
|
+
<span mix={button.labelStyle}>View button docs</span>
|
|
20
|
+
<Glyph mix={button.iconStyle} name="chevronRight" />
|
|
21
|
+
</a>
|
|
22
|
+
</div>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const buttonRowCss = css({
|
|
27
|
+
display: 'flex',
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
gap: theme.space.sm,
|
|
30
|
+
})
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as button from '@remix-run/ui/button'
|
|
2
|
+
import { css } from '@remix-run/ui'
|
|
3
|
+
import { Glyph } from '@remix-run/ui/glyph'
|
|
4
|
+
import { theme } from '@remix-run/ui/theme'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @name Button States
|
|
8
|
+
* @description Buttons support normal, disabled, and busy (loading) states using aria attributes.
|
|
9
|
+
* @order 3
|
|
10
|
+
*/
|
|
11
|
+
export default function Example() {
|
|
12
|
+
return () => (
|
|
13
|
+
<div mix={buttonRowCss}>
|
|
14
|
+
<button mix={[button.baseStyle, button.primaryStyle]}>
|
|
15
|
+
<Glyph mix={button.iconStyle} name="add" />
|
|
16
|
+
<span mix={button.labelStyle}>New issue</span>
|
|
17
|
+
</button>
|
|
18
|
+
|
|
19
|
+
<button mix={[button.baseStyle, button.ghostStyle]}>
|
|
20
|
+
<span mix={button.labelStyle}>Open</span>
|
|
21
|
+
<Glyph mix={button.iconStyle} name="chevronRight" />
|
|
22
|
+
</button>
|
|
23
|
+
|
|
24
|
+
<button disabled mix={[button.baseStyle, button.secondaryStyle]}>
|
|
25
|
+
<span mix={button.labelStyle}>Disabled</span>
|
|
26
|
+
</button>
|
|
27
|
+
|
|
28
|
+
<button aria-busy="true" mix={[button.baseStyle, button.secondaryStyle]}>
|
|
29
|
+
<Glyph mix={[button.iconStyle, spinnerGlyphCss, spinCss]} name="spinner" />
|
|
30
|
+
<span mix={button.labelStyle}>Saving</span>
|
|
31
|
+
</button>
|
|
32
|
+
</div>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const buttonRowCss = css({
|
|
37
|
+
display: 'flex',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
gap: theme.space.sm,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
const spinnerGlyphCss = css({
|
|
43
|
+
opacity: 0.72,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const spinCss = css({
|
|
47
|
+
'@keyframes demo-button-spin': {
|
|
48
|
+
from: { transform: 'rotate(0deg)' },
|
|
49
|
+
to: { transform: 'rotate(360deg)' },
|
|
50
|
+
},
|
|
51
|
+
animation: 'demo-button-spin 1s linear infinite',
|
|
52
|
+
})
|
|
@@ -8,7 +8,7 @@ Use it when the user should type draft text, filter a popup list, and still comm
|
|
|
8
8
|
|
|
9
9
|
```tsx
|
|
10
10
|
import { css, type Handle } from 'remix/ui'
|
|
11
|
-
import { Combobox, ComboboxOption, onComboboxChange } from 'remix/ui'
|
|
11
|
+
import { Combobox, ComboboxOption, onComboboxChange } from 'remix/ui/combobox'
|
|
12
12
|
|
|
13
13
|
let airports = [
|
|
14
14
|
{
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @jsxRuntime classic
|
|
2
|
-
// @jsx createElement
|
|
3
1
|
import {
|
|
4
2
|
attrs,
|
|
5
3
|
css,
|
|
@@ -8,9 +6,11 @@ import {
|
|
|
8
6
|
on,
|
|
9
7
|
ref,
|
|
10
8
|
type CSSMixinDescriptor,
|
|
9
|
+
type Dispatched,
|
|
11
10
|
type ElementProps,
|
|
12
11
|
type Handle,
|
|
13
12
|
type MixinHandle,
|
|
13
|
+
type MixinFactory,
|
|
14
14
|
type Props,
|
|
15
15
|
type RemixNode,
|
|
16
16
|
} from '@remix-run/ui'
|
|
@@ -26,8 +26,8 @@ import { wait } from '../../utils/wait.ts'
|
|
|
26
26
|
const COMBOBOX_CHANGE_EVENT = 'rmx:combobox-change' as const
|
|
27
27
|
const INPUT_COMMIT_DELAY_MS = 50
|
|
28
28
|
|
|
29
|
-
type ComboboxChangeHandler = (
|
|
30
|
-
event: ComboboxChangeEvent,
|
|
29
|
+
type ComboboxChangeHandler<target extends HTMLElement> = (
|
|
30
|
+
event: Dispatched<ComboboxChangeEvent, target>,
|
|
31
31
|
signal: AbortSignal,
|
|
32
32
|
) => void | Promise<void>
|
|
33
33
|
|
|
@@ -214,7 +214,9 @@ function getOptionSearchValue(option: {
|
|
|
214
214
|
return option.searchValue ?? option.textValue ?? option.label
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
function ComboboxProvider(
|
|
217
|
+
function ComboboxProvider(
|
|
218
|
+
handle: Handle<ComboboxContextProps, ComboboxContextValue>,
|
|
219
|
+
): () => RemixNode {
|
|
218
220
|
let inputRef: HTMLInputElement | undefined
|
|
219
221
|
let listboxRef: listbox.ListboxRef | undefined
|
|
220
222
|
let surfaceRef: HTMLElement | undefined
|
|
@@ -808,7 +810,11 @@ function getComboboxContext(handle: Handle | MixinHandle) {
|
|
|
808
810
|
return handle.context.get(ComboboxProvider)
|
|
809
811
|
}
|
|
810
812
|
|
|
811
|
-
const inputMixin
|
|
813
|
+
const inputMixin: MixinFactory<HTMLInputElement, [], ElementProps> = createMixin<
|
|
814
|
+
HTMLInputElement,
|
|
815
|
+
[],
|
|
816
|
+
ElementProps
|
|
817
|
+
>((handle) => {
|
|
812
818
|
let context = getComboboxContext(handle)
|
|
813
819
|
|
|
814
820
|
return (props) => [
|
|
@@ -883,7 +889,11 @@ const inputMixin = createMixin<HTMLInputElement, [], ElementProps>((handle) => {
|
|
|
883
889
|
]
|
|
884
890
|
})
|
|
885
891
|
|
|
886
|
-
const popoverMixin
|
|
892
|
+
const popoverMixin: MixinFactory<HTMLElement, [], ElementProps> = createMixin<
|
|
893
|
+
HTMLElement,
|
|
894
|
+
[],
|
|
895
|
+
ElementProps
|
|
896
|
+
>((handle) => {
|
|
887
897
|
let context = getComboboxContext(handle)
|
|
888
898
|
|
|
889
899
|
return () => [
|
|
@@ -909,12 +919,20 @@ const popoverMixin = createMixin<HTMLElement, [], ElementProps>((handle) => {
|
|
|
909
919
|
]
|
|
910
920
|
})
|
|
911
921
|
|
|
912
|
-
const listMixin
|
|
922
|
+
const listMixin: MixinFactory<HTMLElement, [], ElementProps> = createMixin<
|
|
923
|
+
HTMLElement,
|
|
924
|
+
[],
|
|
925
|
+
ElementProps
|
|
926
|
+
>((handle) => {
|
|
913
927
|
let context = getComboboxContext(handle)
|
|
914
928
|
return () => [attrs({ id: context.listId }), listbox.list()]
|
|
915
929
|
})
|
|
916
930
|
|
|
917
|
-
const hiddenInputMixin
|
|
931
|
+
const hiddenInputMixin: MixinFactory<HTMLInputElement, [], ElementProps> = createMixin<
|
|
932
|
+
HTMLInputElement,
|
|
933
|
+
[],
|
|
934
|
+
ElementProps
|
|
935
|
+
>((handle) => {
|
|
918
936
|
let context = getComboboxContext(handle)
|
|
919
937
|
return () =>
|
|
920
938
|
attrs({
|
|
@@ -925,8 +943,8 @@ const hiddenInputMixin = createMixin<HTMLInputElement, [], ElementProps>((handle
|
|
|
925
943
|
})
|
|
926
944
|
})
|
|
927
945
|
|
|
928
|
-
const optionMixin
|
|
929
|
-
(handle) => {
|
|
946
|
+
const optionMixin: MixinFactory<HTMLElement, [options: ComboboxOptionOptions], ElementProps> =
|
|
947
|
+
createMixin<HTMLElement, [options: ComboboxOptionOptions], ElementProps>((handle) => {
|
|
930
948
|
let context = getComboboxContext(handle)
|
|
931
949
|
|
|
932
950
|
return (options) => {
|
|
@@ -947,8 +965,7 @@ const optionMixin = createMixin<HTMLElement, [options: ComboboxOptionOptions], E
|
|
|
947
965
|
}),
|
|
948
966
|
]
|
|
949
967
|
}
|
|
950
|
-
}
|
|
951
|
-
)
|
|
968
|
+
})
|
|
952
969
|
|
|
953
970
|
export const Context = ComboboxProvider
|
|
954
971
|
export const hiddenInput = hiddenInputMixin
|
|
@@ -966,15 +983,14 @@ const combobox = {
|
|
|
966
983
|
popover: popoverMixin,
|
|
967
984
|
} as const
|
|
968
985
|
|
|
969
|
-
export function onComboboxChange
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
)
|
|
986
|
+
export function onComboboxChange<target extends HTMLElement>(
|
|
987
|
+
handler: ComboboxChangeHandler<target>,
|
|
988
|
+
captureBoolean?: boolean,
|
|
989
|
+
): ReturnType<typeof on<target, typeof COMBOBOX_CHANGE_EVENT>> {
|
|
990
|
+
return on(COMBOBOX_CHANGE_EVENT, handler, captureBoolean)
|
|
975
991
|
}
|
|
976
992
|
|
|
977
|
-
export function Combobox(handle: Handle<ComboboxProps>) {
|
|
993
|
+
export function Combobox(handle: Handle<ComboboxProps>): () => RemixNode {
|
|
978
994
|
return () => {
|
|
979
995
|
let { children, defaultValue, disabled, inputId, name, placeholder, ...divProps } = handle.props
|
|
980
996
|
|
|
@@ -997,7 +1013,7 @@ export function Combobox(handle: Handle<ComboboxProps>) {
|
|
|
997
1013
|
}
|
|
998
1014
|
}
|
|
999
1015
|
|
|
1000
|
-
export function ComboboxOption(handle: Handle<ComboboxOptionProps>) {
|
|
1016
|
+
export function ComboboxOption(handle: Handle<ComboboxOptionProps>): () => RemixNode {
|
|
1001
1017
|
return () => {
|
|
1002
1018
|
let { children, disabled, label, mix, searchValue, value, ...divProps } = handle.props
|
|
1003
1019
|
|