From 69d5dd8ee28c3e335e1a249443e5db64f753144f Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 7 Aug 2026 02:10:37 +0000 Subject: [PATCH 1/2] Add keyboard submission support for project and connection forms --- .jules/palette.md | 3 +++ frontend/src/App.tsx | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index bd0f7324..e47e36f7 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -57,3 +57,6 @@ ## 2026-07-30 - Add window.confirm for destructive actions **Learning:** Destructive actions like deleting groups and edge relationships previously occurred immediately without user confirmation. **Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm. +## 2024-08-07 - Add Keyboard Submission to Inline Forms +**Learning:** For components that contain input fields combined with submission buttons, they often omit a wrapper form element causing Enter-to-submit to fail. Wrapping these generic groupings (like 'New Project' and 'New Connection' creation elements) in standard `
` elements handles native implicit submission smoothly without requiring manual key listeners. +**Action:** When inspecting generic inline create elements containing an input and submit button, always ensure they are wrapped in a `` and handle `onSubmit` (preventing default) instead of relying solely on the submit button's `onClick`. diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0fa62ede..42102eb9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1078,7 +1078,7 @@ export default function App() { -
+ { e.preventDefault(); onCreateProject(); }}>
setProjectName(e.target.value)} />
+
@@ -1126,7 +1125,7 @@ export default function App() {
-
+
{ e.preventDefault(); onCreateConnection(); }}>
+
@@ -1309,20 +1307,22 @@ export default function App() {

프로젝트

프로젝트를 선택하면 해당 다이어그램 목록을 볼 수 있습니다.

-
+
{ e.preventDefault(); onCreateProject(); }} + > setProjectName(event.currentTarget.value)} /> -
+
From 3ee4f5cdbadfefb43d1b0d8fc3fbf2c1777f1d7d Mon Sep 17 00:00:00 2001 From: seonghobae <8172694+seonghobae@users.noreply.github.com> Date: Fri, 7 Aug 2026 03:06:49 +0000 Subject: [PATCH 2/2] Add keyboard submission support for project and connection forms --- .jules/palette.md | 3 --- CHANGELOG.md | 1 + frontend/src/App.coverage.test.tsx | 10 +++++----- frontend/src/App.tsx | 12 +++++++----- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.jules/palette.md b/.jules/palette.md index e47e36f7..bd0f7324 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -57,6 +57,3 @@ ## 2026-07-30 - Add window.confirm for destructive actions **Learning:** Destructive actions like deleting groups and edge relationships previously occurred immediately without user confirmation. **Action:** Always wrap delete operations with window.confirm() dialogs and ensure corresponding tests successfully mock window.confirm. -## 2024-08-07 - Add Keyboard Submission to Inline Forms -**Learning:** For components that contain input fields combined with submission buttons, they often omit a wrapper form element causing Enter-to-submit to fail. Wrapping these generic groupings (like 'New Project' and 'New Connection' creation elements) in standard `
` elements handles native implicit submission smoothly without requiring manual key listeners. -**Action:** When inspecting generic inline create elements containing an input and submit button, always ensure they are wrapped in a `` and handle `onSubmit` (preventing default) instead of relying solely on the submit button's `onClick`. diff --git a/CHANGELOG.md b/CHANGELOG.md index 679a6202..3b7d2b4e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,3 +11,4 @@ - [FE] `autoInfer.ts`에 대한 단위 테스트 및 UI 컴포넌트 단위 테스트를 추가하여 100% 테스트 커버리지를 유지합니다. - [FE] ⬇️ **DBML Export**: ERD 다이어그램을 DBML (Database Markup Language) 형식으로 내보낼 수 있는 기능을 추가했습니다. 상단의 DBML 버튼을 클릭하여 다운로드할 수 있습니다. - [FE] 📚 **Data Dictionary Export**: ERD 테이블/컬럼 메타데이터를 CSV 및 Markdown으로 내보내며, CSV formula injection과 Markdown 렌더링 escape를 적용했습니다. +- [FE] 🎨 **프로젝트 및 연결 생성 폼 엔터키 제출 지원**: 폼(`div` -> `form`) 요소를 통해 네이티브 HTML form 제출(Enter 키 동작)과 웹 접근성(WCAG 키보드 조작)을 개선했습니다. diff --git a/frontend/src/App.coverage.test.tsx b/frontend/src/App.coverage.test.tsx index 0b9a20aa..b7e554ec 100644 --- a/frontend/src/App.coverage.test.tsx +++ b/frontend/src/App.coverage.test.tsx @@ -347,20 +347,20 @@ describe('App orchestration coverage', () => { fireEvent.click(screen.getByRole('button', { name: '편집기' })) fireEvent.change(screen.getByLabelText('New project'), { target: { value: ' New ' } }) - fireEvent.click(screen.getByRole('button', { name: 'Create' })) + fireEvent.submit(screen.getByLabelText('New project').closest('form')!) await waitFor(() => expect(api.createProject).toHaveBeenCalledWith('New')) const dsn = screen.getByLabelText('Connection DSN') fireEvent.change(dsn, { target: { value: 'postgresql://[' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) expect(screen.getByRole('alert')).toHaveTextContent('Connection DSN must use') fireEvent.change(dsn, { target: { value: 'http://bad.example/db' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) expect(screen.getByRole('alert')).toHaveTextContent('Connection DSN must use') expect(dsn).toHaveValue('') fireEvent.change(dsn, { target: { value: 'postgresql://db.example/test' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) await waitFor(() => expect(api.createConnection).toHaveBeenCalledWith('p3', 'target-db', 'postgresql://db.example/test')) fireEvent.change(screen.getByLabelText('Schema filter (optional)'), { target: { value: ' public ' } }) @@ -682,7 +682,7 @@ describe('App orchestration coverage', () => { await renderReadyApp() fireEvent.click(screen.getByRole('button', { name: '편집기' })) fireEvent.change(screen.getByLabelText('Connection DSN'), { target: { value: 'postgresql://db.example/test' } }) - fireEvent.click(screen.getByRole('button', { name: 'Save connection' })) + fireEvent.submit(screen.getByLabelText('Connection DSN').closest('form')!) await waitFor(() => expect(api.createConnection).toHaveBeenCalled()) fireEvent.click(screen.getByRole('button', { name: 'Reverse engineer → snapshot' })) await waitFor(() => expect(api.createSnapshot).toHaveBeenCalledWith('p1', 'c2', undefined)) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 42102eb9..cfaa34ee 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -939,7 +939,8 @@ export default function App() { setLayoutMessage("되돌렸습니다"); } - async function onCreateProject() { + async function handleProjectSubmit(e?: React.FormEvent) { + e?.preventDefault(); const nextProjectName = projectName.trim(); /* v8 ignore next -- the create control is disabled for both guard states */ if (!nextProjectName || isCreatingProject) return; @@ -954,7 +955,8 @@ export default function App() { } } - async function onCreateConnection() { + async function handleConnectionSubmit(e?: React.FormEvent) { + e?.preventDefault(); /* v8 ignore next -- the save control is disabled without a project or while saving */ if (!selectedProjectId || isCreatingConnection) return; const nextConnectionName = connName.trim(); @@ -1078,7 +1080,7 @@ export default function App() {
- { e.preventDefault(); onCreateProject(); }}> +
- { e.preventDefault(); onCreateConnection(); }}> + { e.preventDefault(); onCreateProject(); }} + onSubmit={handleProjectSubmit} >