@dxos/react-ui 0.1.0 → 0.1.2
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/package.json +4 -2
- package/src/components/AlertDialog/AlertDialog.stories.tsx +35 -0
- package/src/components/AlertDialog/AlertDialog.tsx +127 -0
- package/src/components/AlertDialog/index.ts +5 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.tsx +12 -10
- package/src/components/Button/ButtonProps.ts +2 -0
- package/src/components/Button/buttonStyles.ts +4 -2
- package/src/components/Group/Group.tsx +3 -24
- package/src/components/NavMenu/NavMenu.tsx +5 -5
- package/src/components/QrCode/QrCode.tsx +2 -1
- package/src/components/Tag/Tag.stories.tsx +23 -0
- package/src/components/Tag/Tag.tsx +32 -0
- package/src/components/{Main → Tag}/index.ts +1 -1
- package/src/components/index.ts +2 -1
- package/src/plugin.ts +2 -1
- package/src/props/Elevation.ts +5 -0
- package/src/props/MessageValence.ts +1 -1
- package/src/props/index.ts +1 -0
- package/src/styles/group.ts +27 -0
- package/src/styles/index.ts +2 -0
- package/src/styles/ornament.ts +6 -0
- package/src/typings.d.ts +1 -0
- package/src/components/Main/Main.tsx +0 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Vite plugin which configures a low-level design system for DXOS.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"@fontsource/roboto-flex": "^4.5.2",
|
|
18
18
|
"@fontsource/space-grotesk": "^4.5.10",
|
|
19
19
|
"@headlessui/react": "^1.7.3",
|
|
20
|
+
"@radix-ui/react-alert-dialog": "^1.0.2",
|
|
20
21
|
"@radix-ui/react-avatar": "^1.0.1",
|
|
21
22
|
"@radix-ui/react-dialog": "^1.0.0",
|
|
22
23
|
"@radix-ui/react-navigation-menu": "^1.1.1",
|
|
@@ -31,10 +32,11 @@
|
|
|
31
32
|
"postcss": "^8.4.17",
|
|
32
33
|
"qrcode.react": "^3.1.0",
|
|
33
34
|
"tailwindcss": "^3.1.8",
|
|
35
|
+
"tailwindcss-logical": "^3.0.0",
|
|
34
36
|
"tailwindcss-radix": "^2.6.0"
|
|
35
37
|
},
|
|
36
38
|
"devDependencies": {
|
|
37
|
-
"@dxos/vite-plugin": "0.1.
|
|
39
|
+
"@dxos/vite-plugin": "0.1.2",
|
|
38
40
|
"@types/react": "^18.0.21",
|
|
39
41
|
"@types/react-dom": "^18.0.6",
|
|
40
42
|
"@vitejs/plugin-react": "^2.0.1",
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxosTheme';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { templateForComponent } from '../../testing';
|
|
9
|
+
import { Button } from '../Button';
|
|
10
|
+
import { AlertDialog, AlertDialogProps } from './AlertDialog';
|
|
11
|
+
|
|
12
|
+
export default {
|
|
13
|
+
title: 'react-ui/AlertDialog',
|
|
14
|
+
component: AlertDialog
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const Template = ({ children, ...props }: AlertDialogProps) => {
|
|
18
|
+
return <AlertDialog {...props}>{children}</AlertDialog>;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const Default = templateForComponent(Template)({
|
|
22
|
+
openTrigger: '',
|
|
23
|
+
title: '',
|
|
24
|
+
confirmTrigger: <span />
|
|
25
|
+
});
|
|
26
|
+
Default.args = {
|
|
27
|
+
openTrigger: <Button>Reset device</Button>,
|
|
28
|
+
cancelTrigger: <Button>Cancel</Button>,
|
|
29
|
+
confirmTrigger: <Button variant='primary'>GO</Button>,
|
|
30
|
+
destructiveConfirmString: "I've definitely had my coffee",
|
|
31
|
+
destructiveConfirmInputProps: {
|
|
32
|
+
label: "Type “I've definitely had my coffee” to confirm"
|
|
33
|
+
},
|
|
34
|
+
title: 'Reset your device'
|
|
35
|
+
};
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { Transition } from '@headlessui/react';
|
|
6
|
+
import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog';
|
|
7
|
+
import cx from 'classnames';
|
|
8
|
+
import React, { cloneElement, Fragment, ReactHTMLElement, ReactNode, useEffect, useState } from 'react';
|
|
9
|
+
|
|
10
|
+
import { defaultDescription, defaultFocus } from '../../styles';
|
|
11
|
+
import { Input, InputProps } from '../Input';
|
|
12
|
+
|
|
13
|
+
export interface AlertDialogProps {
|
|
14
|
+
title: ReactNode;
|
|
15
|
+
openTrigger?: ReactNode;
|
|
16
|
+
cancelTrigger?: ReactNode;
|
|
17
|
+
confirmTrigger: Omit<ReactHTMLElement<HTMLElement>, 'ref'>;
|
|
18
|
+
destructiveConfirmString?: string;
|
|
19
|
+
destructiveConfirmInputProps?: Omit<InputProps, 'onChange' | 'initialValue'>;
|
|
20
|
+
titleVisuallyHidden?: boolean;
|
|
21
|
+
description?: ReactNode;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
initiallyOpen?: boolean;
|
|
24
|
+
mountAsSibling?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const AlertDialog = ({
|
|
28
|
+
title,
|
|
29
|
+
titleVisuallyHidden,
|
|
30
|
+
description,
|
|
31
|
+
openTrigger,
|
|
32
|
+
cancelTrigger,
|
|
33
|
+
confirmTrigger,
|
|
34
|
+
destructiveConfirmString,
|
|
35
|
+
destructiveConfirmInputProps,
|
|
36
|
+
children,
|
|
37
|
+
initiallyOpen,
|
|
38
|
+
mountAsSibling
|
|
39
|
+
}: AlertDialogProps) => {
|
|
40
|
+
const [isOpen, setIsOpen] = useState(!!initiallyOpen);
|
|
41
|
+
const [confirmDisabled, setConfirmDisabled] = useState(!!destructiveConfirmString);
|
|
42
|
+
const [confirmStringValue, setConfirmStringValue] = useState('');
|
|
43
|
+
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
if (destructiveConfirmString) {
|
|
46
|
+
setConfirmDisabled(confirmStringValue !== destructiveConfirmString);
|
|
47
|
+
}
|
|
48
|
+
}, [confirmStringValue]);
|
|
49
|
+
|
|
50
|
+
const dialogOverlayAndContent = (
|
|
51
|
+
<Transition.Root show={isOpen}>
|
|
52
|
+
<Transition.Child
|
|
53
|
+
as={Fragment}
|
|
54
|
+
enter='ease-out duration-300'
|
|
55
|
+
enterFrom='opacity-0'
|
|
56
|
+
enterTo='opacity-100'
|
|
57
|
+
leave='ease-in duration-200'
|
|
58
|
+
leaveFrom='opacity-100'
|
|
59
|
+
leaveTo='opacity-0'
|
|
60
|
+
>
|
|
61
|
+
<AlertDialogPrimitive.Overlay forceMount className='fixed inset-0 z-20 bg-black/50' />
|
|
62
|
+
</Transition.Child>
|
|
63
|
+
<Transition.Child
|
|
64
|
+
as={Fragment}
|
|
65
|
+
enter='ease-out duration-300'
|
|
66
|
+
enterFrom='opacity-0 scale-95'
|
|
67
|
+
enterTo='opacity-100 scale-100'
|
|
68
|
+
leave='ease-in duration-200'
|
|
69
|
+
leaveFrom='opacity-100 scale-100'
|
|
70
|
+
leaveTo='opacity-0 scale-95'
|
|
71
|
+
>
|
|
72
|
+
<AlertDialogPrimitive.Content
|
|
73
|
+
forceMount
|
|
74
|
+
className={cx(
|
|
75
|
+
'fixed z-50',
|
|
76
|
+
'w-[95vw] max-w-md rounded-xl p-4 md:w-full',
|
|
77
|
+
'top-[50%] left-[50%] -translate-x-[50%] -translate-y-[50%]',
|
|
78
|
+
'shadow-2xl bg-white dark:bg-neutral-800 elevated-buttons',
|
|
79
|
+
defaultFocus
|
|
80
|
+
)}
|
|
81
|
+
>
|
|
82
|
+
<AlertDialogPrimitive.Title
|
|
83
|
+
className={cx(
|
|
84
|
+
'text-2xl font-display font-medium text-neutral-900 dark:text-neutral-100 rounded-md',
|
|
85
|
+
titleVisuallyHidden && 'sr-only',
|
|
86
|
+
defaultFocus
|
|
87
|
+
)}
|
|
88
|
+
tabIndex={0}
|
|
89
|
+
>
|
|
90
|
+
{title}
|
|
91
|
+
</AlertDialogPrimitive.Title>
|
|
92
|
+
{description && (
|
|
93
|
+
<AlertDialogPrimitive.Description className={cx('mt-2', defaultDescription)}>
|
|
94
|
+
{description}
|
|
95
|
+
</AlertDialogPrimitive.Description>
|
|
96
|
+
)}
|
|
97
|
+
|
|
98
|
+
{children}
|
|
99
|
+
|
|
100
|
+
{destructiveConfirmInputProps && <Input {...destructiveConfirmInputProps} onChange={setConfirmStringValue} />}
|
|
101
|
+
|
|
102
|
+
<div className='flex flex-wrap justify-end gap-4'>
|
|
103
|
+
{cancelTrigger && (
|
|
104
|
+
<AlertDialogPrimitive.Cancel asChild={typeof cancelTrigger !== 'string'}>
|
|
105
|
+
{cancelTrigger}
|
|
106
|
+
</AlertDialogPrimitive.Cancel>
|
|
107
|
+
)}
|
|
108
|
+
<AlertDialogPrimitive.Action asChild>
|
|
109
|
+
{cloneElement(confirmTrigger, { disabled: confirmDisabled })}
|
|
110
|
+
</AlertDialogPrimitive.Action>
|
|
111
|
+
</div>
|
|
112
|
+
</AlertDialogPrimitive.Content>
|
|
113
|
+
</Transition.Child>
|
|
114
|
+
</Transition.Root>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<AlertDialogPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>
|
|
119
|
+
{openTrigger && <AlertDialogPrimitive.Trigger asChild>{openTrigger}</AlertDialogPrimitive.Trigger>}
|
|
120
|
+
{mountAsSibling ? (
|
|
121
|
+
dialogOverlayAndContent
|
|
122
|
+
) : (
|
|
123
|
+
<AlertDialogPrimitive.Portal>{dialogOverlayAndContent}</AlertDialogPrimitive.Portal>
|
|
124
|
+
)}
|
|
125
|
+
</AlertDialogPrimitive.Root>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
@@ -61,7 +61,7 @@ export const Avatar = forwardRef(
|
|
|
61
61
|
)}
|
|
62
62
|
<AvatarPrimitive.Fallback
|
|
63
63
|
className={cx(
|
|
64
|
-
'flex h-full w-full items-center justify-center bg-white dark:bg-neutral-800 overflow-hidden',
|
|
64
|
+
'shrink-0 flex h-full w-full items-center justify-center bg-white dark:bg-neutral-800 overflow-hidden',
|
|
65
65
|
shapeStyles[variant]
|
|
66
66
|
)}
|
|
67
67
|
delayMs={0}
|
|
@@ -8,13 +8,15 @@ import React, { forwardRef } from 'react';
|
|
|
8
8
|
import { ButtonProps } from './ButtonProps';
|
|
9
9
|
import { buttonStyles } from './buttonStyles';
|
|
10
10
|
|
|
11
|
-
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
12
|
+
({ children, compact, variant, rounding, ...props }, ref) => (
|
|
13
|
+
<button
|
|
14
|
+
ref={ref}
|
|
15
|
+
{...props}
|
|
16
|
+
className={cx(buttonStyles({ compact, variant, rounding, disabled: props.disabled }), props.className)}
|
|
17
|
+
{...(props.disabled && { disabled: true })}
|
|
18
|
+
>
|
|
19
|
+
{children}
|
|
20
|
+
</button>
|
|
21
|
+
)
|
|
22
|
+
);
|
|
@@ -13,7 +13,9 @@ export const defaultButtonColors = 'bg-white text-neutral-900 dark:bg-neutral-75
|
|
|
13
13
|
export const buttonStyles = (props: ButtonProps) => {
|
|
14
14
|
const resolvedVariant = props.variant || 'default';
|
|
15
15
|
return cx(
|
|
16
|
-
'inline-flex select-none items-center justify-center
|
|
16
|
+
'inline-flex select-none items-center justify-center text-sm font-medium',
|
|
17
|
+
props.rounding ?? 'rounded-md',
|
|
18
|
+
props.compact ? 'p-1.5' : 'pli-4 plb-2',
|
|
17
19
|
'transition-color duration-100',
|
|
18
20
|
defaultHover(props),
|
|
19
21
|
resolvedVariant === 'default' &&
|
|
@@ -22,7 +24,7 @@ export const buttonStyles = (props: ButtonProps) => {
|
|
|
22
24
|
resolvedVariant === 'primary' && 'border border-primary-550 hover:border-transparent',
|
|
23
25
|
resolvedVariant === 'primary' && primaryButtonColors,
|
|
24
26
|
resolvedVariant === 'outline' &&
|
|
25
|
-
'text-neutral-700 border border-neutral-600
|
|
27
|
+
'text-neutral-700 border border-neutral-600 dark:border-neutral-300 dark:text-neutral-150',
|
|
26
28
|
defaultFocus,
|
|
27
29
|
props.disabled ? defaultDisabled : resolvedVariant !== 'outline' && 'button-elevation',
|
|
28
30
|
// Register all radix states
|
|
@@ -6,6 +6,7 @@ import cx from 'classnames';
|
|
|
6
6
|
import React, { ReactNode } from 'react';
|
|
7
7
|
|
|
8
8
|
import { useId } from '../../hooks';
|
|
9
|
+
import { defaultGroup } from '../../styles/group';
|
|
9
10
|
import { Heading, HeadingProps } from '../Heading';
|
|
10
11
|
|
|
11
12
|
export interface GroupProps extends React.ComponentProps<'div'> {
|
|
@@ -15,32 +16,10 @@ export interface GroupProps extends React.ComponentProps<'div'> {
|
|
|
15
16
|
children?: ReactNode;
|
|
16
17
|
}
|
|
17
18
|
|
|
18
|
-
const
|
|
19
|
-
[0, 'shadow-none'],
|
|
20
|
-
[1, 'shadow-sm'],
|
|
21
|
-
[2, 'shadow'],
|
|
22
|
-
[3, 'shadow-md'],
|
|
23
|
-
[4, 'shadow-lg'],
|
|
24
|
-
[5, 'shadow-xl'],
|
|
25
|
-
[6, 'shadow-2xl']
|
|
26
|
-
]);
|
|
27
|
-
|
|
28
|
-
export const Group = ({ elevation, children, label, labelVisuallyHidden, className, ...props }: GroupProps) => {
|
|
19
|
+
export const Group = ({ elevation = 3, children, label, labelVisuallyHidden, className, ...props }: GroupProps) => {
|
|
29
20
|
const labelId = useId('groupLabel');
|
|
30
21
|
return (
|
|
31
|
-
<div
|
|
32
|
-
role='group'
|
|
33
|
-
aria-labelledby={labelId}
|
|
34
|
-
className={cx(
|
|
35
|
-
'rounded-lg p-4',
|
|
36
|
-
elevation === 0
|
|
37
|
-
? 'bg-transparent border border-neutral-200 dark:border-neutral-700'
|
|
38
|
-
: 'bg-white dark:bg-neutral-800 elevated-buttons',
|
|
39
|
-
elevationClassNameMap.get(typeof elevation === 'undefined' ? 3 : elevation),
|
|
40
|
-
className
|
|
41
|
-
)}
|
|
42
|
-
{...props}
|
|
43
|
-
>
|
|
22
|
+
<div role='group' aria-labelledby={labelId} className={cx(defaultGroup({ elevation }), className)} {...props}>
|
|
44
23
|
<Heading {...label} id={labelId} className={cx(labelVisuallyHidden && 'sr-only', 'mb-2', label?.className)} />
|
|
45
24
|
{children}
|
|
46
25
|
</div>
|
|
@@ -6,7 +6,7 @@ import * as NavigationMenuPrimitive from '@radix-ui/react-navigation-menu';
|
|
|
6
6
|
import cx from 'classnames';
|
|
7
7
|
import React, { ComponentProps, ForwardedRef, forwardRef, ReactNode } from 'react';
|
|
8
8
|
|
|
9
|
-
import { defaultFocus, defaultHover } from '../../styles';
|
|
9
|
+
import { defaultFocus, defaultHover, defaultInlineSeparator } from '../../styles';
|
|
10
10
|
import { defaultButtonColors, primaryButtonColors } from '../Button';
|
|
11
11
|
import { Tooltip, TooltipProps } from '../Tooltip';
|
|
12
12
|
|
|
@@ -122,7 +122,7 @@ const NavMenuTooltipLinkItem = forwardRef(
|
|
|
122
122
|
export const NavMenuLink = NavigationMenuPrimitive.Link;
|
|
123
123
|
|
|
124
124
|
export const NavMenuSeparatorItem = (_props: NavMenuSeparatorProps) => {
|
|
125
|
-
return <span role='none' className='
|
|
125
|
+
return <span role='none' className={cx(defaultInlineSeparator, 'bs-5')} />;
|
|
126
126
|
};
|
|
127
127
|
|
|
128
128
|
const isTooltipLinkItem = (o: any): o is NavMenuTooltipLinkItemProps => 'tooltip' in o;
|
|
@@ -132,7 +132,7 @@ const isSeparator = (o: any): o is NavMenuSeparatorProps => 'separator' in o;
|
|
|
132
132
|
export const NavMenu = ({ items, ...rootProps }: NavMenuProps) => {
|
|
133
133
|
return (
|
|
134
134
|
<NavigationMenuPrimitive.Root {...rootProps} className={cx('flex justify-center', rootProps.className)}>
|
|
135
|
-
<NavigationMenuPrimitive.List className='relative flex flex-row items-center gap-
|
|
135
|
+
<NavigationMenuPrimitive.List className='relative flex flex-row items-center gap-1 rounded-lg bg-white dark:bg-neutral-750 p-1 button-elevation overflow-x-auto'>
|
|
136
136
|
{items.map((item: NavMenuItem, i) => {
|
|
137
137
|
return isTooltipLinkItem(item) ? (
|
|
138
138
|
<NavMenuTooltipLinkItem key={i} {...item} />
|
|
@@ -154,7 +154,7 @@ export const NavMenu = ({ items, ...rootProps }: NavMenuProps) => {
|
|
|
154
154
|
'transition-[width_transform] duration-[250ms] ease-[ease]'
|
|
155
155
|
)}
|
|
156
156
|
>
|
|
157
|
-
<div className='top-1 relative bg-white dark:bg-neutral-
|
|
157
|
+
<div className='top-1 relative bg-white dark:bg-neutral-750 w-2 h-2 rotate-45' />
|
|
158
158
|
</NavigationMenuPrimitive.Indicator>
|
|
159
159
|
</NavigationMenuPrimitive.List>
|
|
160
160
|
|
|
@@ -166,7 +166,7 @@ export const NavMenu = ({ items, ...rootProps }: NavMenuProps) => {
|
|
|
166
166
|
>
|
|
167
167
|
<NavigationMenuPrimitive.Viewport
|
|
168
168
|
className={cx(
|
|
169
|
-
'relative mt-2 shadow-lg rounded-md bg-white dark:bg-neutral-
|
|
169
|
+
'relative mt-2 shadow-lg rounded-md bg-white dark:bg-neutral-750 overflow-hidden',
|
|
170
170
|
'w-radix-navigation-menu-viewport',
|
|
171
171
|
'h-radix-navigation-menu-viewport',
|
|
172
172
|
'radix-state-open:animate-scale-in-content',
|
|
@@ -28,8 +28,9 @@ export const QrCode = ({ value, label, size, side, sideOffset, collisionPadding,
|
|
|
28
28
|
return (
|
|
29
29
|
<Tooltip content={label} {...{ side, sideOffset, collisionPadding }}>
|
|
30
30
|
<Button
|
|
31
|
+
compact
|
|
31
32
|
{...buttonProps}
|
|
32
|
-
className={cx('
|
|
33
|
+
className={cx('overflow-hidden p-0', getSize(size ?? 32), buttonProps.className)}
|
|
33
34
|
onClick={copyValue}
|
|
34
35
|
>
|
|
35
36
|
<QRCodeSVG value={value} includeMargin role='none' className='w-full h-auto' />
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxosTheme';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
|
|
8
|
+
import { templateForComponent } from '../../testing';
|
|
9
|
+
import { Tag, TagProps } from './Tag';
|
|
10
|
+
|
|
11
|
+
export default {
|
|
12
|
+
title: 'react-ui/Tag',
|
|
13
|
+
component: Tag
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const Template = ({ children, ...props }: TagProps) => {
|
|
17
|
+
return <Tag {...props}>{children}</Tag>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const defaultProps = {};
|
|
21
|
+
|
|
22
|
+
export const Default = templateForComponent(Template)(defaultProps);
|
|
23
|
+
Default.args = { children: 'Hello' };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import cx from 'classnames';
|
|
6
|
+
import React, { PropsWithChildren, ReactNode } from 'react';
|
|
7
|
+
|
|
8
|
+
import { MessageValence } from '../../props';
|
|
9
|
+
|
|
10
|
+
export interface TagProps extends React.ComponentProps<'span'> {
|
|
11
|
+
valence?: MessageValence;
|
|
12
|
+
children?: ReactNode;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const valenceColorMap: Record<MessageValence, string> = {
|
|
16
|
+
neutral: 'bg-neutral-100 text-neutral-800 dark:bg-neutral-700 dark:text-neutral-300',
|
|
17
|
+
success: 'bg-success-100 text-success-800 dark:bg-success-700 dark:text-success-300',
|
|
18
|
+
info: 'bg-info-100 text-info-800 dark:bg-info-700 dark:text-info-300',
|
|
19
|
+
warning: 'bg-warning-100 text-warning-800 dark:bg-warning-700 dark:text-warning-300',
|
|
20
|
+
error: 'bg-error-100 text-error-800 dark:bg-error-700 dark:text-error-300'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const Tag = ({ children, valence = 'neutral', ...props }: PropsWithChildren<TagProps>) => {
|
|
24
|
+
return (
|
|
25
|
+
<span
|
|
26
|
+
{...props}
|
|
27
|
+
className={cx('text-xs font-semibold px-2.5 py-0.5 rounded', valenceColorMap[valence], props.className)}
|
|
28
|
+
>
|
|
29
|
+
{children}
|
|
30
|
+
</span>
|
|
31
|
+
);
|
|
32
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
export * from './Alert';
|
|
6
|
+
export * from './AlertDialog';
|
|
6
7
|
export * from './Avatar';
|
|
7
8
|
export * from './Button';
|
|
8
9
|
export * from './CompoundButton';
|
|
@@ -11,10 +12,10 @@ export * from './Group';
|
|
|
11
12
|
export * from './Heading';
|
|
12
13
|
export * from './Loading';
|
|
13
14
|
export * from './Input';
|
|
14
|
-
export * from './Main';
|
|
15
15
|
export * from './NavMenu';
|
|
16
16
|
export * from './Popover';
|
|
17
17
|
export * from './QrCode';
|
|
18
|
+
export * from './Tag';
|
|
18
19
|
export * from './Toast';
|
|
19
20
|
export * from './Tooltip';
|
|
20
21
|
export * from './UiProvider';
|
package/src/plugin.ts
CHANGED
|
@@ -6,6 +6,7 @@ import tailwindcssForms from '@tailwindcss/forms';
|
|
|
6
6
|
import autoprefixer from 'autoprefixer';
|
|
7
7
|
import { resolve } from 'path';
|
|
8
8
|
import tailwindcss from 'tailwindcss';
|
|
9
|
+
import tailwindcssLogical from 'tailwindcss-logical';
|
|
9
10
|
import tailwindcssRadix from 'tailwindcss-radix';
|
|
10
11
|
import tailwindColors from 'tailwindcss/colors';
|
|
11
12
|
import defaultConfig from 'tailwindcss/stubs/defaultConfig.stub.js';
|
|
@@ -251,7 +252,7 @@ export const themePlugin = (options: VitePluginTailwindOptions) => {
|
|
|
251
252
|
}
|
|
252
253
|
}
|
|
253
254
|
},
|
|
254
|
-
plugins: [tailwindcssForms, tailwindcssRadix()],
|
|
255
|
+
plugins: [tailwindcssLogical, tailwindcssForms, tailwindcssRadix()],
|
|
255
256
|
...(env.mode === 'development' && { mode: 'jit' }),
|
|
256
257
|
content: [resolve(root || './', 'node_modules/@dxos/react-ui/dist/**/*.js'), ...config.content]
|
|
257
258
|
}),
|
package/src/props/index.ts
CHANGED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import cx from 'classnames';
|
|
6
|
+
|
|
7
|
+
import { Elevation } from '../props';
|
|
8
|
+
|
|
9
|
+
const elevationClassNameMap = new Map<number, string>([
|
|
10
|
+
[0, 'shadow-none'],
|
|
11
|
+
[1, 'shadow-sm'],
|
|
12
|
+
[2, 'shadow'],
|
|
13
|
+
[3, 'shadow-md'],
|
|
14
|
+
[4, 'shadow-lg'],
|
|
15
|
+
[5, 'shadow-xl'],
|
|
16
|
+
[6, 'shadow-2xl']
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
export const defaultGroup = ({ elevation }: { elevation: Elevation }) => {
|
|
20
|
+
return cx(
|
|
21
|
+
'rounded-lg p-4',
|
|
22
|
+
elevation === 0
|
|
23
|
+
? 'bg-transparent border border-neutral-200 dark:border-neutral-700'
|
|
24
|
+
: 'bg-white dark:bg-neutral-800 elevated-buttons',
|
|
25
|
+
elevationClassNameMap.get(elevation)
|
|
26
|
+
);
|
|
27
|
+
};
|
package/src/styles/index.ts
CHANGED
package/src/typings.d.ts
CHANGED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2022 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import cx from 'classnames';
|
|
6
|
-
import React, { ComponentProps, PropsWithChildren } from 'react';
|
|
7
|
-
|
|
8
|
-
export const Main = ({ children, className, ...mainProps }: PropsWithChildren<ComponentProps<'main'>>) => {
|
|
9
|
-
return (
|
|
10
|
-
<main {...mainProps} className={cx('mt-8 px-8 space-y-4', className)}>
|
|
11
|
-
{children}
|
|
12
|
-
</main>
|
|
13
|
-
);
|
|
14
|
-
};
|