Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/web-ui/src/components/ui/SchemaDiagram.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import '@xyflow/react/dist/style.css';
import dagre from 'dagre';
import {useEditor} from '@/hooks/useEditor';
import {SchemaTableNodeComponent} from './SchemaTableNode';
import {SchemaDiagramLegend} from './SchemaDiagramLegend';
import {
Loader2,
ArrowLeftRight,
Expand Down Expand Up @@ -437,7 +438,9 @@ const SchemaDiagramContent = ({
)}

{/* Toolbar per i controlli */}
<div className="absolute top-4 left-4 z-10 flex gap-2">
<div className="absolute top-4 left-4 z-10 flex items-start gap-2">
<SchemaDiagramLegend />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Expanded legend distorts the toolbar layout

The toolbar container (absolute top-4 left-4 z-10 flex gap-2) uses the default items-stretch. When the legend expands (~150px+ tall), every sibling button (Layout toggle, Export, Show all) stretches to the same height, and the legend also shifts the existing controls to the right. The PR claims it does not interfere with existing toolbar layout. Consider items-start on the toolbar container, or render the expanded panel as an absolutely-positioned popover anchored under the trigger button.


<button
onClick={toggleLayoutDirection}
className="flex items-center gap-2 px-3 py-2 bg-elevated hover:bg-surface-secondary text-primary rounded-lg border border-strong transition-colors shadow-lg text-sm font-medium"
Expand Down
107 changes: 107 additions & 0 deletions packages/web-ui/src/components/ui/SchemaDiagramLegend.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import {memo, useState, useCallback, useId} from 'react';
import {useTranslation} from 'react-i18next';
import {Key, Link, Info, ChevronDown, ChevronUp} from 'lucide-react';
import clsx from 'clsx';
import {useEscapeKey} from '@/hooks/useEscapeKey';

export interface SchemaDiagramLegendProps {
className?: string;
}

export const SchemaDiagramLegend = memo(({className}: SchemaDiagramLegendProps) => {
const {t} = useTranslation();
const contentId = useId();
const [isOpen, setIsOpen] = useState(false);
const close = useCallback(() => setIsOpen(false), []);

// Integrate with the application modal escape stack
useEscapeKey(isOpen, close);

return (
<div
className={clsx(
'relative bg-elevated/95 backdrop-blur-sm border border-strong rounded-lg shadow-lg overflow-visible text-sm font-sans select-none',
className,
)}
data-testid="schema-diagram-legend"
>
<button
type="button"
onClick={() => setIsOpen((prev) => !prev)}
className="flex items-center gap-2 px-3 py-2 text-primary hover:bg-surface-secondary rounded-lg focus-visible:outline focus-visible:outline-2 focus-visible:outline-focus transition-colors font-medium"
aria-expanded={isOpen}
aria-controls={contentId}
title={t('erDiagram.legend', 'Legend')}
>
<Info size={16} className="text-secondary" />
<span>{t('erDiagram.legend', 'Legend')}</span>
{isOpen ? (
<ChevronUp size={14} className="text-secondary" />
) : (
<ChevronDown size={14} className="text-secondary" />
)}
</button>

{isOpen && (
<div
id={contentId}
className="absolute top-full left-0 mt-1 p-3 bg-elevated border border-strong rounded-lg shadow-xl flex flex-col gap-2.5 min-w-[260px] max-w-[300px] z-20"
>
{/* Primary Key Item */}
<div className="flex items-start gap-2.5">
<div className="mt-0.5 p-1 rounded bg-semantic-pk/10 shrink-0">
<Key size={12} className="text-semantic-pk" />
</div>
<div className="flex flex-col min-w-0">
<span className="font-semibold text-semantic-pk text-xs leading-tight">
{t('erDiagram.primaryKey', 'Primary Key')}
</span>
<span className="text-[11px] text-muted leading-tight mt-0.5">
{t(
'erDiagram.primaryKeyDesc',
'Unique column identifying rows in the table',
)}
</span>
</div>
</div>

{/* Foreign Key Item */}
<div className="flex items-start gap-2.5">
<div className="mt-0.5 p-1 rounded bg-semantic-fk/10 shrink-0">
<Link size={12} className="text-semantic-fk" />
</div>
<div className="flex flex-col min-w-0">
<span className="font-semibold text-semantic-fk text-xs leading-tight">
{t('erDiagram.foreignKey', 'Foreign Key')}
</span>
<span className="text-[11px] text-muted leading-tight mt-0.5">
{t(
'erDiagram.foreignKeyDesc',
'References a primary or unique key in another table',
)}
</span>
</div>
</div>

{/* Relationship Connector */}
<div className="flex items-start gap-2.5">
<div className="mt-0.5 p-1 rounded bg-surface-secondary shrink-0 flex items-center justify-center w-5 h-5">
<div className="w-3 h-0.5 bg-accent-primary rounded-full shadow-[0_0_4px_var(--accent-primary)]" />
</div>
<div className="flex flex-col min-w-0">
<span className="font-semibold text-primary text-xs leading-tight">
{t('erDiagram.relationship', 'Relationship')}
</span>
<span className="text-[11px] text-muted leading-tight mt-0.5">
{t(
'erDiagram.relationshipDesc',
'Foreign key reference connecting child and parent tables',
)}
</span>
</div>
</div>
</div>
)}
</div>
);
});
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -2426,7 +2426,14 @@
"exportSuccess": "Diagramm exportiert",
"exportDbml": "Als DBML exportieren",
"exportMarkdown": "Als Markdown exportieren",
"export": "Exportieren"
"export": "Exportieren",
"legend": "Legende",
"primaryKey": "Primärschlüssel",
"primaryKeyDesc": "Eindeutige Spalte zur Zeilenidentifikation in der Tabelle",
"foreignKey": "Fremdschlüssel",
"foreignKeyDesc": "Verweist auf einen Primär- oder eindeutigen Schlüssel einer anderen Tabelle",
"relationship": "Beziehung",
"relationshipDesc": "Fremdschlüssel-Referenz zwischen untergeordneter und übergeordneter Tabelle"
},
"views": {
"createView": "Ansicht erstellen",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2497,7 +2497,14 @@
"exportSuccess": "Diagram exported",
"exportDbml": "Export as DBML",
"exportMarkdown": "Export as Markdown",
"export": "Export"
"export": "Export",
"legend": "Legend",
"primaryKey": "Primary Key",
"primaryKeyDesc": "Unique column identifying rows in the table",
"foreignKey": "Foreign Key",
"foreignKeyDesc": "References a primary or unique key in another table",
"relationship": "Relationship",
"relationshipDesc": "Foreign key reference connecting child and parent tables"
},
"views": {
"createView": "Create View",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -2397,7 +2397,14 @@
"exportSuccess": "Diagrama exportado",
"exportDbml": "Exportar como DBML",
"exportMarkdown": "Exportar como Markdown",
"export": "Exportar"
"export": "Exportar",
"legend": "Leyenda",
"primaryKey": "Clave primaria",
"primaryKeyDesc": "Columna única que identifica filas en la tabla",
"foreignKey": "Clave foránea",
"foreignKeyDesc": "Hace referencia a una clave primaria o única en otra tabla",
"relationship": "Relación",
"relationshipDesc": "Referencia de clave foránea entre tablas secundarias y principales"
},
"views": {
"createView": "Crear Vista",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -2466,7 +2466,14 @@
"exportSuccess": "Diagramme exporté",
"exportDbml": "Exporter en DBML",
"exportMarkdown": "Exporter en Markdown",
"export": "Exporter"
"export": "Exporter",
"legend": "Légende",
"primaryKey": "Clé primaire",
"primaryKeyDesc": "Colonne unique identifiant les lignes de la table",
"foreignKey": "Clé étrangère",
"foreignKeyDesc": "Fait référence à une clé primaire ou unique dans une autre table",
"relationship": "Relation",
"relationshipDesc": "Référence de clé étrangère reliant les tables enfants et parentes"
},
"views": {
"createView": "Créer une vue",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -2486,7 +2486,14 @@
"exportSuccess": "Diagramma esportato",
"exportDbml": "Esporta come DBML",
"exportMarkdown": "Esporta come Markdown",
"export": "Esporta"
"export": "Esporta",
"legend": "Legenda",
"primaryKey": "Chiave primaria",
"primaryKeyDesc": "Colonna univoca che identifica le righe della tabella",
"foreignKey": "Chiave esterna",
"foreignKeyDesc": "Fa riferimento a una chiave primaria o univoca in un'altra tabella",
"relationship": "Relazione",
"relationshipDesc": "Riferimento di chiave esterna tra tabella figlia e genitore"
},
"views": {
"createView": "Crea Vista",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -2437,7 +2437,14 @@
"exportSuccess": "図をエクスポートしました",
"exportDbml": "DBML としてエクスポート",
"exportMarkdown": "Markdown としてエクスポート",
"export": "エクスポート"
"export": "エクスポート",
"legend": "凡例",
"primaryKey": "主キー",
"primaryKeyDesc": "テーブル内の行を一意に識別する列",
"foreignKey": "外部キー",
"foreignKeyDesc": "別のテーブルの主キーまたは一意キーを参照します",
"relationship": "リレーション",
"relationshipDesc": "子テーブルと親テーブルを結ぶ外部キー参照"
},
"views": {
"createView": "ビューを作成",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -2400,7 +2400,14 @@
"exportSuccess": "다이어그램 내보내기 완료",
"exportDbml": "DBML로 내보내기",
"exportMarkdown": "Markdown으로 내보내기",
"export": "내보내기"
"export": "내보내기",
"legend": "범례",
"primaryKey": "기본 키",
"primaryKeyDesc": "테이블의 행을 고유하게 식별하는 열",
"foreignKey": "외래 키",
"foreignKeyDesc": "다른 테이블의 기본 키 또는 고유 키를 참조합니다",
"relationship": "관계",
"relationshipDesc": "하위 테이블과 상위 테이블을 연결하는 외래 키 참조"
},
"views": {
"createView": "뷰 생성",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -2444,7 +2444,14 @@
"exportSuccess": "Diagrama exportado",
"exportDbml": "Exportar como DBML",
"exportMarkdown": "Exportar como Markdown",
"export": "Exportar"
"export": "Exportar",
"legend": "Legenda",
"primaryKey": "Chave primária",
"primaryKeyDesc": "Coluna exclusiva que identifica linhas na tabela",
"foreignKey": "Chave estrangeira",
"foreignKeyDesc": "Faz referência a uma chave primária ou exclusiva em outra tabela",
"relationship": "Relacionamento",
"relationshipDesc": "Referência de chave estrangeira entre tabelas dependentes e principais"
},
"views": {
"createView": "Criar View",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -2449,7 +2449,14 @@
"exportSuccess": "Диаграмма экспортирована",
"exportDbml": "Экспортировать как DBML",
"exportMarkdown": "Экспортировать как Markdown",
"export": "Экспорт"
"export": "Экспорт",
"legend": "Легенда",
"primaryKey": "Первичный ключ",
"primaryKeyDesc": "Уникальный столбец, идентифицирующий строки в таблице",
"foreignKey": "Внешний ключ",
"foreignKeyDesc": "Ссылается на первичный или уникальный ключ в другой таблице",
"relationship": "Связь",
"relationshipDesc": "Связь по внешнему ключу между дочерней и родительской таблицами"
},
"views": {
"createView": "Создать представление",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/tl.json
Original file line number Diff line number Diff line change
Expand Up @@ -2456,7 +2456,14 @@
"exportSuccess": "Na-export ang diagram",
"exportDbml": "I-export bilang DBML",
"exportMarkdown": "I-export bilang Markdown",
"export": "I-export"
"export": "I-export",
"legend": "Gabay",
"primaryKey": "Primary Key",
"primaryKeyDesc": "Natatanging column na tumutukoy sa mga hilera sa talahanayan",
"foreignKey": "Foreign Key",
"foreignKeyDesc": "Sumasangguni sa primary o natatanging key sa ibang talahanayan",
"relationship": "Ugnayan",
"relationshipDesc": "Sanggunian ng foreign key na nag-uugnay sa mga kaugnay na talahanayan"
},
"views": {
"createView": "Gumawa ng View",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2463,7 +2463,14 @@
"exportSuccess": "Đã xuất sơ đồ",
"exportDbml": "Xuất ra DBML",
"exportMarkdown": "Xuất ra Markdown",
"export": "Xuất"
"export": "Xuất",
"legend": "Chú giải",
"primaryKey": "Khóa chính",
"primaryKeyDesc": "Cột duy nhất xác định các hàng trong bảng",
"foreignKey": "Khóa ngoại",
"foreignKeyDesc": "Tham chiếu khóa chính hoặc khóa duy nhất trong bảng khác",
"relationship": "Quan hệ",
"relationshipDesc": "Tham chiếu khóa ngoại kết nối bảng con và bảng cha"
},
"views": {
"createView": "Tạo view",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/zh-TW.json
Original file line number Diff line number Diff line change
Expand Up @@ -2462,7 +2462,14 @@
"exportSuccess": "圖表已匯出",
"exportDbml": "匯出為 DBML",
"exportMarkdown": "匯出為 Markdown",
"export": "匯出"
"export": "匯出",
"legend": "圖例",
"primaryKey": "主鍵",
"primaryKeyDesc": "唯一識別表中列的欄位",
"foreignKey": "外鍵",
"foreignKeyDesc": "引用另一個表中的主鍵或唯一鍵",
"relationship": "關聯",
"relationshipDesc": "連接子表與父表的外鍵引用"
},
"views": {
"createView": "建立檢視",
Expand Down
9 changes: 8 additions & 1 deletion packages/web-ui/src/i18n/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -2379,7 +2379,14 @@
"exportSuccess": "图表已导出",
"exportDbml": "导出为 DBML",
"exportMarkdown": "导出为 Markdown",
"export": "导出"
"export": "导出",
"legend": "图例",
"primaryKey": "主键",
"primaryKeyDesc": "唯一标识表中行的列",
"foreignKey": "外键",
"foreignKeyDesc": "引用另一个表中的主键或唯一键",
"relationship": "关系",
"relationshipDesc": "连接子表与父表的外键引用"
},
"views": {
"createView": "创建视图",
Expand Down
Loading