mcpField
D
defaults

defaults

github.com/raphaelsalajaデザイン・UI67167 回インストール6 日前に更新
リポジトリ

defaults について

スクロール、フォーム、フォーカス、読み込み、テーマ、アクセシビリティなど、画面全体に適用する既定ルールをまとめたレビュー用スキルです。具体的なルールと反例で問題を特定し、修正の方向を示します。

主な機能

  1. 01スクロール端とシャドウの確認
  2. 02フォーカス、ダイアログ、操作領域の規定
  3. 03フォーム入力と検証のレビュー
  4. 04テーマ、状態表示、アクセシビリティの確認
  5. 05ルール ID と修正例の提示

活用シーン

  1. 01ダイアログのフォーカス管理とスクロールのレビュー
  2. 02モバイル端末でのフォーム入力の確認
  3. 03テーマ切り替えや状態表示の問題の発見
  4. 04長文や未入力項目があるレイアウトの検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/raphaelsalaja/skills --skill defaults

インストール後、Claude Code で/defaultsを入力して読み込まれたか確認します。

同梱ファイルagents/openai.yamlrecipes.md

詳細

デフォルト

このスキルでは、すべての画面に適用されるインターフェースのデフォルトを定めます。サーフェス、文字、サウンド、フォーカス、フォーム、読み込み、オーバーレイを扱います。

まずトークンを使い、その後にこれらの値を使う

以下の値にプロジェクトのトークンがある場合は、それを使用してください。該当するトークンがない場合は、ここに示す値を厳守してください。スクロールが突然途切れたり、シャドウが切れたりするスタイルは、いずれも指摘対象です。

言葉や句読点は copy に属します。これらをプロジェクトのプリミティブで構築するかどうかは reuse に属します。サウンドやアニメーションをそもそも設けるべきかどうかは restraint に属します。動きは motion に、色とコントラストは color に属します。同心円状の角丸、光学的な位置調整、アイコンの配置は alignment に属します。

スクロール領域の端をフェードさせる

スクロールコンテナの端は、mask-image のグラデーションでフェードさせます。オーバーフロー領域の端が突然切れる場合は defaults-fade-not-cut です。実装方法は recipes.md を参照してください。

シャドウを決して切らない

子要素のシャドウがコンテナ内に収まるよう、スクローラーに十分なパディングを設けてください。overflow: hidden によってシャドウが切れる場合は defaults-no-clipped-shadow です。recipes.md を参照してください。

コードとテーブルは折り返さずにスクロールする

コードブロックとデータテーブルは、スクロールバーを非表示にして横方向にスクロールさせます。コード行が折り返される場合は defaults-scroll-not-wrap です。recipes.md を参照してください。

オーバーレイ内のスクロールを保つ

スクロール可能なダイアログ、ドロワー、メニュー、サイドパネルには overscroll-behavior: contain を設定します。モーダル内のリストの末尾までスクロールすると背後のページがスクロールする場合は defaults-contain-overscroll です。

スティッキー要素の縁を保つ

スティッキーヘッダーまたはフッターには、その下でスクロールするコンテンツとの境界に 1px のボーダーを付けます。ボーダーのないスティッキーヘッダーは defaults-sticky-border です。

scroll-padding-block-start をスティッキーヘッダーの高さに設定し、アンカーやフォーカスされたフィールドがヘッダーの下に表示されるようにします。フォーカスされたフィールドがヘッダーの下に隠れる場合は defaults-clear-sticky-chrome です。

フローティングサーフェスにはボーダーではなくリングを使う

ポップオーバー、メニュー、カードなどのフローティング要素では、シャドウと、シャドウスタックの内側に置く半透明の 1px リングを組み合わせます。シャドウの横に不透明な border がある場合は defaults-ring-not-border です。強制カラーモードでも縁が描画されるよう、リングの下には border: 1px solid transparent を残してください。

シャドウは重ね、下方向に落とす

プロジェクトのエレベーショントークンを使用します。ない場合は、ぼかしを大きく、透明度を低くしながら、下方向にずらしたシャドウを 3 つ重ねます。0 4px 16px rgba(0, 0, 0, 0.2) が 1 つだけの場合は defaults-layered-shadows です。recipes.md を参照してください。

ホバー時にサーフェスを浮き上がらせるには、浮き上がったシャドウを持つ疑似要素をフェードインさせます。box-shadow にトランジションを設定する場合は defaults-fade-the-shadow です。recipes.md を参照してください。

コンテンツ画像には薄いアウトラインを付ける

写真やスクリーンショットには、内側に 1px 入れた 1px のアウトラインを付けます。ライトモードでは黒の 10%、ダークモードでは白の 10% にします。写真の縁がカードになじんで見えなくなる場合は defaults-image-outline です。ロゴや透明なアートワークには適用しません。recipes.md を参照してください。

カードを入れ子にしない

カードを別のカードの中に配置してはいけません。見出しは外に置き、1 つのサーフェスでコンテンツをまとめます。カードの中にカードがある場合は defaults-no-nested-cards です。

ピル型ではなく角丸にする

ボタンとチップには角丸トークンを使用します。border-radius: 9999px は defaults-rounded-not-pill です。

装飾を加えない

装飾的なグラデーション、グロー、ぼかし、奥行き効果を取り除きます。カードの背後にグローがある場合は defaults-no-decoration です。

テーマをブラウザーにも反映する

ダークテーマでは、スクロールバーとネイティブコントロールにもテーマが適用されるよう、ルートに color-scheme: dark を設定します。ダークページに明るいスクロールバーが表示される場合は defaults-color-scheme です。ページ上部の色に合わせ、配色ごとに theme-color タグを 1 つ設定します。

テーマを切り替える際は、1 フレームだけトランジションを無効にします。テーマ変更時にすべての色が同時にフェードする場合は defaults-quiet-theme-switch です。recipes.md を参照してください。

キーボード操作時のみフォーカスリングを表示する

outline とともに :focus-visible を使用します。クリックするたびにリングが表示される場合は defaults-focus-keyboard-only です。

ダイアログ内にフォーカスを保つ

ダイアログを開くとフォーカスが内部に移動し、Tab キーで内部を移動できるように保たれ、閉じるとトリガーにフォーカスが戻ります。ダイアログを開いている間、背後のページにフォーカスが残る状態は defaults-trap-and-return-focus です。showModal() で開いたネイティブの <dialog> はフォーカストラップを処理します。

ターゲットは少なくとも 24px

すべてのインタラクティブなターゲットは、短辺が少なくとも 24px あり、マウスでは 40px、タッチでは 44px を目指します。グリフが小さい場合は、負のインセットを持つ疑似要素でヒット領域を広げます。ヒットボックスが 16px の 16px アイコンボタンは defaults-hit-area です。拡張したヒット領域同士が重なることはありません。recipes.md を参照してください。

コントロールの役割を明確にする

アイコンのみのボタンには、動作を示す aria-label を付けます。名前のないゴミ箱アイコンは defaults-name-icon-buttons です。

ステータスを色だけで示してはいけません。アイコンまたは単語を組み合わせてください。エラーを示す唯一の手がかりが赤い点の場合は defaults-not-color-alone です。

リンクにはリンクを使う

ナビゲーションには <a href> を使うため、新しいタブで開く操作、中クリック、リンクのコピーがすべて機能します。onClick でルートを変更する div は defaults-links-are-links です。

状態は URL に保存する

フィルター、タブ、ページネーション、開いているパネルの状態を URL に書き込むことで、更新、共有、戻る操作でも状態が維持されます。更新すると失われるフィルターは defaults-state-in-url です。

ズームを有効に保つ

viewport タグで maximum-scale=1 や user-scalable=no を設定してはいけません。ピンチズームをブロックするページは defaults-allow-zoom です。

タップを自然にする

ルートに -webkit-tap-highlight-color: transparent を一度だけ設定し、タップ可能なすべての要素に独自の :active 状態を指定します。タップ時にグレーのフラッシュが表示される場合は defaults-no-tap-highlight です。

ボタンとリンクには touch-action: manipulation を設定し、2回目のタップを待たずにタップを実行できるようにします。タップの反応が 300ms 遅れる場合は defaults-fast-tap です。recipes.md を参照してください。

ホバースタイルはホバー対応ポインターでのみ適用する

ホバー時のみのスタイルは @media (hover: hover) and (pointer: fine) で囲みます。そうしないと、タッチ画面でタップした後もスタイルが残ります。タップした後も浮き上がったままのカードは defaults-hover-capable-only です。

全高レイアウトには動的な単位を使う

アプリのシェルや画面下部に固定するバーには 100dvh を使い、最初の画面には min-height: 100svh を使います。下部のボタンが URL バーの下に隠れる 100vh のシェルは defaults-dynamic-viewport です。

コンテンツをノッチから離す

viewport タグに viewport-fit=cover を追加し、固定ヘッダー、タブバー、トースト、シートに env(safe-area-inset-*) でパディングを設定します。ホームインジケーターの下に隠れる下部バーは defaults-safe-areas です。

コントロールを選択不可にする

ボタン、タブ、チップ、ドラッグハンドルには user-select: none を設定し、長押ししてもラベルが選択されないようにします。コンテンツのテキストは選択可能なままにします。長押しでハイライトされるボタンラベルは defaults-controls-not-selectable です。

ホットキーを入力欄で無効にする

入力欄、テキストエリア、または編集可能な要素にフォーカスがある間、ホットキーは実行されません。これを defaults-keys-ignore-inputs とします。recipes.md を参照してください。

Enter で送信する

フィールドが 1 つのフォームでは、Enter キーで送信します。複数のフィールドがあるフォームでは、最後のフィールドで Enter キーを押すと送信します。テキストエリアでは Enter キーで改行し、⌘ または Ctrl と Enter キーの組み合わせで送信します。クリックしないと送信できない検索フィールドは defaults-enter-submits です。

入力欄は貼り付けた内容を受け付ける

カード番号の空白や電話番号の括弧など、入力欄はユーザーが入力または貼り付けた内容をそのまま受け付けます。コード内で書式を取り除き、値を整えて表示します。+1 (555) 010-2030 を拒否する電話番号欄は defaults-accept-messy-input です。貼り付けをブロックしてはいけません。また、一部のキーボードが追加する末尾の空白は削除します。

入力欄に適したキーボードを表示する

すべての入力欄に type、inputmode、autocomplete を設定し、キーボードと自動入力を適切にします。プレーンテキストとして設定されたメールアドレス欄は defaults-input-types です。

モバイルでは、入力欄の文字サイズを 16px 以上にします。そうしないと、iOS ではフォーカス時にページがズームされます。スマートフォンで 14px の入力欄は defaults-input-16px です。

ラベルをクリックするとコントロールが反応します

すべてのコントロールにはラベルがあり、ラベルをクリックするとコントロールが動作します。テキストをクリックしても何も起きないチェックボックスは defaults-label-hit-area です。

フォームは送信時に検証します

リクエストが開始されるまで、送信ボタンは有効なままにします。送信時には、各エラーを対応するフィールドの横に表示し、最初のエラーにフォーカスします。フォームが有効になるまで送信ボタンを無効にする場合は defaults-validate-on-submit です。

ビジーボタンはラベルを維持します

リクエストの実行中もボタンのラベルを維持し、インジケーターを表示してボタンを無効にします。ラベルがスピナーに置き換わり、ボタンが小さくなる場合は defaults-loading-button です。

破壊的な操作は取り消せるようにします

破壊的な操作の後に、元に戻す方法を用意します。取り消せない場合は、メニューやポップオーバーを使ってその場で確認します。どちらも用意されていない削除操作は defaults-undo-destructive です。

数字の桁を揃えます

価格、件数、タイマー、テーブルの列には font-variant-numeric: tabular-nums を使用します。カウントの更新に合わせて幅が揺れる場合は defaults-tabular-numbers です。

見出しのバランスを整え、段落を読みやすく折り返します

見出しには text-wrap: balance を、本文の段落には text-wrap: pretty を設定します。最終行に単語が1つだけ残る見出しは defaults-balanced-wrap です。

テキストをくっきり表示します

ルート要素に一度だけ -webkit-font-smoothing: antialiased と -moz-osx-font-smoothing: grayscale を設定します。スムージングがない場合や、コンポーネントごとに設定している場合は defaults-antialiased-root です。

インラインコードを少し小さく表示します

文章中の等幅フォントは 0.9em に縮小します。文章中でサイズが変わらず、文より大きく見えるインラインコードは defaults-inline-mono です。

省略したテキストを再び読めるようにします

ユーザーが必要とする省略済みテキストは、ツールチップ、展開コントロール、詳細ビューのいずれかで全文を表示できるようにします。読み返す方法がないままファイル名が途中で切れる場合は defaults-truncate-with-way-back です。ファイル名とパスは、ほかと区別できるよう中央で省略します。数字、金額、日付は省略しません。

実際のデータに耐えられるレイアウトにします

すべてのフィールドを、現実的にあり得る最長の値でテストします。テキスト列には min-width: 0 を、アバターなどの固定ボックスには flex-shrink: 0 を設定し、メールアドレスとURLには overflow-wrap: anywhere を設定します。長いメールアドレスのせいで行のメニューが画面外に押し出される場合は defaults-survives-long-content です。

任意項目がない場合は、プレースホルダーを表示せず、その行を省きます。役割の欄にダッシュだけが表示される場合は defaults-omit-empty-fields です。

数字、日付、複数形をロケールに合わせます

Intl.NumberFormat、Intl.DateTimeFormat、Intl.PluralRules を使って書式を設定します。1 members や書式設定されていない 1284 は defaults-locale-format です。

更新を通知します

トースト、結果件数、インライン検証は、空の状態でレンダリングされ、テキストの変更時に更新される丁寧なライブリージョン role="status" に配置します。スクリーンリーダーに通知されないトーストは defaults-announce-updates です。

待機中はすぐにフィードバックを表示します

操作には400ms以内に応答するか、楽観的な値、スケルトン、プログレスバーなどでただちにフィードバックを表示します。ローディング時に null を返す分岐は defaults-instant-feedback です。

スピナーやスケルトンの表示は150~300ms遅らせ、表示したら少なくとも300~500msは表示を続けます。1フレームだけ点滅するスケルトンは defaults-no-flicker-loading です。スケルトンは置き換えるレイアウトに合わせます。recipes.md を参照してください。

音は確認のために使い、音だけに頼らないようにします

音は、支払い、アップロード、送信などの確認に適しています。見逃してはならないエラーにも適しています。すべての音には、ステータスの変更など、目に見える対応物を用意します。画面上で何も変化しないのに成功音が鳴る場合は defaults-sound-has-a-twin です。

入力、ホバー、スクロール、キーボード操作では音を鳴らしません。キー入力のたびにクリック音が鳴る場合は defaults-no-sound-on-repeat です。

ユーザーが音をオフにできるようにし、音量の初期値は 0.3 にします。オフにする方法がなく、audio.volume = 1 がハードコードされている場合は defaults-sound-optional です。再生方法とクリック音の合成については recipes.md を参照してください。

ダイアログは一度に1つだけ表示します

ダイアログの上に別のダイアログを開いてはいけません。メニュー、ポップオーバー、または新しいページを使用します。これは defaults-no-stacked-dialogs です。

ペア

各チェックはペアになっています。修正が必要な行の隣に、置き換える行が表示されます。

ルール問題のある状態置き換え
defaults-fade-not-cutoverflow: auto による唐突な切れ目両端に mask-image のフェードを適用
defaults-no-clipped-shadowoverflow: hidden でカードの影が切れるスクロール領域に padding: 8px
defaults-scroll-not-wrapコードの行が2行に折り返されるwhite-space: nowrap と overflow-x: auto
defaults-contain-overscrollドロワーのリストが末端でページをスクロールさせるドロワーに overscroll-behavior: contain
defaults-sticky-border境界線のないスティッキーヘッダーborder-bottom: 1px solid var(--gray-a4)
defaults-clear-sticky-chrome56px のスティッキーヘッダーの下にフォーカスされたフィールドが隠れるscroll-padding-block-start: 56px
defaults-ring-not-borderポップオーバーに border: 1px solid #e5e5e5 と box-shadow を適用透明な境界線の上に、影の先頭として 0 0 0 1px var(--gray-a4) を指定
defaults-layered-shadowsbox-shadow: 0 4px 16px rgba(0, 0, 0, 0.2)下向きの3つのレイヤーを使い、ぼかしを強くしながら不透明度を下げる
defaults-fade-the-shadowtransition: box-shadow 200ms浮き上がった影を保持する ::after の opacity を変更
defaults-image-outline白いカード上で写真の輪郭が見えないoutline-offset: -1px で outline: 1px solid rgba(0, 0, 0, 0.1) を指定
defaults-no-nested-cards見出しと別のカードを含むカード1つのカードの上に見出しを配置
defaults-rounded-not-pillボタンに border-radius: 9999px を指定border-radius: var(--radius-2)
defaults-no-decorationカードの背後にグラデーションの光彩がある単色の背景
defaults-color-schemeスクロールバーが明るいダークテーマルートに color-scheme: dark を指定
defaults-quiet-theme-switchテーマ切り替え時にすべての色のトランジションが発生する1フレームだけトランジションを無効にする
defaults-focus-keyboard-only.button:focus { box-shadow: 0 0 0 2px var(--accent) }.button:focus-visible { outline: 2px solid var(--accent) }
defaults-trap-and-return-focusTab キーでダイアログの背後にあるページへ移動できるフォーカスをダイアログ内に留め、その後トリガーに戻す
defaults-hit-area16px のアイコンボタンのヒット領域が16px::before に inset: -12px を指定し、40px のターゲットにする
defaults-name-icon-buttons<button><TrashIcon /></button><button aria-label="Delete">
defaults-not-color-aloneエラーを示す手がかりが赤い点だけアイコンまたは Failed の文字を点と併用
defaults-links-are-links<div onClick={() => router.push("/settings")}><a href="/settings">
defaults-state-in-urlフィルターの状態が useState にしか保持されていないURL に ?status=open を指定
defaults-allow-zoommaximum-scale=1, user-scalable=nowidth=device-width, initial-scale=1
defaults-no-tap-highlightタップするたびにブラウザーで灰色のフラッシュが表示される-webkit-tap-highlight-color: transparent と :active のスタイル
defaults-fast-tapタップしてからボタンが反応するまで300msかかるtouch-action: manipulation
defaults-hover-capable-only.card:hover { transform: translateY(-2px) }同じルールを @media (hover: hover) and (pointer: fine) 内に指定
defaults-dynamic-viewportアプリシェルに height: 100vh を指定height: 100dvh
defaults-safe-areasホームインジケーターの下にタブバーがあるviewport-fit=cover とともに padding-bottom: env(safe-area-inset-bottom) を指定
defaults-controls-not-selectable長押しするとタブのラベルが選択されるタブに user-select: none を指定
defaults-keys-ignore-inputs検索中に J キーを押すと選択が移動するホットキーの対象から input、textarea、[contenteditable] を除外
defaults-enter-submits検索フィールドが form で囲まれていないonSubmit で検索を実行する form
defaults-accept-messy-input電話番号フィールドが +1 (555) 010-2030 を拒否する入力を受け付け、+15550102030 として保存し、書式を整えて表示
defaults-input-typesメールアドレスに <input type="text"> を使用type="email" autocomplete="email"
defaults-input-16pxモバイルの入力欄に font-size: 14px を指定font-size: 16px
defaults-label-hit-areaチェックボックスの横に単独の span があるチェックボックスとテキストを1つの label 内に配置
defaults-validate-on-submit送信ボタンに disabled={!isValid} を指定ボタンを有効にし、送信時にエラーを表示して最初のエラーにフォーカス
defaults-loading-buttonラベルをスピナーに置き換えるラベルを残して横にスピナーを表示し、ボタンを無効にする
defaults-undo-destructive元に戻す方法がなく、削除が即時に実行されるUndo を含むトースト
defaults-tabular-numbers時間表示の数字が変わるたびに幅が変わるfont-variant-numeric: tabular-nums
defaults-balanced-wrap見出しの最後の行に単語が1つだけ残るh1 { text-wrap: balance } と p { text-wrap: pretty }
defaults-antialiased-root明るいテキストに既定のサブピクセルスムージングが適用されるルートに -webkit-font-smoothing: antialiased を指定
defaults-inline-mono<code> のサイズが周囲の文章と同じfont-size: 0.9em
defaults-truncate-with-way-backファイル名が省略表示され、それ以外に情報がない完全な名前を表示するツールチップ
defaults-survives-long-content長いメールアドレスが行のメニューを画面外に押し出すテキストに min-width: 0、メニューに flex-shrink: 0 を指定
defaults-omit-empty-fields役割がない場合にダッシュを表示する役割の行を省略
defaults-locale-formatcount が 1 のときに {count} members と表示するIntl.PluralRules で member または members を選択
defaults-announce-updatesテキストとともにトーストをマウントするが、ロールが指定されていないテキストが更新される空の role="status" 領域
defaults-instant-feedbackif (isLoading) return nullif (isLoading) return <Skeleton />
defaults-no-flicker-loading40ms で応答する場合にもスピナーを表示する200ms 後に表示し、少なくとも400msは表示を維持
defaults-sound-has-a-twinステータスを変更せずに playSound("success") を呼び出すサウンドとともに setStatus("success") を呼び出す
defaults-no-sound-on-repeatonChange 内で playSound("keystroke") を呼び出す入力時にサウンドを鳴らさない
defaults-sound-optionalaudio.volume = 1 で、オフにする手段がないサウンド設定を用意し、デフォルトの音量を 0.3 にする
defaults-no-stacked-dialogs設定ダイアログから確認ダイアログを開くダイアログ内でメニューまたはポップオーバーを使用

報告

重大度。 HIGH は、利用やアクセスを妨げます。影が途中で切れている、スクロールが突然途切れる、入力中にホットキーが動作する、ダイアログが重なっている、24px 未満のターゲット、または無言の待機が該当します。また、貼り付けた書式を受け付けないフィールド、視覚的な代替手段やオフスイッチのない音声も該当します。名前のないアイコンボタン、色だけで示されたステータス、ダイアログからフォーカスが抜ける状態、ズームのブロック、リンクのないルートも該当します。また、有効になるまで無効化された送信ボタン、元に戻す方法のない切り詰められた値、取り消しや確認のない破壊的な操作も該当します。長い値によって画面外に押し出されたコンテンツ、操作部品を隠す 100vh のシェル、ホームインジケーターに重なるバーも該当します。

MEDIUM は、ピル型ボタン、クリック時のフォーカスリング、またはタッチ操作で解除されないホバー状態です。データ内のプロポーショナル数字、頻繁に行う操作で鳴る音、オーバーレイから漏れるスクロール、更新時に失われる状態、ちらつくスケルトンも該当します。また、不適切なキーボードが表示されるフィールド、16px 未満のモバイル入力欄、機能しないラベル、送信されない Enter キー、インジケーターのない処理中のボタンも該当します。通知のない更新、固定表示の UI の下に隠れたフィールド、カード内のカードも該当します。タップ時のフラッシュや遅延、選択可能なコントロールのラベル、書式設定されていない数値や複数形も該当します。

LOW は、影の横にある不透明な境界線、装飾的なグロー、単一の強い影、またはトランジションする box-shadow です。バランスの悪い見出し、画像のアウトラインの欠落、境界線のない固定ヘッダー、暗いページ上の明るいスクロールバー、にじんだテーマ切り替え、ルート要素のフォントスムージングの欠落も該当します。フルサイズのインラインコードや、空のフィールドに対するプレースホルダーのダッシュも該当します。

形式。 根本原因ごとに指摘事項を 1 つ記載します。

file:line - [rule-id] what is wrong

続けて Rule | Count | Severity の概要を記載します。HIGH が 1 件でも残っている場合は Block、それ以外は Approve とします。読んでいないファイルを Approve にしないでください。レイアウトに依存するチェックでは画面を開き、実行できなかったチェックはすべて Not verified と記載してください。

コメント