# ThinkMove — Interaction Atelier & UI Library

30の触れる作品・36種類の動画素材と、従来の18種類の実務用UI部品を収録したローカルライブラリ。

- **作品を見る・触る**: `index.html` をブラウザで開く。
- **動画で使う**: `motion.html`。MP4・透過WebM・HyperFramesソース。詳しくは `MOTION.md`。
- **実務用の18部品**: `workbench.html`。従来の一覧を保持。
- **1ファイルで持ち出す**: 作品は `standalone.html`、実務用部品は `workbench-standalone.html`。ロゴ・CSS・JSを内包し、ネット接続もサーバーも不要。
- **まとめて保存**: `thinkmove-ui-library.zip`。
- **今後の制作から探す**: `components.json`。名称・用途・コード・ソースを検索できる。
- **前回のオリジナル**: `../20260906-playful-toggle-ui/demo/`。今回の一覧にはそのThinkMove版をコピーして収録。


## 触れる作品・30種類

今回のユーザー要望は「もっとギミックとデザインの魅力がある作品」。従来の控えめな動きの基準を一律適用せず、ドラッグに追従する変形と、離したときのばねによる収束を作品の中心にした。動きが苦手な場合にはOS設定に従って補間を省略する。外部API・課金・データ送信はない。

| kind | 作品 | 触ったときの変化 |
| --- | --- | --- |
| elastic | Elastic intent | 球と細い接続部分が伸び、離すと左右どちらかへ収まる |
| magnetic | Shared gravity | 2つの立体が近づき、角度を揃えて結合する |
| aperture | Open question | 7枚の絞りが開いて、奥の形を見せる |
| orbit | Another angle | 立体の球面を回転させて視点を変える |
| signal | Find the signal | 小さな揺らぎから大きな波形へ整える |
| layers | Room to think | 3枚の紙が扇状に広がる |
| bloom | Small beginnings | 花びらが回転しながら広がり、一輪の花になる |
| gears | Better together | 歯数に合わせた比率で3つの歯車が連動する |
| paperplane | Let it fly | 紙飛行機が曲線に沿って飛び、軌跡が残る |
| ripple | Quiet influence | 一滴が落ち、水面に5重の波紋が広がる |
| cradle | Pass it on | 片側で持ち上げた振り子の動きを反対側へ渡す |
| zipper | A little opening | ファスナーを開くと、奥の形と言葉が現れる |
| prism | Hidden spectrum | プリズムに光が入り、異なる色の光が伸びる |
| hourglass | Time to settle | 砂が上から下へ移り、砂時計の下側に積もる |
| constellation | Connect the little things | 散らばった星をつなぎ、ひとつの星座にする |
| marble | The scenic route | ビー玉が曲がりくねった溝に沿って進む |
| compass | Your own north | コンパスの針と目盛りが回り、北へ揃う |
| ribbon | A softer way | 重なったリボンがほどけ、波打つ一本の帯になる |

| sprout | Give it a little room | 芽が出る、その余白を。 |
| bridge | Meet in the middle | あいだに、橋をかける。 |
| book | A page ahead | ひらけば、続きがある。 |
| lantern | A quiet light | 気づきが、灯る。 |
| balance | Find the balance | ちょうどいいを、探そう。 |
| pebbles | One thing at a time | ひとつずつ、積み重ねる。 |
| helix | Two ways, one thread | 違いが、ひとつをつくる。 |
| key | A way in | きっかけを、回そう。 |
| puzzle | A place for each | ぴったりくる、関わり方。 |
| balloon | A little lift | 少し、軽くなってみる。 |
| thread | Follow the thread | 想いを、縫いつないで。 |
| door | Beyond the familiar | その先を、のぞいてみる。 |

最初の6作品は `kinetic-objects.js`、次の12作品は `kinetic-objects-extra.js`、新しい12作品は `kinetic-objects-world.js` を読み込むと、作品カードを再利用できる。ページ全体のレイアウトは `objects.css`。実装はHTML/CSS/SVGで、画像生成は利用していない。

```html
<script src="kinetic-objects.js" defer></script>
<script src="kinetic-objects-extra.js" defer></script>
<script src="kinetic-objects-world.js" defer></script>
<tm-object kind="bloom"></tm-object>
```

- 横ドラッグに応じて途中の形を表示。離すと中間点を基準にオン・オフへ収束する。
- クリック / Enter / Spaceでも切り替え。右・上・Endでオン、左・下・Homeでオフ。
- `.checked` は読み書き可能。`checked` 属性で初期オン。`.reset()` でオフへ戻す。
- ユーザーの切り替え・reset時に `change` がbubbles/composed付きで発火し、`detail` は `{kind, checked}`。属性設定からは発火しない。
- 定常的な自動再生はしない。ばねの収束時に描画を停止し、要素破棄時に描画を解除する。
- `kind` は接続前に指定。`aria-checked` は確定状態を示す。ドラッグ中の途中状態は数値表示。
- 同じページに同種を複数配置可能。SVG内の参照IDはインスタンス単位で採番する。

追加作品は `customElements.get('tm-object').register(kind, {description, template, draw, style})` で共通エンジンに登録する。拡張ファイルが読み込まれるまで該当カードは初期化を待つ。

### 今回の制作メモ

ユーザーが6作品の立体感とかわいらしさを承認し、同じ方向で増作を依頼。`../20260906-playful-toggle-ui/README.md` と既存6作品を参照し、指先に追従する変形・操作後のばね収束・ミントとネイビーの配色を継承した。追加12作品の形状と座標計算は独自のSVG実装。振り子・砂時計・プリズムは触って楽しむ視覚表現であり、物理現象の厳密なシミュレーターではない。

## 実務用部品一覧

| 種類 | タグ | 主な機能・状態 |
| --- | --- | --- |
| スイッチ6種類 | `playful-toggle` | Liquid / Eclipse / Orbit / Shutter / Magnetic / Signal |
| アクションボタン | `tm-action` | 実行、処理中、無効 |
| 選択スイッチ | `tm-choice` | 選択値、選択状態 |
| タブ | `tm-tabs` | 概要・分析・次の一手、左右矢印/Home/End |
| メールアドレス入力 | `tm-field` | 必須・形式エラー、入力値 |
| 絞り込み検索 | `tm-search` | 日本語・大文字小文字・全半角の正規化、0件表示 |
| チェックリスト | `tm-checklist` | 複数選択、完了数 |
| 開閉する補足 | `tm-accordion` | 複数項目の開閉 |
| 手順ナビゲーション | `tm-stepper` | 現在の手順と完了済みの手順 |
| 進捗バー | `tm-progress` | 0〜100% |
| 完了通知 | `tm-notice` | 表示、読み上げ、閉じる |
| 確認ダイアログ | `tm-dialog` | 確認、戻る、Escape、フォーカス制御 |
| 指標と比較 | `tm-metric` | 数値、増減率、比較元が0の場合 |

## 組み込む

通常部品は `thinkmove-ui.js`、スイッチは `playful-toggle.js` を必要なページにコピーする。
各部品はShadow DOMでCSSを隔離している。外側のページ全体のスタイルを変更しない。
`catalog.js` はデモ専用の処理なので、実際のアプリには持ち込まない。

```html
<link rel="stylesheet" href="tokens.css">
<script src="thinkmove-ui.js" defer></script>
<script src="playful-toggle.js" defer></script>
<tm-action id="save" label="保存する"></tm-action>
<tm-progress id="progress" value="25"></tm-progress>
<playful-toggle variant="shutter" label="詳細表示"></playful-toggle>
```

操作の実体は利用先で接続する。フォーム送信、API更新、認証、データ保存などはこの部品集に含まない。
外部システムでの成功を確認してから、完了表示へ進める。

```js
await customElements.whenDefined('tm-action');
const save = document.querySelector('#save');
save.addEventListener('tm-action', async () => {
  save.setAttribute('busy', '');
  try {
    await saveYourData(); // 利用先の保存処理
  } finally {
    save.removeAttribute('busy');
  }
});
```

## 設定とイベント

- リスト形式の属性（`items` / `options` / `steps`）はJSON文字列。例はカタログの「組み込みコード」と `components.json` に収録。リストの設定は要素接続前に行う。動的更新が必要なら属性設定後に `render()` を呼び、選択状態を必要に応じて復元する。
- `tm-action`: `label`, `busy`, `disabled` 属性。クリック時に `tm-action` イベント。
- `tm-choice`: `label`, `options`, 初期 `value` 属性。選択は `.value`、変更は `tm-change` の `detail.value`。
- `tm-tabs`: `items` は `{label, content}[]`。切替は `tm-change` の `detail.index` と `detail.label`。
- `tm-field`: `label`, `required` 属性。読み取りは `.value`、形式確認は `.validate()`。入力時に `tm-input`。ネイティブformへの自動参加や自動送信はしない。
- `tm-search`: `label`, `items: string[]`。`tm-search` の `detail.query`, `detail.count`。
- `tm-checklist`: `items: string[]`。`.value` は選択中の文字列配列。`tm-change` の `detail.value` と `detail.total`。
- `tm-accordion`: `items: {title, body}[]`。ネイティブdetailsを利用。
- `tm-stepper`: `steps: string[]`、`.value` は0から始まる手順番号。先へ進める処理は利用先で用意する。
- `tm-progress`: `label` と `value` 属性、または `.value`。0〜100に制限。
- `tm-notice`: `.show(message)` で表示。閉じると `tm-dismiss`。
- `tm-dialog`: `heading`, `description`, `confirm-label` 属性。`.show()` で表示、確認時に `tm-confirm`。戻る/Escapeでは確認イベントは発火しない。
- `tm-metric`: `label`, `current`, `previous`, `unit` 属性。比較元が0のときは割合を計算しない。数値の善し悪しを自動判定しない。
- `playful-toggle`: `variant`, `label`, `checked`, `disabled` 属性。`.checked` / `.disabled` プロパティ。`change` の `detail.checked`, `detail.variant`。
- カスタムイベントは全て `bubbles: true`, `composed: true`。属性やプロパティの更新時にユーザー操作イベントは発火しない。

## デザインの共通データ

- `brand-tokens.json`: `thinkmove-design-system/theme/design.json` の参照スナップショットに、この部品集の余白データを追加。
- `tokens.css`: このライブラリで使うCSS変数。間隔は8px単位を基本に追加。
- 色: 白主体、ネイビーで情報、ティールで操作。白文字のボタンにはコントラストを確保しやすい `#0a7a70` を使用。
- 角丸: 8 / 12 / 16 / 20px。動き: 180ms / 420ms。
- 参照: `knowledge/strategy/brand-worldview-v3.md`、`projects/thinkmove-tools/app/globals.css`。
- 公式ロゴ: `thinkmove-design-system/assets/logo.png`。ロゴを生成していない。
- スイッチの発想: ユーザー提供の動画 `../20260906-playful-toggle-ui/source.mov`。元作者のコードは含まない。

## 動作確認と範囲

モダンブラウザ向け。ダイアログにネイティブdialog、部品にCustom ElementsとShadow DOMを利用。
デモの名称・数値・処理中表示はサンプル。実際の顧客データ、送信、永続保存、アクセス解析はない。
スマートフォン・キーボードでの使用を考慮。対象アプリに組み込んだ際には、その画面での操作と読み上げを確認する。

編集後は `python3 build.py` で単体HTMLとZIPを更新する。

確認済み: Chromeで追加12部品の操作、入力エラーから正常入力への復帰、全角SEO検索、検索0件、ダイアログのEscapeと確定、320px / 390pxでの横はみ出しなし。フォルダ版と単体HTML版を確認。実際の読み上げソフトでの検証は未実施。

作品版の確認: Chromeで6種類のクリック、Elasticのドラッグによる引き戻し、Space・左右キー・全体リセット、390px/320pxの横はみ出しなし、単体HTMLで6種類の表示と切替を確認。写真や生成画像に動きを後付けしたものではなく、形状をSVGとして描画し、操作に応じて座標を更新する。

増作分の確認（2026-09-08）: Chromeで追加12作品すべてのクリックとSVG描画、花のドラッグ、リボンの左右キー・Space、全18作品のリセットを確認。390px / 320pxで横はみ出しなし。単体HTMLに18作品があり、外部CSS・JSの読み込みがないこと、花とリボンの切替を確認。アプリ内プレビューも更新し、エラーログなし。部品一覧36件の重複・依存ファイル、ZIPの整合性を確認。

動画への展開（2026-09-08）: さらに12作品を追加して全30作品に拡張。全30作品の6秒ループと6種類の動画部品を、MP4・透過WebMで書き出した。HyperFramesによる63.2秒の紹介動画、用途検索、形式別ダウンロード、再編集用セットも収録。詳細は `MOTION.md`。
