@iota/apps-ui-kit 0.9.2 → 0.9.4
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/CHANGELOG.md +28 -0
- package/README.md +34 -4
- package/dist/index.d.ts +24 -37
- package/dist/index.es.js +2553 -2465
- package/dist/index.es.js.map +1 -1
- package/dist/index.umd.js +10 -10
- package/dist/index.umd.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -3
- package/src/lib/components/atoms/button/Button.tsx +4 -2
- package/src/lib/components/atoms/button-segment/ButtonSegment.tsx +4 -2
- package/src/lib/components/atoms/checkbox/Checkbox.tsx +3 -1
- package/src/lib/components/atoms/header/Header.tsx +2 -0
- package/src/lib/components/atoms/key-value-info/KeyValueInfo.tsx +1 -1
- package/src/lib/components/atoms/list-item/ListItem.tsx +3 -1
- package/src/lib/components/atoms/radio-button/RadioButton.tsx +3 -1
- package/src/lib/components/atoms/snackbar/Snackbar.tsx +4 -4
- package/src/lib/components/atoms/toggle/Toggle.tsx +4 -1
- package/src/lib/components/atoms/toggle/toggle.classes.ts +3 -3
- package/src/lib/components/molecules/account/Account.tsx +6 -46
- package/src/lib/components/molecules/address/Address.tsx +5 -4
- package/src/lib/components/molecules/card/Card.tsx +6 -2
- package/src/lib/components/molecules/chip/Chip.tsx +11 -5
- package/src/lib/components/molecules/display-stats/DisplayStats.tsx +1 -1
- package/src/lib/components/molecules/input/Input.tsx +2 -0
- package/src/lib/components/molecules/navbar-item/NavbarItem.tsx +1 -1
- package/src/lib/components/molecules/navbar-item/NavbarItemHorizontal.tsx +3 -0
- package/src/lib/components/molecules/navbar-item/NavbarItemVertical.tsx +3 -0
- package/src/lib/components/molecules/search/Search.tsx +11 -1
- package/src/lib/components/molecules/select/Select.tsx +32 -24
- package/src/lib/components/molecules/table-header-cell/TableHeaderCell.tsx +12 -1
- package/src/lib/components/molecules/visual-asset-card/VisualAssetCard.tsx +2 -1
- package/src/lib/components/organisms/accordion/Accordion.tsx +2 -0
- package/src/lib/components/organisms/dialog/Dialog.tsx +10 -3
- package/src/lib/components/organisms/navbar/Navbar.tsx +2 -0
- package/src/lib/components/organisms/navbar/NavbarSlideout.tsx +1 -0
- package/src/lib/components/organisms/table/Table.tsx +7 -0
- package/src/lib/tailwind/base.presets.ts +42 -0
- package/src/storybook/stories/molecules/Account.stories.tsx +2 -14
|
@@ -16,7 +16,9 @@ export type SelectOption =
|
|
|
16
16
|
| { id: string; renderLabel: () => React.JSX.Element }
|
|
17
17
|
| { id: string; label: React.ReactNode };
|
|
18
18
|
|
|
19
|
-
interface SelectProps
|
|
19
|
+
interface SelectProps
|
|
20
|
+
extends Pick<React.HTMLProps<HTMLSelectElement>, 'disabled'>,
|
|
21
|
+
React.AriaAttributes {
|
|
20
22
|
/**
|
|
21
23
|
* The selected option value.
|
|
22
24
|
*/
|
|
@@ -83,6 +85,7 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
83
85
|
value,
|
|
84
86
|
dropdownPosition = DropdownPosition.Bottom,
|
|
85
87
|
size = SelectSize.Default,
|
|
88
|
+
...ariaProps
|
|
86
89
|
},
|
|
87
90
|
ref,
|
|
88
91
|
) => {
|
|
@@ -156,10 +159,13 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
156
159
|
ref={ref}
|
|
157
160
|
onClick={onSelectorClick}
|
|
158
161
|
disabled={disabled}
|
|
162
|
+
aria-expanded={isOpen}
|
|
163
|
+
aria-haspopup="listbox"
|
|
159
164
|
className={cx(
|
|
160
165
|
'select-container select-border-color focus-visible:enabled:select-border-focus-color active:enabled:select-border-focus-color group-[.errored]:select-border-error-color group-[.opened]:select-border-focus-color [&:is(:focus,_:focus-visible,_:active)]:enabled:select-border-focus-color hover:enabled:select-border-hover-color flex flex-row items-center gap-x-3 rounded-lg border py-sm disabled:cursor-not-allowed [&_svg]:h-5 [&_svg]:w-5',
|
|
161
166
|
selectPadding,
|
|
162
167
|
)}
|
|
168
|
+
{...ariaProps}
|
|
163
169
|
>
|
|
164
170
|
{leadingIcon && <span className="select-icon-color">{leadingIcon}</span>}
|
|
165
171
|
|
|
@@ -195,29 +201,31 @@ export const Select = forwardRef<HTMLButtonElement, SelectProps>(
|
|
|
195
201
|
onClick={closeDropdown}
|
|
196
202
|
/>
|
|
197
203
|
)}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
204
|
+
{isOpen && (
|
|
205
|
+
<div
|
|
206
|
+
className={cx(
|
|
207
|
+
'absolute z-50 min-w-full animate-dropdown-show',
|
|
208
|
+
dropdownPosition === DropdownPosition.Top
|
|
209
|
+
? 'bottom-full origin-bottom'
|
|
210
|
+
: 'top-full origin-top',
|
|
211
|
+
)}
|
|
212
|
+
>
|
|
213
|
+
<Dropdown>
|
|
214
|
+
{options.map((option) => {
|
|
215
|
+
const optionIsString = typeof option === 'string';
|
|
216
|
+
return (
|
|
217
|
+
<ListItem
|
|
218
|
+
onClick={() => handleOptionClick(option)}
|
|
219
|
+
hideBottomBorder
|
|
220
|
+
key={optionIsString ? option : option.id}
|
|
221
|
+
>
|
|
222
|
+
<OptionLabel option={option} />
|
|
223
|
+
</ListItem>
|
|
224
|
+
);
|
|
225
|
+
})}
|
|
226
|
+
</Dropdown>
|
|
227
|
+
</div>
|
|
228
|
+
)}
|
|
221
229
|
</div>
|
|
222
230
|
</InputWrapper>
|
|
223
231
|
);
|
|
@@ -6,7 +6,7 @@ import cx from 'classnames';
|
|
|
6
6
|
import { Checkbox } from '@/components/atoms/checkbox';
|
|
7
7
|
import { TableHeaderCellSortOrder } from './tableHeaderCell.enums';
|
|
8
8
|
|
|
9
|
-
export interface TableHeaderCellProps {
|
|
9
|
+
export interface TableHeaderCellProps extends React.AriaAttributes {
|
|
10
10
|
/**
|
|
11
11
|
* The column key.
|
|
12
12
|
*/
|
|
@@ -68,6 +68,7 @@ export function TableHeaderCell({
|
|
|
68
68
|
onSortClick,
|
|
69
69
|
onCheckboxChange,
|
|
70
70
|
sortOrder,
|
|
71
|
+
...ariaProps
|
|
71
72
|
}: TableHeaderCellProps): JSX.Element {
|
|
72
73
|
const handleSort = () => {
|
|
73
74
|
const newSortOrder =
|
|
@@ -107,6 +108,16 @@ export function TableHeaderCell({
|
|
|
107
108
|
'cursor-pointer': hasSort,
|
|
108
109
|
},
|
|
109
110
|
)}
|
|
111
|
+
aria-sort={
|
|
112
|
+
hasSort
|
|
113
|
+
? sortOrder === TableHeaderCellSortOrder.Asc
|
|
114
|
+
? 'ascending'
|
|
115
|
+
: sortOrder === TableHeaderCellSortOrder.Desc
|
|
116
|
+
? 'descending'
|
|
117
|
+
: 'none'
|
|
118
|
+
: undefined
|
|
119
|
+
}
|
|
120
|
+
{...ariaProps}
|
|
110
121
|
>
|
|
111
122
|
<div
|
|
112
123
|
className={cx(
|
|
@@ -7,7 +7,7 @@ import cx from 'classnames';
|
|
|
7
7
|
import { AssetMediaRenderer } from '../../molecules/asset-media-renderer';
|
|
8
8
|
import type { AssetMediaRendererProps } from '../../molecules/asset-media-renderer';
|
|
9
9
|
|
|
10
|
-
interface VisualAssetBaseProps {
|
|
10
|
+
interface VisualAssetBaseProps extends React.AriaAttributes {
|
|
11
11
|
/**
|
|
12
12
|
* The onClick event for the icon.
|
|
13
13
|
*/
|
|
@@ -73,6 +73,7 @@ export function VisualAssetCard({
|
|
|
73
73
|
<ButtonUnstyled
|
|
74
74
|
className="visual-asset-icon-color absolute right-2 top-2 z-10 h-9 w-9 cursor-pointer rounded-full p-xs opacity-0 transition-opacity duration-300 group-hover:bg-shader-neutral-light-72 group-hover:opacity-100 [&_svg]:h-5 [&_svg]:w-5"
|
|
75
75
|
onClick={handleIconClick}
|
|
76
|
+
aria-label="More options"
|
|
76
77
|
>
|
|
77
78
|
{icon}
|
|
78
79
|
</ButtonUnstyled>
|
|
@@ -48,6 +48,8 @@ export function AccordionHeader({
|
|
|
48
48
|
return (
|
|
49
49
|
<div
|
|
50
50
|
onClick={onToggle}
|
|
51
|
+
role="button"
|
|
52
|
+
aria-expanded={isExpanded}
|
|
51
53
|
className={cx(
|
|
52
54
|
'state-layer relative flex cursor-pointer items-center justify-between gap-md overflow-hidden rounded-xl py-sm--rs',
|
|
53
55
|
{
|
|
@@ -42,11 +42,15 @@ const DialogOverlay = React.forwardRef<
|
|
|
42
42
|
<RadixDialog.Overlay
|
|
43
43
|
ref={ref}
|
|
44
44
|
className={cx(
|
|
45
|
-
'
|
|
45
|
+
'dialog-overlay-bg absolute h-full w-full backdrop-blur-md names:backdrop-blur-lg',
|
|
46
|
+
'data-[state=open]:animate-dialog-overlay-show',
|
|
46
47
|
)}
|
|
47
48
|
{...props}
|
|
48
49
|
>
|
|
49
|
-
<DialogClose
|
|
50
|
+
<DialogClose
|
|
51
|
+
className={cx('fixed right-3 top-3', { hidden: !showCloseIcon })}
|
|
52
|
+
aria-label="Close"
|
|
53
|
+
>
|
|
50
54
|
<Close className="button-text-color-neutral" />
|
|
51
55
|
</DialogClose>
|
|
52
56
|
</RadixDialog.Overlay>
|
|
@@ -104,7 +108,7 @@ const DialogContent = React.forwardRef<
|
|
|
104
108
|
: 'overflow-y-auto overflow-x-hidden left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-xl';
|
|
105
109
|
const widthClass =
|
|
106
110
|
position === DialogPosition.Right ? 'md:w-96 max-w-[500px]' : customWidth;
|
|
107
|
-
const heightClass = position === DialogPosition.Right ? 'h-screen' : 'max-h-[
|
|
111
|
+
const heightClass = position === DialogPosition.Right ? 'h-screen' : 'max-h-[90vh] h-full';
|
|
108
112
|
return (
|
|
109
113
|
<RadixDialog.Portal container={containerElement}>
|
|
110
114
|
<DialogContainer isFixedPosition={isFixedPosition}>
|
|
@@ -115,6 +119,9 @@ const DialogContent = React.forwardRef<
|
|
|
115
119
|
'dialog-content-bg dialog-outline absolute flex flex-col justify-center',
|
|
116
120
|
dialogPositioning,
|
|
117
121
|
widthClass,
|
|
122
|
+
position === DialogPosition.Right
|
|
123
|
+
? 'data-[state=open]:animate-dialog-panel-show'
|
|
124
|
+
: 'data-[state=open]:animate-dialog-content-show',
|
|
118
125
|
)}
|
|
119
126
|
{...props}
|
|
120
127
|
>
|
|
@@ -61,6 +61,8 @@ export function Navbar({
|
|
|
61
61
|
<div
|
|
62
62
|
className="state-layer navbar-icon-color relative rounded-full p-xs hover:cursor-pointer sm:hidden [&_svg]:h-6 [&_svg]:w-6"
|
|
63
63
|
onClick={onToggleNavbar}
|
|
64
|
+
role="button"
|
|
65
|
+
aria-label="Toggle menu"
|
|
64
66
|
>
|
|
65
67
|
<MenuIcon />
|
|
66
68
|
</div>
|
|
@@ -119,6 +119,7 @@ export function Table({
|
|
|
119
119
|
icon={<DoubleArrowLeft />}
|
|
120
120
|
disabled={!paginationOptions.hasFirst}
|
|
121
121
|
onClick={paginationOptions.onFirst}
|
|
122
|
+
aria-label="First page"
|
|
122
123
|
/>
|
|
123
124
|
<Button
|
|
124
125
|
type={ButtonType.Secondary}
|
|
@@ -126,6 +127,7 @@ export function Table({
|
|
|
126
127
|
icon={<ArrowLeft />}
|
|
127
128
|
disabled={!paginationOptions.hasPrev}
|
|
128
129
|
onClick={paginationOptions.onPrev}
|
|
130
|
+
aria-label="Previous page"
|
|
129
131
|
/>
|
|
130
132
|
<Button
|
|
131
133
|
type={ButtonType.Secondary}
|
|
@@ -133,6 +135,7 @@ export function Table({
|
|
|
133
135
|
icon={<ArrowRight />}
|
|
134
136
|
disabled={!paginationOptions.hasNext}
|
|
135
137
|
onClick={paginationOptions.onNext}
|
|
138
|
+
aria-label="Next page"
|
|
136
139
|
/>
|
|
137
140
|
<Button
|
|
138
141
|
type={ButtonType.Secondary}
|
|
@@ -140,6 +143,7 @@ export function Table({
|
|
|
140
143
|
icon={<DoubleArrowRight />}
|
|
141
144
|
disabled={!paginationOptions.hasLast}
|
|
142
145
|
onClick={paginationOptions.onLast}
|
|
146
|
+
aria-label="Last page"
|
|
143
147
|
/>
|
|
144
148
|
</>
|
|
145
149
|
)}
|
|
@@ -192,11 +196,13 @@ export function TableBody({ children }: PropsWithChildren): JSX.Element {
|
|
|
192
196
|
export interface TableRowCheckboxProps {
|
|
193
197
|
rowIndex: number;
|
|
194
198
|
onCheckboxChange: (checked: boolean) => void;
|
|
199
|
+
isDisabled?: boolean;
|
|
195
200
|
}
|
|
196
201
|
|
|
197
202
|
export function TableRowCheckbox({
|
|
198
203
|
rowIndex,
|
|
199
204
|
onCheckboxChange,
|
|
205
|
+
isDisabled,
|
|
200
206
|
}: TableRowCheckboxProps): React.JSX.Element {
|
|
201
207
|
const { selectedRowIndexes } = useTableContext();
|
|
202
208
|
|
|
@@ -207,6 +213,7 @@ export function TableRowCheckbox({
|
|
|
207
213
|
onCheckboxChange(event.target.checked);
|
|
208
214
|
}}
|
|
209
215
|
isChecked={selectedRowIndexes.has(rowIndex)}
|
|
216
|
+
isDisabled={isDisabled}
|
|
210
217
|
/>
|
|
211
218
|
</TableCellBase>
|
|
212
219
|
);
|
|
@@ -53,6 +53,48 @@ export const BASE_CONFIG: Config = {
|
|
|
53
53
|
backgroundImage: {
|
|
54
54
|
...NAMES_GRADIENTS,
|
|
55
55
|
},
|
|
56
|
+
keyframes: {
|
|
57
|
+
'dialog-overlay-show': {
|
|
58
|
+
from: { opacity: '0' },
|
|
59
|
+
to: { opacity: '1' },
|
|
60
|
+
},
|
|
61
|
+
'dialog-content-show': {
|
|
62
|
+
from: {
|
|
63
|
+
opacity: '0',
|
|
64
|
+
transform: 'translate(-50%, -50%) scale(0.92)',
|
|
65
|
+
},
|
|
66
|
+
to: {
|
|
67
|
+
opacity: '1',
|
|
68
|
+
transform: 'translate(-50%, -50%) scale(1)',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
'dialog-panel-show': {
|
|
72
|
+
from: {
|
|
73
|
+
opacity: '0',
|
|
74
|
+
transform: 'translateX(12px)',
|
|
75
|
+
},
|
|
76
|
+
to: {
|
|
77
|
+
opacity: '1',
|
|
78
|
+
transform: 'translateX(0)',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
'dropdown-show': {
|
|
82
|
+
from: {
|
|
83
|
+
opacity: '0',
|
|
84
|
+
transform: 'scale(0.94)',
|
|
85
|
+
},
|
|
86
|
+
to: {
|
|
87
|
+
opacity: '1',
|
|
88
|
+
transform: 'scale(1)',
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
animation: {
|
|
93
|
+
'dialog-overlay-show': 'dialog-overlay-show 170ms ease-out',
|
|
94
|
+
'dialog-content-show': 'dialog-content-show 170ms ease-out',
|
|
95
|
+
'dialog-panel-show': 'dialog-panel-show 210ms ease-out',
|
|
96
|
+
'dropdown-show': 'dropdown-show 125ms ease-out',
|
|
97
|
+
},
|
|
56
98
|
},
|
|
57
99
|
},
|
|
58
100
|
};
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
|
|
4
4
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
5
5
|
import { Account, BadgeType } from '@/components';
|
|
6
|
-
import cx from 'classnames';
|
|
7
6
|
|
|
8
7
|
const meta: Meta<typeof Account> = {
|
|
9
8
|
component: Account,
|
|
@@ -21,10 +20,7 @@ export default meta;
|
|
|
21
20
|
|
|
22
21
|
type Story = StoryObj<typeof meta>;
|
|
23
22
|
|
|
24
|
-
const Avatar = (
|
|
25
|
-
const circleFillClass = isLocked
|
|
26
|
-
? 'fill-iota-neutral-80 dark:fill-iota-neutral-30 names:fill-names-neutral-30'
|
|
27
|
-
: 'fill-iota-primary-30';
|
|
23
|
+
const Avatar = () => {
|
|
28
24
|
return (
|
|
29
25
|
<svg
|
|
30
26
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -33,7 +29,7 @@ const Avatar = ({ isLocked }: { isLocked?: boolean }) => {
|
|
|
33
29
|
viewBox="0 0 33 32"
|
|
34
30
|
fill="none"
|
|
35
31
|
>
|
|
36
|
-
<circle cx="16.5" cy="16" r="16" className=
|
|
32
|
+
<circle cx="16.5" cy="16" r="16" className="fill-iota-primary-30" />
|
|
37
33
|
</svg>
|
|
38
34
|
);
|
|
39
35
|
};
|
|
@@ -42,7 +38,6 @@ export const Default: Story = {
|
|
|
42
38
|
args: {
|
|
43
39
|
title: 'Account',
|
|
44
40
|
subtitle: '0x0d7...3f37',
|
|
45
|
-
isLocked: true,
|
|
46
41
|
avatarContent: Avatar,
|
|
47
42
|
},
|
|
48
43
|
argTypes: {
|
|
@@ -50,17 +45,10 @@ export const Default: Story = {
|
|
|
50
45
|
control: 'select',
|
|
51
46
|
options: Object.values(BadgeType),
|
|
52
47
|
},
|
|
53
|
-
isLocked: {
|
|
54
|
-
control: 'boolean',
|
|
55
|
-
},
|
|
56
48
|
onOptionsClick: {
|
|
57
49
|
action: 'onOptionsClick',
|
|
58
50
|
control: 'none',
|
|
59
51
|
},
|
|
60
|
-
onLockAccountClick: {
|
|
61
|
-
action: 'onLockAccount',
|
|
62
|
-
control: 'none',
|
|
63
|
-
},
|
|
64
52
|
avatarContent: {
|
|
65
53
|
control: 'none',
|
|
66
54
|
},
|