fix(web): render the create-bot modal outside the side panel; tidy Shell leftovers
The centered Create new Bot modal was rendered inside the side panel's condition, so the empty states that open it (nothing selected, or a project without bots) only showed it while a panel happened to be open. It is a portal to the document body, so it now renders after the panel. - The project drag grip's accessible name goes through Lingui (German "Ziehen zum Umsortieren") instead of a hard-coded English label. - Drop the project drag state that was set but never read, and imports Shell.tsx no longer uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MRtGG9ARfqqhma3t85Ro2u
This commit is contained in:
parent
f395ed9a23
commit
8c15a18565
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
import { useSortable } from "@dnd-kit/sortable";
|
import { useSortable } from "@dnd-kit/sortable";
|
||||||
import { CSS } from "@dnd-kit/utilities";
|
import { CSS } from "@dnd-kit/utilities";
|
||||||
|
import { useLingui } from "@lingui/react/macro";
|
||||||
import { createContext, memo, useContext, useMemo } from "react";
|
import { createContext, memo, useContext, useMemo } from "react";
|
||||||
|
|
||||||
interface SortableGroupProps {
|
interface SortableGroupProps {
|
||||||
@ -30,13 +31,14 @@ export const ProjectDragGrip = memo(function ProjectDragGrip({
|
|||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
const { t } = useLingui();
|
||||||
const handle = useSortableGroupHandle();
|
const handle = useSortableGroupHandle();
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
ref={handle?.setActivatorNodeRef}
|
ref={handle?.setActivatorNodeRef}
|
||||||
className={className}
|
className={className}
|
||||||
aria-label="Drag to reorder"
|
aria-label={t`Drag to reorder`}
|
||||||
{...handle?.attributes}
|
{...handle?.attributes}
|
||||||
{...handle?.listeners}
|
{...handle?.listeners}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Skill-Entwurf"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr "Entwerfe die Spezifikation…"
|
msgstr "Entwerfe die Spezifikation…"
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr "Ziehen zum Umsortieren"
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Bild ziehen, ablegen oder einfügen"
|
msgstr "Bild ziehen, ablegen oder einfügen"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Draft skill"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr "Drafting the spec…"
|
msgstr "Drafting the spec…"
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr "Drag to reorder"
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Drag, drop, or paste an image"
|
msgstr "Drag, drop, or paste an image"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Habilidad en borrador"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Arrastra, suelta o pega una imagen"
|
msgstr "Arrastra, suelta o pega una imagen"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "ड्राफ़्ट स्किल"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "छवि खींचें, छोड़ें या पेस्ट करें"
|
msgstr "छवि खींचें, छोड़ें या पेस्ट करें"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "작업 기술 초안"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "이미지를 끌어다 놓거나 붙여넣으세요"
|
msgstr "이미지를 끌어다 놓거나 붙여넣으세요"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Habilidade de rascunho"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Arraste, solte ou cole uma imagem"
|
msgstr "Arraste, solte ou cole uma imagem"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Черновик навыка"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Перетащите или вставьте изображение"
|
msgstr "Перетащите или вставьте изображение"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "Taslak beceri"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "Görüntüyü sürükleyip bırakın veya yapıştırın"
|
msgstr "Görüntüyü sürükleyip bırakın veya yapıştırın"
|
||||||
|
|||||||
@ -2100,6 +2100,10 @@ msgstr "技能草稿"
|
|||||||
msgid "Drafting the spec…"
|
msgid "Drafting the spec…"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: src/components/SortableGroup.tsx
|
||||||
|
msgid "Drag to reorder"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: src/pages/shell/avatar-studio-popover.tsx
|
#: src/pages/shell/avatar-studio-popover.tsx
|
||||||
msgid "Drag, drop, or paste an image"
|
msgid "Drag, drop, or paste an image"
|
||||||
msgstr "拖放或粘贴图片"
|
msgstr "拖放或粘贴图片"
|
||||||
|
|||||||
@ -1,10 +1,5 @@
|
|||||||
import { closestCenter, DndContext, DragOverlay } from "@dnd-kit/core";
|
import { closestCenter, DndContext } from "@dnd-kit/core";
|
||||||
import {
|
import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
||||||
SortableContext,
|
|
||||||
sortableKeyboardCoordinates,
|
|
||||||
verticalListSortingStrategy,
|
|
||||||
} from "@dnd-kit/sortable";
|
|
||||||
import { CSS as DndCSS } from "@dnd-kit/utilities";
|
|
||||||
import { Trans, useLingui } from "@lingui/react/macro";
|
import { Trans, useLingui } from "@lingui/react/macro";
|
||||||
import type {
|
import type {
|
||||||
Bot,
|
Bot,
|
||||||
@ -72,13 +67,10 @@ import {
|
|||||||
ArrowLeft,
|
ArrowLeft,
|
||||||
Calendar,
|
Calendar,
|
||||||
Globe,
|
Globe,
|
||||||
LayoutGrid,
|
|
||||||
PanelRight,
|
PanelRight,
|
||||||
Pencil,
|
Pencil,
|
||||||
Plus,
|
Plus,
|
||||||
RefreshCw,
|
|
||||||
Search,
|
Search,
|
||||||
Settings,
|
|
||||||
Trash2,
|
Trash2,
|
||||||
X,
|
X,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
@ -1320,9 +1312,7 @@ export function ShellPage() {
|
|||||||
mainConversationEntry,
|
mainConversationEntry,
|
||||||
projectSidebarGroups,
|
projectSidebarGroups,
|
||||||
sensors,
|
sensors,
|
||||||
setDraggedProjectId,
|
|
||||||
handleProjectDragEnd,
|
handleProjectDragEnd,
|
||||||
handleProjectDragStart,
|
|
||||||
} = useSidebarModel({
|
} = useSidebarModel({
|
||||||
query,
|
query,
|
||||||
spaces,
|
spaces,
|
||||||
@ -2943,8 +2933,6 @@ export function ShellPage() {
|
|||||||
sensors={sensors}
|
sensors={sensors}
|
||||||
collisionDetection={closestCenter}
|
collisionDetection={closestCenter}
|
||||||
onDragEnd={handleProjectDragEnd}
|
onDragEnd={handleProjectDragEnd}
|
||||||
onDragStart={handleProjectDragStart}
|
|
||||||
onDragCancel={() => setDraggedProjectId(null)}
|
|
||||||
>
|
>
|
||||||
<SortableContext
|
<SortableContext
|
||||||
items={projectSidebarGroups.filter((g) => g.title).map((g) => g.spaceId)}
|
items={projectSidebarGroups.filter((g) => g.title).map((g) => g.spaceId)}
|
||||||
@ -3544,44 +3532,6 @@ export function ShellPage() {
|
|||||||
onImport={(manifest) => importBot(manifest)}
|
onImport={(manifest) => importBot(manifest)}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
{/* Centered Create Bot Modal */}
|
|
||||||
{showCreateBotModal &&
|
|
||||||
createPortal(
|
|
||||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="absolute inset-0 bg-overlay"
|
|
||||||
aria-label={t`Close`}
|
|
||||||
onClick={() => setShowCreateBotModal(false)}
|
|
||||||
/>
|
|
||||||
<div className="relative z-10 max-h-[90vh] w-[480px] overflow-y-auto rounded-2xl border border-border bg-popover p-6 text-popover-foreground shadow-2xl">
|
|
||||||
<div className="mb-4 flex items-center justify-between">
|
|
||||||
<h2 className="text-lg font-semibold text-foreground">
|
|
||||||
<Trans>Create new Bot</Trans>
|
|
||||||
</h2>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={() => setShowCreateBotModal(false)}
|
|
||||||
className="text-muted-foreground hover:text-foreground"
|
|
||||||
aria-label={t`Close`}
|
|
||||||
>
|
|
||||||
<X strokeWidth={1.8} className="size-icon-md" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<CreateBotForm
|
|
||||||
onCancel={() => setShowCreateBotModal(false)}
|
|
||||||
onCreate={async (input) => {
|
|
||||||
await createBot(input);
|
|
||||||
}}
|
|
||||||
onImport={async (manifest) => {
|
|
||||||
await importBot(manifest);
|
|
||||||
setShowCreateBotModal(false);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>,
|
|
||||||
document.body,
|
|
||||||
)}
|
|
||||||
{panel === "settings" && active ? (
|
{panel === "settings" && active ? (
|
||||||
<BotSettings
|
<BotSettings
|
||||||
key={active.id}
|
key={active.id}
|
||||||
@ -3773,6 +3723,44 @@ export function ShellPage() {
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
</aside>
|
</aside>
|
||||||
|
{/* Centered Create Bot Modal */}
|
||||||
|
{showCreateBotModal &&
|
||||||
|
createPortal(
|
||||||
|
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="absolute inset-0 bg-overlay"
|
||||||
|
aria-label={t`Close`}
|
||||||
|
onClick={() => setShowCreateBotModal(false)}
|
||||||
|
/>
|
||||||
|
<div className="relative z-10 max-h-[90vh] w-[480px] overflow-y-auto rounded-2xl border border-border bg-popover p-6 text-popover-foreground shadow-2xl">
|
||||||
|
<div className="mb-4 flex items-center justify-between">
|
||||||
|
<h2 className="text-lg font-semibold text-foreground">
|
||||||
|
<Trans>Create new Bot</Trans>
|
||||||
|
</h2>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => setShowCreateBotModal(false)}
|
||||||
|
className="text-muted-foreground hover:text-foreground"
|
||||||
|
aria-label={t`Close`}
|
||||||
|
>
|
||||||
|
<X strokeWidth={1.8} className="size-icon-md" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<CreateBotForm
|
||||||
|
onCancel={() => setShowCreateBotModal(false)}
|
||||||
|
onCreate={async (input) => {
|
||||||
|
await createBot(input);
|
||||||
|
}}
|
||||||
|
onImport={async (manifest) => {
|
||||||
|
await importBot(manifest);
|
||||||
|
setShowCreateBotModal(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>,
|
||||||
|
document.body,
|
||||||
|
)}
|
||||||
|
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
{contextChat && botMenu ? (
|
{contextChat && botMenu ? (
|
||||||
|
|||||||
@ -32,7 +32,6 @@ export function useSidebarModel({
|
|||||||
setProjectOrder(orderedIds);
|
setProjectOrder(orderedIds);
|
||||||
writeProjectSidebarOrder(orderedIds);
|
writeProjectSidebarOrder(orderedIds);
|
||||||
}, []);
|
}, []);
|
||||||
const [draggedProjectId, setDraggedProjectId] = useState<string | null>(null);
|
|
||||||
const sensors = useSensors(
|
const sensors = useSensors(
|
||||||
useSensor(MouseSensor, { activationConstraint: { distance: 8 } }),
|
useSensor(MouseSensor, { activationConstraint: { distance: 8 } }),
|
||||||
useSensor(TouchSensor, { activationConstraint: { distance: 8 } }),
|
useSensor(TouchSensor, { activationConstraint: { distance: 8 } }),
|
||||||
@ -242,9 +241,6 @@ export function useSidebarModel({
|
|||||||
},
|
},
|
||||||
[projectSidebarGroups, handleReorderProjects],
|
[projectSidebarGroups, handleReorderProjects],
|
||||||
);
|
);
|
||||||
const handleProjectDragStart = useCallback((event: { active: { id: string | number } }) => {
|
|
||||||
setDraggedProjectId(String(event.active.id));
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
homeSpaceBots,
|
homeSpaceBots,
|
||||||
@ -252,8 +248,6 @@ export function useSidebarModel({
|
|||||||
mainConversationEntry,
|
mainConversationEntry,
|
||||||
projectSidebarGroups,
|
projectSidebarGroups,
|
||||||
sensors,
|
sensors,
|
||||||
setDraggedProjectId,
|
|
||||||
handleProjectDragEnd,
|
handleProjectDragEnd,
|
||||||
handleProjectDragStart,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user