@dxos/ui-theme 0.8.4-main.6fa680abb7 → 0.8.4-main.74a063c4e0
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/lib/browser/index.mjs +355 -443
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +355 -443
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/plugin/node-cjs/{theme.css → main.css} +66 -31
- package/dist/plugin/node-cjs/main.css.map +7 -0
- package/dist/plugin/node-cjs/meta.json +1 -1
- package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs +8 -15
- package/dist/plugin/node-cjs/plugins/ThemePlugin.cjs.map +3 -3
- package/dist/plugin/node-esm/{theme.css → main.css} +66 -31
- package/dist/plugin/node-esm/main.css.map +7 -0
- package/dist/plugin/node-esm/meta.json +1 -1
- package/dist/plugin/node-esm/plugins/ThemePlugin.mjs +8 -15
- package/dist/plugin/node-esm/plugins/ThemePlugin.mjs.map +3 -3
- package/dist/types/src/fragments/index.d.ts +0 -5
- package/dist/types/src/fragments/index.d.ts.map +1 -1
- package/dist/types/src/fragments/text.d.ts +0 -4
- package/dist/types/src/fragments/text.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/plugins/ThemePlugin.d.ts.map +1 -1
- package/dist/types/src/theme/components/avatar.d.ts.map +1 -1
- package/dist/types/src/theme/components/card.d.ts +3 -2
- package/dist/types/src/theme/components/card.d.ts.map +1 -1
- package/dist/types/src/theme/components/dialog.d.ts.map +1 -1
- package/dist/types/src/theme/components/focus.d.ts +6 -0
- package/dist/types/src/theme/components/focus.d.ts.map +1 -0
- package/dist/types/src/theme/components/icon-button.d.ts.map +1 -1
- package/dist/types/src/theme/components/icon.d.ts +3 -0
- package/dist/types/src/theme/components/icon.d.ts.map +1 -1
- package/dist/types/src/theme/components/index.d.ts +1 -0
- package/dist/types/src/theme/components/index.d.ts.map +1 -1
- package/dist/types/src/theme/components/input.d.ts.map +1 -1
- package/dist/types/src/theme/components/link.d.ts.map +1 -1
- package/dist/types/src/theme/components/list.d.ts.map +1 -1
- package/dist/types/src/theme/components/message.d.ts.map +1 -1
- package/dist/types/src/theme/components/popover.d.ts.map +1 -1
- package/dist/types/src/theme/components/scroll-area.d.ts +12 -2
- package/dist/types/src/theme/components/scroll-area.d.ts.map +1 -1
- package/dist/types/src/theme/components/select.d.ts.map +1 -1
- package/dist/types/src/theme/components/status.d.ts +1 -1
- package/dist/types/src/theme/components/status.d.ts.map +1 -1
- package/dist/types/src/theme/components/toast.d.ts.map +1 -1
- package/dist/types/src/theme/components/toolbar.d.ts +0 -1
- package/dist/types/src/theme/components/toolbar.d.ts.map +1 -1
- package/dist/types/src/theme/components/tooltip.d.ts.map +1 -1
- package/dist/types/src/theme/components/treegrid.d.ts.map +1 -1
- package/dist/types/src/theme/index.d.ts +1 -0
- package/dist/types/src/theme/index.d.ts.map +1 -1
- package/dist/types/src/theme/primitives/column.d.ts +8 -3
- package/dist/types/src/theme/primitives/column.d.ts.map +1 -1
- package/dist/types/src/theme/primitives/panel.d.ts +9 -5
- package/dist/types/src/theme/primitives/panel.d.ts.map +1 -1
- package/dist/types/src/theme/theme.d.ts.map +1 -1
- package/dist/types/src/util/elevation.d.ts.map +1 -0
- package/dist/types/src/util/index.d.ts +3 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/mx.d.ts +28 -284
- package/dist/types/src/util/mx.d.ts.map +1 -1
- package/dist/types/src/util/size.d.ts +27 -0
- package/dist/types/src/util/size.d.ts.map +1 -0
- package/dist/types/src/util/valence.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -4
- package/src/css/components/button.css +2 -1
- package/src/css/components/{focus-ring.css → focus.css} +15 -1
- package/src/css/components/icon.css +9 -0
- package/src/css/components/selected.css +30 -0
- package/src/css/integrations/codemirror.css +5 -3
- package/src/css/integrations/tldraw.css +1 -0
- package/src/css/layout/main.css +0 -7
- package/src/css/layout/size.css +8 -31
- package/src/css/theme/palette.css +8 -0
- package/src/css/theme/semantic.css +24 -9
- package/src/css/theme/spacing.css +35 -18
- package/src/css/utilities.css +72 -3
- package/src/fragments/AUDIT.md +58 -0
- package/src/fragments/index.ts +1 -6
- package/src/fragments/text.ts +0 -5
- package/src/index.ts +1 -1
- package/src/{theme.css → main.css} +10 -6
- package/src/plugins/ThemePlugin.ts +12 -24
- package/src/plugins/main.css +45 -0
- package/src/theme/components/avatar.ts +3 -4
- package/src/theme/components/button.ts +1 -1
- package/src/theme/components/card.ts +14 -10
- package/src/theme/components/dialog.ts +1 -2
- package/src/theme/components/focus.ts +33 -0
- package/src/theme/components/icon-button.ts +1 -3
- package/src/theme/components/icon.ts +13 -4
- package/src/theme/components/index.ts +1 -0
- package/src/theme/components/input.ts +10 -25
- package/src/theme/components/link.ts +1 -2
- package/src/theme/components/list.ts +4 -4
- package/src/theme/components/menu.ts +4 -4
- package/src/theme/components/message.ts +2 -3
- package/src/theme/components/popover.ts +3 -4
- package/src/theme/components/scroll-area.ts +47 -40
- package/src/theme/components/select.ts +2 -3
- package/src/theme/components/status.ts +5 -5
- package/src/theme/components/toast.ts +2 -3
- package/src/theme/components/toolbar.ts +1 -7
- package/src/theme/components/tooltip.ts +1 -2
- package/src/theme/components/treegrid.ts +1 -1
- package/src/theme/index.ts +1 -0
- package/src/theme/primitives/column.ts +27 -10
- package/src/theme/primitives/panel.ts +18 -25
- package/src/theme/theme.ts +2 -0
- package/src/typings.d.ts +3 -0
- package/src/util/index.ts +3 -0
- package/src/util/mx.ts +106 -7
- package/src/util/size.ts +103 -0
- package/dist/plugin/node-cjs/theme.css.map +0 -7
- package/dist/plugin/node-esm/theme.css.map +0 -7
- package/dist/types/src/fragments/elevation.d.ts.map +0 -1
- package/dist/types/src/fragments/focus.d.ts +0 -4
- package/dist/types/src/fragments/focus.d.ts.map +0 -1
- package/dist/types/src/fragments/selected.d.ts +0 -4
- package/dist/types/src/fragments/selected.d.ts.map +0 -1
- package/dist/types/src/fragments/size.d.ts +0 -7
- package/dist/types/src/fragments/size.d.ts.map +0 -1
- package/dist/types/src/fragments/valence.d.ts.map +0 -1
- package/src/fragments/focus.ts +0 -11
- package/src/fragments/selected.ts +0 -12
- package/src/fragments/size.ts +0 -117
- /package/dist/types/src/{fragments → util}/elevation.d.ts +0 -0
- /package/dist/types/src/{fragments → util}/valence.d.ts +0 -0
- /package/src/{fragments → util}/elevation.ts +0 -0
- /package/src/{fragments → util}/valence.ts +0 -0
|
@@ -4,11 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
/* eslint-disable no-console */
|
|
6
6
|
|
|
7
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
8
|
-
import { dirname, resolve } from 'node:path';
|
|
9
|
-
|
|
10
7
|
import tailwindcss from '@tailwindcss/postcss';
|
|
11
8
|
import autoprefixer from 'autoprefixer';
|
|
9
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
10
|
+
import { dirname, resolve } from 'node:path';
|
|
12
11
|
import postcssImport from 'postcss-import';
|
|
13
12
|
import postcssNesting from 'postcss-nesting';
|
|
14
13
|
import { type HtmlTagDescriptor, type Plugin, type UserConfig } from 'vite';
|
|
@@ -44,16 +43,15 @@ export type ThemePluginOptions = {
|
|
|
44
43
|
*/
|
|
45
44
|
export const ThemePlugin = (options: ThemePluginOptions): Plugin => {
|
|
46
45
|
// Prefer source CSS if available (monorepo dev), fall back to dist for installed package.
|
|
47
|
-
const srcThemePath = resolve(import.meta.dirname, ROOT, 'src/
|
|
48
|
-
const distThemePath = resolve(import.meta.dirname, '../
|
|
46
|
+
const srcThemePath = resolve(import.meta.dirname, ROOT, 'src/main.css');
|
|
47
|
+
const distThemePath = resolve(import.meta.dirname, '../main.css');
|
|
49
48
|
const isMonorepo = existsSync(srcThemePath);
|
|
50
49
|
|
|
51
|
-
//
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
const
|
|
55
|
-
const
|
|
56
|
-
const darkModeScriptPath = existsSync(srcDarkModePath) ? srcDarkModePath : distDarkModePath;
|
|
50
|
+
// Static assets shipped via "files": ["src"] in package.json.
|
|
51
|
+
// Both monorepo and installed package resolve to the same src/plugins/ directory.
|
|
52
|
+
const pluginsDir = resolve(import.meta.dirname, ROOT, 'src/plugins');
|
|
53
|
+
const darkModeScriptPath = resolve(pluginsDir, 'dark-mode.ts');
|
|
54
|
+
const mainCssPath = resolve(pluginsDir, 'main.css');
|
|
57
55
|
|
|
58
56
|
const config: ThemePluginOptions = {
|
|
59
57
|
srcCssPath: isMonorepo ? srcThemePath : distThemePath,
|
|
@@ -112,23 +110,13 @@ export const ThemePlugin = (options: ThemePluginOptions): Plugin => {
|
|
|
112
110
|
injectTo: 'head-prepend',
|
|
113
111
|
};
|
|
114
112
|
|
|
115
|
-
// Critical
|
|
116
|
-
//
|
|
117
|
-
// removed before the new one is inserted, briefly leaving all --color-* vars undefined.
|
|
118
|
-
// These static approximations of neutral-50/950 survive that gap.
|
|
119
|
-
// Values are intentionally kept in sync with @theme tokens in semantic.css.
|
|
113
|
+
// Critical styles: font sizing, overscroll, color fallbacks.
|
|
114
|
+
// Loaded from critical.css to keep styles maintainable and out of index.html.
|
|
120
115
|
const criticalTag: HtmlTagDescriptor = {
|
|
121
116
|
tag: 'style',
|
|
122
117
|
attrs: { 'data-dxos-critical': '' },
|
|
123
118
|
injectTo: 'head-prepend',
|
|
124
|
-
children:
|
|
125
|
-
':root { color-scheme: light; }',
|
|
126
|
-
'html { color: oklch(0.145 0 0); background-color: oklch(0.985 0 0); }', // ≈ neutral-950 / neutral-50
|
|
127
|
-
'html.dark { color-scheme: dark; color: oklch(0.985 0 0); background-color: oklch(0.145 0 0); }',
|
|
128
|
-
'@media (prefers-color-scheme: dark) {',
|
|
129
|
-
' html:not(.dark) { color: oklch(0.985 0 0); background-color: oklch(0.145 0 0); }',
|
|
130
|
-
'}',
|
|
131
|
-
].join('\n'),
|
|
119
|
+
children: readFileSync(mainCssPath, 'utf-8'),
|
|
132
120
|
};
|
|
133
121
|
|
|
134
122
|
return [darkModeTag, layersTag, criticalTag];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Critical styles injected into <head> by the Vite ThemePlugin before any stylesheets load.
|
|
3
|
+
* Ensures text is readable and layout is stable on the very first paint.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/* Base font size: larger default for touch devices, smaller for precision pointers. */
|
|
7
|
+
html {
|
|
8
|
+
font-size: 20px;
|
|
9
|
+
}
|
|
10
|
+
@media (pointer: fine) {
|
|
11
|
+
html {
|
|
12
|
+
font-size: 16px;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/* Prevent overscroll bounce and ensure full viewport height. */
|
|
17
|
+
html,
|
|
18
|
+
body {
|
|
19
|
+
overscroll-behavior: none;
|
|
20
|
+
-webkit-overflow-scrolling: touch;
|
|
21
|
+
}
|
|
22
|
+
body {
|
|
23
|
+
height: 100vh;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Pre-CSS color fallbacks so text is readable before and during Vite HMR. */
|
|
27
|
+
/* Values are intentionally kept in sync with @theme tokens in semantic.css. */
|
|
28
|
+
:root {
|
|
29
|
+
color-scheme: light;
|
|
30
|
+
}
|
|
31
|
+
html {
|
|
32
|
+
color: oklch(0.145 0 0);
|
|
33
|
+
background-color: oklch(0.985 0 0);
|
|
34
|
+
}
|
|
35
|
+
html.dark {
|
|
36
|
+
color-scheme: dark;
|
|
37
|
+
color: oklch(0.985 0 0);
|
|
38
|
+
background-color: oklch(0.145 0 0);
|
|
39
|
+
}
|
|
40
|
+
@media (prefers-color-scheme: dark) {
|
|
41
|
+
html:not(.dark) {
|
|
42
|
+
color: oklch(0.985 0 0);
|
|
43
|
+
background-color: oklch(0.145 0 0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Size, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { getSize,
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { mx, getSize, getHeight } from '../../util';
|
|
9
8
|
|
|
10
9
|
export type AvatarStyleProps = Partial<{
|
|
11
10
|
size: Size;
|
|
@@ -30,7 +29,7 @@ export const avatarDescription: ComponentFunction<AvatarStyleProps> = ({ srOnly
|
|
|
30
29
|
mx('text-description', srOnly && 'sr-only', ...etc);
|
|
31
30
|
|
|
32
31
|
export const avatarFrame: ComponentFunction<AvatarStyleProps> = ({ variant }, ...etc) =>
|
|
33
|
-
mx('
|
|
32
|
+
mx('h-full w-full bg-(--surface-bg)', variant === 'circle' ? 'rounded-full' : 'rounded-sm', ...etc);
|
|
34
33
|
|
|
35
34
|
export const avatarStatusIcon: ComponentFunction<AvatarStyleProps> = ({ status, size = 3 }, ...etc) =>
|
|
36
35
|
mx(
|
|
@@ -75,7 +74,7 @@ export const avatarGroupLabel: ComponentFunction<AvatarStyleProps> = ({ size, sr
|
|
|
75
74
|
srOnly
|
|
76
75
|
? 'sr-only'
|
|
77
76
|
: 'rounded-full truncate text-sm leading-none py-1 px-2 relative z-[1] flex items-center justify-center',
|
|
78
|
-
size &&
|
|
77
|
+
size && getHeight(size),
|
|
79
78
|
...etc,
|
|
80
79
|
);
|
|
81
80
|
|
|
@@ -32,7 +32,7 @@ export type ButtonStyleProps = Partial<{
|
|
|
32
32
|
}>;
|
|
33
33
|
|
|
34
34
|
const buttonRoot: ComponentFunction<ButtonStyleProps> = (_props, ...etc) => {
|
|
35
|
-
return mx('dx-button dx-focus-ring group
|
|
35
|
+
return mx('dx-button dx-focus-ring group [&_span]:truncate', ...etc);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
const buttonGroup: ComponentFunction<{ elevation?: Elevation }> = (_props, ...etc) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { type ComponentFunction, type Theme } from '@dxos/ui-types';
|
|
5
|
+
import { type ComponentFunction, type Density, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
7
|
import { mx } from '../../util';
|
|
8
8
|
|
|
@@ -11,23 +11,23 @@ export type CardStyleProps = {
|
|
|
11
11
|
fullWidth?: boolean;
|
|
12
12
|
srOnly?: boolean;
|
|
13
13
|
variant?: 'default' | 'subtitle' | 'description';
|
|
14
|
-
|
|
14
|
+
density?: Density;
|
|
15
15
|
truncate?: boolean;
|
|
16
|
+
padding?: boolean;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
const cardRoot: ComponentFunction<CardStyleProps> = ({ border, fullWidth }, ...etc) =>
|
|
19
20
|
mx(
|
|
20
|
-
'dx-card
|
|
21
|
+
'dx-card dx-card-min-width dx-card-max-width min-h-(--dx-rail-item) group/card relative overflow-hidden',
|
|
21
22
|
border &&
|
|
22
23
|
'bg-card-surface border border-separator dark:border-subdued-separator rounded-xs dx-focus-ring-group-y-indicator',
|
|
23
24
|
fullWidth && 'max-w-none!',
|
|
24
25
|
...etc,
|
|
25
26
|
);
|
|
26
27
|
|
|
27
|
-
const cardToolbar: ComponentFunction<CardStyleProps> = (
|
|
28
|
+
const cardToolbar: ComponentFunction<CardStyleProps> = (_, ...etc) =>
|
|
28
29
|
mx(
|
|
29
|
-
'dx-card__toolbar dx-density-fine bg-transparent col-span-3 !
|
|
30
|
-
coarse && 'grid-cols-[var(--dx-l0-avatar-size)_minmax(0,1fr)_var(--dx-rail-item)]',
|
|
30
|
+
'dx-card__toolbar dx-density-fine bg-transparent p-0! gap-0! col-span-3 grid! grid-cols-subgrid! [contain:none]',
|
|
31
31
|
...etc,
|
|
32
32
|
);
|
|
33
33
|
|
|
@@ -46,9 +46,9 @@ const cardHeading: ComponentFunction<CardStyleProps> = ({ variant = 'default' },
|
|
|
46
46
|
|
|
47
47
|
const cardText: ComponentFunction<CardStyleProps> = ({ variant = 'default', truncate: _truncate }, ...etc) =>
|
|
48
48
|
mx(
|
|
49
|
-
'dx-card__text
|
|
49
|
+
'dx-card__text items-center overflow-hidden',
|
|
50
50
|
variant === 'default' && 'py-1',
|
|
51
|
-
variant === 'description' && 'py-1.5',
|
|
51
|
+
variant === 'description' && 'py-1.5 text-description',
|
|
52
52
|
...etc,
|
|
53
53
|
);
|
|
54
54
|
|
|
@@ -73,8 +73,12 @@ const cardLink: ComponentFunction<CardStyleProps> = (_props, ...etc) =>
|
|
|
73
73
|
const cardLinkLabel: ComponentFunction<CardStyleProps> = (_props, ...etc) =>
|
|
74
74
|
mx('dx-card__link-label min-w-0 flex-1 truncate', ...etc);
|
|
75
75
|
|
|
76
|
-
const cardIconBlock: ComponentFunction<CardStyleProps> = (
|
|
77
|
-
mx(
|
|
76
|
+
const cardIconBlock: ComponentFunction<CardStyleProps> = ({ padding }, ...etc) =>
|
|
77
|
+
mx(
|
|
78
|
+
'dx-card__icon-block grid h-[var(--dx-rail-item)] w-[var(--dx-rail-item)] place-items-center',
|
|
79
|
+
padding && '[&>*]:p-1',
|
|
80
|
+
...etc,
|
|
81
|
+
);
|
|
78
82
|
|
|
79
83
|
export const cardTheme: Theme<CardStyleProps> = {
|
|
80
84
|
root: cardRoot,
|
|
@@ -37,8 +37,7 @@ export const dialogContent: ComponentFunction<DialogStyleProps> = ({ inOverlayLa
|
|
|
37
37
|
export const dialogHeader: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
38
38
|
mx('dx-dialog__header flex pb-4 items-center justify-between', ...etc);
|
|
39
39
|
|
|
40
|
-
export const dialogBody: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
41
|
-
mx('dx-dialog__body flex flex-col h-full py-2 gap-2', ...etc);
|
|
40
|
+
export const dialogBody: ComponentFunction<DialogStyleProps> = (_props, ...etc) => mx('dx-dialog__body', ...etc);
|
|
42
41
|
|
|
43
42
|
export const dialogActionBar: ComponentFunction<DialogStyleProps> = (_props, ...etc) =>
|
|
44
43
|
mx('dx-dialog__actionbar flex items-center pt-4 gap-2 dx-density-coarse', ...etc);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2026 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { type ComponentFunction, type Theme } from '@dxos/ui-types';
|
|
6
|
+
|
|
7
|
+
import { mx } from '../../util';
|
|
8
|
+
|
|
9
|
+
export type FocusStyleProps = {
|
|
10
|
+
border?: boolean;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Focus ring styles shared by Focus.Group and Focus.Item.
|
|
15
|
+
* Uses a `::after` pseudo-element overlay so the ring paints above child content
|
|
16
|
+
* (inset box-shadow alone is obscured by children with backgrounds).
|
|
17
|
+
* The pseudo-element is `pointer-events-none` and absolutely positioned over the element.
|
|
18
|
+
* When `border` is true, a subdued CSS border is always visible (e.g., for grid cell edges).
|
|
19
|
+
*/
|
|
20
|
+
const focusRing: ComponentFunction<FocusStyleProps> = ({ border }, ...etc) =>
|
|
21
|
+
mx(
|
|
22
|
+
'dx-ring-pseudo outline-hidden',
|
|
23
|
+
'focus:after:ring-neutral-focus-indicator',
|
|
24
|
+
'data-[focus-state=active]:after:ring-neutral-focus-indicator',
|
|
25
|
+
'data-[focus-state=error]:after:ring-rose-500',
|
|
26
|
+
border && 'border border-separator',
|
|
27
|
+
...etc,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const focusTheme: Theme<FocusStyleProps> = {
|
|
31
|
+
group: focusRing,
|
|
32
|
+
item: focusRing,
|
|
33
|
+
};
|
|
@@ -5,14 +5,12 @@
|
|
|
5
5
|
import type { ComponentFunction, Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
7
|
import { mx } from '../../util';
|
|
8
|
-
|
|
9
8
|
import { type ButtonStyleProps } from './button';
|
|
10
9
|
|
|
11
10
|
export type IconButtonStyleProps = ButtonStyleProps & { iconOnly?: boolean };
|
|
12
11
|
|
|
13
|
-
// TODO(burdon): Gap/font size should depend on density.
|
|
14
12
|
export const iconButtonRoot: ComponentFunction<IconButtonStyleProps> = ({ iconOnly }, ...etc) => {
|
|
15
|
-
return mx('
|
|
13
|
+
return mx('px-1.5', !iconOnly && 'gap-2', ...etc);
|
|
16
14
|
};
|
|
17
15
|
|
|
18
16
|
export const iconButtonTheme: Theme<IconButtonStyleProps> = {
|
|
@@ -4,15 +4,24 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Size, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { getSize } from '../../
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { getSize, mx } from '../../util';
|
|
9
8
|
|
|
10
9
|
export type IconStyleProps = {
|
|
11
10
|
size?: Size;
|
|
12
11
|
};
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Size can be specified directly, or inherited from a container (e.g., toolbar).
|
|
15
|
+
*/
|
|
16
|
+
export const iconRoot: ComponentFunction<IconStyleProps> = ({ size }, etc) => {
|
|
17
|
+
return mx(
|
|
18
|
+
'shrink-0 text-[var(--icons-color,currentColor)]',
|
|
19
|
+
size
|
|
20
|
+
? getSize(size)
|
|
21
|
+
: '[width:var(--icon-size,var(--dx-default-icons-size))] [height:var(--icon-size,var(--dx-default-icons-size))]',
|
|
22
|
+
etc,
|
|
23
|
+
);
|
|
24
|
+
};
|
|
16
25
|
|
|
17
26
|
export const iconTheme: Theme<IconStyleProps> = {
|
|
18
27
|
root: iconRoot,
|
|
@@ -11,23 +11,8 @@ import {
|
|
|
11
11
|
type Size,
|
|
12
12
|
} from '@dxos/ui-types';
|
|
13
13
|
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
coarseDimensions,
|
|
17
|
-
computeSize,
|
|
18
|
-
fineBlockSize,
|
|
19
|
-
fineDimensions,
|
|
20
|
-
focusRing,
|
|
21
|
-
getSize,
|
|
22
|
-
getSizeHeight,
|
|
23
|
-
getSizeWidth,
|
|
24
|
-
sizeValue,
|
|
25
|
-
staticDisabled,
|
|
26
|
-
staticFocusRing,
|
|
27
|
-
subduedFocus,
|
|
28
|
-
textValence,
|
|
29
|
-
} from '../../fragments';
|
|
30
|
-
import { mx } from '../../util';
|
|
14
|
+
import { coarseBlockSize, coarseDimensions, fineBlockSize, fineDimensions, staticDisabled } from '../../fragments';
|
|
15
|
+
import { getSize, getHeight, getWidth, mx, snapSize, sizeValue, textValence } from '../../util';
|
|
31
16
|
|
|
32
17
|
export type InputStyleProps = Partial<{
|
|
33
18
|
variant: 'default' | 'subdued' | 'static';
|
|
@@ -76,7 +61,7 @@ const sharedSubduedInputStyles: ComponentFragment<InputStyleProps> = (props) =>
|
|
|
76
61
|
'py-0 w-full bg-transparent text-current placeholder-placeholder',
|
|
77
62
|
'[[data-drag-autoscroll="active"]_&]:pointer-events-none',
|
|
78
63
|
props.density === 'fine' ? fineBlockSize : coarseBlockSize,
|
|
79
|
-
|
|
64
|
+
'dx-focus-subdued',
|
|
80
65
|
props.disabled && staticDisabled,
|
|
81
66
|
];
|
|
82
67
|
|
|
@@ -96,7 +81,7 @@ const sharedStaticInputStyles: ComponentFragment<InputStyleProps> = (props) => [
|
|
|
96
81
|
props.focused && 'bg-attention-surface',
|
|
97
82
|
inputValence(props.validationValence),
|
|
98
83
|
props.disabled && staticDisabled,
|
|
99
|
-
props.focused &&
|
|
84
|
+
props.focused && 'dx-focus-static',
|
|
100
85
|
];
|
|
101
86
|
|
|
102
87
|
const inputInput: ComponentFunction<InputStyleProps> = (props, ...etc) =>
|
|
@@ -106,28 +91,28 @@ const inputInput: ComponentFunction<InputStyleProps> = (props, ...etc) =>
|
|
|
106
91
|
? mx(...sharedStaticInputStyles(props), ...etc)
|
|
107
92
|
: mx(
|
|
108
93
|
...sharedDefaultInputStyles(props),
|
|
109
|
-
!props.disabled &&
|
|
94
|
+
!props.disabled && 'dx-focus-ring',
|
|
110
95
|
inputValence(props.validationValence),
|
|
111
96
|
...etc,
|
|
112
97
|
);
|
|
113
98
|
|
|
114
|
-
const inputTextArea: ComponentFunction<InputStyleProps> = (props, ...etc) => inputInput(props, ...
|
|
99
|
+
const inputTextArea: ComponentFunction<InputStyleProps> = (props, ...etc) => inputInput(props, ...etc);
|
|
115
100
|
|
|
116
101
|
const inputCheckbox: ComponentFunction<InputStyleProps> = ({ size = 5 }, ...etc) =>
|
|
117
102
|
mx('dx-checkbox dx-focus-ring', getSize(size), ...etc);
|
|
118
103
|
|
|
119
104
|
const inputCheckboxIndicator: ComponentFunction<InputStyleProps> = ({ size = 5, checked }, ...etc) =>
|
|
120
|
-
mx(getSize(
|
|
105
|
+
mx(getSize(snapSize(sizeValue(size) * 0.65, 4)), !checked && 'invisible', ...etc);
|
|
121
106
|
|
|
122
107
|
const inputSwitch: ComponentFunction<InputStyleProps> = ({ size = 5, disabled }, ...etc) =>
|
|
123
108
|
mx(
|
|
124
|
-
|
|
125
|
-
|
|
109
|
+
getHeight(size),
|
|
110
|
+
getWidth(snapSize(sizeValue(size) * 1.75, 9)),
|
|
126
111
|
booleanInputSurface,
|
|
127
112
|
!disabled && booleanInputSurfaceHover,
|
|
128
113
|
// TODO(burdon): Added m-1 margin to make 40px width to align with 40px icon button.
|
|
129
114
|
'cursor-pointer shrink-0 rounded-full px-1 mx-1 relative',
|
|
130
|
-
|
|
115
|
+
'dx-focus-ring',
|
|
131
116
|
...etc,
|
|
132
117
|
);
|
|
133
118
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { focusRing } from '../../fragments';
|
|
8
7
|
import { mx } from '../../util';
|
|
9
8
|
|
|
10
9
|
export type LinkStyleProps = {
|
|
@@ -17,7 +16,7 @@ export const linkRoot: ComponentFunction<LinkStyleProps> = ({ variant }, ...etc)
|
|
|
17
16
|
variant === 'neutral'
|
|
18
17
|
? 'text-inherit hover:opacity-90 visited:text-inherit visited:hover:opacity-90'
|
|
19
18
|
: 'text-accent-text hover:text-accent-text-hover visited:text-accent-text visited:hover:text-accent-text-hover',
|
|
20
|
-
|
|
19
|
+
'dx-focus-ring',
|
|
21
20
|
...etc,
|
|
22
21
|
);
|
|
23
22
|
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Density, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { densityBlockSize,
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { densityBlockSize, ghostHover } from '../../fragments';
|
|
8
|
+
import { getSize, mx } from '../../util';
|
|
9
9
|
|
|
10
10
|
export type ListStyleProps = Partial<{
|
|
11
11
|
density: Density;
|
|
@@ -21,13 +21,13 @@ export const listItemEndcap: ComponentFunction<ListStyleProps> = ({ density }, .
|
|
|
21
21
|
mx(density === 'fine' ? getSize(8) : getSize(10), 'shrink-0 flex items-center justify-center', ...etc);
|
|
22
22
|
|
|
23
23
|
export const listItemHeading: ComponentFunction<ListStyleProps> = ({ density }, ...etc) =>
|
|
24
|
-
mx(densityBlockSize(density), 'flex items-center', ...etc);
|
|
24
|
+
mx(densityBlockSize(density), 'flex items-center overflow-hidden [&>span]:truncate', ...etc);
|
|
25
25
|
|
|
26
26
|
export const listItemDragHandleIcon: ComponentFunction<ListStyleProps> = (_props, ...etc) =>
|
|
27
27
|
mx(getSize(5), 'mt-2.5', ...etc);
|
|
28
28
|
|
|
29
29
|
export const listItemOpenTrigger: ComponentFunction<ListStyleProps> = ({ density }, ...etc) =>
|
|
30
|
-
mx('w-5 rounded-sm flex justify-center items-center', densityBlockSize(density), ghostHover,
|
|
30
|
+
mx('w-5 rounded-sm flex justify-center items-center', densityBlockSize(density), ghostHover, 'dx-focus-ring', ...etc);
|
|
31
31
|
|
|
32
32
|
export const listItemOpenTriggerIcon: ComponentFunction<ListStyleProps> = (_props, ...etc) => {
|
|
33
33
|
return mx(getSize(5), ...etc);
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Elevation, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { dataDisabled
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { dataDisabled } from '../../fragments';
|
|
8
|
+
import { mx, surfaceShadow, surfaceZIndex } from '../../util';
|
|
9
9
|
|
|
10
10
|
export type MenuStyleProps = Partial<{
|
|
11
11
|
constrainBlockSize: boolean;
|
|
@@ -26,8 +26,8 @@ export const menuViewport: ComponentFunction<MenuStyleProps> = (_props, ...etc)
|
|
|
26
26
|
export const menuItem: ComponentFunction<MenuStyleProps> = (_props, ...etc) =>
|
|
27
27
|
mx(
|
|
28
28
|
'flex cursor-pointer select-none items-center gap-2 rounded-xs px-2 py-2 text-sm',
|
|
29
|
-
'data-[highlighted]:bg-hover-surface',
|
|
30
|
-
|
|
29
|
+
'hover:bg-hover-surface data-[highlighted]:bg-hover-surface',
|
|
30
|
+
'dx-focus-subdued',
|
|
31
31
|
dataDisabled,
|
|
32
32
|
...etc,
|
|
33
33
|
);
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Elevation, type MessageValence, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import { messageValence } from '../../
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { mx, messageValence } from '../../util';
|
|
9
8
|
|
|
10
9
|
export type MessageStyleProps = {
|
|
11
10
|
valence?: MessageValence;
|
|
@@ -21,7 +20,7 @@ export const messageHeader: ComponentFunction<MessageStyleProps> = (_, etc) => {
|
|
|
21
20
|
};
|
|
22
21
|
|
|
23
22
|
export const messageTitle: ComponentFunction<MessageStyleProps> = (_, etc) => {
|
|
24
|
-
return mx('col-start-2
|
|
23
|
+
return mx('col-start-2 gap-trim-sm [&>svg]:inline-block', etc);
|
|
25
24
|
};
|
|
26
25
|
|
|
27
26
|
export const messageIcon: ComponentFunction<MessageStyleProps> = (_, etc) => {
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentFunction, type Elevation, type Theme } from '@dxos/ui-types';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { mx } from '../../util';
|
|
7
|
+
import { mx, surfaceShadow, surfaceZIndex } from '../../util';
|
|
9
8
|
|
|
10
9
|
export type PopoverStyleProps = Partial<{
|
|
11
10
|
constrainBlock: boolean;
|
|
@@ -18,7 +17,7 @@ export const popoverContent: ComponentFunction<PopoverStyleProps> = ({ elevation
|
|
|
18
17
|
'dx-modal-surface border border-separator rounded-sm',
|
|
19
18
|
surfaceShadow({ elevation: 'positioned' }),
|
|
20
19
|
surfaceZIndex({ elevation, level: 'menu' }),
|
|
21
|
-
|
|
20
|
+
'dx-focus-ring',
|
|
22
21
|
...etc,
|
|
23
22
|
);
|
|
24
23
|
|
|
@@ -26,7 +25,7 @@ export const popoverViewport: ComponentFunction<PopoverStyleProps> = ({ constrai
|
|
|
26
25
|
mx(
|
|
27
26
|
'flex flex-col min-h-0 min-w-popover-min-width',
|
|
28
27
|
(constrainBlock || constrainInline) && 'overflow-hidden',
|
|
29
|
-
|
|
28
|
+
constrainBlock && 'max-h-(--radix-popover-content-available-height)',
|
|
30
29
|
constrainBlock &&
|
|
31
30
|
'max-h-[min(var(--radix-popover-content-available-height),calc(100dvh-var(--spacing-screen-border)*2))]',
|
|
32
31
|
constrainInline && 'max-w-(--radix-popover-content-available-width)',
|
|
@@ -6,11 +6,22 @@ import { type AllowedAxis, type ComponentFunction, type Theme } from '@dxos/ui-t
|
|
|
6
6
|
|
|
7
7
|
import { mx } from '../../util';
|
|
8
8
|
|
|
9
|
+
export const scrollbar = {
|
|
10
|
+
thin: {
|
|
11
|
+
size: 4,
|
|
12
|
+
padding: 4,
|
|
13
|
+
},
|
|
14
|
+
coarse: {
|
|
15
|
+
size: 8,
|
|
16
|
+
padding: 8,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
9
20
|
export type ScrollAreaStyleProps = {
|
|
10
21
|
orientation?: AllowedAxis;
|
|
11
22
|
autoHide?: boolean;
|
|
12
|
-
/** Balance left/right, top/bottom
|
|
13
|
-
|
|
23
|
+
/** Balance left/right, top/bottom offset with scrollbar. */
|
|
24
|
+
centered?: boolean;
|
|
14
25
|
/** Add default padding. */
|
|
15
26
|
/** TODO(burdon): Integrate with Column.Root padding. */
|
|
16
27
|
padding?: boolean;
|
|
@@ -21,30 +32,18 @@ export type ScrollAreaStyleProps = {
|
|
|
21
32
|
snap?: boolean;
|
|
22
33
|
};
|
|
23
34
|
|
|
24
|
-
export const scrollAreaRoot: ComponentFunction<ScrollAreaStyleProps> = ({ orientation
|
|
35
|
+
export const scrollAreaRoot: ComponentFunction<ScrollAreaStyleProps> = ({ orientation }, ...etc) =>
|
|
25
36
|
mx(
|
|
26
|
-
|
|
37
|
+
// Expand
|
|
38
|
+
'dx-container',
|
|
27
39
|
|
|
28
|
-
orientation === 'vertical' && 'group/scroll-v
|
|
29
|
-
orientation === 'horizontal' && 'group/scroll-h
|
|
30
|
-
orientation === 'all' && 'group/scroll-all
|
|
40
|
+
orientation === 'vertical' && 'group/scroll-v flex flex-col',
|
|
41
|
+
orientation === 'horizontal' && 'group/scroll-h flex',
|
|
42
|
+
orientation === 'all' && 'group/scroll-all',
|
|
31
43
|
|
|
32
|
-
// TODO(burdon): Audit composition.
|
|
33
44
|
// Apply col-span-full only when inside a Column.Root grid (detected via dx-column marker).
|
|
34
45
|
'[.dx-column_&]:col-span-full',
|
|
35
46
|
|
|
36
|
-
// NOTE: Uses --gutter CSS variable
|
|
37
|
-
// If contained within Column.Root grid, the gutter is set by that component.
|
|
38
|
-
margin && [
|
|
39
|
-
orientation === 'vertical' &&
|
|
40
|
-
(thin
|
|
41
|
-
? 'pl-[var(--gutter,4px)] pr-[calc(var(--gutter,4px)-4px)]'
|
|
42
|
-
: 'pl-[var(--gutter,8px)] pr-[calc(var(--gutter,8px)-8px)]'),
|
|
43
|
-
orientation === 'horizontal' && (thin ? 'py-[var(--gutter,4px)]' : 'py-[var(--gutter,8px)]'),
|
|
44
|
-
orientation === 'all' &&
|
|
45
|
-
(thin ? 'pl-[var(--gutter,4px)] py-[var(--gutter,8px)]' : 'pl-[var(--gutter,8px)] py-[var(--gutter,8px)]'),
|
|
46
|
-
],
|
|
47
|
-
|
|
48
47
|
...etc,
|
|
49
48
|
);
|
|
50
49
|
|
|
@@ -52,24 +51,43 @@ export const scrollAreaRoot: ComponentFunction<ScrollAreaStyleProps> = ({ orient
|
|
|
52
51
|
* NOTE: The browser reserves space for scrollbars.
|
|
53
52
|
*/
|
|
54
53
|
export const scrollAreaViewport: ComponentFunction<ScrollAreaStyleProps> = (
|
|
55
|
-
{ orientation,
|
|
54
|
+
{ orientation, centered, padding, snap, thin, autoHide },
|
|
56
55
|
...etc
|
|
57
|
-
) =>
|
|
58
|
-
mx(
|
|
56
|
+
) => {
|
|
57
|
+
return mx(
|
|
59
58
|
'h-full w-full',
|
|
60
59
|
|
|
61
60
|
orientation === 'vertical' && 'flex flex-col overflow-y-scroll',
|
|
62
|
-
orientation === 'horizontal' && 'flex overflow-x-scroll',
|
|
61
|
+
orientation === 'horizontal' && 'flex overflow-x-scroll overscroll-x-contain',
|
|
63
62
|
orientation === 'all' && 'overflow-scroll',
|
|
64
63
|
|
|
65
|
-
thin
|
|
66
|
-
? '[&::-webkit-scrollbar]:w-[4px] [&::-webkit-scrollbar]:h-[4px]'
|
|
67
|
-
: '[&::-webkit-scrollbar]:w-[8px] [&::-webkit-scrollbar]:h-[8px]',
|
|
68
|
-
|
|
69
64
|
'[&::-webkit-scrollbar-corner]:bg-transparent',
|
|
70
65
|
'[&::-webkit-scrollbar-track]:bg-transparent',
|
|
71
66
|
'[&::-webkit-scrollbar-thumb]:rounded-none',
|
|
72
67
|
|
|
68
|
+
'[&::-webkit-scrollbar]:w-[var(--scroll-width)] [&::-webkit-scrollbar]:h-[var(--scroll-width)]',
|
|
69
|
+
|
|
70
|
+
// If contained within Column.Root grid the gutter is set by that component (--gutter CSS variable).
|
|
71
|
+
// If centered, left padding compensates for scrollbar width so content is visually centered.
|
|
72
|
+
(orientation === 'vertical' || orientation === 'all') &&
|
|
73
|
+
(padding
|
|
74
|
+
? [
|
|
75
|
+
centered ? 'pl-[var(--gutter,calc(var(--scroll-width)+var(--scroll-padding)))]' : 'pl-[var(--gutter,0)]',
|
|
76
|
+
'pr-[calc(var(--gutter,calc(var(--scroll-width)+var(--scroll-padding)))-var(--scroll-width))]',
|
|
77
|
+
]
|
|
78
|
+
: centered && 'pl-[var(--scroll-width)]'),
|
|
79
|
+
|
|
80
|
+
(orientation === 'horizontal' || orientation === 'all') &&
|
|
81
|
+
(padding
|
|
82
|
+
? [centered && 'pt-[calc(var(--scroll-width)+var(--scroll-padding))]', 'pb-[var(--scroll-padding)]']
|
|
83
|
+
: centered && 'pt-[var(--scroll-width)]'),
|
|
84
|
+
|
|
85
|
+
snap && [
|
|
86
|
+
orientation === 'vertical' && 'snap-y snap-mandatory',
|
|
87
|
+
orientation === 'horizontal' && 'snap-x snap-mandatory',
|
|
88
|
+
orientation === 'all' && 'snap-both snap-mandatory',
|
|
89
|
+
],
|
|
90
|
+
|
|
73
91
|
autoHide
|
|
74
92
|
? [
|
|
75
93
|
orientation === 'vertical' && 'group-hover/scroll-v:[&::-webkit-scrollbar-thumb]:bg-scrollbar-thumb',
|
|
@@ -82,20 +100,9 @@ export const scrollAreaViewport: ComponentFunction<ScrollAreaStyleProps> = (
|
|
|
82
100
|
orientation === 'all' && '[&::-webkit-scrollbar-thumb]:bg-scrollbar-thumb',
|
|
83
101
|
],
|
|
84
102
|
|
|
85
|
-
padding && [
|
|
86
|
-
orientation === 'vertical' && 'px-[4px]',
|
|
87
|
-
orientation === 'horizontal' && 'pb-[4px]',
|
|
88
|
-
orientation === 'all' && 'pl-[4px] pb-[4px]',
|
|
89
|
-
],
|
|
90
|
-
|
|
91
|
-
snap && [
|
|
92
|
-
orientation === 'vertical' && 'snap-y snap-mandatory',
|
|
93
|
-
orientation === 'horizontal' && 'snap-x snap-mandatory',
|
|
94
|
-
orientation === 'all' && 'snap-both snap-mandatory',
|
|
95
|
-
],
|
|
96
|
-
|
|
97
103
|
...etc,
|
|
98
104
|
);
|
|
105
|
+
};
|
|
99
106
|
|
|
100
107
|
export const scrollAreaTheme: Theme<ScrollAreaStyleProps> = {
|
|
101
108
|
root: scrollAreaRoot,
|