oneslash-design-system 1.8.5 → 2.0.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 +20 -6
- package/dist/components/alert.jsx +10 -10
- package/dist/components/button.jsx +22 -22
- package/dist/components/checkBox.jsx +10 -10
- package/dist/components/emptyBox.jsx +2 -2
- package/dist/components/icon.jsx +8 -8
- package/dist/components/iconButton.jsx +16 -16
- package/dist/components/line.jsx +1 -1
- package/dist/components/link.jsx +13 -13
- package/dist/components/loadingScreen.jsx +1 -1
- package/dist/components/menu.jsx +2 -1
- package/dist/components/menuItem.jsx +8 -8
- package/dist/components/modal.jsx +7 -6
- package/dist/components/navigation.jsx +1 -1
- package/dist/components/popover.jsx +3 -2
- package/dist/components/radioGroup.jsx +6 -6
- package/dist/components/select.jsx +10 -10
- package/dist/components/sharedStyles.d.ts +5 -5
- package/dist/components/sharedStyles.jsx +5 -5
- package/dist/components/tab.jsx +4 -4
- package/dist/components/tableCell.jsx +1 -1
- package/dist/components/tableContainer.jsx +1 -1
- package/dist/components/tableHeader.jsx +1 -1
- package/dist/components/tableHeaderCell.jsx +1 -1
- package/dist/components/tabsContainer.jsx +2 -2
- package/dist/components/tag.jsx +36 -36
- package/dist/components/textField.jsx +9 -9
- package/dist/components/textarea.jsx +8 -8
- package/dist/components/timeStamp.jsx +2 -2
- package/dist/components/tooltip.jsx +1 -1
- package/dist/components/useDarkMode.d.ts +3 -0
- package/dist/components/useDarkMode.js +25 -9
- package/dist/components/userImage.jsx +6 -3
- package/dist/designTokens.d.ts +619 -269
- package/dist/designTokens.js +103 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stories/EmptyBox.stories.jsx +1 -0
- package/dist/tailwind-preset-auto.js +402 -0
- package/dist/tailwind-preset.js +396 -0
- package/dist/theme-auto.css +256 -0
- package/dist/theme.css +251 -0
- package/dist/themes/default-auto.css +248 -0
- package/dist/themes/default.css +165 -0
- package/dist/themes/forest-auto.css +248 -0
- package/dist/themes/forest.css +165 -0
- package/dist/tokens.css +19 -0
- package/dist/typography.css +81 -0
- package/package.json +18 -5
- package/dist/output.css +0 -2021
- package/dist/tailwind.config.d.ts +0 -3
- package/dist/tailwind.config.js +0 -222
- package/dist/tsconfig.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -4,17 +4,31 @@ React components and design tokens for oneSlash apps.
|
|
|
4
4
|
|
|
5
5
|
## Using the design system in an app
|
|
6
6
|
|
|
7
|
-
The package ships Tailwind class names,
|
|
8
|
-
|
|
9
|
-
1. **
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
The package ships Tailwind class names, CSS variables and untranspiled `.jsx`. Each app compiles the components itself and picks a theme. Full steps and class renames are in [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md).
|
|
8
|
+
|
|
9
|
+
1. **Import one theme file** (it includes `tokens.css`):
|
|
10
|
+
- light/dark toggle that sets `.dark` on `<html>`: `oneslash-design-system/themes/default.css`
|
|
11
|
+
- follows the OS: `oneslash-design-system/themes/default-auto.css` (`.light` opts out of OS dark)
|
|
12
|
+
- Scindo: `themes/forest.css` / `themes/forest-auto.css`
|
|
13
|
+
2. **Tailwind v3:** `presets: [require("oneslash-design-system/tailwind")]` (toggle) or `oneslash-design-system/tailwind-auto` (OS). Without the preset the components render unstyled.
|
|
14
|
+
3. **Tailwind v4:** import `oneslash-design-system/theme.css` (toggle) or `theme-auto.css` (OS), plus `typography.css` if you want the type scale.
|
|
15
|
+
4. **Next.js:** `transpilePackages: ["oneslash-design-system"]` in `next.config`.
|
|
16
|
+
5. **Scan the components:** v3 `content` gets `./node_modules/oneslash-design-system/dist/**/*.{js,jsx}`; v4 CSS gets `@source "../node_modules/oneslash-design-system/dist/**/*.jsx";`.
|
|
17
|
+
|
|
18
|
+
```css
|
|
19
|
+
/* Tailwind v4, OS-driven dark mode */
|
|
20
|
+
@import "tailwindcss";
|
|
21
|
+
@import "oneslash-design-system/themes/default-auto.css";
|
|
22
|
+
@import "oneslash-design-system/theme-auto.css";
|
|
23
|
+
@import "oneslash-design-system/typography.css";
|
|
24
|
+
@source "../node_modules/oneslash-design-system/dist/**/*.jsx";
|
|
25
|
+
```
|
|
12
26
|
|
|
13
27
|
Use class names that mean the same thing in Tailwind v3 and v4 inside components, since apps on both versions compile them.
|
|
14
28
|
|
|
15
29
|
## Releasing
|
|
16
30
|
|
|
17
|
-
Bump `version` in `package.json`, run `npm run build`, and merge to `main`. The Release workflow publishes to npm, creates the tag and GitHub Release with notes from the merged PR titles, and updates the docs site.
|
|
31
|
+
Bump `version` in `package.json`, run `npm run build`, and merge to `main`. The Release workflow runs the tests and `npm run check:contrast`, then publishes to npm, creates the tag and GitHub Release with notes from the merged PR titles, and updates the docs site.
|
|
18
32
|
|
|
19
33
|
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
|
20
34
|
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
import React, { useEffect, useRef, useState } from 'react';
|
|
3
3
|
import IconButton from './iconButton';
|
|
4
4
|
var bgClassMap = {
|
|
5
|
-
error: 'bg-
|
|
6
|
-
warning: 'bg-
|
|
7
|
-
info: 'bg-
|
|
8
|
-
success: 'bg-
|
|
9
|
-
default: 'bg-
|
|
5
|
+
error: 'bg-error-alertBg',
|
|
6
|
+
warning: 'bg-warning-alertBg',
|
|
7
|
+
info: 'bg-info-alertBg',
|
|
8
|
+
success: 'bg-success-alertBg',
|
|
9
|
+
default: 'bg-secondary-light',
|
|
10
10
|
};
|
|
11
11
|
var AUTO_DISMISS_MS = 5000;
|
|
12
12
|
var EXIT_MS = 150;
|
|
13
13
|
// Toasts slide in from the top edge (position + opacity only), overshooting once, and leave quickly
|
|
14
14
|
var motionClasses = {
|
|
15
|
-
enter: 'duration-[
|
|
16
|
-
exit: 'duration-
|
|
15
|
+
enter: 'duration-[var(--os-duration-pop)] ease-spring',
|
|
16
|
+
exit: 'duration-[var(--os-duration-fast)] ease-in',
|
|
17
17
|
};
|
|
18
18
|
export default function Alert(_a) {
|
|
19
19
|
var _b;
|
|
@@ -64,8 +64,8 @@ export default function Alert(_a) {
|
|
|
64
64
|
var bgClasses = (_b = bgClassMap[type]) !== null && _b !== void 0 ? _b : bgClassMap.default;
|
|
65
65
|
var alertContent = (<div
|
|
66
66
|
// Errors interrupt screen readers; everything else is announced politely
|
|
67
|
-
role={type === 'error' ? 'alert' : 'status'} onMouseEnter={function () { return setIsPaused(true); }} onMouseLeave={function () { return setIsPaused(false); }} onFocus={function () { return setIsPaused(true); }} onBlur={function () { return setIsPaused(false); }} className={"flex ".concat(secondMessage ? 'items-start' : 'items-center', " justify-between w-full p-2 rounded-
|
|
68
|
-
<div className="flex items-start gap-2 text-
|
|
67
|
+
role={type === 'error' ? 'alert' : 'status'} onMouseEnter={function () { return setIsPaused(true); }} onMouseLeave={function () { return setIsPaused(false); }} onFocus={function () { return setIsPaused(true); }} onBlur={function () { return setIsPaused(false); }} className={"flex ".concat(secondMessage ? 'items-start' : 'items-center', " justify-between w-full p-2 rounded-control transition-[opacity,transform] ").concat(isVisible ? motionClasses.enter : motionClasses.exit, " motion-reduce:transition-none ").concat(bgClasses, " ").concat(isVisible ? 'opacity-100 translate-y-0' : variant === 'toast' ? 'opacity-0 -translate-y-[calc(100%+1rem)]' : 'opacity-0', " ").concat(variant === 'toast' ? 'max-w-md pointer-events-auto' : '')}>
|
|
68
|
+
<div className="flex items-start gap-2 text-fg-primary">
|
|
69
69
|
{/* With two lines, nudge the text so its first line centers on the close button */}
|
|
70
70
|
<div className={"flex flex-col text-left ".concat(secondMessage && showCloseButton ? 'pt-[3px]' : '')}>
|
|
71
71
|
<span className="text-body2">{message}</span>
|
|
@@ -79,7 +79,7 @@ export default function Alert(_a) {
|
|
|
79
79
|
if (variant === 'inline') {
|
|
80
80
|
return alertContent;
|
|
81
81
|
}
|
|
82
|
-
return (<div className="fixed top-4 inset-x-0 z-
|
|
82
|
+
return (<div className="fixed top-4 inset-x-0 z-[var(--os-z-overlay)] flex justify-center pointer-events-none">
|
|
83
83
|
{alertContent}
|
|
84
84
|
</div>);
|
|
85
85
|
}
|
|
@@ -25,48 +25,48 @@ export default function Button(_a) {
|
|
|
25
25
|
var spinnerSize = { large: 'large', medium: 'small', small: 'tiny', tiny: 'tiny' }[size];
|
|
26
26
|
var baseTypeClasses = {
|
|
27
27
|
default: {
|
|
28
|
-
primary: 'bg-
|
|
29
|
-
secondary: 'bg-
|
|
30
|
-
tertiary: 'bg-
|
|
31
|
-
textOnly: 'text-
|
|
28
|
+
primary: 'bg-accent-main text-accent-contrast',
|
|
29
|
+
secondary: 'bg-secondary-main text-fg-primary',
|
|
30
|
+
tertiary: 'bg-background-accent100 text-fg-primary',
|
|
31
|
+
textOnly: 'text-fg-primary',
|
|
32
32
|
},
|
|
33
33
|
danger: {
|
|
34
|
-
primary: 'bg-
|
|
35
|
-
secondary: 'bg-
|
|
34
|
+
primary: 'bg-error-main text-error-contrast',
|
|
35
|
+
secondary: 'bg-error-alertBg text-error-text',
|
|
36
36
|
// Inset ring instead of a border so it adds no height
|
|
37
|
-
tertiary: 'bg-transparent ring-1 ring-inset ring-
|
|
38
|
-
textOnly: 'text-
|
|
37
|
+
tertiary: 'bg-transparent ring-1 ring-inset ring-error-main text-error-main',
|
|
38
|
+
textOnly: 'text-error-main',
|
|
39
39
|
},
|
|
40
40
|
}[color][type];
|
|
41
41
|
var hoverTypeClasses = {
|
|
42
42
|
default: {
|
|
43
|
-
primary: 'hover:bg-
|
|
44
|
-
secondary: 'hover:bg-
|
|
45
|
-
tertiary: 'hover:bg-
|
|
46
|
-
textOnly: 'hover:bg-
|
|
43
|
+
primary: 'hover:bg-accent-dark',
|
|
44
|
+
secondary: 'hover:bg-secondary-dark',
|
|
45
|
+
tertiary: 'hover:bg-background-accent200',
|
|
46
|
+
textOnly: 'hover:bg-background-accent100',
|
|
47
47
|
},
|
|
48
48
|
danger: {
|
|
49
|
-
primary: 'hover:bg-
|
|
50
|
-
secondary: 'hover:bg-
|
|
51
|
-
tertiary: 'hover:bg-
|
|
52
|
-
textOnly: 'hover:bg-
|
|
49
|
+
primary: 'hover:bg-error-dark',
|
|
50
|
+
secondary: 'hover:bg-error-tint/60',
|
|
51
|
+
tertiary: 'hover:bg-error-main/10',
|
|
52
|
+
textOnly: 'hover:bg-error-main/10',
|
|
53
53
|
},
|
|
54
54
|
}[color][type];
|
|
55
55
|
// Same outline as real keyboard focus (focusRing), so the demo state matches it and
|
|
56
56
|
// paints no box behind a transparent textOnly button
|
|
57
57
|
var focusedOutline = color === 'danger'
|
|
58
|
-
? 'outline outline-2 outline-offset-2 outline-
|
|
59
|
-
: 'outline outline-2 outline-offset-2 outline-
|
|
58
|
+
? 'outline outline-2 outline-offset-2 outline-error-main'
|
|
59
|
+
: 'outline outline-2 outline-offset-2 outline-fg-primary';
|
|
60
60
|
var stateClasses = {
|
|
61
61
|
enabled: 'cursor-pointer',
|
|
62
62
|
focused: focusedOutline,
|
|
63
63
|
disabled: type === 'textOnly'
|
|
64
|
-
? 'cursor-not-allowed text-
|
|
65
|
-
: 'cursor-not-allowed text-
|
|
66
|
-
selected: 'cursor-pointer bg-
|
|
64
|
+
? 'cursor-not-allowed text-fg-disabled bg-transparent'
|
|
65
|
+
: 'cursor-not-allowed text-fg-disabled bg-actionBackground-disabled',
|
|
66
|
+
selected: 'cursor-pointer bg-primary-dark text-primary-contrast',
|
|
67
67
|
};
|
|
68
68
|
// Hover is pure CSS; `state="hovered"` and `state="focused"` only exist to show those states in docs
|
|
69
|
-
var buttonClasses = "\n flex flex-row items-center rounded-
|
|
69
|
+
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
70
|
return (<button type="button" className={buttonClasses} disabled={state === 'disabled' || loading} aria-busy={loading || undefined} onClick={onClickButton}>
|
|
71
71
|
{/* Group IconLeft and label in a flex container for left alignment */}
|
|
72
72
|
<div className={"flex items-center ".concat(size === 'tiny' ? 'gap-0.5' : 'gap-1')}>
|
|
@@ -17,30 +17,30 @@ export default function Checkbox(_a) {
|
|
|
17
17
|
return (<label className={"group flex items-start ".concat(disabled ? 'cursor-not-allowed' : 'cursor-pointer')}>
|
|
18
18
|
{/* Native input keeps keyboard focus, Space to toggle and screen-reader semantics */}
|
|
19
19
|
<input type="checkbox" className="peer sr-only" checked={isChecked} disabled={disabled} onChange={handleChange}/>
|
|
20
|
-
<span className={"relative flex flex-shrink-0 items-center justify-center w-6 h-6 rounded-full ".concat(stateTransition, "\n peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-0 peer-focus-visible:outline-
|
|
20
|
+
<span className={"relative flex flex-shrink-0 items-center justify-center w-6 h-6 rounded-full ".concat(stateTransition, "\n peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-0 peer-focus-visible:outline-fg-primary\n ").concat(disabled ? '' : 'group-hover:bg-action-selected')}>
|
|
21
21
|
{/* Checkbox */}
|
|
22
22
|
<span className={"relative w-4 h-4 border-2 rounded ".concat(stateTransition, " ").concat(disabled
|
|
23
23
|
? isChecked
|
|
24
|
-
? 'bg-
|
|
25
|
-
: 'border-
|
|
24
|
+
? 'bg-fg-disabled border-transparent'
|
|
25
|
+
: 'border-fg-disabled'
|
|
26
26
|
: isChecked
|
|
27
|
-
? 'bg-
|
|
28
|
-
: 'border-
|
|
27
|
+
? 'bg-fg-primary border-transparent'
|
|
28
|
+
: 'border-fg-secondary', " flex items-center justify-center")}>
|
|
29
29
|
{/* Always rendered so the tick can scale in and out */}
|
|
30
|
-
<svg className={"w-3 h-3 text-
|
|
30
|
+
<svg className={"w-3 h-3 text-fg-contrast ".concat(popTransition, " ").concat(isChecked ? 'scale-100' : 'scale-0')} fill="none" stroke="currentColor" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg" aria-hidden>
|
|
31
31
|
<path strokeWidth="2" d="M1 6l4 3 6-7"/>
|
|
32
32
|
</svg>
|
|
33
33
|
</span>
|
|
34
34
|
</span>
|
|
35
35
|
{(label || secondLabel) && (<span className="flex flex-col ml-2">
|
|
36
36
|
{label && (<span className={"text-body1 ".concat(disabled
|
|
37
|
-
? 'text-
|
|
38
|
-
: 'text-
|
|
37
|
+
? 'text-fg-disabled'
|
|
38
|
+
: 'text-fg-primary')}>
|
|
39
39
|
{label}
|
|
40
40
|
</span>)}
|
|
41
41
|
{secondLabel && (<span className={"text-body2 opacity-70 ".concat(disabled
|
|
42
|
-
? 'text-
|
|
43
|
-
: 'text-
|
|
42
|
+
? 'text-fg-disabled'
|
|
43
|
+
: 'text-fg-primary')}>
|
|
44
44
|
{secondLabel}
|
|
45
45
|
</span>)}
|
|
46
46
|
</span>)}
|
|
@@ -4,8 +4,8 @@ import { AlertCircle } from 'lucide-react';
|
|
|
4
4
|
export default function EmptyBox(_a) {
|
|
5
5
|
var text = _a.text, secondText = _a.secondText, size = _a.size;
|
|
6
6
|
// The icon can be faint; the text needs readable contrast
|
|
7
|
-
var iconColor = 'text-
|
|
8
|
-
var textColor = 'text-
|
|
7
|
+
var iconColor = 'text-fg-disabled';
|
|
8
|
+
var textColor = 'text-fg-secondary';
|
|
9
9
|
var height = size === 'small' ? 'py-6' : 'h-full';
|
|
10
10
|
var iconSize = 'size-6';
|
|
11
11
|
return (<div className={"flex flex-col space-y-2 justify-center items-center w-full ".concat(height)}>
|
package/dist/components/icon.jsx
CHANGED
|
@@ -8,14 +8,14 @@ var sizeMap = {
|
|
|
8
8
|
large: 32,
|
|
9
9
|
};
|
|
10
10
|
var colorMap = {
|
|
11
|
-
primary: 'text-
|
|
12
|
-
secondary: 'text-
|
|
13
|
-
disabled: 'text-
|
|
14
|
-
error: 'text-
|
|
15
|
-
warning: 'text-
|
|
16
|
-
success: 'text-
|
|
17
|
-
info: 'text-
|
|
18
|
-
accent: 'text-
|
|
11
|
+
primary: 'text-fg-primary',
|
|
12
|
+
secondary: 'text-fg-secondary',
|
|
13
|
+
disabled: 'text-fg-disabled',
|
|
14
|
+
error: 'text-error-main',
|
|
15
|
+
warning: 'text-warning-main',
|
|
16
|
+
success: 'text-success-main',
|
|
17
|
+
info: 'text-info-main',
|
|
18
|
+
accent: 'text-accent-main',
|
|
19
19
|
inherit: '',
|
|
20
20
|
};
|
|
21
21
|
export default function Icon(_a) {
|
|
@@ -24,41 +24,41 @@ export default function IconButton(_a) {
|
|
|
24
24
|
tiny: 'size-4', // 16px
|
|
25
25
|
};
|
|
26
26
|
// Base classes (padding and corner radius)
|
|
27
|
-
var baseClasses = "".concat(sizeClasses[size], " rounded-
|
|
27
|
+
var baseClasses = "".concat(sizeClasses[size], " rounded-control leading-none relative");
|
|
28
28
|
// Background color
|
|
29
29
|
var bgColor = isDisabled
|
|
30
|
-
? (color === 'iconOnly' ? '' : 'bg-
|
|
30
|
+
? (color === 'iconOnly' ? '' : 'bg-actionBackground-disabled')
|
|
31
31
|
: state === 'selected'
|
|
32
|
-
? 'bg-
|
|
32
|
+
? 'bg-primary-dark' // Selected state
|
|
33
33
|
: color === 'primary'
|
|
34
|
-
? 'bg-
|
|
34
|
+
? 'bg-accent-main' // Primary
|
|
35
35
|
: color === 'secondary'
|
|
36
|
-
? 'bg-
|
|
36
|
+
? 'bg-secondary-main' // Secondary
|
|
37
37
|
: color === 'tertiary'
|
|
38
|
-
? 'bg-
|
|
38
|
+
? 'bg-background-accent100' // Tertiary
|
|
39
39
|
: ' '; // iconOnly: none
|
|
40
40
|
// Background hover color; `enabled:` skips it while disabled or loading
|
|
41
41
|
var bgColorHover = state === 'selected'
|
|
42
42
|
? '' // No hover effect when selected
|
|
43
43
|
: color === 'primary'
|
|
44
|
-
? 'enabled:hover:bg-
|
|
44
|
+
? 'enabled:hover:bg-accent-dark/75' // Primary
|
|
45
45
|
: color === 'secondary'
|
|
46
|
-
? 'enabled:hover:bg-
|
|
46
|
+
? 'enabled:hover:bg-secondary-dark/75' // Secondary
|
|
47
47
|
: color === 'tertiary'
|
|
48
|
-
? 'enabled:hover:bg-
|
|
49
|
-
: 'enabled:hover:bg-
|
|
48
|
+
? 'enabled:hover:bg-background-accent200/75' // Tertiary
|
|
49
|
+
: 'enabled:hover:bg-background-accent200/75'; // iconOnly
|
|
50
50
|
// Icon color
|
|
51
51
|
var iconColor = isDisabled
|
|
52
|
-
? 'text-
|
|
52
|
+
? 'text-fg-disabled'
|
|
53
53
|
: state === 'selected'
|
|
54
|
-
? 'text-
|
|
54
|
+
? 'text-primary-contrast' // Selected state
|
|
55
55
|
: color === 'primary'
|
|
56
|
-
? 'text-
|
|
56
|
+
? 'text-accent-contrast' // Primary
|
|
57
57
|
: color === 'secondary'
|
|
58
|
-
? 'text-
|
|
58
|
+
? 'text-fg-primary' // Secondary
|
|
59
59
|
: color === 'tertiary'
|
|
60
|
-
? 'text-
|
|
61
|
-
: 'text-
|
|
60
|
+
? 'text-fg-primary' // Tertiary
|
|
61
|
+
: 'text-fg-primary'; // iconOnly
|
|
62
62
|
// State classes, including loading
|
|
63
63
|
var stateClasses = loading
|
|
64
64
|
? 'cursor-wait' // Show a waiting cursor during loading
|
package/dist/components/line.jsx
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export default function Line(_a) {
|
|
4
4
|
var _b = _a.direction, direction = _b === void 0 ? 'horizontal' : _b, _c = _a.className, className = _c === void 0 ? '' : _c;
|
|
5
|
-
var baseClasses = 'bg-
|
|
5
|
+
var baseClasses = 'bg-misc-divider';
|
|
6
6
|
if (direction === 'vertical') {
|
|
7
7
|
return (<div className={"".concat(baseClasses, " w-px h-full ").concat(className)}/>);
|
|
8
8
|
}
|
package/dist/components/link.jsx
CHANGED
|
@@ -19,24 +19,24 @@ export default function Link(_a) {
|
|
|
19
19
|
// Light mode uses the -dark shade so link text keeps 4.5:1 on light backgrounds
|
|
20
20
|
var colorClasses = {
|
|
21
21
|
info: {
|
|
22
|
-
default: 'text-
|
|
23
|
-
hover: 'hover:underline-offset-[4px]
|
|
24
|
-
visited: 'visited:text-
|
|
22
|
+
default: 'text-info-text',
|
|
23
|
+
hover: 'hover:underline-offset-[4px] hover:text-info-textHover',
|
|
24
|
+
visited: 'visited:text-info-textHover',
|
|
25
25
|
},
|
|
26
26
|
error: {
|
|
27
|
-
default: 'text-
|
|
28
|
-
hover: 'hover:underline-offset-[4px]
|
|
29
|
-
visited: 'visited:text-
|
|
27
|
+
default: 'text-error-text',
|
|
28
|
+
hover: 'hover:underline-offset-[4px] hover:text-error-textHover',
|
|
29
|
+
visited: 'visited:text-error-textHover',
|
|
30
30
|
},
|
|
31
31
|
warning: {
|
|
32
|
-
default: 'text-
|
|
33
|
-
hover: 'hover:underline-offset-[4px]
|
|
34
|
-
visited: 'visited:text-
|
|
32
|
+
default: 'text-warning-text',
|
|
33
|
+
hover: 'hover:underline-offset-[4px] hover:text-warning-textHover',
|
|
34
|
+
visited: 'visited:text-warning-textHover',
|
|
35
35
|
},
|
|
36
36
|
success: {
|
|
37
|
-
default: 'text-
|
|
38
|
-
hover: 'hover:underline-offset-[4px]
|
|
39
|
-
visited: 'visited:text-
|
|
37
|
+
default: 'text-success-text',
|
|
38
|
+
hover: 'hover:underline-offset-[4px] hover:text-success-textHover',
|
|
39
|
+
visited: 'visited:text-success-textHover',
|
|
40
40
|
},
|
|
41
41
|
};
|
|
42
42
|
var selectedColorClasses = colorClasses[color];
|
|
@@ -58,7 +58,7 @@ export default function Link(_a) {
|
|
|
58
58
|
body2: 'text-body2',
|
|
59
59
|
caption: 'text-caption',
|
|
60
60
|
}[size];
|
|
61
|
-
var linkClasses = "\n ".concat(sizeClass, "\n ").concat(selectedColorClasses.default, "\n ").concat(selectedColorClasses.hover, "\n ").concat(selectedColorClasses.visited, "\n underline\n underline-offset-[2px]\n decoration-2\n cursor-pointer\n rounded-
|
|
61
|
+
var linkClasses = "\n ".concat(sizeClass, "\n ").concat(selectedColorClasses.default, "\n ").concat(selectedColorClasses.hover, "\n ").concat(selectedColorClasses.visited, "\n underline\n underline-offset-[2px]\n decoration-2\n cursor-pointer\n rounded-inline\n transition-[color,text-underline-offset]\n duration-[var(--os-duration-fast)]\n ease-out\n motion-reduce:transition-none\n ").concat(focusRing, "\n ").concat(className, "\n ").trim().replace(/\s+/g, ' ');
|
|
62
62
|
var commonProps = __assign({ className: linkClasses }, (shouldOpenInNewTab && {
|
|
63
63
|
target: '_blank',
|
|
64
64
|
rel: 'noopener noreferrer',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export default function LoadingScreen() {
|
|
4
4
|
return (<div role="status" aria-label="Loading" className="flex justify-center items-center h-full w-full min-h-[200px]">
|
|
5
|
-
<div className="w-12 h-12 rounded-full border-4 border-current border-t-transparent text-
|
|
5
|
+
<div className="w-12 h-12 rounded-full border-4 border-current border-t-transparent text-fg-primary animate-spin"></div>
|
|
6
6
|
</div>);
|
|
7
7
|
}
|
|
8
8
|
;
|
package/dist/components/menu.jsx
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
import React, { forwardRef } from 'react';
|
|
3
3
|
var Menu = forwardRef(function (_a, ref) {
|
|
4
4
|
var children = _a.children, width = _a.width, _b = _a.className, className = _b === void 0 ? '' : _b;
|
|
5
|
-
|
|
5
|
+
// 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)
|
|
6
|
+
return (<div ref={ref} className={"\n bg-background-overlay\n rounded-container\n shadow-overlay\n dark:ring-1 dark:ring-misc-divider\n overflow-hidden\n ".concat(className, "\n ")} style={{ width: width || 'auto' }}>
|
|
6
7
|
{/* 4px padding keeps the 8px item corners concentric with the 12px menu corners */}
|
|
7
8
|
<div className="p-1 flex flex-col gap-0.5">
|
|
8
9
|
{children}
|
|
@@ -20,9 +20,9 @@ export default function MenuItem(_a) {
|
|
|
20
20
|
var paddingClass = size === 'tiny' ? 'p-1' : 'p-2';
|
|
21
21
|
var content = (<div id={id} role={href ? undefined : role}
|
|
22
22
|
// A link wrapper is already focusable; otherwise the row itself takes focus
|
|
23
|
-
tabIndex={href ? undefined : tabIndex} aria-selected={role === 'option' ? !!isSelected : undefined} className={"\n flex items-center ".concat(paddingClass, " rounded-
|
|
24
|
-
? 'bg-
|
|
25
|
-
: "hover:bg-
|
|
23
|
+
tabIndex={href ? undefined : tabIndex} aria-selected={role === 'option' ? !!isSelected : undefined} className={"\n flex items-center ".concat(paddingClass, " rounded-control cursor-pointer justify-between text-left ").concat(stateTransition, " ").concat(pressFeedbackAny, " ").concat(focusRing, "\n ").concat(isSelected
|
|
24
|
+
? 'bg-primary-dark text-primary-contrast'
|
|
25
|
+
: "hover:bg-background-accent200 ".concat(isActive ? 'bg-background-accent200' : ''), "\n ").concat(className, "\n ")} style={{ width: '100%' }} onClick={onClick} onKeyDown={function (e) {
|
|
26
26
|
if (!href && e.target === e.currentTarget && (e.key === 'Enter' || e.key === ' ')) {
|
|
27
27
|
e.preventDefault();
|
|
28
28
|
e.currentTarget.click();
|
|
@@ -30,12 +30,12 @@ export default function MenuItem(_a) {
|
|
|
30
30
|
}}>
|
|
31
31
|
{/* Left group: icon/userImg + label with 8px gap */}
|
|
32
32
|
<div className="flex items-center gap-2 min-w-0">
|
|
33
|
-
{userImgUrl ? (<UserImage userHandle={userHandle || ''} userImgUrl={userImgUrl}/>) : icon ? (<span className={"".concat(iconSize, " flex-shrink-0 flex items-center justify-center")}>{icon}</span>) : (IconLeft && (<IconLeft className={"".concat(iconSize, " flex-shrink-0 ").concat(isSelected ? 'text-
|
|
33
|
+
{userImgUrl ? (<UserImage userHandle={userHandle || ''} userImgUrl={userImgUrl}/>) : icon ? (<span className={"".concat(iconSize, " flex-shrink-0 flex items-center justify-center")}>{icon}</span>) : (IconLeft && (<IconLeft className={"".concat(iconSize, " flex-shrink-0 ").concat(isSelected ? 'text-primary-contrast' : 'text-fg-secondary')} strokeWidth={2}/>))}
|
|
34
34
|
<div className="flex flex-col min-w-0">
|
|
35
|
-
<span className={"truncate ".concat(labelClass, " ").concat(isSelected ? 'text-
|
|
35
|
+
<span className={"truncate ".concat(labelClass, " ").concat(isSelected ? 'text-primary-contrast' : 'text-fg-primary')}>
|
|
36
36
|
{label}
|
|
37
37
|
</span>
|
|
38
|
-
{secondLabel && (<span className={"truncate ".concat(secondLabelClass, " opacity-70 ").concat(isSelected ? 'text-
|
|
38
|
+
{secondLabel && (<span className={"truncate ".concat(secondLabelClass, " opacity-70 ").concat(isSelected ? 'text-primary-contrast' : 'text-fg-primary')}>
|
|
39
39
|
{secondLabel}
|
|
40
40
|
</span>)}
|
|
41
41
|
</div>
|
|
@@ -46,11 +46,11 @@ export default function MenuItem(_a) {
|
|
|
46
46
|
{tag && (<Tag variant={tag.variant || 'contained'} size={tagSize} label={tag.label} iconName={tag.iconName}
|
|
47
47
|
// 'default' has a fill that stays visible on the menu background
|
|
48
48
|
color={(_b = tag.color) !== null && _b !== void 0 ? _b : 'default'}/>)}
|
|
49
|
-
{IconRight && (<IconRight className={"".concat(iconSize, " ").concat(isSelected ? 'text-
|
|
49
|
+
{IconRight && (<IconRight className={"".concat(iconSize, " ").concat(isSelected ? 'text-primary-contrast' : 'text-fg-secondary', " flex-shrink-0")} strokeWidth={2}/>)}
|
|
50
50
|
{rightAction && (<div onClick={function (e) { return e.stopPropagation(); }}>
|
|
51
51
|
{rightAction}
|
|
52
52
|
</div>)}
|
|
53
53
|
</div>
|
|
54
54
|
</div>);
|
|
55
|
-
return href ? <NextLink href={href} className={"block rounded-
|
|
55
|
+
return href ? <NextLink href={href} className={"block rounded-control ".concat(focusRing)}>{content}</NextLink> : content;
|
|
56
56
|
}
|
|
@@ -70,19 +70,20 @@ export default function Modal(_a) {
|
|
|
70
70
|
};
|
|
71
71
|
if (!mounted)
|
|
72
72
|
return null;
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
// 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)
|
|
74
|
+
return (<div className={"fixed bg-misc-scrim/40 flex items-center justify-center z-[var(--os-z-overlay)]\n transition-opacity duration-[var(--os-duration-fast)] ease-out motion-reduce:transition-none ".concat(visible ? 'opacity-100' : 'opacity-0')} style={{ top: 0, left: 0, right: 0, bottom: 0 }} onClick={handleOverlayClick}>
|
|
75
|
+
<div ref={panelRef} role="dialog" aria-modal="true" aria-labelledby={title ? titleId : undefined} tabIndex={-1} className={"bg-background-elevated dark:ring-1 dark:ring-misc-divider rounded-control ".concat(modalWidth, " flex flex-col outline-none\n ").concat(overlayTransition, " ").concat(visible ? overlayVisible : overlayHidden)} style={{
|
|
75
76
|
maxWidth: maxWidth,
|
|
76
77
|
width: 'calc(100vw - 64px)',
|
|
77
78
|
maxHeight: '90vh',
|
|
78
79
|
overflow: 'hidden',
|
|
79
80
|
}}>
|
|
80
|
-
{(title || actions) && (<div className="px-6 py-3 border-b border-
|
|
81
|
+
{(title || actions) && (<div className="px-6 py-3 border-b border-misc-divider flex justify-between items-start" style={{ flexShrink: 0 }}>
|
|
81
82
|
{title && (<div className="flex flex-col">
|
|
82
|
-
<h2 id={titleId} className="text-h5 text-
|
|
83
|
+
<h2 id={titleId} className="text-h5 text-fg-primary">
|
|
83
84
|
{title}
|
|
84
85
|
</h2>
|
|
85
|
-
{secondTitle && (<span className="text-body2 opacity-70 text-
|
|
86
|
+
{secondTitle && (<span className="text-body2 opacity-70 text-fg-primary">
|
|
86
87
|
{secondTitle}
|
|
87
88
|
</span>)}
|
|
88
89
|
</div>)}
|
|
@@ -91,7 +92,7 @@ export default function Modal(_a) {
|
|
|
91
92
|
</div>)}
|
|
92
93
|
</div>)}
|
|
93
94
|
|
|
94
|
-
<div className="text-body1 space-y-4 text-
|
|
95
|
+
<div className="text-body1 space-y-4 text-fg-primary p-6" style={{
|
|
95
96
|
overflowY: 'auto',
|
|
96
97
|
flexGrow: 1,
|
|
97
98
|
minHeight: 0,
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
export default function Navigation(_a) {
|
|
4
4
|
var children = _a.children, _b = _a.className, className = _b === void 0 ? '' : _b;
|
|
5
|
-
return (<nav className={"\n bg-
|
|
5
|
+
return (<nav className={"\n bg-background-default\n border-r border-misc-divider\n p-2 flex flex-col gap-0.5\n ".concat(className, "\n ")}>
|
|
6
6
|
{children}
|
|
7
7
|
</nav>);
|
|
8
8
|
}
|
|
@@ -45,9 +45,10 @@ export default function Popover(_a) {
|
|
|
45
45
|
if (!mounted || !hasMounted || !anchorEl)
|
|
46
46
|
return null;
|
|
47
47
|
// Render popover in a portal to prevent layout shifts and positioning issues
|
|
48
|
-
|
|
48
|
+
// 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
|
+
return createPortal(<div id={id} ref={setPopoverElement} style={styles.popper} {...attributes.popper} className="z-[var(--os-z-overlay)]" role="dialog">
|
|
49
50
|
{/* Popper owns the outer transform, so the fade and scale go on this inner panel */}
|
|
50
|
-
<div className={"bg-
|
|
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)}>
|
|
51
52
|
{children}
|
|
52
53
|
</div>
|
|
53
54
|
</div>, document.body // Mounting the popover in the document body for isolation
|
|
@@ -11,18 +11,18 @@ export default function RadioGroup(_a) {
|
|
|
11
11
|
return (<label key={option.value} className="group flex items-start cursor-pointer">
|
|
12
12
|
<input type="radio" name={groupName} value={option.value} checked={isSelected} onChange={function () { return onChange(option.value); }} className="peer sr-only"/>
|
|
13
13
|
{/* Hover halo and hit area, same as Checkbox */}
|
|
14
|
-
<span className={"relative flex flex-shrink-0 items-center justify-center w-6 h-6 rounded-full ".concat(stateTransition, "\n group-hover:bg-
|
|
14
|
+
<span className={"relative flex flex-shrink-0 items-center justify-center w-6 h-6 rounded-full ".concat(stateTransition, "\n group-hover:bg-action-selected\n peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-0 peer-focus-visible:outline-fg-primary")}>
|
|
15
15
|
{/* outer circle */}
|
|
16
16
|
<span className={"relative flex justify-center items-center w-4 h-4 rounded-full border-2 ".concat(stateTransition, "\n ").concat(isSelected
|
|
17
|
-
? 'border-
|
|
18
|
-
: 'border-
|
|
17
|
+
? 'border-fg-primary'
|
|
18
|
+
: 'border-fg-secondary', "\n ")}>
|
|
19
19
|
{/* Inner circle; always rendered so it can scale in and out */}
|
|
20
|
-
<span className={"absolute w-2 h-2 rounded-full bg-
|
|
20
|
+
<span className={"absolute w-2 h-2 rounded-full bg-fg-primary ".concat(popTransition, " ").concat(isSelected ? 'scale-100' : 'scale-0')}/>
|
|
21
21
|
</span>
|
|
22
22
|
</span>
|
|
23
23
|
<span className="flex flex-col ml-2">
|
|
24
|
-
<span className="text-body1 text-
|
|
25
|
-
{option.secondLabel && (<span className="text-body2 opacity-70 text-
|
|
24
|
+
<span className="text-body1 text-fg-primary">{option.label}</span>
|
|
25
|
+
{option.secondLabel && (<span className="text-body2 opacity-70 text-fg-primary">{option.secondLabel}</span>)}
|
|
26
26
|
</span>
|
|
27
27
|
</label>);
|
|
28
28
|
})}
|
|
@@ -151,31 +151,31 @@ export default function Select(_a) {
|
|
|
151
151
|
// Determine border and background styles based on state
|
|
152
152
|
var getStateStyles = function () {
|
|
153
153
|
if (disabled) {
|
|
154
|
-
return 'border border-
|
|
154
|
+
return 'border border-actionOutlinedBorder-disabled bg-background-default';
|
|
155
155
|
}
|
|
156
156
|
if (isOpen) {
|
|
157
157
|
// Same 2px offset outline as focus and Button
|
|
158
|
-
return 'border border-
|
|
158
|
+
return 'border border-actionOutlinedBorder-enabled outline outline-2 outline-offset-2 outline-fg-primary bg-background-default';
|
|
159
159
|
}
|
|
160
|
-
return "border border-
|
|
160
|
+
return "border border-actionOutlinedBorder-enabled bg-background-default\n hover:border-fg-secondary hover:bg-action-hover";
|
|
161
161
|
};
|
|
162
162
|
// Determine text color
|
|
163
163
|
var getTextColor = function () {
|
|
164
164
|
if (disabled) {
|
|
165
|
-
return 'text-
|
|
165
|
+
return 'text-fg-disabled';
|
|
166
166
|
}
|
|
167
|
-
return 'text-
|
|
167
|
+
return 'text-fg-primary';
|
|
168
168
|
};
|
|
169
169
|
// Determine icon color
|
|
170
170
|
var getIconColor = function () {
|
|
171
171
|
if (disabled) {
|
|
172
|
-
return 'text-
|
|
172
|
+
return 'text-fg-disabled';
|
|
173
173
|
}
|
|
174
|
-
return 'text-
|
|
174
|
+
return 'text-fg-secondary';
|
|
175
175
|
};
|
|
176
176
|
return (<div className={"relative ".concat(className)} style={{ width: width || '100%' }}>
|
|
177
177
|
{/* Select Button */}
|
|
178
|
-
<div ref={selectRef} role="combobox" aria-haspopup="listbox" aria-expanded={isOpen} aria-controls={listboxId} aria-activedescendant={isOpen && activeIndex >= 0 ? optionId(activeIndex) : undefined} aria-disabled={disabled || undefined} className={"\n rounded-
|
|
178
|
+
<div ref={selectRef} role="combobox" aria-haspopup="listbox" aria-expanded={isOpen} aria-controls={listboxId} aria-activedescendant={isOpen && activeIndex >= 0 ? optionId(activeIndex) : undefined} aria-disabled={disabled || undefined} className={"\n rounded-control\n ".concat(getStateStyles(), "\n ").concat(disabled ? 'cursor-not-allowed' : 'cursor-pointer', "\n ").concat(stateTransition, "\n ").concat(focusRing, "\n ")} onClick={handleToggle} tabIndex={disabled ? -1 : 0} onKeyDown={handleKeyDown}>
|
|
179
179
|
{/* Inner Content Container; 7px vertical padding makes the control 40px like Button and TextField */}
|
|
180
180
|
<div className={"flex items-center justify-between px-2 py-[7px] ".concat(getTextColor())}>
|
|
181
181
|
{/* Content Container */}
|
|
@@ -190,12 +190,12 @@ export default function Select(_a) {
|
|
|
190
190
|
</div>
|
|
191
191
|
|
|
192
192
|
{/* Chevron Icon */}
|
|
193
|
-
<ChevronDown className={"\n w-6 h-6 flex-shrink-0 ml-1\n ".concat(getIconColor(), "\n transition-transform duration-
|
|
193
|
+
<ChevronDown className={"\n w-6 h-6 flex-shrink-0 ml-1\n ".concat(getIconColor(), "\n transition-transform duration-[var(--os-duration-fast)] ease-out motion-reduce:transition-none\n ").concat(isOpen ? 'transform rotate-180' : '', "\n ")} strokeWidth={2} aria-hidden/>
|
|
194
194
|
</div>
|
|
195
195
|
</div>
|
|
196
196
|
|
|
197
197
|
{/* Dropdown Menu */}
|
|
198
|
-
{menuMounted && (<div id={listboxId} role="listbox" aria-multiselectable={multiple || undefined} className={"absolute z-
|
|
198
|
+
{menuMounted && (<div id={listboxId} role="listbox" aria-multiselectable={multiple || undefined} className={"absolute z-[var(--os-z-overlay)] mt-1 left-0 origin-top ".concat(overlayTransition, " ").concat(menuVisible ? overlayVisible : overlayHidden)} style={{ width: width || '100%' }}>
|
|
199
199
|
<Menu ref={menuRef} width={width || '100%'} className="max-h-[320px] overflow-y-auto">
|
|
200
200
|
{options.map(function (option, index) { return (<MenuItem key={option.value} id={optionId(index)} role="option" tabIndex={-1} isActive={index === activeIndex} label={option.label} iconName={option.iconName} isSelected={isSelected(option.value)} onClick={function () { return handleSelect(option.value); }} className="w-full"/>); })}
|
|
201
201
|
</Menu>
|