feat(canvas): add shared workspace access and controls
This commit is contained in:
@@ -5,6 +5,17 @@
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.workspace-title.is-disabled .workspace-title-name,
|
||||
.workspace-title.is-disabled .title-ghost {
|
||||
color: #a7adb5;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.workspace-title.is-disabled .workspace-title-name:hover,
|
||||
.workspace-title.is-disabled .title-ghost:hover {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.moteva-mark {
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
|
||||
@@ -10,6 +10,7 @@ type WorkspaceTitleProps = {
|
||||
backHomeLabel: string;
|
||||
copyLabel: string;
|
||||
moreLabel: string;
|
||||
disabled?: boolean;
|
||||
onBackHome: () => void;
|
||||
onRename: (title: string) => Promise<void>;
|
||||
};
|
||||
@@ -22,6 +23,7 @@ export function WorkspaceTitle({
|
||||
backHomeLabel,
|
||||
copyLabel,
|
||||
moreLabel,
|
||||
disabled = false,
|
||||
onBackHome,
|
||||
onRename
|
||||
}: WorkspaceTitleProps) {
|
||||
@@ -37,6 +39,10 @@ export function WorkspaceTitle({
|
||||
if (!editing) setDraftTitle(title);
|
||||
}, [editing, title]);
|
||||
|
||||
useEffect(() => {
|
||||
if (disabled) setEditing(false);
|
||||
}, [disabled]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!editing) return;
|
||||
const input = inputRef.current;
|
||||
@@ -46,7 +52,7 @@ export function WorkspaceTitle({
|
||||
}, [editing]);
|
||||
|
||||
const startEditing = () => {
|
||||
if (renaming) return;
|
||||
if (disabled || renaming) return;
|
||||
setDraftTitle(trimmedTitle);
|
||||
setEditing(true);
|
||||
};
|
||||
@@ -57,7 +63,7 @@ export function WorkspaceTitle({
|
||||
};
|
||||
|
||||
const commitEditing = async () => {
|
||||
if (committingRef.current) return;
|
||||
if (disabled || committingRef.current) return;
|
||||
const nextTitle = draftTitle.trim();
|
||||
if (!nextTitle || nextTitle === trimmedTitle) {
|
||||
cancelEditing();
|
||||
@@ -77,7 +83,7 @@ export function WorkspaceTitle({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="workspace-title">
|
||||
<div className={`workspace-title ${disabled ? "is-disabled" : ""}`} aria-disabled={disabled}>
|
||||
<button className="moteva-mark" type="button" onClick={onBackHome} aria-label={backHomeLabel}>
|
||||
<BrandMark className="workspace-brand-mark" />
|
||||
</button>
|
||||
@@ -88,6 +94,7 @@ export function WorkspaceTitle({
|
||||
value={draftTitle}
|
||||
placeholder={placeholder}
|
||||
readOnly={renaming}
|
||||
disabled={disabled}
|
||||
onChange={(event) => setDraftTitle(event.target.value)}
|
||||
onBlur={() => void commitEditing()}
|
||||
onKeyDown={(event) => {
|
||||
@@ -104,14 +111,14 @@ export function WorkspaceTitle({
|
||||
{renaming && <Loader2 className="spin" size={13} />}
|
||||
</span>
|
||||
) : (
|
||||
<button className="workspace-title-name" type="button" title={displayTitle} aria-label={renameLabel} onClick={startEditing}>
|
||||
<button className="workspace-title-name" type="button" title={displayTitle} aria-label={renameLabel} onClick={startEditing} disabled={disabled}>
|
||||
<strong>{displayTitle}</strong>
|
||||
</button>
|
||||
)}
|
||||
<button className="title-ghost" type="button" aria-label={copyLabel}>
|
||||
<button className="title-ghost" type="button" aria-label={copyLabel} disabled={disabled}>
|
||||
<Copy size={14} />
|
||||
</button>
|
||||
<button className="title-ghost" type="button" aria-label={moreLabel}>
|
||||
<button className="title-ghost" type="button" aria-label={moreLabel} disabled={disabled}>
|
||||
<ChevronDown size={14} />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user