├── .eslintrc.json ├── .github └── workflows │ └── nextjs.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── app ├── _components │ ├── field-list.tsx │ ├── hero.tsx │ └── intro.tsx ├── globals.css ├── icon.svg ├── layout.tsx ├── opengraph-image.png ├── page.tsx └── stop-enter-submit │ ├── _components │ ├── correct-form.tsx │ ├── correct-textarea-form.tsx │ ├── incorrect-form.tsx │ └── petition-form.tsx │ ├── opengraph-image.png │ └── page.tsx ├── bun.lockb ├── components.json ├── components └── ui │ ├── accordion.tsx │ ├── button.tsx │ ├── code-block.tsx │ ├── collapsible.tsx │ ├── copy-button.tsx │ ├── external-link.tsx │ ├── footer.tsx │ ├── form-unit.tsx │ ├── form.tsx │ ├── github-link.tsx │ ├── input.tsx │ ├── label.tsx │ ├── ref.tsx │ ├── select.tsx │ ├── tabs.tsx │ └── textarea.tsx ├── fields ├── address │ ├── component.tsx │ ├── doc.mdx │ ├── html.html │ └── zod.ts ├── email │ ├── component.tsx │ ├── doc.mdx │ ├── html.html │ └── zod.ts ├── name │ ├── component.tsx │ ├── doc.mdx │ ├── html.html │ └── zod.ts ├── password │ ├── component.tsx │ ├── doc.mdx │ ├── html.html │ └── zod.ts └── tel │ ├── component.tsx │ ├── doc.mdx │ ├── html.html │ └── zod.ts ├── lib ├── config.ts ├── fields.ts ├── file.ts └── utils.ts ├── mdx-components.tsx ├── next.config.js ├── package.json ├── postcss.config.js ├── public ├── hero.svg └── stop-enter-trigger │ ├── chrome.mp4 │ ├── ogimage.png │ └── safari.mp4 ├── tailwind.config.js ├── tsconfig.json └── types └── field-meta.ts /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } -------------------------------------------------------------------------------- /.github/workflows/nextjs.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Next.js site to GitHub Pages 2 | # 3 | # To get started with Next.js see: https://nextjs.org/docs/getting-started 4 | # 5 | name: Deploy Next.js site to Pages 6 | 7 | on: 8 | # Runs on pushes targeting the default branch 9 | push: 10 | branches: ['main'] 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 16 | permissions: 17 | contents: read 18 | pages: write 19 | id-token: write 20 | 21 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 22 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 23 | concurrency: 24 | group: 'pages' 25 | cancel-in-progress: false 26 | 27 | jobs: 28 | # Build job 29 | build: 30 | runs-on: ubuntu-latest 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v3 34 | - uses: oven-sh/setup-bun@v1 35 | with: 36 | bun-version: latest 37 | - name: Setup Node 38 | uses: actions/setup-node@v3 39 | with: 40 | node-version: '16' 41 | - name: Setup Pages 42 | uses: actions/configure-pages@v3 43 | with: 44 | # Automatically inject basePath in your Next.js configuration file and disable 45 | # server side image optimization (https://nextjs.org/docs/api-reference/next/image#unoptimized). 46 | # 47 | # You may remove this line if you want to manage the configuration yourself. 48 | static_site_generator: next 49 | - name: Restore cache 50 | uses: actions/cache@v3 51 | with: 52 | path: | 53 | .next/cache 54 | # Generate a new cache whenever packages or source files change. 55 | key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/bun.lockb') }}-${{ hashFiles('**.[jt]s', '**.[jt]sx') }} 56 | # If source files changed but packages didn't, rebuild from a prior cache. 57 | restore-keys: | 58 | ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json', '**/yarn.lock') }}- 59 | - name: Install dependencies 60 | run: bun install 61 | - name: Build with Next.js 62 | run: bun run build 63 | - name: Upload artifact 64 | uses: actions/upload-pages-artifact@v2 65 | with: 66 | path: ./out 67 | 68 | # Deployment job 69 | deploy: 70 | environment: 71 | name: github-pages 72 | url: ${{ steps.deployment.outputs.page_url }} 73 | runs-on: ubuntu-latest 74 | needs: build 75 | steps: 76 | - name: Deploy to GitHub Pages 77 | id: deployment 78 | uses: actions/deploy-pages@v2 79 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | 27 | # local env files 28 | .env*.local 29 | 30 | # vercel 31 | .vercel 32 | 33 | # typescript 34 | *.tsbuildinfo 35 | next-env.d.ts 36 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 貢献者ガイド 2 | 3 | ふぉーむがいどへの貢献に興味を持っていただきありがとうございます。ここにあなたがいることを私たちは嬉しく思っています。 4 | 5 | 初めてプルリクエストを提出する前に、このドキュメントを一度確認してください。また、類似の内容で既に誰かが作業していないか、オープンなイシューとプルリクエストを確認することを強くお勧めします。 6 | 7 | 何か助けが必要な場合は、[@d151005](https://twitter.com/d151005) までお気軽にご連絡ください。 8 | 9 | ## このリポジトリについて 10 | 11 | このリポジトリでは主に以下のライブラリを使用しています。 12 | 13 | - Next.js(App Router) 14 | - [shadcn/ui](https://ui.shadcn.com) 15 | 16 | ## 構造 17 | 18 | このリポジトリの構造は以下のようになっています。 19 | 20 | ``` 21 | ├── app 22 | ├── components 23 | │ └── ui 24 | ├── fields 25 | └── lib 26 | ``` 27 | 28 | | Path | Description | 29 | | --------------- | ---------------------------------------- | 30 | | `components/ui` | アプリケーションで使用するコンポーネント | 31 | | `fields` | ドキュメントの各フォームフィールド関連 | 32 | | `lib` | ヘルパー関数 | 33 | 34 | ## 開発 35 | 36 | ### リポジトリのクローンから始める 37 | 38 | ``` 39 | git clone https://github.com/dninomiya/form-guide.git 40 | ``` 41 | 42 | ### 依存関係のインストール 43 | 44 | ``` 45 | bun install 46 | bun dev 47 | 48 | http://localhost:3000/form-guide 49 | ``` 50 | 51 | _/form-guide を末尾につける点に注意してください。_ 52 | 53 | ## フォームフィールド 54 | 55 | 各フォームフィールドのディレクトリにあるファイルを編集すると自動的にドキュメントサイトに反映されます。誤字脱字を除いては、基本的には Discussions で合意を得た上でプルリクエストをお願いします。 56 | 57 | ```bash 58 | └── fields 59 | ├── address 60 | │ ├── component.tsx # プレビュー 61 | │ ├── doc.mdx # ドキュメント 62 | │ ├── html.html # HTMLコード 63 | │ └── zod.ts # zodコード 64 | ``` 65 | 66 | zod のコードは実際に `component.tsx` で使用される点にご注意ください。(ただのサンプルコードではありません) 67 | 68 | ## コミットコメント 69 | 70 | 内容がわかれば問題ありませんが、可能であれば[Angular Commit Message Guidelines](https://github.com/angular/angular/blob/22b96b9/CONTRIBUTING.md#-commit-message-guidelines)に準拠してください。 71 | 72 | ## 新しい機能やフォームフィールドのリクエスト 73 | 74 | 新しいコンポーネントや機能のリクエストがある場合は、GitHub でディスカッションを開始してください。お手伝いできることがあります。 75 | 76 | ## テスト 77 | 78 | 現在テストはなく、実装予定もありませんが実装いただける場合プルリクエストをお願いします。 79 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Daichi Ninomiya 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ふぉーむがいど 2 | 3 | オープンソースのフォーム実装ガイドです。 4 | 5 |  6 | 7 | ## ドキュメント 8 | 9 | https://dninomiya.github.io/form-guide/ 10 | 11 | ## 貢献する 12 | 13 | [貢献者ガイド](/CONTRIBUTING.md) をご参照ください。 14 | 15 | ## ライセンス 16 | 17 | [MIT license](/LICENSE.md). 18 | -------------------------------------------------------------------------------- /app/_components/field-list.tsx: -------------------------------------------------------------------------------- 1 | import FormUnit from '@/components/ui/form-unit'; 2 | import { FIELDS } from '@/lib/fields'; 3 | import { getFile } from '@/lib/file'; 4 | 5 | export default function FieldList() { 6 | const units = FIELDS.map((field) => { 7 | const html = getFile(`fields/${field.id}/html.html`); 8 | const zod = getFile(`fields/${field.id}/zod.ts`); 9 | 10 | return { 11 | id: field.id, 12 | sources: [ 13 | { 14 | code: html, 15 | lang: 'html', 16 | label: 'HTML', 17 | }, 18 | { 19 | code: zod, 20 | lang: 'ts', 21 | label: 'Zod', 22 | }, 23 | ], 24 | }; 25 | }); 26 | 27 | return ( 28 |
29 | オープンソースのフォーム実装ガイド 30 |
31 |77 | このページはオープンソースのフォーム実装ガイドです。フォームの実装において、ユーザー体験を向上させるためのベストプラクティスをまとめています。プルリクエストやコメントを歓迎しています。 78 |
79 | 80 |81 | 82 | 完成度を高めるため、積極的に意見を募っています🙏🏻 83 | 84 |
85 | 86 |submitted: {data}
} 20 |submitted: {data}
} 28 |submitted: {data}
} 23 |Enter key to Submit
behaviors by
36 | directly hooking into the raw keypress event. 🙏🏻
37 | 39 | 45 |
46 |47 | Setting the Enter key as a send trigger can make it challenging for 48 | Japanese users utilizing Safari to use the form. In Japanese, users 49 | compose text using the Enter key to convert into Kanji. If the Enter key 50 | is set as the send trigger, the text might be submitted prematurely. 51 |
52 | 53 |54 | This issue is currently prevalent in many web applications abroad. 55 | Regrettably, solutions are not being actively implemented, and products 56 | with similar problems continue to be produced daily. 57 |
58 | 59 |{`If you have difficulty understanding the problem even after watching the video, imagine a situation where "the space key acts as a send trigger." It's like when you try to type "I am Taro", and just after typing "I", it gets sent.`}
75 | 76 |watasi
using the Japanese
83 | keyboard, and when the conversion balloon appears, press{' '}
84 | enter
.
85 |
114 | When there is only one input field, using{' '}
115 |
140 | For text areas, the solution is to use{' '}
141 |
169 | Lastly, these issues would be resolved if Safari handled{' '}
170 |
181 | 189 | Star 190 | 191 |
192 | 193 | 194 | 195 |
196 | Thank you for everyone's support. If you have a better approach or
197 | any questions, please join{' '}
198 |
223 | 224 | {`I am not familiar with English, so this text 225 | was primarily composed using ChatGPT. I apologize if it's difficult to 226 | read. If you find any expressions that seem off, please provide 227 | feedback!🙏🏻`} 228 | 229 |
230 | 231 |162 | {body} 163 |
164 | ); 165 | }); 166 | FormMessage.displayName = 'FormMessage'; 167 | 168 | export { 169 | Form, 170 | FormControl, 171 | FormDescription, 172 | FormField, 173 | FormItem, 174 | FormLabel, 175 | FormMessage, 176 | useFormField, 177 | }; 178 | -------------------------------------------------------------------------------- /components/ui/github-link.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function GithubLink({ href }: { href: string }) { 4 | return ( 5 | <> 6 | 12 | 39 | 40 | 68 | > 69 | ); 70 | } 71 | -------------------------------------------------------------------------------- /components/ui/input.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | export interface InputProps 6 | extends React.InputHTMLAttributes