oneslash-design-system 2.0.2 → 2.0.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/dist/components/button.d.ts +6 -2
- package/dist/components/button.jsx +13 -2
- package/dist/components/iconButton.d.ts +6 -2
- package/dist/components/iconButton.jsx +13 -2
- package/dist/components/popover.jsx +9 -2
- package/dist/components/tag.d.ts +3 -1
- package/dist/components/tag.jsx +9 -7
- package/dist/components/textField.d.ts +5 -1
- package/dist/components/textField.jsx +2 -2
- package/dist/components/textarea.d.ts +5 -1
- package/dist/components/textarea.jsx +2 -2
- package/dist/stories/Button.stories.d.ts +1 -0
- package/dist/stories/Button.stories.jsx +15 -0
- package/dist/stories/IconButton.stories.d.ts +1 -0
- package/dist/stories/IconButton.stories.jsx +15 -0
- package/dist/stories/Tag.stories.d.ts +1 -0
- package/dist/stories/Tag.stories.jsx +11 -0
- package/dist/stories/TextField.stories.d.ts +1 -0
- package/dist/stories/TextField.stories.jsx +13 -0
- package/dist/stories/Textarea.stories.d.ts +1 -0
- package/dist/stories/Textarea.stories.jsx +13 -0
- package/package.json +1 -1
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
/** `aria-*`, `data-*`, `id` and `title` are forwarded to the rendered `<button>` */
|
|
3
|
+
interface ButtonProps extends React.AriaAttributes {
|
|
4
|
+
id?: string;
|
|
5
|
+
title?: string;
|
|
6
|
+
[dataAttr: `data-${string}`]: string | number | boolean | undefined;
|
|
3
7
|
size: 'tiny' | 'small' | 'medium' | 'large';
|
|
4
8
|
type: 'primary' | 'secondary' | 'tertiary' | 'textOnly';
|
|
5
9
|
color?: 'default' | 'danger';
|
|
@@ -14,5 +18,5 @@ interface ButtonProps {
|
|
|
14
18
|
/** Shows a spinner in the icon slot, keeps the label, and disables the button */
|
|
15
19
|
loading?: boolean;
|
|
16
20
|
}
|
|
17
|
-
export default function Button({ size, type, color, state, label, secondLabel, decoIcon, actionIcon, onClickButton, onClickActionIcon, className, loading, }: ButtonProps): React.JSX.Element;
|
|
21
|
+
export default function Button({ size, type, color, state, label, secondLabel, decoIcon, actionIcon, onClickButton, onClickActionIcon, className, loading, ...rest }: ButtonProps): React.JSX.Element;
|
|
18
22
|
export {};
|
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
import React from 'react';
|
|
3
14
|
import * as LucideIcons from 'lucide-react';
|
|
4
15
|
import { LoadingSmall } from './loadingScreen';
|
|
5
16
|
import { focusRing, focusRingDanger, pressFeedback, stateTransition } from './sharedStyles';
|
|
6
17
|
export default function Button(_a) {
|
|
7
|
-
var size = _a.size, type = _a.type, _b = _a.color, color = _b === void 0 ? 'default' : _b, state = _a.state, label = _a.label, secondLabel = _a.secondLabel, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon, onClickButton = _a.onClickButton, onClickActionIcon = _a.onClickActionIcon, _c = _a.className, className = _c === void 0 ? '' : _c, _d = _a.loading, loading = _d === void 0 ? false : _d;
|
|
18
|
+
var size = _a.size, type = _a.type, _b = _a.color, color = _b === void 0 ? 'default' : _b, state = _a.state, label = _a.label, secondLabel = _a.secondLabel, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon, onClickButton = _a.onClickButton, onClickActionIcon = _a.onClickActionIcon, _c = _a.className, className = _c === void 0 ? '' : _c, _d = _a.loading, loading = _d === void 0 ? false : _d, rest = __rest(_a, ["size", "type", "color", "state", "label", "secondLabel", "decoIcon", "actionIcon", "onClickButton", "onClickActionIcon", "className", "loading"]);
|
|
8
19
|
// Synchronous lookup so icons render on the first paint
|
|
9
20
|
var IconLeft = decoIcon ? LucideIcons[decoIcon] : null;
|
|
10
21
|
var IconRight = actionIcon ? LucideIcons[actionIcon] : null;
|
|
@@ -67,7 +78,7 @@ export default function Button(_a) {
|
|
|
67
78
|
};
|
|
68
79
|
// Hover is pure CSS; `state="hovered"` and `state="focused"` only exist to show those states in docs
|
|
69
80
|
var buttonClasses = "\n flex flex-row items-center rounded-control justify-between ".concat(stateTransition, " ").concat(pressFeedback, "\n ").concat(color === 'danger' ? focusRingDanger : focusRing, "\n ").concat(sizeClasses, "\n ").concat(state === 'selected' ? stateClasses.selected : '', "\n ").concat(state === 'enabled' || state === 'hovered' ? "".concat(baseTypeClasses, " ").concat(loading ? 'cursor-wait' : "".concat(stateClasses.enabled, " ").concat(hoverTypeClasses)) : '', "\n ").concat(state === 'focused' ? "".concat(baseTypeClasses, " ").concat(hoverTypeClasses, " ").concat(stateClasses.focused) : '', "\n ").concat(state === 'disabled' ? stateClasses.disabled : '', "\n ").concat(className, "\n ");
|
|
70
|
-
return (<button type="button" className={buttonClasses} disabled={state === 'disabled' || loading} aria-busy={loading || undefined} onClick={onClickButton}>
|
|
81
|
+
return (<button {...rest} type="button" className={buttonClasses} disabled={state === 'disabled' || loading} aria-busy={loading || undefined} onClick={onClickButton}>
|
|
71
82
|
{/* Group IconLeft and label in a flex container for left alignment */}
|
|
72
83
|
<div className={"flex items-center ".concat(size === 'tiny' ? 'gap-0.5' : 'gap-1')}>
|
|
73
84
|
{loading ? (<LoadingSmall size={spinnerSize}/>) : (IconLeft && <IconLeft className={"".concat(sizeIcon, " flex-shrink-0")} strokeWidth={2}/>)}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import * as LucideIcons from 'lucide-react';
|
|
3
|
-
|
|
3
|
+
/** `aria-*`, `data-*`, `id` and `title` are forwarded to the rendered `<button>` */
|
|
4
|
+
interface IconButtonProps extends React.AriaAttributes {
|
|
5
|
+
id?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
[dataAttr: `data-${string}`]: string | number | boolean | undefined;
|
|
4
8
|
color: "primary" | "secondary" | "tertiary" | "iconOnly";
|
|
5
9
|
state: "enabled" | "selected" | "disabled";
|
|
6
10
|
size: "large" | "medium" | "small" | "tiny";
|
|
@@ -11,5 +15,5 @@ interface IconButtonProps {
|
|
|
11
15
|
ariaLabel?: string;
|
|
12
16
|
}
|
|
13
17
|
export default function IconButton({ color, state, size, iconName, onClick, loading, // Default to false
|
|
14
|
-
ariaLabel, }: IconButtonProps): React.JSX.Element;
|
|
18
|
+
ariaLabel, ...rest }: IconButtonProps): React.JSX.Element;
|
|
15
19
|
export {};
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
2
13
|
import React from 'react';
|
|
3
14
|
import * as LucideIcons from 'lucide-react';
|
|
4
15
|
import { LoadingSmall } from './loadingScreen';
|
|
5
16
|
import { focusRing, pressFeedback, stateTransition } from './sharedStyles';
|
|
6
17
|
export default function IconButton(_a) {
|
|
7
18
|
var color = _a.color, state = _a.state, size = _a.size, iconName = _a.iconName, onClick = _a.onClick, _b = _a.loading, loading = _b === void 0 ? false : _b, // Default to false
|
|
8
|
-
ariaLabel = _a.ariaLabel;
|
|
19
|
+
ariaLabel = _a.ariaLabel, rest = __rest(_a, ["color", "state", "size", "iconName", "onClick", "loading", "ariaLabel"]);
|
|
9
20
|
var Icon = LucideIcons[iconName];
|
|
10
21
|
// "ChevronDown" -> "Chevron Down"
|
|
11
22
|
var label = ariaLabel !== null && ariaLabel !== void 0 ? ariaLabel : String(iconName).replace(/([a-z])([A-Z0-9])/g, '$1 $2');
|
|
@@ -67,7 +78,7 @@ export default function IconButton(_a) {
|
|
|
67
78
|
: state === 'selected'
|
|
68
79
|
? 'cursor-pointer'
|
|
69
80
|
: 'cursor-pointer';
|
|
70
|
-
return (<button type="button" className={"".concat(baseClasses, " ").concat(bgColor, " ").concat(iconColor, " ").concat(bgColorHover, " ").concat(stateClasses, " ").concat(stateTransition, " ").concat(pressFeedback, " ").concat(focusRing, " flex items-center justify-center")} disabled={isDisabled || loading} // Disable button during loading
|
|
81
|
+
return (<button {...rest} type="button" className={"".concat(baseClasses, " ").concat(bgColor, " ").concat(iconColor, " ").concat(bgColorHover, " ").concat(stateClasses, " ").concat(stateTransition, " ").concat(pressFeedback, " ").concat(focusRing, " flex items-center justify-center")} disabled={isDisabled || loading} // Disable button during loading
|
|
71
82
|
onClick={onClick} aria-label={loading ? 'Loading' : label}>
|
|
72
83
|
{loading ? (<LoadingSmall size={size}/>) : (Icon && <Icon className={iconSizeClasses[size]} strokeWidth={2}/>)}
|
|
73
84
|
</button>);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import React, { useState, useEffect, isValidElement } from 'react';
|
|
3
3
|
import { createPortal } from 'react-dom';
|
|
4
4
|
import { usePopper } from 'react-popper';
|
|
5
5
|
import { overlayHidden, overlayTransition, overlayVisible } from './sharedStyles';
|
|
6
6
|
import { useOverlayTransition } from './useOverlayTransition';
|
|
7
|
+
import Menu from './menu';
|
|
7
8
|
export default function Popover(_a) {
|
|
8
9
|
var id = _a.id, anchorEl = _a.anchorEl, open = _a.open, onClose = _a.onClose, children = _a.children;
|
|
9
10
|
var _b = useState(null), popoverElement = _b[0], setPopoverElement = _b[1];
|
|
@@ -44,11 +45,17 @@ export default function Popover(_a) {
|
|
|
44
45
|
}, []);
|
|
45
46
|
if (!mounted || !hasMounted || !anchorEl)
|
|
46
47
|
return null;
|
|
48
|
+
// A Menu brings its own surface (4px inset, container corners), so the
|
|
49
|
+
// popover adds none around it rather than doubling the padding and edges.
|
|
50
|
+
var isMenu = isValidElement(children) && children.type === Menu;
|
|
51
|
+
var panelClass = isMenu
|
|
52
|
+
? ''
|
|
53
|
+
: 'bg-background-overlay dark:ring-1 dark:ring-misc-divider rounded-control shadow-overlay p-2';
|
|
47
54
|
// Render popover in a portal to prevent layout shifts and positioning issues
|
|
48
55
|
// dark-only edge: a ring only in dark mode, so it keeps a dark: variant (it follows whatever dark variant the app's preset/@theme defines, class-only or OS-aware)
|
|
49
56
|
return createPortal(<div id={id} ref={setPopoverElement} style={styles.popper} {...attributes.popper} className="z-[var(--os-z-overlay)]" role="dialog">
|
|
50
57
|
{/* Popper owns the outer transform, so the fade and scale go on this inner panel */}
|
|
51
|
-
<div className={"
|
|
58
|
+
<div className={"".concat(panelClass, " origin-top-left\n ").concat(overlayTransition, " ").concat(visible ? overlayVisible : overlayHidden)}>
|
|
52
59
|
{children}
|
|
53
60
|
</div>
|
|
54
61
|
</div>, document.body // Mounting the popover in the document body for isolation
|
package/dist/components/tag.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ interface TagProps {
|
|
|
10
10
|
secondLabel?: string;
|
|
11
11
|
iconName?: IconName;
|
|
12
12
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
|
13
|
+
/** Only applies to a clickable tag: dims it, drops it from the tab order and ignores clicks */
|
|
14
|
+
disabled?: boolean;
|
|
13
15
|
}
|
|
14
|
-
export default function Tag({ variant, size, state, color, label, secondLabel, iconName, onClick, }: TagProps): JSX.Element;
|
|
16
|
+
export default function Tag({ variant, size, state, color, label, secondLabel, iconName, onClick, disabled, }: TagProps): JSX.Element;
|
|
15
17
|
export {};
|
package/dist/components/tag.jsx
CHANGED
|
@@ -47,7 +47,7 @@ var colorConfig = {
|
|
|
47
47
|
},
|
|
48
48
|
};
|
|
49
49
|
export default function Tag(_a) {
|
|
50
|
-
var variant = _a.variant, size = _a.size, _b = _a.state, state = _b === void 0 ? 'enabled' : _b, color = _a.color, label = _a.label, secondLabel = _a.secondLabel, iconName = _a.iconName, onClick = _a.onClick;
|
|
50
|
+
var variant = _a.variant, size = _a.size, _b = _a.state, state = _b === void 0 ? 'enabled' : _b, color = _a.color, label = _a.label, secondLabel = _a.secondLabel, iconName = _a.iconName, onClick = _a.onClick, _c = _a.disabled, disabled = _c === void 0 ? false : _c;
|
|
51
51
|
// Get icon directly from icons map
|
|
52
52
|
var Icon = iconName ? icons[iconName] : null;
|
|
53
53
|
// Size and padding
|
|
@@ -114,20 +114,22 @@ export default function Tag(_a) {
|
|
|
114
114
|
}
|
|
115
115
|
// Dot color
|
|
116
116
|
var dotColor = (colorStyles === null || colorStyles === void 0 ? void 0 : colorStyles.dot) || colorConfig.default.dot;
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
var isDisabled = !!onClick && disabled;
|
|
118
|
+
// Hover (only when not selected, not disabled, no color, and onClick is provided)
|
|
119
|
+
var hoverClasses = !isSelected && !isDisabled && !color && variant === 'contained' && onClick
|
|
119
120
|
? 'hover:bg-background-accent200'
|
|
120
121
|
: '';
|
|
121
|
-
var cursorClass = onClick && !isSelected ? 'cursor-pointer' : '';
|
|
122
|
+
var cursorClass = isDisabled ? 'cursor-not-allowed opacity-50' : onClick && !isSelected ? 'cursor-pointer' : '';
|
|
122
123
|
// inline-flex so a tag wraps its content instead of stretching to its container
|
|
123
124
|
var baseClasses = "inline-flex items-center gap-1 rounded-full whitespace-nowrap ".concat(stateTransition);
|
|
124
125
|
// A clickable tag is a keyboard-reachable toggle button
|
|
125
126
|
var interactiveProps = onClick
|
|
126
127
|
? {
|
|
127
128
|
role: 'button',
|
|
128
|
-
tabIndex: 0,
|
|
129
|
+
tabIndex: isDisabled ? -1 : 0,
|
|
129
130
|
'aria-pressed': isSelected,
|
|
130
|
-
|
|
131
|
+
'aria-disabled': isDisabled || undefined,
|
|
132
|
+
onClick: isDisabled ? undefined : onClick,
|
|
131
133
|
onKeyDown: function (e) {
|
|
132
134
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
133
135
|
e.preventDefault();
|
|
@@ -136,7 +138,7 @@ export default function Tag(_a) {
|
|
|
136
138
|
},
|
|
137
139
|
}
|
|
138
140
|
: {};
|
|
139
|
-
return (<div className={"".concat(baseClasses, " ").concat(sizeClasses, " ").concat(bgClasses, " ").concat(fontClasses, " ").concat(borderClasses, " ").concat(hoverClasses, " ").concat(cursorClass, " ").concat(onClick ?
|
|
141
|
+
return (<div className={"".concat(baseClasses, " ").concat(sizeClasses, " ").concat(bgClasses, " ").concat(fontClasses, " ").concat(borderClasses, " ").concat(hoverClasses, " ").concat(cursorClass, " ").concat(onClick ? focusRing : '', " ").concat(onClick && !isDisabled ? pressFeedbackAny : '')} {...interactiveProps}>
|
|
140
142
|
{variant === 'dot' && (<span className={"w-3 h-3 rounded-full flex-shrink-0 ".concat(dotColor)}/>)}
|
|
141
143
|
{Icon && variant !== 'dot' && <Icon className={"".concat(size === 'tiny' ? 'w-3 h-3' : 'w-4 h-4', " flex-shrink-0")} strokeWidth={2}/>}
|
|
142
144
|
<div className="flex flex-col text-center">
|
|
@@ -19,6 +19,10 @@ interface TextFieldProps {
|
|
|
19
19
|
required?: boolean;
|
|
20
20
|
size?: 'large' | 'medium' | 'small' | 'tiny';
|
|
21
21
|
placeholder?: string;
|
|
22
|
+
name?: string;
|
|
23
|
+
/** Browser autofill hint, e.g. "username" or "current-password". Defaults to "off". */
|
|
24
|
+
autoComplete?: string;
|
|
25
|
+
tabIndex?: number;
|
|
22
26
|
}
|
|
23
|
-
export default function TextField({ id, label, value, type, onChange, onBlur, onFocus, onKeyDown, onSubmit, autoFocus, multiline, maxRows, disabled, error, errorText, required, size, placeholder, }: TextFieldProps): React.JSX.Element;
|
|
27
|
+
export default function TextField({ id, label, value, type, onChange, onBlur, onFocus, onKeyDown, onSubmit, autoFocus, multiline, maxRows, disabled, error, errorText, required, size, placeholder, name, autoComplete, tabIndex, }: TextFieldProps): React.JSX.Element;
|
|
24
28
|
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
import { stateTransition } from './sharedStyles';
|
|
4
4
|
export default function TextField(_a) {
|
|
5
|
-
var id = _a.id, label = _a.label, value = _a.value, _b = _a.type, type = _b === void 0 ? 'text' : _b, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onSubmit = _a.onSubmit, _c = _a.autoFocus, autoFocus = _c === void 0 ? false : _c, _d = _a.multiline, multiline = _d === void 0 ? false : _d, _e = _a.maxRows, maxRows = _e === void 0 ? 6 : _e, _f = _a.disabled, disabled = _f === void 0 ? false : _f, _g = _a.error, error = _g === void 0 ? false : _g, _h = _a.errorText, errorText = _h === void 0 ? 'This field is required' : _h, _j = _a.required, required = _j === void 0 ? false : _j, _k = _a.size, size = _k === void 0 ? 'medium' : _k, placeholder = _a.placeholder;
|
|
5
|
+
var id = _a.id, label = _a.label, value = _a.value, _b = _a.type, type = _b === void 0 ? 'text' : _b, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onSubmit = _a.onSubmit, _c = _a.autoFocus, autoFocus = _c === void 0 ? false : _c, _d = _a.multiline, multiline = _d === void 0 ? false : _d, _e = _a.maxRows, maxRows = _e === void 0 ? 6 : _e, _f = _a.disabled, disabled = _f === void 0 ? false : _f, _g = _a.error, error = _g === void 0 ? false : _g, _h = _a.errorText, errorText = _h === void 0 ? 'This field is required' : _h, _j = _a.required, required = _j === void 0 ? false : _j, _k = _a.size, size = _k === void 0 ? 'medium' : _k, placeholder = _a.placeholder, name = _a.name, _l = _a.autoComplete, autoComplete = _l === void 0 ? 'off' : _l, tabIndex = _a.tabIndex;
|
|
6
6
|
var handleKeyDown = function (e) {
|
|
7
7
|
// Ctrl+Enter or Cmd+Enter to submit
|
|
8
8
|
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter' && onSubmit) {
|
|
@@ -62,7 +62,7 @@ export default function TextField(_a) {
|
|
|
62
62
|
{label}{required && <span className="text-error-text ml-0.5">*</span>}
|
|
63
63
|
</label>)}
|
|
64
64
|
<div className="relative">
|
|
65
|
-
{multiline ? (<textarea id={id} rows={maxRows} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} autoComplete=
|
|
65
|
+
{multiline ? (<textarea id={id} rows={maxRows} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} name={name} autoComplete={autoComplete} tabIndex={tabIndex} {...errorProps}/>) : (<input id={id} type={type} inputMode={getInputMode()} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} name={name} autoComplete={autoComplete} tabIndex={tabIndex} {...errorProps}/>)}
|
|
66
66
|
</div>
|
|
67
67
|
{error && (<p id={errorId} className="mt-1 text-error-text text-body2">
|
|
68
68
|
{errorText}
|
|
@@ -18,6 +18,10 @@ interface TextareaProps {
|
|
|
18
18
|
errorText?: string;
|
|
19
19
|
size?: 'medium' | 'small' | 'tiny';
|
|
20
20
|
placeholder?: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
/** Browser autofill hint. Defaults to "off". */
|
|
23
|
+
autoComplete?: string;
|
|
24
|
+
tabIndex?: number;
|
|
21
25
|
}
|
|
22
|
-
export default function Textarea({ id, label, value, onChange, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, onSubmit, autoFocus, maxRows, disabled, error, errorText, size, placeholder, }: TextareaProps): React.JSX.Element;
|
|
26
|
+
export default function Textarea({ id, label, value, onChange, onBlur, onFocus, onKeyDown, onCompositionStart, onCompositionEnd, onSubmit, autoFocus, maxRows, disabled, error, errorText, size, placeholder, name, autoComplete, tabIndex, }: TextareaProps): React.JSX.Element;
|
|
23
27
|
export {};
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React, { useCallback, useEffect, useRef } from 'react';
|
|
3
3
|
import { stateTransition } from './sharedStyles';
|
|
4
4
|
export default function Textarea(_a) {
|
|
5
|
-
var id = _a.id, label = _a.label, value = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onCompositionStart = _a.onCompositionStart, onCompositionEnd = _a.onCompositionEnd, onSubmit = _a.onSubmit, _b = _a.autoFocus, autoFocus = _b === void 0 ? false : _b, _c = _a.maxRows, maxRows = _c === void 0 ? 6 : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.error, error = _e === void 0 ? false : _e, _f = _a.errorText, errorText = _f === void 0 ? 'This field is required' : _f, _g = _a.size, size = _g === void 0 ? 'medium' : _g, placeholder = _a.placeholder;
|
|
5
|
+
var id = _a.id, label = _a.label, value = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onCompositionStart = _a.onCompositionStart, onCompositionEnd = _a.onCompositionEnd, onSubmit = _a.onSubmit, _b = _a.autoFocus, autoFocus = _b === void 0 ? false : _b, _c = _a.maxRows, maxRows = _c === void 0 ? 6 : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.error, error = _e === void 0 ? false : _e, _f = _a.errorText, errorText = _f === void 0 ? 'This field is required' : _f, _g = _a.size, size = _g === void 0 ? 'medium' : _g, placeholder = _a.placeholder, name = _a.name, _h = _a.autoComplete, autoComplete = _h === void 0 ? 'off' : _h, tabIndex = _a.tabIndex;
|
|
6
6
|
var textareaRef = useRef(null);
|
|
7
7
|
var handleKeyDown = function (e) {
|
|
8
8
|
// Ctrl+Enter or Cmd+Enter to submit
|
|
@@ -65,7 +65,7 @@ export default function Textarea(_a) {
|
|
|
65
65
|
{label}
|
|
66
66
|
</label>)}
|
|
67
67
|
<div className="relative">
|
|
68
|
-
<textarea ref={textareaRef} id={id} rows={1} className={containerClasses} value={value} onChange={onChange} onInput={adjustHeight} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} onCompositionStart={onCompositionStart} onCompositionEnd={onCompositionEnd} autoFocus={autoFocus} disabled={disabled} autoComplete=
|
|
68
|
+
<textarea ref={textareaRef} id={id} rows={1} className={containerClasses} value={value} onChange={onChange} onInput={adjustHeight} placeholder={placeholder} onFocus={onFocus} onBlur={onBlur} onKeyDown={handleKeyDown} onCompositionStart={onCompositionStart} onCompositionEnd={onCompositionEnd} autoFocus={autoFocus} disabled={disabled} name={name} autoComplete={autoComplete} tabIndex={tabIndex} aria-invalid={error || undefined} aria-describedby={error ? errorId : undefined}/>
|
|
69
69
|
</div>
|
|
70
70
|
{error && (<p id={errorId} className="mt-1 text-error-text text-body2">
|
|
71
71
|
{errorText}
|
|
@@ -146,3 +146,18 @@ export var Loading = {
|
|
|
146
146
|
<Button size="tiny" type="textOnly" state="enabled" label="Saving" loading/>
|
|
147
147
|
</div>); },
|
|
148
148
|
};
|
|
149
|
+
// `aria-*`, `data-*`, `id` and `title` reach the <button>, so an app can mark a toggle
|
|
150
|
+
export var AriaExpanded = {
|
|
151
|
+
args: {
|
|
152
|
+
size: "medium",
|
|
153
|
+
type: "secondary",
|
|
154
|
+
state: "enabled",
|
|
155
|
+
label: "Filters",
|
|
156
|
+
actionIcon: "ChevronDown",
|
|
157
|
+
id: "filters-trigger",
|
|
158
|
+
title: "Show filters",
|
|
159
|
+
"aria-expanded": false,
|
|
160
|
+
"aria-controls": "filters-panel",
|
|
161
|
+
"data-testid": "filters-trigger",
|
|
162
|
+
},
|
|
163
|
+
};
|
|
@@ -86,3 +86,18 @@ export var AllSizes = {
|
|
|
86
86
|
<IconButton color="primary" state="enabled" size="large" iconName="Star"/>
|
|
87
87
|
</div>); },
|
|
88
88
|
};
|
|
89
|
+
// `aria-*`, `data-*`, `id` and `title` reach the <button>, so an app can mark a toggle
|
|
90
|
+
export var AriaExpanded = {
|
|
91
|
+
args: {
|
|
92
|
+
color: "iconOnly",
|
|
93
|
+
state: "enabled",
|
|
94
|
+
size: "medium",
|
|
95
|
+
iconName: "ChevronDown",
|
|
96
|
+
ariaLabel: "Show details",
|
|
97
|
+
id: "details-trigger",
|
|
98
|
+
title: "Show details",
|
|
99
|
+
"aria-expanded": true,
|
|
100
|
+
"aria-controls": "details-panel",
|
|
101
|
+
"data-testid": "details-trigger",
|
|
102
|
+
},
|
|
103
|
+
};
|
|
@@ -9,6 +9,7 @@ export declare const Selected: Story;
|
|
|
9
9
|
export declare const WithIcon: Story;
|
|
10
10
|
export declare const Small: Story;
|
|
11
11
|
export declare const Clickable: Story;
|
|
12
|
+
export declare const ClickableDisabled: Story;
|
|
12
13
|
export declare const AllVariants: Story;
|
|
13
14
|
export declare const Success: Story;
|
|
14
15
|
export declare const Warning: Story;
|
|
@@ -80,6 +80,17 @@ export var Clickable = {
|
|
|
80
80
|
onClick: function () { return alert("Tag clicked!"); },
|
|
81
81
|
},
|
|
82
82
|
};
|
|
83
|
+
// A clickable tag with `disabled`: dimmed, aria-disabled, out of the tab order, clicks ignored
|
|
84
|
+
export var ClickableDisabled = {
|
|
85
|
+
args: {
|
|
86
|
+
variant: "contained",
|
|
87
|
+
size: "medium",
|
|
88
|
+
state: "enabled",
|
|
89
|
+
label: "Unavailable",
|
|
90
|
+
onClick: function () { return alert("Should not fire"); },
|
|
91
|
+
disabled: true,
|
|
92
|
+
},
|
|
93
|
+
};
|
|
83
94
|
export var AllVariants = {
|
|
84
95
|
render: function () { return (<div style={{ display: "flex", gap: "8px", flexWrap: "wrap", alignItems: "center" }}>
|
|
85
96
|
<Tag variant="contained" size="medium" label="Contained"/>
|
|
@@ -143,3 +143,16 @@ export var Number = {
|
|
|
143
143
|
size: "medium",
|
|
144
144
|
},
|
|
145
145
|
};
|
|
146
|
+
// `name` and `autoComplete` let the browser autofill a login form; `tabIndex` reaches the input too
|
|
147
|
+
export var Autofill = {
|
|
148
|
+
render: function (args) { return <TextFieldWrapper {...args}/>; },
|
|
149
|
+
args: {
|
|
150
|
+
id: "autofill-textfield",
|
|
151
|
+
label: "Username",
|
|
152
|
+
value: "",
|
|
153
|
+
name: "username",
|
|
154
|
+
autoComplete: "username",
|
|
155
|
+
tabIndex: 0,
|
|
156
|
+
size: "medium",
|
|
157
|
+
},
|
|
158
|
+
};
|
|
@@ -82,3 +82,16 @@ export var AllSizes = {
|
|
|
82
82
|
<TextareaWrapper id="size-medium" label="Medium" size="medium"/>
|
|
83
83
|
</div>); },
|
|
84
84
|
};
|
|
85
|
+
// `name`, `autoComplete` and `tabIndex` reach the <textarea>
|
|
86
|
+
export var Named = {
|
|
87
|
+
render: function (args) { return <TextareaWrapper {...args}/>; },
|
|
88
|
+
args: {
|
|
89
|
+
id: "named-textarea",
|
|
90
|
+
label: "Message",
|
|
91
|
+
value: "",
|
|
92
|
+
name: "message",
|
|
93
|
+
autoComplete: "off",
|
|
94
|
+
tabIndex: 0,
|
|
95
|
+
size: "medium",
|
|
96
|
+
},
|
|
97
|
+
};
|