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.
@@ -1,5 +1,9 @@
1
1
  import React from 'react';
2
- interface ButtonProps {
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
- interface IconButtonProps {
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={"bg-background-overlay dark:ring-1 dark:ring-misc-divider rounded-control shadow-overlay p-2 origin-top-left\n ".concat(overlayTransition, " ").concat(visible ? overlayVisible : overlayHidden)}>
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
@@ -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 {};
@@ -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
- // Hover (only when not selected, no color, and onClick is provided)
118
- var hoverClasses = !isSelected && !color && variant === 'contained' && onClick
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
- onClick: onClick,
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 ? "".concat(focusRing, " ").concat(pressFeedbackAny) : '')} {...interactiveProps}>
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="off" {...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} autoComplete="off" {...errorProps}/>)}
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="off" aria-invalid={error || undefined} aria-describedby={error ? errorId : undefined}/>
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}
@@ -17,3 +17,4 @@ export declare const DangerTertiary: Story;
17
17
  export declare const DangerTextOnly: Story;
18
18
  export declare const DangerVariants: Story;
19
19
  export declare const Loading: Story;
20
+ export declare const AriaExpanded: Story;
@@ -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
+ };
@@ -11,3 +11,4 @@ export declare const Selected: Story;
11
11
  export declare const Disabled: Story;
12
12
  export declare const Loading: Story;
13
13
  export declare const AllSizes: Story;
14
+ export declare const AriaExpanded: Story;
@@ -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"/>
@@ -15,3 +15,4 @@ export declare const Email: Story;
15
15
  export declare const Password: Story;
16
16
  export declare const Required: Story;
17
17
  export declare const Number: Story;
18
+ export declare const Autofill: Story;
@@ -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
+ };
@@ -10,3 +10,4 @@ export declare const WithError: Story;
10
10
  export declare const SmallSize: Story;
11
11
  export declare const AutoExpanding: Story;
12
12
  export declare const AllSizes: Story;
13
+ export declare const Named: Story;
@@ -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
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "oneslash-design-system",
3
3
  "description": "A design system for the Oneslash projects",
4
- "version": "2.0.2",
4
+ "version": "2.0.4",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",