@geckou/ui-react
v0.9.0
Published
A set of reusable React UI components (forms) by Geckou
Downloads
1,238
Readme
@geckou/ui-react
Web(React 19 / Next.js)用の UI コンポーネント集。
ロジックは @geckou/ui-core が持ち、このパッケージは DOM の記述だけを担当する。
同じ core を @geckou/ui-vue も使うため、バリデーション・日付処理の挙動は両者で一致する。
Mobile(Expo / NativeWind)では使えない(DOM 前提のため)。
インストール
yarn add @geckou/ui-reactビルド済みの JavaScript と型定義(dist/)を配布しています。トランスパイルの設定は要りません。
- グローバル CSS に
@import '@geckou/ui-react/styles/tokens.css';を追加(デザイントークン) - Tailwind を使う場合は、配布物をスキャン対象に加える
Tailwind CSS v4 が必須です。 コンポーネントは bg-(--background-color)、
rounded-(--radius-size)、flex-none! のような v4 の記法を直書きしているため、
v3 ではこれらのクラスが生成されません。v4 はスキャン対象を CSS 側の @source で指定します。
/* グローバル CSS */
@import 'tailwindcss';
@source '../node_modules/@geckou/ui-react/dist';
@import '@geckou/ui-react/styles/tokens.css';@source のパスは、その CSS ファイルからの相対で書きます。
'use client' はビルド後も各ファイルの先頭に残るので、Next.js の App Router では
Server Component から直接 import できます(状態を持つコンポーネントだけが Client Component になります)。
0.1.1 以前から更新する場合: ソース配布をやめたため、
next.config.tsのtranspilePackagesから'@geckou/ui-react'を外し、Tailwind のスキャン対象をsrc/**/*.{ts,tsx}からdistに変えてください。transpilePackagesは 残しても動きますが、スキャン対象がsrcのままだとクラスが検出されずスタイルが当たりません。
tokens.css は既定値です。上書きする変数の一覧はリポジトリの README を参照してください。
使い方
import { TextBox, BasicButton, ModalBox } from '@geckou/ui-react'フォーム全体の検証状態
useFormValidation で各入力の検証結果を集約する。
Vue 版の FormValidationManager と同じストア(@geckou/ui-core)を使う。
store を入力コンポーネントの formValidationStore に渡してください(渡さない入力は集計されません)。
対応しているのは DatePicker / DateRangePicker / DateSelector。
const { isAllValid, store } = useFormValidation()
const [startedOn, setStartedOn] = useState('')
const [period, setPeriod] = useState({ start: '', end: '' })
return (
<form>
<DatePicker
name="startedOn"
value={startedOn}
onChange={setStartedOn}
isRequired
formValidationStore={store}
/>
<DateRangePicker name="period" value={period} onChange={setPeriod} />
<button disabled={!isAllValid}>送信</button>
</form>
)props は Vue 版(@geckou/ui-vue)と揃えている。v-model にあたるものが
value + onChange になるだけで、名前と意味は同じ。
| Component | value | 主な props |
|-----------|-------|-----------|
| DatePicker | string(YYYY-MM-DD / type="month" なら YYYY-MM) | name / isRequired / isDisabled / minDate / maxDate / size / type / formValidationStore |
| DateRangePicker | { start: string; end: string } | DatePicker と同じ(開始日と終了日の min / max が自動連動)。各入力の name は <name>Start / <name>End |
| DateSelector | string(YYYY-MM-DD / type="month" なら YYYY-MM) | name / isRequired / type / formValidationStore |
DatePicker / DateSelector の年月日欄の読み上げ名は、既定では name から作られます
(name="startedOn" なら「startedOnの年」)。CheckBox と同じ ariaLabel / ariaLabelledBy
を渡すと、そちらを土台に「の年」「の月」「の日」を繋げます。可視ラベルがあるなら
ariaLabelledBy でその要素を指してください(WCAG 2.5.3 Label in Name)。
<DatePicker name="startedOn" ariaLabel="開始日" /> {/* 「開始日の年」 */}
<DatePicker name="startedOn" ariaLabelledBy={labelId} /> {/* 可視ラベル + 「の年」 */}収録コンポーネント
フォーム系 25 種(TextBox / TextArea / SelectBox / SearchableSelectBox / CheckBox 系 /
RadioButtons / ToggleButton / DatePicker / DateRangePicker / DateSelector /
FileInput / ModalBox / PopupBox / DropdownUi / SlideDownUi / TabUI ほか)とアイコン 5 種。
記事一覧(ArticleList)は Vue 版のみに収録している。
テスト
yarn workspace @geckou/ui-react test0.9.0 の変更
DropdownUiが Escape で閉じ、トリガーへフォーカスを戻す。処理したときはpreventDefault()するので、ModalBoxの中に置いてもダイアログまで閉じないDropdownUi/SlideDownUiのトリガーにaria-controlsが付き、DropdownUiにはaria-haspopup="true"も付く
0.8.0 の変更
BasicButtonはローディング中にdisabledにしない(押した瞬間にフォーカスがbodyへ落ちるため)。代わりにaria-disabled/aria-busyを付け、pointer-eventsとonClickガードで押せなくする。:disabledを前提に スタイルを当てている場合は[aria-disabled]の追従が要るBasicButtonのローディング中もアクセシブル名を保つ(invisible→opacity-0)。LoadingSpinnerはaria-hidden="true"BasicButtonの hover 色がcolor-mix()になった。${色}ccの文字列連結だったため、 3 桁 hex('#fff')・rgb()・名前色・var()では不正値になっていたPopupBoxは表示している間だけ子要素を描画する。常時 DOM にあるとopacityの切り替えでは支援技術に通知されず、非表示中も文言が読めていたModalBoxは開いたままアンマウントされてもフォーカスを戻すModalBoxの背景クリック判定が「押し始めも背景だったとき」だけになった。 ダイアログ内でテキスト選択を始めて背景で離すと閉じていたRadioButtonsがrole="radiogroup"になり、ariaLabel/ariaLabelledByを受ける。 エラーはaria-describedbyで結び付くErrorMessageがidを受ける(aria-describedbyから参照するため)
0.7.0 の変更
CheckBox/LabeledCheckboxにvalueを追加。CheckBoxesは各選択肢のvalueを送信用の hidden へ渡すようになった。これまでは全てvalue="on"で、 ネイティブ送信(Server Actions /<form action>)でどれが選ばれたか区別できなかったDatePickerの年月日欄は入力中にエラー文言を出さない。判定は入力のたびに 更新し、文言は欄を離れた時点(blur)で出す。あわせて 1 桁の月・日は blur で 2 桁へ正規化する(「1」→「01」)DatePickerの年月日欄が不正なとき、送信値とonChangeが空文字になる (これまでは valid のときだけ更新していたため、画面と送信値が食い違っていた)SelectBoxがisDisabledかつ値が0/'NA'のときにプレースホルダを 出す分岐を削除した。0 は正当な選択値として扱うSelectBoxがエラー時にInputBoxへisErroredを渡し、aria-invalidを付けるSearchableSelectBoxはisDisabledの選択肢を候補に出さず、確定後の入力欄にはvalueではなくラベルを表示する(通知は従来どおりvalue)。ariaLabelledByを追加(TextBoxにも追加)TextAreaのautoAdjustHeightがbox-sizingを見て高さを補正する (border-box のリセット CSS を当てた環境で 2rem 足りなかった)DateRangePickerは範囲の比較前に日付を正規化するErrorMessageは同じ文言を複数受け取っても重複キーの警告を出さないSlideDownUiのトリガーが<button>の中に<div>を置かなくなった
0.6.0 の変更
ModalBoxを重ねたとき、Escape で閉じるのは最前面の 1 枚だけになった (従来は内側と外側のonCloseが両方呼ばれていた)。あわせて自分が Escape を 処理したらpreventDefault()する。外側で Escape を見ているアプリ側のハンドラが 一緒に反応しなくなるので、defaultPreventedを見ずに閉じている処理があれば追従が要るSearchableSelectBoxが候補 0 件のときは Escape を握らない(preventDefault()しない)。ModalBoxの中で「何にもマッチしない語を入れた状態だと Escape を 2 回押す必要がある」 のが直るDatePickerのカレンダー起動用入力にアクセシブル名(「◯◯のカレンダー」)が付き、 キーボードで到達したときアイコン側に可視フォーカスが出るPopupBoxがrole="status"(ライブリージョン)になり、支援技術に通知が伝わるDateRange型を公開の入口から export するようにした (import type { DateRange } from '@geckou/ui-react')
0.5.0 の変更
DatePicker/DateSelectorがariaLabel/ariaLabelledByを受ける (未指定なら従来どおりnameから読み上げ名を作る)CheckBox/ToggleButtonが<button>の中に<input>を置かなくなった。 状態は<button>のdata-checked/disabledで表し、送信用の入力は チェック時だけ<input type="hidden">として<button>の外に描かれる。 DOM を辿っているテストやスタイルがあれば追従が要るModalBoxが開いている間、Tab / Shift+Tab をダイアログ内で循環させる(フォーカストラップ)SearchableSelectBoxが WAI-ARIA の Combobox パターンに沿い、↑↓ / Enter / Escape で操作できる
0.4.0 の変更
RadioButtonsが必須エラー(「必須項目です」)を描画する。Vue 版と同じく、 値が空へ変化したときに出るCheckBox/ToggleButtonのロールがaria-pressedからrole="checkbox" + aria-checked/role="switch" + aria-checkedに変わった。 アクセシブル名はariaLabel/ariaLabelledByで渡せる(未指定なら従来どおりname)DateSelectorにminYear/maxYearを追加(既定は従来どおり「今年 -100 〜 今年 -14」)DateRangePickerが範囲(開始 > 終了)を検証し、<name>Rangeという名前でFormValidationStoreに登録する。invalidNamesを見ている場合は増えるTabUIのcolor.textを配線した
