Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,6 @@
## 2024-07-14 - Native Keyboard Submission with Forms for Modals
**Learning:** Modals designed with plain `<div>` elements as wrappers instead of `<form>` lack native keyboard submission support, forcing users to switch from keyboard to mouse to confirm actions like "Save".
**Action:** When designing modals or popups containing inputs, always use a `<form>` element to wrap the content, handle the `onSubmit` event (calling `e.preventDefault()`), and set the primary confirmation button to `type="submit"` to enable seamless Enter-key submission for keyboard users.
## 2025-02-28 - Native form submission for "New Project"
**Learning:** In React SPA patterns, interactive input groups (like creating a new project) are often built with simple `<div>` and `<button>` wrappers. By replacing these with `<form>` elements, `<button type="submit">`, and `onSubmit={(e) => e.preventDefault()}`, we effortlessly unlock native keyboard accessibility (submitting by pressing "Enter") without needing complex event listeners.
**Action:** Always wrap data submission input/button groups in a `<form>` element instead of a plain `<div>`, and set the primary action button to `type="submit"`.
26 changes: 18 additions & 8 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1075,15 +1075,20 @@ export default function App() {

<div className="field">
<label htmlFor="project-name">New project</label>
<div className="row">
<form
className="row"
onSubmit={(e) => {
e.preventDefault();
onCreateProject();
}}
>
<input
id="project-name"
value={projectName}
onChange={(e) => setProjectName(e.target.value)}
/>
<button
type="button"
onClick={onCreateProject}
type="submit"
disabled={!projectName.trim() || isCreatingProject}
aria-busy={isCreatingProject}
aria-describedby={
Expand All @@ -1092,7 +1097,7 @@ export default function App() {
>
{isCreatingProject ? "Creating…" : "Create"}
</button>
</div>
</form>
{createProjectHint ? (
<span id="create-project-hint" className="field-hint">
{createProjectHint}
Expand Down Expand Up @@ -1304,20 +1309,25 @@ export default function App() {
<h1 id="projects-title">ν”„λ‘œμ νŠΈ</h1>
<p>ν”„λ‘œμ νŠΈλ₯Ό μ„ νƒν•˜λ©΄ ν•΄λ‹Ή λ‹€μ΄μ–΄κ·Έλž¨ λͺ©λ‘μ„ λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€.</p>
</div>
<div className="inlineCreate">
<form
className="inlineCreate"
onSubmit={(e) => {
e.preventDefault();
onCreateProject();
}}
>
<input
aria-label="μƒˆ ν”„λ‘œμ νŠΈ 이름"
value={projectName}
onChange={(event) => setProjectName(event.currentTarget.value)}
/>
<button
type="button"
onClick={onCreateProject}
type="submit"
disabled={!projectName.trim() || isCreatingProject}
>
{isCreatingProject ? "생성 쀑" : "μƒˆ ν”„λ‘œμ νŠΈ"}
</button>
</div>
</form>
</div>
<div className="dataTable" role="table" aria-label="ν”„λ‘œμ νŠΈ λͺ©λ‘">
<div className="dataTable__row dataTable__row--projects dataTable__row--head" role="row">
Expand Down
Loading