@openwarelabs/ui 0.1.0 → 0.2.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 +2 -2
- package/dist/components/Accordion/Accordion.d.cts +1 -1
- package/dist/components/Accordion/Accordion.d.ts +1 -1
- package/dist/components/Avatar/Avatar.d.cts +13 -2
- package/dist/components/Avatar/Avatar.d.ts +13 -2
- package/dist/components/Avatar/AvatarGroup.d.cts +7 -6
- package/dist/components/Avatar/AvatarGroup.d.ts +7 -6
- package/dist/components/CodeBlock/CodeBlock.d.cts +1 -1
- package/dist/components/CodeBlock/CodeBlock.d.ts +1 -1
- package/dist/components/FileDropZone/FileDropZone.d.cts +1 -1
- package/dist/components/FileDropZone/FileDropZone.d.ts +1 -1
- package/dist/components/FileTree/FileTree.d.cts +1 -1
- package/dist/components/FileTree/FileTree.d.ts +1 -1
- package/dist/components/Progress/Progress.d.cts +1 -1
- package/dist/components/Progress/Progress.d.ts +1 -1
- package/dist/components/Stat/Stat.d.cts +1 -1
- package/dist/components/Stat/Stat.d.ts +1 -1
- package/dist/components/Steps/Steps.d.cts +2 -2
- package/dist/components/Steps/Steps.d.ts +2 -2
- package/dist/components/Table/Table.d.cts +6 -1
- package/dist/components/Table/Table.d.ts +6 -1
- package/dist/components/Tabs/Tabs.d.cts +1 -1
- package/dist/components/Tabs/Tabs.d.ts +1 -1
- package/dist/components/Tooltip/Tooltip.d.cts +3 -3
- package/dist/components/Tooltip/Tooltip.d.ts +3 -3
- package/dist/components.css +58 -16
- package/dist/hooks/useFloating.d.cts +2 -2
- package/dist/hooks/useFloating.d.ts +2 -2
- package/dist/index.cjs +46 -7
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -7
- package/dist/index.js.map +3 -3
- package/dist/openware-ui.iife.js +5 -5
- package/dist/styles.css +61 -16
- package/dist/tailwind.css +1 -0
- package/dist/tokens.css +3 -0
- package/dist/tokens.json +1110 -191
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Openware UI
|
|
2
2
|
|
|
3
|
-
React components and design tokens with
|
|
3
|
+
React components and design tokens with a quiet, tactile look: a midnight brand colour, a brass accent kept small, cool slate surfaces, buttons that press in, and Inter. Light and dark themes, and a brand colour you can swap.
|
|
4
4
|
|
|
5
5
|
## Docs
|
|
6
6
|
|
|
@@ -98,4 +98,4 @@ The docs' header has a colour picker that does this live, and the Theming page s
|
|
|
98
98
|
|
|
99
99
|
## Credits
|
|
100
100
|
|
|
101
|
-
|
|
101
|
+
Icons drawn inside the components are Lucide shapes (ISC). Inter and Geist Mono are under the SIL Open Font License 1.1. Toasts use sonner and the colour picker uses react-colorful, both under the MIT licence.
|
|
@@ -21,7 +21,7 @@ export interface DisclosureProps {
|
|
|
21
21
|
children: ReactNode;
|
|
22
22
|
className?: string;
|
|
23
23
|
}
|
|
24
|
-
/** A section that opens and closes under its title, like
|
|
24
|
+
/** A section that opens and closes under its title, like "3 files changed" in a code review. */
|
|
25
25
|
export declare function Disclosure({ open, defaultOpen, onOpenChange, variant, headingLevel, className, ...props }: DisclosureProps): import("react").JSX.Element;
|
|
26
26
|
export interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, "defaultValue" | "onChange"> {
|
|
27
27
|
/** `single` keeps one item open at a time; `multiple` lets any number be open.
|
|
@@ -21,7 +21,7 @@ export interface DisclosureProps {
|
|
|
21
21
|
children: ReactNode;
|
|
22
22
|
className?: string;
|
|
23
23
|
}
|
|
24
|
-
/** A section that opens and closes under its title, like
|
|
24
|
+
/** A section that opens and closes under its title, like "3 files changed" in a code review. */
|
|
25
25
|
export declare function Disclosure({ open, defaultOpen, onOpenChange, variant, headingLevel, className, ...props }: DisclosureProps): import("react").JSX.Element;
|
|
26
26
|
export interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, "defaultValue" | "onChange"> {
|
|
27
27
|
/** `single` keeps one item open at a time; `multiple` lets any number be open.
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
1
2
|
export interface AvatarProps {
|
|
2
3
|
/** The person's name; its initials show when there's no image. */
|
|
3
4
|
name: string;
|
|
4
5
|
/** A photo URL. If it fails to load, the initials show instead. */
|
|
5
6
|
src?: string;
|
|
6
|
-
/** sm 24px, md 28px, lg 36px.
|
|
7
|
+
/** sm 24px, md 28px, lg 36px, xl 48px, or any size in pixels, such as 96 for a team page. The initials scale with it.
|
|
7
8
|
* @default "md" */
|
|
8
|
-
size?:
|
|
9
|
+
size?: AvatarSize;
|
|
9
10
|
/** Give it when the avatar stands alone; beside the name, leave it out and it's hidden from screen readers. */
|
|
10
11
|
label?: string;
|
|
11
12
|
className?: string;
|
|
12
13
|
}
|
|
14
|
+
export type AvatarSize = "sm" | "md" | "lg" | "xl" | number;
|
|
15
|
+
/**
|
|
16
|
+
* The class and style that size an avatar: a named size's class, or a pixel size through --ow-avatar-size.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function avatarSize(size: AvatarSize): {
|
|
20
|
+
className: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
pixels: number;
|
|
23
|
+
};
|
|
13
24
|
/** A round picture of a person: their photo, else their initials on the brand colour, else a person icon. */
|
|
14
25
|
export declare function Avatar({ name, src, size, label, className }: AvatarProps): import("react").JSX.Element;
|
|
@@ -1,14 +1,25 @@
|
|
|
1
|
+
import { type CSSProperties } from "react";
|
|
1
2
|
export interface AvatarProps {
|
|
2
3
|
/** The person's name; its initials show when there's no image. */
|
|
3
4
|
name: string;
|
|
4
5
|
/** A photo URL. If it fails to load, the initials show instead. */
|
|
5
6
|
src?: string;
|
|
6
|
-
/** sm 24px, md 28px, lg 36px.
|
|
7
|
+
/** sm 24px, md 28px, lg 36px, xl 48px, or any size in pixels, such as 96 for a team page. The initials scale with it.
|
|
7
8
|
* @default "md" */
|
|
8
|
-
size?:
|
|
9
|
+
size?: AvatarSize;
|
|
9
10
|
/** Give it when the avatar stands alone; beside the name, leave it out and it's hidden from screen readers. */
|
|
10
11
|
label?: string;
|
|
11
12
|
className?: string;
|
|
12
13
|
}
|
|
14
|
+
export type AvatarSize = "sm" | "md" | "lg" | "xl" | number;
|
|
15
|
+
/**
|
|
16
|
+
* The class and style that size an avatar: a named size's class, or a pixel size through --ow-avatar-size.
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
export declare function avatarSize(size: AvatarSize): {
|
|
20
|
+
className: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
pixels: number;
|
|
23
|
+
};
|
|
13
24
|
/** A round picture of a person: their photo, else their initials on the brand colour, else a person icon. */
|
|
14
25
|
export declare function Avatar({ name, src, size, label, className }: AvatarProps): import("react").JSX.Element;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type
|
|
2
|
+
import { type AvatarSize } from "./Avatar.cjs";
|
|
3
3
|
export interface AvatarGroupProps {
|
|
4
4
|
/** Avatars. */
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
/** Shows this many, then a "+3" count.
|
|
7
7
|
* @default 4 */
|
|
8
8
|
max?: number;
|
|
9
|
-
/** Applied to every avatar in the group.
|
|
9
|
+
/** Applied to every avatar in the group: a named size or pixels.
|
|
10
10
|
* @default "md" */
|
|
11
|
-
size?:
|
|
11
|
+
size?: AvatarSize;
|
|
12
12
|
/** Names the group for screen readers, e.g. "5 people on this project". */
|
|
13
13
|
label?: string;
|
|
14
14
|
className?: string;
|
|
@@ -20,9 +20,10 @@ export interface UserProps {
|
|
|
20
20
|
/** A second line: an email, a role. */
|
|
21
21
|
description?: ReactNode;
|
|
22
22
|
src?: string;
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/** The avatar's size; the name and gap grow with it from xl (48px) up.
|
|
24
|
+
* @default "md" */
|
|
25
|
+
size?: AvatarSize;
|
|
25
26
|
className?: string;
|
|
26
27
|
}
|
|
27
|
-
/** A person: avatar, name and a line about them, as in
|
|
28
|
+
/** A person: avatar, name and a line about them, as in an account menu. */
|
|
28
29
|
export declare function User({ name, description, src, size, className }: UserProps): import("react").JSX.Element;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import { type
|
|
2
|
+
import { type AvatarSize } from "./Avatar.js";
|
|
3
3
|
export interface AvatarGroupProps {
|
|
4
4
|
/** Avatars. */
|
|
5
5
|
children: ReactNode;
|
|
6
6
|
/** Shows this many, then a "+3" count.
|
|
7
7
|
* @default 4 */
|
|
8
8
|
max?: number;
|
|
9
|
-
/** Applied to every avatar in the group.
|
|
9
|
+
/** Applied to every avatar in the group: a named size or pixels.
|
|
10
10
|
* @default "md" */
|
|
11
|
-
size?:
|
|
11
|
+
size?: AvatarSize;
|
|
12
12
|
/** Names the group for screen readers, e.g. "5 people on this project". */
|
|
13
13
|
label?: string;
|
|
14
14
|
className?: string;
|
|
@@ -20,9 +20,10 @@ export interface UserProps {
|
|
|
20
20
|
/** A second line: an email, a role. */
|
|
21
21
|
description?: ReactNode;
|
|
22
22
|
src?: string;
|
|
23
|
-
/**
|
|
24
|
-
|
|
23
|
+
/** The avatar's size; the name and gap grow with it from xl (48px) up.
|
|
24
|
+
* @default "md" */
|
|
25
|
+
size?: AvatarSize;
|
|
25
26
|
className?: string;
|
|
26
27
|
}
|
|
27
|
-
/** A person: avatar, name and a line about them, as in
|
|
28
|
+
/** A person: avatar, name and a line about them, as in an account menu. */
|
|
28
29
|
export declare function User({ name, description, src, size, className }: UserProps): import("react").JSX.Element;
|
|
@@ -36,7 +36,7 @@ export interface CodeBlockProps {
|
|
|
36
36
|
maxHeight?: number;
|
|
37
37
|
className?: string;
|
|
38
38
|
}
|
|
39
|
-
/** Code on
|
|
39
|
+
/** Code on a night ground, the same in both themes, with a copy button. */
|
|
40
40
|
export declare function CodeBlock({ code, html, title, language, showLineNumbers, copyable, maxHeight, className }: CodeBlockProps): import("react").JSX.Element;
|
|
41
41
|
export interface SnippetProps {
|
|
42
42
|
/** The command or value, copied as is. */
|
|
@@ -36,7 +36,7 @@ export interface CodeBlockProps {
|
|
|
36
36
|
maxHeight?: number;
|
|
37
37
|
className?: string;
|
|
38
38
|
}
|
|
39
|
-
/** Code on
|
|
39
|
+
/** Code on a night ground, the same in both themes, with a copy button. */
|
|
40
40
|
export declare function CodeBlock({ code, html, title, language, showLineNumbers, copyable, maxHeight, className }: CodeBlockProps): import("react").JSX.Element;
|
|
41
41
|
export interface SnippetProps {
|
|
42
42
|
/** The command or value, copied as is. */
|
|
@@ -23,7 +23,7 @@ export interface FileDropZoneProps {
|
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A drop zone for files: drop them on it, or press it to pick them.
|
|
27
27
|
* It checks the type and size and says what was wrong.
|
|
28
28
|
*/
|
|
29
29
|
export declare function FileDropZone({ onFiles, accept, multiple, maxSize, label, hint, error, icon, disabled, name, className, }: FileDropZoneProps): import("react").JSX.Element;
|
|
@@ -23,7 +23,7 @@ export interface FileDropZoneProps {
|
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A drop zone for files: drop them on it, or press it to pick them.
|
|
27
27
|
* It checks the type and size and says what was wrong.
|
|
28
28
|
*/
|
|
29
29
|
export declare function FileDropZone({ onFiles, accept, multiple, maxSize, label, hint, error, icon, disabled, name, className, }: FileDropZoneProps): import("react").JSX.Element;
|
|
@@ -23,7 +23,7 @@ export interface FileTreeProps {
|
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A project structure explorer: folders open and close, files can be selected.
|
|
27
27
|
* Up and Down move, Right opens a folder or goes into it, Left closes it or goes to its parent.
|
|
28
28
|
*/
|
|
29
29
|
export declare function FileTree({ items, selected, defaultSelected, onSelect, defaultExpanded, label, className, }: FileTreeProps): import("react").JSX.Element;
|
|
@@ -23,7 +23,7 @@ export interface FileTreeProps {
|
|
|
23
23
|
className?: string;
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* A project structure explorer: folders open and close, files can be selected.
|
|
27
27
|
* Up and Down move, Right opens a folder or goes into it, Left closes it or goes to its parent.
|
|
28
28
|
*/
|
|
29
29
|
export declare function FileTree({ items, selected, defaultSelected, onSelect, defaultExpanded, label, className, }: FileTreeProps): import("react").JSX.Element;
|
|
@@ -12,7 +12,7 @@ export interface ProgressBarProps {
|
|
|
12
12
|
showValue?: boolean;
|
|
13
13
|
/** The text shown and read out for the value, e.g. "3 of 8 stages". Defaults to a percentage. */
|
|
14
14
|
valueLabel?: string;
|
|
15
|
-
/** sm is 4px,
|
|
15
|
+
/** sm is 4px, for a pipeline bar; md is 8px.
|
|
16
16
|
* @default "sm" */
|
|
17
17
|
size?: "sm" | "md";
|
|
18
18
|
/** @default "primary" */
|
|
@@ -12,7 +12,7 @@ export interface ProgressBarProps {
|
|
|
12
12
|
showValue?: boolean;
|
|
13
13
|
/** The text shown and read out for the value, e.g. "3 of 8 stages". Defaults to a percentage. */
|
|
14
14
|
valueLabel?: string;
|
|
15
|
-
/** sm is 4px,
|
|
15
|
+
/** sm is 4px, for a pipeline bar; md is 8px.
|
|
16
16
|
* @default "sm" */
|
|
17
17
|
size?: "sm" | "md";
|
|
18
18
|
/** @default "primary" */
|
|
@@ -16,5 +16,5 @@ export interface StatProps {
|
|
|
16
16
|
trend?: number[];
|
|
17
17
|
className?: string;
|
|
18
18
|
}
|
|
19
|
-
/** One headline number with its label, change and trend,
|
|
19
|
+
/** One headline number with its label, change and trend, for overview cards. */
|
|
20
20
|
export declare function Stat({ label, value, icon, change, changeTone, description, trend, className }: StatProps): import("react").JSX.Element;
|
|
@@ -16,5 +16,5 @@ export interface StatProps {
|
|
|
16
16
|
trend?: number[];
|
|
17
17
|
className?: string;
|
|
18
18
|
}
|
|
19
|
-
/** One headline number with its label, change and trend,
|
|
19
|
+
/** One headline number with its label, change and trend, for overview cards. */
|
|
20
20
|
export declare function Stat({ label, value, icon, change, changeTone, description, trend, className }: StatProps): import("react").JSX.Element;
|
|
@@ -3,7 +3,7 @@ export interface StepItem {
|
|
|
3
3
|
title: ReactNode;
|
|
4
4
|
/** A line under the title. Hidden once the step is done, in the vertical layout. */
|
|
5
5
|
description?: ReactNode;
|
|
6
|
-
/** A control on the right of the current
|
|
6
|
+
/** A control on the right of the step while it's the current one, such as a small Button. Other steps don't show it. */
|
|
7
7
|
action?: ReactNode;
|
|
8
8
|
/** Overrides the status worked out from `current`. */
|
|
9
9
|
status?: "done" | "current" | "upcoming";
|
|
@@ -13,7 +13,7 @@ export interface StepsProps {
|
|
|
13
13
|
/** The index of the step in progress. Steps before it are done. Use items.length when every step is done.
|
|
14
14
|
* @default 0 */
|
|
15
15
|
current?: number;
|
|
16
|
-
/** `vertical` is
|
|
16
|
+
/** `vertical` is a first-run checklist; `horizontal` is a compact progress strip.
|
|
17
17
|
* @default "vertical" */
|
|
18
18
|
orientation?: "vertical" | "horizontal";
|
|
19
19
|
/** A heading above a vertical list, with a "2 of 4 done" count beside it. */
|
|
@@ -3,7 +3,7 @@ export interface StepItem {
|
|
|
3
3
|
title: ReactNode;
|
|
4
4
|
/** A line under the title. Hidden once the step is done, in the vertical layout. */
|
|
5
5
|
description?: ReactNode;
|
|
6
|
-
/** A control on the right of the current
|
|
6
|
+
/** A control on the right of the step while it's the current one, such as a small Button. Other steps don't show it. */
|
|
7
7
|
action?: ReactNode;
|
|
8
8
|
/** Overrides the status worked out from `current`. */
|
|
9
9
|
status?: "done" | "current" | "upcoming";
|
|
@@ -13,7 +13,7 @@ export interface StepsProps {
|
|
|
13
13
|
/** The index of the step in progress. Steps before it are done. Use items.length when every step is done.
|
|
14
14
|
* @default 0 */
|
|
15
15
|
current?: number;
|
|
16
|
-
/** `vertical` is
|
|
16
|
+
/** `vertical` is a first-run checklist; `horizontal` is a compact progress strip.
|
|
17
17
|
* @default "vertical" */
|
|
18
18
|
orientation?: "vertical" | "horizontal";
|
|
19
19
|
/** A heading above a vertical list, with a "2 of 4 done" count beside it. */
|
|
@@ -41,6 +41,11 @@ export interface TableProps<Row> {
|
|
|
41
41
|
selectedKeys?: Key[];
|
|
42
42
|
defaultSelectedKeys?: Key[];
|
|
43
43
|
onSelectionChange?(keys: Key[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Names a row for its checkbox, read out as "Select …": the person, the file, the project. Defaults to the
|
|
46
|
+
* first column's value when it's text or a number, else "row 3".
|
|
47
|
+
*/
|
|
48
|
+
rowLabel?(row: Row): string;
|
|
44
49
|
/** Shown in place of the rows when there are none, such as an EmptyState. */
|
|
45
50
|
emptyContent?: ReactNode;
|
|
46
51
|
/** `compact` rows are 36px; `comfortable` 44px.
|
|
@@ -52,4 +57,4 @@ export interface TableProps<Row> {
|
|
|
52
57
|
className?: string;
|
|
53
58
|
}
|
|
54
59
|
/** Rows of records with sortable columns and optional selection, in a bordered card. */
|
|
55
|
-
export declare function Table<Row extends object>({ columns, rows, rowKey, caption, hideCaption, sort, defaultSort, onSortChange, manualSort, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, emptyContent, density, stickyHeader, maxHeight, className, }: TableProps<Row>): import("react").JSX.Element;
|
|
60
|
+
export declare function Table<Row extends object>({ columns, rows, rowKey, caption, hideCaption, sort, defaultSort, onSortChange, manualSort, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, rowLabel, emptyContent, density, stickyHeader, maxHeight, className, }: TableProps<Row>): import("react").JSX.Element;
|
|
@@ -41,6 +41,11 @@ export interface TableProps<Row> {
|
|
|
41
41
|
selectedKeys?: Key[];
|
|
42
42
|
defaultSelectedKeys?: Key[];
|
|
43
43
|
onSelectionChange?(keys: Key[]): void;
|
|
44
|
+
/**
|
|
45
|
+
* Names a row for its checkbox, read out as "Select …": the person, the file, the project. Defaults to the
|
|
46
|
+
* first column's value when it's text or a number, else "row 3".
|
|
47
|
+
*/
|
|
48
|
+
rowLabel?(row: Row): string;
|
|
44
49
|
/** Shown in place of the rows when there are none, such as an EmptyState. */
|
|
45
50
|
emptyContent?: ReactNode;
|
|
46
51
|
/** `compact` rows are 36px; `comfortable` 44px.
|
|
@@ -52,4 +57,4 @@ export interface TableProps<Row> {
|
|
|
52
57
|
className?: string;
|
|
53
58
|
}
|
|
54
59
|
/** Rows of records with sortable columns and optional selection, in a bordered card. */
|
|
55
|
-
export declare function Table<Row extends object>({ columns, rows, rowKey, caption, hideCaption, sort, defaultSort, onSortChange, manualSort, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, emptyContent, density, stickyHeader, maxHeight, className, }: TableProps<Row>): import("react").JSX.Element;
|
|
60
|
+
export declare function Table<Row extends object>({ columns, rows, rowKey, caption, hideCaption, sort, defaultSort, onSortChange, manualSort, selectionMode, selectedKeys, defaultSelectedKeys, onSelectionChange, rowLabel, emptyContent, density, stickyHeader, maxHeight, className, }: TableProps<Row>): import("react").JSX.Element;
|
|
@@ -5,7 +5,7 @@ export interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChang
|
|
|
5
5
|
/** The tab selected first when uncontrolled. */
|
|
6
6
|
defaultValue?: string;
|
|
7
7
|
onValueChange?(value: string): void;
|
|
8
|
-
/** `segmented` raises the chosen tab in a well
|
|
8
|
+
/** `segmented` raises the chosen tab in a well; `line` underlines it.
|
|
9
9
|
* @default "segmented" */
|
|
10
10
|
variant?: "segmented" | "line";
|
|
11
11
|
children: ReactNode;
|
|
@@ -5,7 +5,7 @@ export interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, "onChang
|
|
|
5
5
|
/** The tab selected first when uncontrolled. */
|
|
6
6
|
defaultValue?: string;
|
|
7
7
|
onValueChange?(value: string): void;
|
|
8
|
-
/** `segmented` raises the chosen tab in a well
|
|
8
|
+
/** `segmented` raises the chosen tab in a well; `line` underlines it.
|
|
9
9
|
* @default "segmented" */
|
|
10
10
|
variant?: "segmented" | "line";
|
|
11
11
|
children: ReactNode;
|
|
@@ -4,15 +4,15 @@ export interface TooltipProps {
|
|
|
4
4
|
label: ReactNode;
|
|
5
5
|
/** The thing it explains: usually an icon-only Button with the same words as its aria-label. */
|
|
6
6
|
children: ReactNode;
|
|
7
|
-
/** Which side it prefers; it flips when there's no room.
|
|
7
|
+
/** Which side it prefers; it flips to the opposite side when there's no room. `right` suits icons in a folded sidebar.
|
|
8
8
|
* @default "top" */
|
|
9
|
-
placement?: "top" | "bottom";
|
|
9
|
+
placement?: "top" | "bottom" | "left" | "right";
|
|
10
10
|
/** Milliseconds of hovering before it shows. Moving to a neighbour while one is showing skips the wait.
|
|
11
11
|
* @default 400 */
|
|
12
12
|
delay?: number;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* A small dark label
|
|
15
|
+
* A small dark label beside its child (above, unless `placement` says otherwise) on hover or keyboard focus. It's for sighted users only: the child
|
|
16
16
|
* carries the same words for screen readers (an aria-label, or visually hidden text), so they aren't read twice.
|
|
17
17
|
* It sits in the top layer, so scroll areas and dialogs can't clip it.
|
|
18
18
|
*/
|
|
@@ -4,15 +4,15 @@ export interface TooltipProps {
|
|
|
4
4
|
label: ReactNode;
|
|
5
5
|
/** The thing it explains: usually an icon-only Button with the same words as its aria-label. */
|
|
6
6
|
children: ReactNode;
|
|
7
|
-
/** Which side it prefers; it flips when there's no room.
|
|
7
|
+
/** Which side it prefers; it flips to the opposite side when there's no room. `right` suits icons in a folded sidebar.
|
|
8
8
|
* @default "top" */
|
|
9
|
-
placement?: "top" | "bottom";
|
|
9
|
+
placement?: "top" | "bottom" | "left" | "right";
|
|
10
10
|
/** Milliseconds of hovering before it shows. Moving to a neighbour while one is showing skips the wait.
|
|
11
11
|
* @default 400 */
|
|
12
12
|
delay?: number;
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* A small dark label
|
|
15
|
+
* A small dark label beside its child (above, unless `placement` says otherwise) on hover or keyboard focus. It's for sighted users only: the child
|
|
16
16
|
* carries the same words for screen readers (an aria-label, or visually hidden text), so they aren't read twice.
|
|
17
17
|
* It sits in the top layer, so scroll areas and dialogs can't clip it.
|
|
18
18
|
*/
|
package/dist/components.css
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
back into it. useFloating sets data-side and --ow-floating-origin; usePresence sets data-state. */
|
|
40
40
|
.ow-floating {
|
|
41
41
|
--ow-floating-shift: -4px;
|
|
42
|
+
--ow-floating-shift-x: 0px;
|
|
42
43
|
transform-origin: var(--ow-floating-origin, top center);
|
|
43
44
|
}
|
|
44
45
|
|
|
@@ -46,6 +47,16 @@
|
|
|
46
47
|
--ow-floating-shift: 4px;
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
.ow-floating[data-side="left"] {
|
|
51
|
+
--ow-floating-shift: 0px;
|
|
52
|
+
--ow-floating-shift-x: 4px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.ow-floating[data-side="right"] {
|
|
56
|
+
--ow-floating-shift: 0px;
|
|
57
|
+
--ow-floating-shift-x: -4px;
|
|
58
|
+
}
|
|
59
|
+
|
|
49
60
|
.ow-floating[data-state="open"] {
|
|
50
61
|
animation: ow-floating-in var(--ow-duration-base) var(--ow-ease-emphasized);
|
|
51
62
|
}
|
|
@@ -58,14 +69,14 @@
|
|
|
58
69
|
@keyframes ow-floating-in {
|
|
59
70
|
from {
|
|
60
71
|
opacity: 0;
|
|
61
|
-
transform:
|
|
72
|
+
transform: translate(var(--ow-floating-shift-x), var(--ow-floating-shift)) scale(0.96);
|
|
62
73
|
}
|
|
63
74
|
}
|
|
64
75
|
|
|
65
76
|
@keyframes ow-floating-out {
|
|
66
77
|
to {
|
|
67
78
|
opacity: 0;
|
|
68
|
-
transform:
|
|
79
|
+
transform: translate(var(--ow-floating-shift-x), var(--ow-floating-shift)) scale(0.97);
|
|
69
80
|
}
|
|
70
81
|
}
|
|
71
82
|
|
|
@@ -441,7 +452,7 @@
|
|
|
441
452
|
border-bottom-right-radius: 0;
|
|
442
453
|
}
|
|
443
454
|
|
|
444
|
-
/* CloseButton:
|
|
455
|
+
/* CloseButton: a quiet square that darkens on hover, for dialogs and panels. */
|
|
445
456
|
.ow-close-button {
|
|
446
457
|
display: inline-flex;
|
|
447
458
|
flex-shrink: 0;
|
|
@@ -481,7 +492,7 @@
|
|
|
481
492
|
}
|
|
482
493
|
|
|
483
494
|
/* components/SegmentedControl/SegmentedControl.css */
|
|
484
|
-
/* SegmentedControl and segmented Tabs:
|
|
495
|
+
/* SegmentedControl and segmented Tabs: a well with the chosen segment raised. */
|
|
485
496
|
.ow-segmented,
|
|
486
497
|
.ow-tabs--segmented .ow-tabs__list {
|
|
487
498
|
position: relative;
|
|
@@ -494,6 +505,8 @@
|
|
|
494
505
|
border-radius: var(--ow-radius-container);
|
|
495
506
|
background: var(--ow-track);
|
|
496
507
|
padding: var(--ow-space-2xs);
|
|
508
|
+
/* A hairline edge, so the well shows on the canvas as well as on a surface. */
|
|
509
|
+
box-shadow: inset 0 0 0 1px var(--ow-border);
|
|
497
510
|
}
|
|
498
511
|
|
|
499
512
|
.ow-segmented--full {
|
|
@@ -797,6 +810,8 @@
|
|
|
797
810
|
.ow-input-group {
|
|
798
811
|
display: flex;
|
|
799
812
|
width: 100%;
|
|
813
|
+
/* Shrink in a narrow grid or flex column instead of pushing past it. */
|
|
814
|
+
min-width: 0;
|
|
800
815
|
height: 40px;
|
|
801
816
|
align-items: center;
|
|
802
817
|
gap: var(--ow-space-sm);
|
|
@@ -843,6 +858,8 @@
|
|
|
843
858
|
}
|
|
844
859
|
|
|
845
860
|
.ow-input-group__input {
|
|
861
|
+
/* A percentage width lets the field's minimum size come from its start and end content alone. */
|
|
862
|
+
width: 100%;
|
|
846
863
|
min-width: 0;
|
|
847
864
|
height: 100%;
|
|
848
865
|
flex: 1;
|
|
@@ -1449,7 +1466,7 @@
|
|
|
1449
1466
|
width: 16px;
|
|
1450
1467
|
height: 16px;
|
|
1451
1468
|
border-radius: var(--ow-radius-pill);
|
|
1452
|
-
background:
|
|
1469
|
+
background: var(--ow-knob);
|
|
1453
1470
|
box-shadow: var(--ow-shadow-control);
|
|
1454
1471
|
transform: translateX(2px);
|
|
1455
1472
|
transition:
|
|
@@ -1471,7 +1488,7 @@
|
|
|
1471
1488
|
}
|
|
1472
1489
|
|
|
1473
1490
|
/* components/Slider/Slider.css */
|
|
1474
|
-
/* Slider: native range inputs over a drawn track. The thumb is the switch's knob:
|
|
1491
|
+
/* Slider: native range inputs over a drawn track. The thumb is the switch's knob (ow-knob): round, with a soft shadow. */
|
|
1475
1492
|
.ow-slider {
|
|
1476
1493
|
display: grid;
|
|
1477
1494
|
gap: var(--ow-space-sm);
|
|
@@ -1562,7 +1579,7 @@
|
|
|
1562
1579
|
appearance: none;
|
|
1563
1580
|
border: 1px solid var(--ow-border-strong);
|
|
1564
1581
|
border-radius: 50%;
|
|
1565
|
-
background:
|
|
1582
|
+
background: var(--ow-knob);
|
|
1566
1583
|
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.18);
|
|
1567
1584
|
pointer-events: auto;
|
|
1568
1585
|
cursor: grab;
|
|
@@ -1575,7 +1592,7 @@
|
|
|
1575
1592
|
height: 18px;
|
|
1576
1593
|
border: 1px solid var(--ow-border-strong);
|
|
1577
1594
|
border-radius: 50%;
|
|
1578
|
-
background:
|
|
1595
|
+
background: var(--ow-knob);
|
|
1579
1596
|
box-shadow: 0 1px 3px rgba(15, 23, 42, 0.18);
|
|
1580
1597
|
pointer-events: auto;
|
|
1581
1598
|
cursor: grab;
|
|
@@ -1781,7 +1798,7 @@
|
|
|
1781
1798
|
}
|
|
1782
1799
|
|
|
1783
1800
|
/* components/FileDropZone/FileDropZone.css */
|
|
1784
|
-
/* FileDropZone:
|
|
1801
|
+
/* FileDropZone: a dashed well that turns primary while something is dragged over it. */
|
|
1785
1802
|
.ow-dropzone {
|
|
1786
1803
|
display: flex;
|
|
1787
1804
|
min-height: 128px;
|
|
@@ -2123,7 +2140,7 @@
|
|
|
2123
2140
|
transition: width var(--ow-duration-slow) var(--ow-ease-standard);
|
|
2124
2141
|
}
|
|
2125
2142
|
|
|
2126
|
-
/* Unknown length: a segment sliding across
|
|
2143
|
+
/* Unknown length: a segment sliding across. */
|
|
2127
2144
|
.ow-progress__track--indeterminate .ow-progress__fill {
|
|
2128
2145
|
width: 37%;
|
|
2129
2146
|
animation: ow-progress-slide 1.3s var(--ow-ease-standard) infinite;
|
|
@@ -2185,7 +2202,7 @@
|
|
|
2185
2202
|
}
|
|
2186
2203
|
|
|
2187
2204
|
/* components/Tooltip/Tooltip.css */
|
|
2188
|
-
/* Tooltip: a small dark label in the top layer,
|
|
2205
|
+
/* Tooltip: a small dark label in the top layer, on the side of the child it prefers (or the other side when there's no room). */
|
|
2189
2206
|
.ow-tooltip {
|
|
2190
2207
|
display: inline-flex;
|
|
2191
2208
|
}
|
|
@@ -2341,7 +2358,7 @@
|
|
|
2341
2358
|
box-shadow: none;
|
|
2342
2359
|
}
|
|
2343
2360
|
|
|
2344
|
-
/* The ✕ sits on the corner
|
|
2361
|
+
/* The ✕ sits on the corner. */
|
|
2345
2362
|
.ow-toaster.ow-toaster [data-sonner-toast][data-styled="true"] [data-close-button] {
|
|
2346
2363
|
width: 22px;
|
|
2347
2364
|
height: 22px;
|
|
@@ -3360,7 +3377,7 @@
|
|
|
3360
3377
|
}
|
|
3361
3378
|
|
|
3362
3379
|
/* components/Accordion/Accordion.css */
|
|
3363
|
-
/* Disclosure and Accordion:
|
|
3380
|
+
/* Disclosure and Accordion: a header with a chevron that turns as the panel opens. */
|
|
3364
3381
|
.ow-disclosure,
|
|
3365
3382
|
.ow-accordion--bordered,
|
|
3366
3383
|
.ow-accordion--separated .ow-accordion__item {
|
|
@@ -3699,7 +3716,7 @@
|
|
|
3699
3716
|
}
|
|
3700
3717
|
|
|
3701
3718
|
/* components/Steps/Steps.css */
|
|
3702
|
-
/* Steps:
|
|
3719
|
+
/* Steps: a setup checklist (vertical) and a compact strip (horizontal). */
|
|
3703
3720
|
.ow-steps--vertical {
|
|
3704
3721
|
border: 1px solid var(--ow-border);
|
|
3705
3722
|
border-radius: var(--ow-radius-container);
|
|
@@ -3989,6 +4006,19 @@
|
|
|
3989
4006
|
font-size: 13px;
|
|
3990
4007
|
}
|
|
3991
4008
|
|
|
4009
|
+
.ow-avatar--xl {
|
|
4010
|
+
width: 48px;
|
|
4011
|
+
height: 48px;
|
|
4012
|
+
font-size: 17px;
|
|
4013
|
+
}
|
|
4014
|
+
|
|
4015
|
+
/* Any size in pixels, through --ow-avatar-size: the initials stay in proportion. */
|
|
4016
|
+
.ow-avatar--custom {
|
|
4017
|
+
width: var(--ow-avatar-size);
|
|
4018
|
+
height: var(--ow-avatar-size);
|
|
4019
|
+
font-size: calc(var(--ow-avatar-size) * 0.36);
|
|
4020
|
+
}
|
|
4021
|
+
|
|
3992
4022
|
.ow-avatar__image {
|
|
3993
4023
|
width: 100%;
|
|
3994
4024
|
height: 100%;
|
|
@@ -4025,6 +4055,18 @@
|
|
|
4025
4055
|
gap: var(--ow-space-md);
|
|
4026
4056
|
}
|
|
4027
4057
|
|
|
4058
|
+
.ow-user--xl {
|
|
4059
|
+
gap: var(--ow-space-lg);
|
|
4060
|
+
}
|
|
4061
|
+
|
|
4062
|
+
.ow-user--xl .ow-user__name {
|
|
4063
|
+
font-size: 15px;
|
|
4064
|
+
}
|
|
4065
|
+
|
|
4066
|
+
.ow-user--xl .ow-user__description {
|
|
4067
|
+
font-size: 13px;
|
|
4068
|
+
}
|
|
4069
|
+
|
|
4028
4070
|
.ow-user__text {
|
|
4029
4071
|
display: grid;
|
|
4030
4072
|
min-width: 0;
|
|
@@ -4565,7 +4607,7 @@
|
|
|
4565
4607
|
}
|
|
4566
4608
|
|
|
4567
4609
|
/* components/Stat/Stat.css */
|
|
4568
|
-
/* Stat:
|
|
4610
|
+
/* Stat: an overview card. A muted label, a big tabular number, a change and an optional trend line. */
|
|
4569
4611
|
.ow-stat {
|
|
4570
4612
|
display: grid;
|
|
4571
4613
|
min-width: 0;
|
|
@@ -4675,7 +4717,7 @@
|
|
|
4675
4717
|
}
|
|
4676
4718
|
|
|
4677
4719
|
/* components/FileTree/FileTree.css */
|
|
4678
|
-
/* FileTree:
|
|
4720
|
+
/* FileTree: a project structure explorer. Monospace names, hairline guides, a tinted selected file. */
|
|
4679
4721
|
.ow-tree,
|
|
4680
4722
|
.ow-tree__group {
|
|
4681
4723
|
margin: 0;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type CSSProperties, type RefObject } from "react";
|
|
2
|
-
export type Placement = "bottom-start" | "bottom-end" | "bottom" | "top-start" | "top-end" | "top";
|
|
2
|
+
export type Placement = "bottom-start" | "bottom-end" | "bottom" | "top-start" | "top-end" | "top" | "left" | "right";
|
|
3
3
|
interface Options {
|
|
4
4
|
open: boolean;
|
|
5
5
|
anchorRef: RefObject<HTMLElement | null>;
|
|
@@ -14,7 +14,7 @@ interface Options {
|
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
16
|
* Positions a floating element (a popover, a listbox) against its anchor with fixed coordinates, flips it above
|
|
17
|
-
* or below when there's no room, keeps it on screen, and follows the anchor when the page scrolls or resizes.
|
|
17
|
+
* or below (or, for "left" and "right", to the other side) when there's no room, keeps it on screen, and follows the anchor when the page scrolls or resizes.
|
|
18
18
|
* It also puts the element in the browser's top layer (popover="manual"), so dialogs and overflow can't clip it.
|
|
19
19
|
* Pass the element's `mounted` from usePresence as `open`, so it stays placed while it animates out.
|
|
20
20
|
*/
|