Skip to content

React

import * as Hooks from '@dxos/app-framework/Hooks';

A plugin’s components read capabilities, invoke operations and read settings through hooks. They work in any component under the app’s plugin manager, which every surface is.

useCapability returns a singleton capability, and useCapabilities every contribution to a multi capability. Both re-render when contributions change. useOptionalCapability returns undefined when no plugin provides it.

import * as
import Capabilities
Capabilities
from '@dxos/app-framework/Capabilities';
import * as
import Hooks
Hooks
from '@dxos/app-framework/Hooks';
export const
const SurfaceCount: () => React.JSX.Element
SurfaceCount
= () => {
// Every contribution to a multi capability, re-rendering when plugins add or
// remove one.
const
const surfaces: any[]
surfaces
=
import Hooks
Hooks
.
const useCapabilities: <any>(interfaceDef: Capability.InterfaceDef<any>) => any[]

Hook to request capabilities from the plugin context.

@returns ― An array of capabilities.

useCapabilities
(
import Capabilities
Capabilities
.
const ReactSurface: Capability.MultiTag<any, "org.dxos.app-framework.capability.reactSurface">

Surface definitions that can be either React components or Web Components.

@category ― Capability

ReactSurface
);
return <
JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>
span
>{
const surfaces: any[]
surfaces
.
Array<any>.length: number

Gets or sets the length of the array. This is a number one higher than the highest index in the array.

length
}</
JSX.IntrinsicElements.span: React.DetailedHTMLProps<React.HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>
span
>;
};

useOperation binds an operation to a callback; its argument maps the callback’s arguments to the operation’s input. useOperationInvoker returns the invoker, whose invokePromise returns the operation’s output.

import {
function useCallback<T extends Function>(callback: T, deps: React.DependencyList): T

useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.

useCallback
} from 'react';
import * as
import Hooks
Hooks
from '@dxos/app-framework/Hooks';
import * as
import LayoutOperation
LayoutOperation
from '@dxos/app-toolkit/LayoutOperation';
import * as
import Button
Button
from '@dxos/react-ui/Button';
export const
const OpenButton: ({ path }: {
path: string;
}) => React.JSX.Element
OpenButton
= ({
path: string
path
}: {
path: string
path
: string }) => {
const
const open: () => void
open
=
import Hooks
Hooks
.
const useOperation: <[], {
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}>(operation: Definition<{
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, unknown, any>, map: () => {
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, options?: InvokeOptions) => () => void

Binds an operation to a UI callback in one step: map turns the component's callback arguments into the operation's input. The handler identity is stable across renders (the mapper and options read through refs), so it replaces per-handler useCallback boilerplate.

useOperation
(
import LayoutOperation
LayoutOperation
.
const Open: Definition<{
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, readonly string[], Capability.Service>
Open
, () => ({
subject: readonly string[]
subject
: [
path: string
path
],
}));
return <
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const open: () => void
open
()}>Open</
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
>;
};
export const
const OpenTwice: ({ path }: {
path: string;
}) => React.JSX.Element
OpenTwice
= ({
path: string
path
}: {
path: string
path
: string }) => {
const {
const invokePromise: <I, O>(op: Definition<I, O>, ...args: void extends I ? [input?: I, options?: InvokeOptions] : [input: I, options?: InvokeOptions]) => Promise<{
data?: O;
error?: Error;
}>
invokePromise
} =
import Hooks
Hooks
.
const useOperationInvoker: () => Capabilities.OperationInvoker

Hook to get the operation invoker capability.

useOperationInvoker
();
const
const handleClick: () => Promise<void>
handleClick
=
useCallback<() => Promise<void>>(callback: () => Promise<void>, deps: React.DependencyList): () => Promise<void>

useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.

useCallback
(async () => {
await
const invokePromise: <{
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, readonly string[]>(op: Definition<{
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, readonly string[], any>, input: {
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, options?: InvokeOptions | undefined) => Promise<...>
invokePromise
(
import LayoutOperation
LayoutOperation
.
const Open: Definition<{
readonly subject: readonly string[];
readonly variant?: string | undefined;
readonly name?: string | undefined;
readonly workspace?: string | undefined;
readonly scrollIntoView?: boolean | undefined;
readonly focus?: "content" | boolean | undefined;
readonly navigation?: "immediate" | "validate" | undefined;
readonly pivotId?: string | undefined;
readonly disposition?: "add" | "auto" | "detail" | "solo" | undefined;
readonly modifiers?: {
readonly shift?: boolean | undefined;
} | undefined;
}, readonly string[], Capability.Service>
Open
, {
subject: readonly string[]
subject
: [
path: string
path
] });
}, [
const invokePromise: <I, O>(op: Definition<I, O>, ...args: void extends I ? [input?: I, options?: InvokeOptions] : [input: I, options?: InvokeOptions]) => Promise<{
data?: O;
error?: Error;
}>
invokePromise
,
path: string
path
]);
return <
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={
const handleClick: () => Promise<void>
handleClick
}>Open</
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
>;
};

useAtomCapability reads an atom capability, such as a plugin’s settings, and re-renders when it changes. useAtomCapabilityState also returns a setter. useTranslation from @dxos/react-ui/Hooks takes the plugin’s namespace.

import * as
import Hooks
Hooks
from '@dxos/app-framework/Hooks';
import * as
import Button
Button
from '@dxos/react-ui/Button';
import * as
import UiHooks
UiHooks
from '@dxos/react-ui/Hooks';
export const
const CompactToggle: () => React.JSX.Element
CompactToggle
= () => {
const [
const settings: {
compact: boolean;
}
settings
,
const setSettings: (fn: (current: {
compact: boolean;
}) => {
compact: boolean;
}) => void
setSettings
] =
import Hooks
Hooks
.
const useAtomCapabilityState: <{
compact: boolean;
}>(atomCapability: Capability.InterfaceDef<Writable<{
compact: boolean;
}, {
compact: boolean;
}>>) => [{
compact: boolean;
}, (fn: (current: {
compact: boolean;
}) => {
compact: boolean;
}) => void]

Hook to get value and updater for an atom capability. Returns [currentValue, updateFn] similar to useState.

@example const [settings, updateSettings] = useAtomCapabilityState(CommentCapabilities.Settings);

useAtomCapabilityState
(
const Settings: Capability.Tag<Writable<{
compact: boolean;
}, {
compact: boolean;
}>, "com.example.plugin.notes.capability.settings">
Settings
);
const {
const t: TFunction<Namespace<string>, KeyPrefix<Namespace<string>>>
t
} =
import UiHooks
UiHooks
.
function useTranslation(ns?: string | string[] | readonly string[] | undefined, options?: UseTranslationOptions<KeyPrefix<Namespace<string>>> | undefined): {
toString(): string;
toLocaleString(): string;
toLocaleString(locales: string | string[], options?: Intl.NumberFormatOptions & Intl.DateTimeFormatOptions): string;
pop(): boolean | TFunction<Namespace<string>, KeyPrefix<Namespace<string>>> | import("i18next").i18n | undefined;
push(...items: (boolean | TFunction<Namespace<string>, KeyPrefix<Namespace<string>>> | import("i18next").i18n)[]): number;
concat(...items: ConcatArray<boolean | TFunction<...> | import("i18next").i18n>[]): (boolean | TFunction<...> | import("i18next").i18n)[];
concat(...items: (boolean | ConcatArray<boolean | TFunction<...> | import("i18next").i18n> | TFunction<...> | import("i18next").i18n)[]): (boolean | TFunction<...> | import("i18next").i18n)[];
join(separator?: string): string;
reverse(): (boolean | TFunction<...> | import("i18next").i18n)[];
shift(): boolean | TFunction<...> | import("i18next").i18n | undefined;
slice(start?: number, end?: number): (boolean | TFunction<...> | import("i18next").i18n)[];
sort(compareFn?: ((a: boolean | TFunction<...> | import("i18next").i18n, b: boolean | TFunction<...> | import("i18next").i18n) => number) | undefined): UseTranslationResponse<...>;
splice(start: number, deleteCount?: number): (boolean | TFunction<...> | import("i18next").i18n)[];
splice(start: number, deleteCount: number, ...items: (boolean | TFunction<...> | import("i18next").i18n)[]): (boolean | TFunction<...> | import("i18next").i18n)[];
unshift(...items: (boolean | TFunction<...> | import("i18next").i18n)[]): number;
indexOf(searchElement: boolean | TFunction<...> | import("i18next").i18n, fromIndex?: number): number;
lastIndexOf(searchElement: boolean | TFunction<...> | import("i18next").i18n, fromIndex?: number): number;
every<S extends boolean | TFunction<...> | import("i18next").i18n>(predicate: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => value is S, thisArg?: any): this is S[];
every(predicate: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => unknown, thisArg?: any): boolean;
some(predicate: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => unknown, thisArg?: any): boolean;
forEach(callbackfn: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => void, thisArg?: any): void;
map<U>(callbackfn: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => U, thisArg?: any): U[];
filter<S extends boolean | TFunction<...> | import("i18next").i18n>(predicate: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => value is S, thisArg?: any): S[];
filter(predicate: (value: boolean | TFunction<...> | import("i18next").i18n, index: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => unknown, thisArg?: any): (boolean | TFunction<...> | import("i18next").i18n)[];
reduce(callbackfn: (previousValue: boolean | TFunction<...> | import("i18next").i18n, currentValue: boolean | TFunction<...> | import("i18next").i18n, currentIndex: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => boolean | TFunction<...> | import("i18next").i18n): boolean | TFunction<...> | import("i18next").i18n;
reduce(callbackfn: (previousValue: boolean | TFunction<...> | import("i18next").i18n, currentValue: boolean | TFunction<...> | import("i18next").i18n, currentIndex: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => boolean | TFunction<...> | import("i18next").i18n, initialValue: boolean | TFunction<...> | import("i18next").i18n): boolean | TFunction<...> | import("i18next").i18n;
reduce<U>(callbackfn: (previousValue: U, currentValue: boolean | TFunction<...> | import("i18next").i18n, currentIndex: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => U, initialValue: U): U;
reduceRight(callbackfn: (previousValue: boolean | TFunction<...> | import("i18next").i18n, currentValue: boolean | TFunction<...> | import("i18next").i18n, currentIndex: number, array: (boolean | TFunction<...> | import("i18next").i18n)[]) => boolean | TFunction<...> | import("i18next").i18n): boolean | TFunction<...> | import("i18next").i18n;
reduceRight(callbackfn: (previousValue: boolean | TFunction<...> | import("i18next").i18n, currentValue: boolean | TFunction<...> | import("i18next").i18n, currentIndex: number, array: (boolean | TFunction<...> | ...
export useTranslation
useTranslation
('com.example.plugin.notes');
return (
<
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={() =>
const setSettings: (fn: (current: {
compact: boolean;
}) => {
compact: boolean;
}) => void
setSettings
((
current: {
compact: boolean;
}
current
) => ({ ...
current: {
compact: boolean;
}
current
,
compact: boolean
compact
: !
current: {
compact: boolean;
}
current
.
compact: boolean
compact
}))
}
>
{
const settings: {
compact: boolean;
}
settings
.
compact: boolean
compact
?
const t: TFunction
<"expand.label", ((string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<AwaitedReactNode>) & (string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | Iterable<ReactI18NextChild>)) | null | undefined, StringMap>(key: "expand.label" | "expand.label"[], options?: string | ... 1 more ... | undefined) => ((string | ... 6 more ... | Promise<AwaitedReactNode>) & (string | ... 7 more ... | Iterable<...>)) | ... 1 more ... | undefined (+1 overload)
t
('expand.label') :
const t: TFunction
<"compact.label", ((string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<AwaitedReactNode>) & (string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<AwaitedReactNode> | Iterable<ReactI18NextChild>)) | null | undefined, StringMap>(key: "compact.label" | "compact.label"[], options?: string | ... 1 more ... | undefined) => ((string | ... 6 more ... | Promise<AwaitedReactNode>) & (string | ... 7 more ... | Iterable<...>)) | ... 1 more ... | undefined (+1 overload)
t
('compact.label')}
</
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
>
);
};

@dxos/app-toolkit/Hooks adds hooks for app state, such as useActiveSpace, useAppGraph and useLayout.

  • Reading an ECHO object’s field in render does not subscribe the component. Use useObject for a snapshot that does, and useQuery for a list. See the ECHO React guide.
  • Write objects inside Obj.update, from an event handler or an operation, never during render.
  • A component never assumes it is the only view of an object. The same object can be open in another plank, on another device, or in the assistant’s hands.
import {
function useCallback<T extends Function>(callback: T, deps: React.DependencyList): T

useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.

useCallback
} from 'react';
import * as
import ToolkitHooks
ToolkitHooks
from '@dxos/app-toolkit/Hooks';
import {
import Obj
Obj
} from '@dxos/echo';
import {
const useObject: {
<T extends Obj.Unknown>(ref: Ref<T>): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
<T extends Obj.Unknown>(ref: Ref<T> | undefined): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
<T extends Obj.Unknown>(ref: Ref<T> | undefined, options: LoadOptions): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
<T extends Obj.Unknown>(obj: T): [Obj.Snapshot<T>, ObjectUpdateCallback<T>];
<T extends Obj.Unknown>(obj: T | undefined): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
<T extends Obj.Unknown>(objOrRef: T | Ref<T> | undefined): [Obj.Snapshot<T> | undefined, ObjectUpdateCallback<T>];
<T extends Obj.Unknown, K extends keyof T>(obj: T, property: K): [T[K], ObjectPropUpdateCallback<T[K]>];
<T extends Obj.Unknown, K extends keyof T>(obj: T | undefined, property: K): [T[K] | undefined, ObjectPropUpdateCallback<T[K]>];
<T, K extends keyof T>(ref: Ref<T>, property: K): [T[K] | undefined, ObjectPropUpdateCallback<T[K]>];
<T, K extends keyof T>(ref: Ref<T> | undefined, property: K): [T[K] | undefined, ObjectPropUpdateCallback<T[K]>];
}
useObject
} from '@dxos/echo-react';
import * as
import Button
Button
from '@dxos/react-ui/Button';
export const
const NoteTitle: ({ note }: {
note: Note;
}) => React.JSX.Element
NoteTitle
= ({
note: Note
note
}: {
note: Note
note
:
class Note
Note
}) => {
// Reading `note.title` in render does not subscribe. `useObject` returns a
// snapshot that does.
const [
const snapshot: Obj.Snapshot<Note>
snapshot
] =
useObject<Note>(obj: Note): [Obj.Snapshot<Note>, ObjectUpdateCallback<Note>] (+9 overloads)

Hook to subscribe to an entire Echo object. Returns a snapshot of the current object value and automatically re-renders when the object changes.

@param ― obj - The Echo object to subscribe to (objects only, not relations)

@returns ― The current object snapshot and update callback

useObject
(
note: Note
note
);
const
const space: Space | undefined
space
=
import ToolkitHooks
ToolkitHooks
.
const useActiveSpace: () => import("@dxos/client-protocol").Space | undefined
useActiveSpace
();
const
const rename: () => Note
rename
=
useCallback<() => Note>(callback: () => Note, deps: React.DependencyList): () => Note

useCallback will return a memoized version of the callback that only changes if one of the inputs has changed.

useCallback
(
() =>
import Obj
Obj
.
const update: <Note>(obj: Note, callback: ChangeCallback<Note>) => Note

Perform mutations on an echo object within a controlled context.

All mutations within the callback are batched and trigger a single notification when the callback completes. Direct mutations outside of Obj.update will throw an error for echo objects.

This function also works with nested objects within echo objects (e.g., Template structs) that are reactive at runtime.

@param ― obj - The echo object to mutate. Use Relation.update for relations.

@param ― callback - The callback that performs mutations on the object.

@example

const person = Obj.make(Person, { name: 'John', age: 25 });
// Mutate within Obj.update
Obj.update(person, (obj) => {
obj.name = 'Jane';
obj.age = 30;
});
// ONE notification fires here
// Direct mutation throws
person.name = 'Bob'; // Error: Cannot modify outside Obj.update()

Note: Only accepts objects. Use Relation.update for relations.

@performance ― Synchronous; costs the mutations made in the callback plus one batched notification and an O(owning fields) parent pass.

update
(
note: Note
note
, (
note: {
title?: string | undefined;
id: EntityId;
"~@dxos/echo/Kind": EntityKind.Object;
}
note
) => (
note: {
title?: string | undefined;
id: EntityId;
"~@dxos/echo/Kind": EntityKind.Object;
}
note
.
title?: string | undefined
title
= 'Renamed')),
[
note: Note
note
],
);
return (
<
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
onClick?: React.MouseEventHandler<HTMLButtonElement> | undefined
onClick
={
const rename: () => Note
rename
}
data-testid: SpaceId | undefined
data-testid
={
const space: Space | undefined
space
?.
Space.id: SpaceId | undefined

Unique space identifier.

id
}>
{
const snapshot: Obj.Snapshot<Note>
snapshot
.
title?: string | undefined
title
}
</
import Button
Button
.
const Root: React.ForwardRefExoticComponent<Omit<Button.RootProps, "className"> & {
classNames?: ClassNameValue;
} & Pick<React.HTMLAttributes<Element>, "children" | "style" | "role"> & React.RefAttributes<HTMLButtonElement>>
export Root
Root
>
);
};
Page What it covers
Surface Where these components render.
Operation Defining the operations a component invokes.