@k8o/arte-odyssey 4.1.0 → 4.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -66,15 +66,9 @@ function MyPage() {
66
66
  }
67
67
  ```
68
68
 
69
- ## AI Agent Skills
69
+ ## AI Agent Documentation
70
70
 
71
- ArteOdyssey provides an Agent Skill for AI coding assistants. It gives your agent knowledge of the design system, component APIs, and design principles.
72
-
73
- ```bash
74
- npx skills add k35o/ArteOdyssey --skill arte-odyssey-usage
75
- ```
76
-
77
- Compatible with Claude Code, Cursor, GitHub Copilot, and other [Agent Skills](https://agentskills.io/) compatible tools.
71
+ ArteOdyssey includes design system documentation in `docs/` directory. When installed via npm, AI coding assistants can reference `node_modules/@k8o/arte-odyssey/docs/GUIDE.md` for design principles, component APIs, and usage patterns.
78
72
 
79
73
  ## Component Categories
80
74
 
@@ -132,7 +126,6 @@ Compatible with Claude Code, Cursor, GitHub Copilot, and other [Agent Skills](ht
132
126
 
133
127
  ### Utilities
134
128
 
135
- - **ErrorBoundary** - Error handling wrapper
136
129
  - **ArteOdysseyProvider** - Context providers for the library
137
130
  - **Icons** - Icon component collection
138
131
 
@@ -2,7 +2,7 @@ import { FC, ReactNode } from "react";
2
2
 
3
3
  //#region src/components/icons/base.d.ts
4
4
  type BaseIconProps = {
5
- size: 'sm' | 'md' | 'lg';
5
+ size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl';
6
6
  };
7
7
  declare const BaseIcon: FC<BaseIconProps & {
8
8
  renderItem: (arg: {
@@ -1,7 +1,16 @@
1
1
  import { cn } from "../../helpers/cn.mjs";
2
2
  //#region src/components/icons/base.tsx
3
+ const sizeClass = {
4
+ xs: "size-3",
5
+ sm: "size-4",
6
+ md: "size-6",
7
+ lg: "size-8",
8
+ xl: "size-10",
9
+ "2xl": "size-12",
10
+ "3xl": "size-14"
11
+ };
3
12
  const BaseIcon = ({ size, renderItem }) => {
4
- return renderItem({ className: cn(size === "sm" && "size-4", size === "md" && "size-6", size === "lg" && "size-8") });
13
+ return renderItem({ className: cn(sizeClass[size]) });
5
14
  };
6
15
  //#endregion
7
16
  export { BaseIcon };
@@ -52,5 +52,4 @@ import { Popover } from "./overlays/popover/popover.mjs";
52
52
  import { Tooltip } from "./overlays/tooltip/tooltip.mjs";
53
53
  import { ArteOdysseyProvider } from "./providers/arte-odyssey-provider.mjs";
54
54
  import { PortalRootProvider, usePortalRoot } from "./providers/portal-root.mjs";
55
- import { ErrorBoundary } from "./utility/error-boundary/index.mjs";
56
- export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ErrorBoundary, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, useOpenContext, usePortalRoot, useToast };
55
+ export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, useOpenContext, usePortalRoot, useToast };
@@ -52,5 +52,4 @@ import { Popover } from "./overlays/popover/popover.mjs";
52
52
  import { DropdownMenu } from "./overlays/dropdown-menu/dropdown-menu.mjs";
53
53
  import { ListBox } from "./overlays/list-box/list-box.mjs";
54
54
  import { Tooltip } from "./overlays/tooltip/tooltip.mjs";
55
- import { ErrorBoundary } from "./utility/error-boundary/index.mjs";
56
- export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ErrorBoundary, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, useOpenContext, usePortalRoot, useToast };
55
+ export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, useOpenContext, usePortalRoot, useToast };
package/dist/index.d.mts CHANGED
@@ -53,7 +53,6 @@ import { Popover } from "./components/overlays/popover/popover.mjs";
53
53
  import { Tooltip } from "./components/overlays/tooltip/tooltip.mjs";
54
54
  import { ArteOdysseyProvider } from "./components/providers/arte-odyssey-provider.mjs";
55
55
  import { PortalRootProvider, usePortalRoot } from "./components/providers/portal-root.mjs";
56
- import { ErrorBoundary } from "./components/utility/error-boundary/index.mjs";
57
56
  import { cn } from "./helpers/cn.mjs";
58
57
  import { findAllColors } from "./helpers/color/find-all-colors.mjs";
59
58
  import { isInternalRoute } from "./helpers/is-internal-route.mjs";
@@ -74,4 +73,4 @@ import { useStep } from "./hooks/step/index.mjs";
74
73
  import { useTimeout } from "./hooks/timeout/index.mjs";
75
74
  import { useWindowResize } from "./hooks/window-resize/index.mjs";
76
75
  import { useWindowSize } from "./hooks/window-size/index.mjs";
77
- export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Direction, Drawer, DropdownMenu, EasyIcon, ErrorBoundary, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Option, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, Status, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, useClickAway, useClient, useClipboard, useHash, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useStep, useTimeout, useToast, useWindowResize, useWindowSize, uuidV4 };
76
+ export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Direction, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, Option, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, Status, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, useClickAway, useClient, useClipboard, useHash, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useStep, useTimeout, useToast, useWindowResize, useWindowSize, uuidV4 };
package/dist/index.mjs CHANGED
@@ -62,7 +62,6 @@ import { Popover } from "./components/overlays/popover/popover.mjs";
62
62
  import { DropdownMenu } from "./components/overlays/dropdown-menu/dropdown-menu.mjs";
63
63
  import { ListBox } from "./components/overlays/list-box/list-box.mjs";
64
64
  import { Tooltip } from "./components/overlays/tooltip/tooltip.mjs";
65
- import { ErrorBoundary } from "./components/utility/error-boundary/index.mjs";
66
65
  import { useClient } from "./hooks/client/index.mjs";
67
66
  import { useClipboard } from "./hooks/clipboard/index.mjs";
68
67
  import { useHash } from "./hooks/hash/index.mjs";
@@ -73,4 +72,4 @@ import { useScrollDirection } from "./hooks/scroll-direction/index.mjs";
73
72
  import { useStep } from "./hooks/step/index.mjs";
74
73
  import { useWindowResize } from "./hooks/window-resize/index.mjs";
75
74
  import { useWindowSize } from "./hooks/window-size/index.mjs";
76
- export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ErrorBoundary, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, useClickAway, useClient, useClipboard, useHash, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useStep, useTimeout, useToast, useWindowResize, useWindowSize, uuidV4 };
75
+ export { AIIcon, AccessibilityIcon, Accordion, Alert, AlertIcon, Anchor, ArteOdyssey, ArteOdysseyProvider, AtomIcon, Autocomplete, Avatar, BadIcon, Badge, BaselineStatus, BlogIcon, BoringIcon, Breadcrumb, Button, Card, CheckIcon, Checkbox, CheckboxCard, CheckboxGroup, ChevronIcon, CloseIcon, Code, ColorContrastIcon, ColorInfoIcon, CopyIcon, DarkModeIcon, Dialog, DifficultIcon, Drawer, DropdownMenu, EasyIcon, ExternalLinkIcon, FileField, FormControl, FormIcon, GitHubIcon, GoodIcon, Heading, HistoryIcon, IconButton, IconLink, InformativeIcon, InteractiveCard, InterestingIcon, LightModeIcon, LinkButton, LinkIcon, ListBox, ListIcon, LocationIcon, Logo, LogoIcon, MailIcon, MinusIcon, MixedColorIcon, Modal, NavigationMenuIcon, NewsIcon, NumberField, PaletteIcon, PasswordInput, PlusIcon, Popover, PortalRootProvider, PrepareIcon, Progress, PublishDateIcon, QiitaIcon, RSSIcon, Radio, RadioCard, ScrollLinked, Select, SendIcon, Separator, ShallowIcon, ShieldCheckIcon, Skeleton, SlideIcon, Slider, SparklesIcon, Spinner, SubscribeIcon, Switch, Table, TableIcon, Tabs, TagIcon, TextField, Textarea, ToastProvider, Tooltip, TwitterIcon, UpdateDateIcon, ViewIcon, ViewOffIcon, between, cast, cn, commalize, findAllColors, isInternalRoute, toPrecision, useClickAway, useClient, useClipboard, useHash, useInterval, useLocalStorage, useOpenContext, usePortalRoot, useResize, useScrollDirection, useStep, useTimeout, useToast, useWindowResize, useWindowSize, uuidV4 };
package/docs/GUIDE.md ADDED
@@ -0,0 +1,232 @@
1
+ # ArteOdyssey Design Guide
2
+
3
+ `@k8o/arte-odyssey` デザインシステムを使って UI を作るためのガイド。
4
+
5
+ ## セットアップ
6
+
7
+ ```bash
8
+ npm install @k8o/arte-odyssey
9
+ ```
10
+
11
+ ```tsx
12
+ // 1. スタイルシートを読み込む(エントリポイントで1回)
13
+ import '@k8o/arte-odyssey/styles.css';
14
+
15
+ // 2. Provider でアプリを囲む
16
+ import { ArteOdysseyProvider } from '@k8o/arte-odyssey/providers';
17
+
18
+ function App() {
19
+ return (
20
+ <ArteOdysseyProvider>
21
+ <YourApp />
22
+ </ArteOdysseyProvider>
23
+ );
24
+ }
25
+
26
+ // 3. コンポーネントを使う
27
+ import { Button } from '@k8o/arte-odyssey/button';
28
+ import { Card } from '@k8o/arte-odyssey/card';
29
+ ```
30
+
31
+ ### Tailwind CSS の設定
32
+
33
+ `@k8o/arte-odyssey` は Tailwind CSS 4 以上が必要。プロジェクトの CSS で以下を追加:
34
+
35
+ ```css
36
+ @import 'tailwindcss';
37
+ @import '@k8o/arte-odyssey/styles.css';
38
+ ```
39
+
40
+ ## デザインの方向性
41
+
42
+ ### コアコンセプト
43
+
44
+ **「静謐で落ち着いた、余白を活かしたUI」**
45
+
46
+ - **引き算の美学**: 装飾は最小限。必要なものだけ残す
47
+ - **余白で語る**: 詰め込まず、空間にゆとりを持たせる
48
+ - **静かな変化**: アニメーションは控えめに、繊細なフィードバック
49
+ - **穏やかな色**: 目に優しいトーン、グレー系を活かす
50
+
51
+ ### トーン
52
+
53
+ 「図書館の読書スペース」のような空気感。静かで集中できる、心地よい緊張感。
54
+
55
+ ## 美学ガイドライン
56
+
57
+ ### タイポグラフィ
58
+
59
+ **DO:**
60
+
61
+ - 日本語フォント(Noto Sans JP, M PLUS 2)を使う
62
+ - フォントウェイトは 3種類まで(`font-normal`, `font-medium`, `font-bold`)
63
+ - `font-medium` が 450(一般的な 500 より軽い)であることを活かした繊細な強調
64
+
65
+ **DON'T:**
66
+
67
+ - Inter / Roboto / Open Sans を使う
68
+ - 4種類以上のフォントサイズを1画面で使う
69
+ - テキストにグラデーションをかける
70
+
71
+ > [タイポグラフィ詳細](references/typography.md)
72
+
73
+ ### カラー
74
+
75
+ **DO:**
76
+
77
+ - 60-30-10 ルール(ニュートラル60%, サポート30%, アクセント10%)
78
+ - セマンティックカラートークンを使う(`bg-bg-subtle`, `text-fg-mute` 等)
79
+ - ダークモードを独立したトーンで設計する
80
+
81
+ **DON'T:**
82
+
83
+ - グラデーション背景
84
+ - ホバーに `bg-primary-bg` — `bg-bg-mute` を使う
85
+ - 透明度(`/90`)で状態表現 — 専用トークンを使う
86
+ - 生のカラー値(`bg-teal-500`)— セマンティックトークン(`bg-primary-bg`)を使う
87
+
88
+ > [カラー詳細](references/color.md)
89
+
90
+ ### スペーシング
91
+
92
+ **DO:**
93
+
94
+ - `p-6` を標準パディングとする
95
+ - 余白の差で関連度を表す(`mt-2` 近い、`mt-4` 標準、`mt-8` セクション間)
96
+ - Separator でセクションを区切る
97
+
98
+ **DON'T:**
99
+
100
+ - すべてを Card に入れる
101
+ - Card を入れ子にする(Card in Card)
102
+ - `gap-1` のような極端に狭いスペーシング
103
+
104
+ > [スペーシング詳細](references/spatial-design.md)
105
+
106
+ ### インタラクション
107
+
108
+ **DO:**
109
+
110
+ - `transition-colors` を基本にする
111
+ - `focus-visible:ring-2 focus-visible:ring-border-info` でフォーカス表現
112
+ - `hover:bg-bg-mute` で穏やかなホバー
113
+
114
+ **DON'T:**
115
+
116
+ - bounce / spring 系のイージング
117
+ - 300ms を超えるアニメーション
118
+ - ホバーに強い原色を使う
119
+
120
+ > [インタラクション詳細](references/interaction-design.md)
121
+
122
+ ## コンポーネント使用の原則
123
+
124
+ ### Button / LinkButton
125
+
126
+ `color` と `variant` で統一されたスタイル。
127
+
128
+ ```tsx
129
+ import { Button } from '@k8o/arte-odyssey/button';
130
+ import { LinkButton } from '@k8o/arte-odyssey/link-button';
131
+
132
+ // プライマリアクション
133
+ <Button color="primary" variant="contained">保存する</Button>
134
+
135
+ // セカンダリアクション
136
+ <Button color="gray" variant="outlined">キャンセル</Button>
137
+
138
+ // テキストのみ
139
+ <Button variant="skeleton">詳細を見る</Button>
140
+
141
+ // リンクボタン(同じ props)
142
+ <LinkButton href="/settings" color="gray">設定へ</LinkButton>
143
+ ```
144
+
145
+ ### IconButton / IconLink
146
+
147
+ `bg` prop でスタイルを制御(`variant` ではない)。
148
+
149
+ ```tsx
150
+ import { IconButton } from '@k8o/arte-odyssey/icon-button';
151
+ import { IconLink } from '@k8o/arte-odyssey/icon-link';
152
+
153
+ <IconButton bg="transparent" label="コピー"><CopyIcon /></IconButton>
154
+ <IconButton bg="primary" label="送信"><SendIcon /></IconButton>
155
+ <IconLink href="/home" bg="base" label="ホーム"><HomeIcon /></IconLink>
156
+ ```
157
+
158
+ ### Card / InteractiveCard
159
+
160
+ `appearance` prop でシャドウかボーダーかを選択。
161
+
162
+ ```tsx
163
+ import { Card, InteractiveCard } from '@k8o/arte-odyssey/card';
164
+
165
+ // 静的カード
166
+ <Card title="設定" appearance="bordered">
167
+ <p>カードのコンテンツ</p>
168
+ </Card>
169
+
170
+ // クリック可能なカード(ホバーでスケールアップ)
171
+ <InteractiveCard title="記事" appearance="shadow">
172
+ <p>コンテンツ</p>
173
+ </InteractiveCard>
174
+ ```
175
+
176
+ ### フォーム
177
+
178
+ ```tsx
179
+ import { TextField } from '@k8o/arte-odyssey/text-field';
180
+ import { Select } from '@k8o/arte-odyssey/select';
181
+ import { FileField } from '@k8o/arte-odyssey/file-field';
182
+
183
+ <TextField id="email" placeholder="example@mail.com" />
184
+
185
+ <Select
186
+ label="カテゴリ"
187
+ options={[{ value: '1', label: 'オプション1' }]}
188
+ value={value}
189
+ onChange={onChange}
190
+ />
191
+
192
+ <FileField.Root accept="image/*" multiple>
193
+ <FileField.Trigger>ファイルを選択</FileField.Trigger>
194
+ <FileField.ItemList />
195
+ </FileField.Root>
196
+ ```
197
+
198
+ ## アンチパターン: 「AI スロップ」を避ける
199
+
200
+ AI が生成したと一目でわかるUIの特徴を避ける。
201
+
202
+ | アンチパターン | ArteOdyssey での代替 |
203
+ | ------------------------------ | -------------------------------------------------- |
204
+ | パープルグラデーション | Teal/Cyan のフラットカラー |
205
+ | Card in Card(入れ子カード) | Separator + 余白で区切り |
206
+ | グレー背景にグレーテキスト | `text-fg-base` / `text-fg-mute` のコントラスト確保 |
207
+ | すべてに `rounded-2xl` | `rounded-lg` を基本、用途で使い分け |
208
+ | bounce / spring アニメーション | `transition-colors duration-150 ease-out` |
209
+ | Inter フォント | Noto Sans JP / M PLUS 2 |
210
+ | 過剰な glassmorphism | border + subtle な背景色 |
211
+ | 装飾的な絵文字やアイコン | lucide-react の線画アイコンを控えめに |
212
+ | 情報の詰め込み | 余白を活かした疎な配置 |
213
+
214
+ ### AI スロップテスト
215
+
216
+ > このUIを誰かに見せて「AIが作った」と言ったら、すぐに信じるだろうか?
217
+ > もし「はい」なら、それが問題だ。
218
+
219
+ ## 実装の原則
220
+
221
+ - **既存コンポーネントを使う**: カスタムUIの前にまず ArteOdyssey コンポーネントを探す
222
+ - **セマンティックトークンを使う**: 生のカラー値(`bg-teal-500`)ではなくトークン(`bg-primary-bg`)
223
+ - **ダークモードを忘れない**: セマンティックトークンを使えば自動対応
224
+ - **アクセシビリティ**: `aria-label`, キーボードナビゲーション, カラーだけに頼らない状態表現
225
+
226
+ ## 詳細リファレンス
227
+
228
+ - タイポグラフィ: [references/typography.md](references/typography.md)
229
+ - カラーシステム: [references/color.md](references/color.md)
230
+ - スペーシング・レイアウト: [references/spatial-design.md](references/spatial-design.md)
231
+ - インタラクション: [references/interaction-design.md](references/interaction-design.md)
232
+ - コンポーネント一覧: [references/components.md](references/components.md)
@@ -0,0 +1,86 @@
1
+ # カラーシステム
2
+
3
+ ArteOdyssey のカラーは「穏やかさ」を第一に設計されている。
4
+
5
+ ## 設計思想
6
+
7
+ - **60-30-10 ルール**: 60% ニュートラル(グレー系)、30% サポート(bg-subtle 等)、10% アクセント(primary/secondary)
8
+ - Primary に Teal、Secondary に Cyan を使用
9
+ - ダークモードは「ライトモードの反転」ではなく、独立したトーンで設計
10
+ - セマンティックトークンを使えばダークモードは自動対応
11
+
12
+ ## セマンティックカラー(前景)
13
+
14
+ | Tailwind クラス | Light | Dark | 用途 |
15
+ | ----------------- | ---------- | ---------- | ---------------- |
16
+ | `text-fg-base` | gray-900 | gray-50 | 基本テキスト |
17
+ | `text-fg-subtle` | gray-400 | gray-500 | プレースホルダー |
18
+ | `text-fg-mute` | gray-700 | gray-300 | 補足テキスト |
19
+ | `text-fg-inverse` | gray-50 | gray-900 | 反転テキスト |
20
+ | `text-fg-info` | blue-700 | blue-300 | 情報 |
21
+ | `text-fg-success` | green-700 | green-300 | 成功 |
22
+ | `text-fg-warning` | yellow-700 | yellow-300 | 警告 |
23
+ | `text-fg-error` | red-700 | red-300 | エラー |
24
+
25
+ ## セマンティックカラー(背景)
26
+
27
+ | Tailwind クラス | Light | Dark | 用途 |
28
+ | ----------------- | -------- | -------- | ---------------- |
29
+ | `bg-bg-base` | white | gray-900 | 基本背景 |
30
+ | `bg-bg-subtle` | gray-100 | gray-800 | 控えめな背景 |
31
+ | `bg-bg-mute` | gray-200 | gray-700 | ホバー状態用 |
32
+ | `bg-bg-emphasize` | gray-300 | gray-600 | アクティブ状態用 |
33
+ | `bg-bg-inverse` | gray-900 | white | 反転背景 |
34
+
35
+ ## セマンティックカラー(ボーダー)
36
+
37
+ | Tailwind クラス | Light | Dark | 用途 |
38
+ | ------------------------- | -------- | -------- | -------------- |
39
+ | `border-border-base` | gray-400 | gray-600 | 標準ボーダー |
40
+ | `border-border-subtle` | gray-100 | gray-900 | 薄いボーダー |
41
+ | `border-border-mute` | gray-200 | gray-800 | 控えめボーダー |
42
+ | `border-border-emphasize` | gray-500 | gray-500 | 強調ボーダー |
43
+
44
+ ## ブランドカラー(Primary: Teal)
45
+
46
+ | Tailwind クラス | Light | Dark | 用途 |
47
+ | ----------------------- | -------- | -------- | ------------------- |
48
+ | `text-primary-fg` | teal-700 | teal-300 | Primary テキスト |
49
+ | `bg-primary-bg` | teal-300 | teal-700 | Primary 背景 |
50
+ | `bg-primary-bg-subtle` | teal-100 | teal-900 | 薄い Primary 背景 |
51
+ | `bg-primary-bg-mute` | teal-200 | teal-800 | 控えめ Primary 背景 |
52
+ | `border-primary-border` | teal-600 | teal-600 | Primary ボーダー |
53
+
54
+ ## ブランドカラー(Secondary: Cyan)
55
+
56
+ | Tailwind クラス | Light | Dark | 用途 |
57
+ | ------------------------- | -------- | -------- | ------------------- |
58
+ | `text-secondary-fg` | cyan-700 | cyan-300 | Secondary テキスト |
59
+ | `bg-secondary-bg` | cyan-300 | cyan-700 | Secondary 背景 |
60
+ | `bg-secondary-bg-subtle` | cyan-100 | cyan-900 | 薄い Secondary 背景 |
61
+ | `border-secondary-border` | cyan-600 | cyan-600 | Secondary ボーダー |
62
+
63
+ ## 使い方の例
64
+
65
+ ```tsx
66
+ // 基本的なカード風レイアウト
67
+ <div className="bg-bg-base border border-border-mute rounded-lg p-6">
68
+ <h2 className="text-fg-base font-bold">タイトル</h2>
69
+ <p className="text-fg-mute mt-2">補足テキスト</p>
70
+ <span className="text-primary-fg">アクセントテキスト</span>
71
+ </div>
72
+
73
+ // ホバー状態
74
+ <button className="bg-bg-base hover:bg-bg-mute transition-colors">
75
+ ボタン
76
+ </button>
77
+ ```
78
+
79
+ ## やってはいけないこと
80
+
81
+ - グラデーション背景(`bg-gradient-to-*`)
82
+ - 彩度の高い色の広範囲使用(アクセントは小面積で)
83
+ - 透明度による状態表現(`/90`, `/80` など)— 専用のセマンティックカラーを使う
84
+ - ホバーに `bg-primary-bg` を使う — `bg-bg-mute` を優先
85
+ - 生のカラー値(`bg-teal-500`)— セマンティックトークンを使う
86
+ - ダークモードで単純にカラーを反転させる
@@ -0,0 +1,449 @@
1
+ # ArteOdyssey コンポーネント一覧
2
+
3
+ ## インポート方法
4
+
5
+ ```tsx
6
+ // スタイルシート(必須)
7
+ import '@k8o/arte-odyssey/styles.css';
8
+
9
+ // プロバイダー(アプリルートで1回)
10
+ import { ArteOdysseyProvider } from '@k8o/arte-odyssey/providers';
11
+
12
+ // 各コンポーネント(個別インポート)
13
+ import { Button } from '@k8o/arte-odyssey/button';
14
+ import { Card } from '@k8o/arte-odyssey/card';
15
+ ```
16
+
17
+ ## レイアウト・ナビゲーション
18
+
19
+ ### Accordion
20
+
21
+ 折りたたみ可能なセクション。
22
+
23
+ ```tsx
24
+ import { Accordion, AccordionItem } from '@k8o/arte-odyssey/accordion';
25
+
26
+ <Accordion>
27
+ <AccordionItem title="セクション1">コンテンツ</AccordionItem>
28
+ </Accordion>;
29
+ ```
30
+
31
+ ### Breadcrumb
32
+
33
+ パンくずリスト。
34
+
35
+ ```tsx
36
+ import { Breadcrumb, BreadcrumbItem } from '@k8o/arte-odyssey/breadcrumb';
37
+
38
+ <Breadcrumb>
39
+ <BreadcrumbItem href="/">ホーム</BreadcrumbItem>
40
+ <BreadcrumbItem href="/products">製品</BreadcrumbItem>
41
+ <BreadcrumbItem>詳細</BreadcrumbItem>
42
+ </Breadcrumb>;
43
+ ```
44
+
45
+ ### Card / InteractiveCard
46
+
47
+ コンテンツをグループ化するカード。
48
+
49
+ ```tsx
50
+ import { Card, InteractiveCard } from '@k8o/arte-odyssey/card';
51
+
52
+ // 静的カード
53
+ <Card title="タイトル" variant="primary" width="full" appearance="shadow">
54
+ <div className="p-6">コンテンツ</div>
55
+ </Card>
56
+
57
+ // クリック可能なカード(hover:scale-[1.02], active:scale-[0.98])
58
+ <InteractiveCard title="記事" appearance="bordered">
59
+ <div className="p-6">コンテンツ</div>
60
+ </InteractiveCard>
61
+ ```
62
+
63
+ Props:
64
+
65
+ - `variant`: `'primary'` | `'secondary'`
66
+ - `title`: string
67
+ - `width`: `'full'` | `'fit'`
68
+ - `appearance`: `'shadow'` | `'bordered'`
69
+
70
+ ### Tabs
71
+
72
+ タブ切り替え。
73
+
74
+ ```tsx
75
+ import { Tabs, TabList, Tab, TabPanel } from '@k8o/arte-odyssey/tabs';
76
+
77
+ <Tabs>
78
+ <TabList>
79
+ <Tab>タブ1</Tab>
80
+ <Tab>タブ2</Tab>
81
+ </TabList>
82
+ <TabPanel>パネル1</TabPanel>
83
+ <TabPanel>パネル2</TabPanel>
84
+ </Tabs>;
85
+ ```
86
+
87
+ ### Separator
88
+
89
+ 区切り線。
90
+
91
+ ```tsx
92
+ import { Separator } from '@k8o/arte-odyssey/separator';
93
+
94
+ <Separator />
95
+ <Separator color="mute" />
96
+ <Separator color="subtle" />
97
+ <Separator orientation="vertical" />
98
+ ```
99
+
100
+ ### ScrollLinked
101
+
102
+ スクロール進捗をプログレスバーで表示。
103
+
104
+ ```tsx
105
+ import { ScrollLinked } from '@k8o/arte-odyssey/scroll-linked';
106
+
107
+ <ScrollLinked />
108
+ <ScrollLinked container={containerRef} />
109
+ ```
110
+
111
+ ## ボタン・リンク
112
+
113
+ ### Button
114
+
115
+ ```tsx
116
+ import { Button } from '@k8o/arte-odyssey/button';
117
+
118
+ <Button
119
+ size="sm" | "md" | "lg"
120
+ color="primary" | "gray"
121
+ variant="contained" | "outlined" | "skeleton"
122
+ fullWidth={false}
123
+ startIcon={<Icon />}
124
+ endIcon={<Icon />}
125
+ disabled={false}
126
+ >
127
+ ボタン
128
+ </Button>
129
+ ```
130
+
131
+ ### IconButton
132
+
133
+ アイコンのみのボタン。`bg` prop でスタイルを制御。
134
+
135
+ ```tsx
136
+ import { IconButton } from '@k8o/arte-odyssey/icon-button';
137
+
138
+ <IconButton label="閉じる" bg="transparent" size="md">
139
+ <XIcon />
140
+ </IconButton>;
141
+ ```
142
+
143
+ Props:
144
+
145
+ - `bg`: `'transparent'` | `'base'` | `'primary'`(デフォルト: `'transparent'`)
146
+ - `size`: `'sm'` | `'md'` | `'lg'`
147
+ - `label`: string(必須、aria-label として使用)
148
+
149
+ ### LinkButton
150
+
151
+ リンクスタイルのボタン。Button と同じ `color` / `variant` props。
152
+
153
+ ```tsx
154
+ import { LinkButton } from '@k8o/arte-odyssey/link-button';
155
+
156
+ <LinkButton href="/page" color="gray" variant="outlined">
157
+ リンク
158
+ </LinkButton>;
159
+ ```
160
+
161
+ ### IconLink
162
+
163
+ アイコンのみのリンク。IconButton と同じ `bg` prop。
164
+
165
+ ```tsx
166
+ import { IconLink } from '@k8o/arte-odyssey/icon-link';
167
+
168
+ <IconLink href="/home" bg="base" label="ホーム">
169
+ <HomeIcon />
170
+ </IconLink>;
171
+ ```
172
+
173
+ ### Anchor
174
+
175
+ テキストリンク。
176
+
177
+ ```tsx
178
+ import { Anchor } from '@k8o/arte-odyssey/anchor';
179
+
180
+ <Anchor href="https://example.com" isExternal>
181
+ 外部リンク
182
+ </Anchor>;
183
+ ```
184
+
185
+ ## フォーム
186
+
187
+ ### TextField
188
+
189
+ ```tsx
190
+ import { TextField } from '@k8o/arte-odyssey/text-field';
191
+
192
+ <TextField id="email" defaultValue="" placeholder="example@mail.com" />;
193
+ ```
194
+
195
+ ### Textarea
196
+
197
+ ```tsx
198
+ import { Textarea } from '@k8o/arte-odyssey/textarea';
199
+
200
+ <Textarea label="説明" rows={4} value={value} onChange={onChange} />;
201
+ ```
202
+
203
+ ### Checkbox
204
+
205
+ ```tsx
206
+ import { Checkbox } from '@k8o/arte-odyssey/checkbox';
207
+
208
+ <Checkbox checked={checked} onChange={onChange}>
209
+ 同意する
210
+ </Checkbox>;
211
+ ```
212
+
213
+ ### Radio
214
+
215
+ ```tsx
216
+ import { Radio } from '@k8o/arte-odyssey/radio';
217
+
218
+ <Radio
219
+ labelId="example-radio"
220
+ name="example"
221
+ onChange={onChange}
222
+ options={[
223
+ { value: 'a', label: '選択肢A' },
224
+ { value: 'b', label: '選択肢B' },
225
+ ]}
226
+ value={value}
227
+ />;
228
+ ```
229
+
230
+ ### Select
231
+
232
+ ```tsx
233
+ import { Select } from '@k8o/arte-odyssey/select';
234
+
235
+ <Select
236
+ label="選択"
237
+ options={[
238
+ { value: '1', label: 'オプション1' },
239
+ { value: '2', label: 'オプション2' },
240
+ ]}
241
+ value={value}
242
+ onChange={onChange}
243
+ />;
244
+ ```
245
+
246
+ ### NumberField
247
+
248
+ ```tsx
249
+ import { NumberField } from '@k8o/arte-odyssey/number-field';
250
+
251
+ <NumberField label="数量" min={0} max={100} value={value} onChange={onChange} />;
252
+ ```
253
+
254
+ ### RangeField
255
+
256
+ ```tsx
257
+ import { RangeField } from '@k8o/arte-odyssey/range-field';
258
+
259
+ <RangeField label="音量" min={0} max={100} value={value} onChange={onChange} />;
260
+ ```
261
+
262
+ ### Autocomplete
263
+
264
+ ```tsx
265
+ import { Autocomplete } from '@k8o/arte-odyssey/autocomplete';
266
+
267
+ <Autocomplete label="検索" options={options} value={value} onChange={onChange} />;
268
+ ```
269
+
270
+ ### FileField
271
+
272
+ コンポジットパターンのファイルアップロード。
273
+
274
+ ```tsx
275
+ import { FileField } from '@k8o/arte-odyssey/file-field';
276
+
277
+ <FileField.Root accept="image/*" multiple maxFiles={5}>
278
+ <FileField.Trigger>ファイルを選択</FileField.Trigger>
279
+ <FileField.ItemList />
280
+ </FileField.Root>;
281
+ ```
282
+
283
+ Props (Root):
284
+
285
+ - `accept`: string
286
+ - `multiple`: boolean
287
+ - `maxFiles`: number
288
+ - `isDisabled`, `isInvalid`, `isRequired`: boolean
289
+
290
+ ### FormControl
291
+
292
+ フォームフィールドのラッパー(ラベル・エラー表示を統一)。
293
+
294
+ ```tsx
295
+ import { FormControl } from '@k8o/arte-odyssey/form-control';
296
+
297
+ <FormControl label="ラベル" error="エラーメッセージ" isRequired>
298
+ <TextField id="name" />
299
+ </FormControl>;
300
+ ```
301
+
302
+ ## フィードバック
303
+
304
+ ### Alert
305
+
306
+ ```tsx
307
+ import { Alert } from '@k8o/arte-odyssey/alert';
308
+
309
+ <Alert status="info" | "success" | "warning" | "error">
310
+ メッセージ
311
+ </Alert>
312
+ ```
313
+
314
+ ### Toast
315
+
316
+ ```tsx
317
+ import { useToast } from '@k8o/arte-odyssey/toast';
318
+
319
+ const toast = useToast();
320
+ toast.show({ message: '保存しました', status: 'success' });
321
+ ```
322
+
323
+ ### Progress
324
+
325
+ ```tsx
326
+ import { Progress } from '@k8o/arte-odyssey/progress';
327
+
328
+ <Progress value={50} max={100} />;
329
+ ```
330
+
331
+ ### BaselineStatus
332
+
333
+ Web API のブラウザサポート状況を表示。
334
+
335
+ ```tsx
336
+ import { BaselineStatus } from '@k8o/arte-odyssey/baseline-status';
337
+
338
+ <BaselineStatus featureId="dialog" />;
339
+ ```
340
+
341
+ ## オーバーレイ
342
+
343
+ ### Dialog
344
+
345
+ ```tsx
346
+ import { Dialog } from '@k8o/arte-odyssey/dialog';
347
+
348
+ <Dialog open={open} onClose={onClose} title="確認">
349
+ コンテンツ
350
+ </Dialog>;
351
+ ```
352
+
353
+ ### Drawer
354
+
355
+ ```tsx
356
+ import { Drawer } from '@k8o/arte-odyssey/drawer';
357
+
358
+ <Drawer open={open} onClose={onClose} position="right">
359
+ コンテンツ
360
+ </Drawer>;
361
+ ```
362
+
363
+ ### Modal
364
+
365
+ ```tsx
366
+ import { Modal } from '@k8o/arte-odyssey/modal';
367
+
368
+ <Modal open={open} onClose={onClose}>
369
+ コンテンツ
370
+ </Modal>;
371
+ ```
372
+
373
+ ### Popover
374
+
375
+ ```tsx
376
+ import { Popover } from '@k8o/arte-odyssey/popover';
377
+
378
+ <Popover trigger={<Button>開く</Button>}>ポップオーバーコンテンツ</Popover>;
379
+ ```
380
+
381
+ ### Tooltip
382
+
383
+ ```tsx
384
+ import { Tooltip } from '@k8o/arte-odyssey/tooltip';
385
+
386
+ <Tooltip content="ヒント">
387
+ <Button>ホバー</Button>
388
+ </Tooltip>;
389
+ ```
390
+
391
+ ### DropdownMenu
392
+
393
+ ```tsx
394
+ import { DropdownMenu, DropdownMenuItem } from '@k8o/arte-odyssey/dropdown-menu';
395
+
396
+ <DropdownMenu trigger={<Button>メニュー</Button>}>
397
+ <DropdownMenuItem onClick={handleClick}>アイテム1</DropdownMenuItem>
398
+ <DropdownMenuItem>アイテム2</DropdownMenuItem>
399
+ </DropdownMenu>;
400
+ ```
401
+
402
+ ## データ表示
403
+
404
+ ### Code
405
+
406
+ ```tsx
407
+ import { Code } from '@k8o/arte-odyssey/code';
408
+
409
+ <Code language="typescript">{`const x = 1;`}</Code>;
410
+ ```
411
+
412
+ ### Heading
413
+
414
+ ```tsx
415
+ import { Heading } from '@k8o/arte-odyssey/heading';
416
+
417
+ <Heading level={1}>見出し</Heading>;
418
+ ```
419
+
420
+ ### TextTag
421
+
422
+ ```tsx
423
+ import { TextTag } from '@k8o/arte-odyssey/text-tag';
424
+
425
+ <TextTag>タグ</TextTag>;
426
+ ```
427
+
428
+ ### ListBox
429
+
430
+ ```tsx
431
+ import { ListBox, ListBoxItem } from '@k8o/arte-odyssey/list-box';
432
+
433
+ <ListBox>
434
+ <ListBoxItem>アイテム1</ListBoxItem>
435
+ <ListBoxItem>アイテム2</ListBoxItem>
436
+ </ListBox>;
437
+ ```
438
+
439
+ ## ユーティリティ
440
+
441
+ ### ArteOdysseyProvider
442
+
443
+ ```tsx
444
+ import { ArteOdysseyProvider } from '@k8o/arte-odyssey/providers';
445
+
446
+ <ArteOdysseyProvider>
447
+ <App />
448
+ </ArteOdysseyProvider>;
449
+ ```
@@ -0,0 +1,74 @@
1
+ # インタラクションデザイン
2
+
3
+ ArteOdyssey のインタラクションは「静かな変化」を原則とする。
4
+
5
+ ## インタラクティブ状態
6
+
7
+ 8つの状態を意識して設計する。
8
+
9
+ | 状態 | スタイル |
10
+ | -------- | ----------------------------------------------------- |
11
+ | Default | 基本スタイル |
12
+ | Hover | `hover:bg-bg-mute` — 穏やかな色変化 |
13
+ | Focus | `focus-visible:ring-2 focus-visible:ring-border-info` |
14
+ | Active | `active:bg-bg-emphasize` |
15
+ | Disabled | `opacity-50 cursor-not-allowed` |
16
+ | Loading | スピナーまたはスケルトン |
17
+ | Selected | `bg-primary-bg-subtle` |
18
+ | Error | `border-border-error` + `text-fg-error` |
19
+
20
+ ## トランジション
21
+
22
+ 控えめで自然な動き。
23
+
24
+ | 用途 | 推奨設定 |
25
+ | -------------------- | ------------------------------------------ |
26
+ | ホバー色変化 | `transition-colors duration-150 ease-out` |
27
+ | 透過度変化 | `transition-opacity duration-200 ease-out` |
28
+ | サイズ変化を伴う場合 | `transition-all duration-150 ease-out` |
29
+
30
+ ### タイミングの原則
31
+
32
+ - **100ms**: 即時フィードバック(ボタンプレス)
33
+ - **150–200ms**: 標準トランジション(ホバー、フォーカス)
34
+ - **300ms**: 開閉アニメーション(Accordion, Drawer の限度)
35
+ - **300ms を超えない** — 重く感じる
36
+
37
+ ## フォーカス管理
38
+
39
+ - `focus-visible` を使う(`focus` ではなく)— マウスクリック時にリングが出ない
40
+ - フォーカスリングは `ring-border-info` で統一
41
+ - `outline-hidden` でデフォルトのアウトラインを消してから ring を適用
42
+
43
+ ```tsx
44
+ className = 'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-border-info';
45
+ ```
46
+
47
+ ## フォームデザイン
48
+
49
+ - ラベルは入力の上に配置(左配置は日本語で読みにくい)
50
+ - エラーメッセージは入力の直下に `text-fg-error text-sm`
51
+ - 必須マークは `*` でラベルの後ろに
52
+ - `FormControl` コンポーネントでラベル・エラー表示を統一
53
+
54
+ ```tsx
55
+ import { FormControl } from '@k8o/arte-odyssey/form-control';
56
+
57
+ <FormControl label="メールアドレス" error="入力してください" isRequired>
58
+ <TextField id="email" placeholder="example@mail.com" />
59
+ </FormControl>;
60
+ ```
61
+
62
+ ## アクセシビリティ
63
+
64
+ - `aria-label` / `aria-describedby` を適切に設定
65
+ - キーボードナビゲーションを確保(Tab, Enter, Escape, 矢印キー)
66
+ - `prefers-reduced-motion` を考慮 — ArteOdyssey の motion ライブラリが自動対応
67
+ - カラーだけに頼らない状態表現(アイコンやテキストを併用)
68
+
69
+ ## やってはいけないこと
70
+
71
+ - bounce / spring 系のイージング
72
+ - 300ms を超えるアニメーション
73
+ - ホバーに強い原色(`bg-primary-bg`)を使う
74
+ - `cursor-pointer` をボタン以外に付ける(リンクにも不要)
@@ -0,0 +1,101 @@
1
+ # スペーシング・レイアウト
2
+
3
+ ArteOdyssey は「余白で語る」デザイン。詰め込まず、空間にゆとりを持たせる。
4
+
5
+ ## スペーシングの原則
6
+
7
+ 4pt ベースのスペーシングシステム。Tailwind の標準スケールを使用。
8
+
9
+ ### コンポーネント内部パディング
10
+
11
+ | 用途 | クラス | 値 |
12
+ | ---------- | ------ | ---- |
13
+ | コンパクト | `p-4` | 16px |
14
+ | 標準 | `p-6` | 24px |
15
+ | ゆったり | `p-8` | 32px |
16
+
17
+ ### リスト・メニューアイテム
18
+
19
+ ```tsx
20
+ className = 'px-3 py-2'; // 水平に余裕、垂直はコンパクト
21
+ ```
22
+
23
+ ### テキスト間の余白
24
+
25
+ | 関係性 | クラス | 用途 |
26
+ | -------------- | ------- | ---------------------------- |
27
+ | 近い要素 | `mt-2` | 説明テキスト、ヘルプテキスト |
28
+ | 標準 | `mt-4` | 段落間、フォームフィールド間 |
29
+ | セクション間 | `mt-8` | セクション区切り |
30
+ | 大セクション間 | `mt-12` | ページレベルの区切り |
31
+
32
+ ## 角丸
33
+
34
+ | 用途 | クラス |
35
+ | -------------------------- | -------------- |
36
+ | Badge, Tag 等小さい要素 | `rounded-sm` |
37
+ | Button, Input | `rounded-md` |
38
+ | Card, Modal, Dialog | `rounded-lg` |
39
+ | プログレスバー, IconButton | `rounded-full` |
40
+
41
+ `rounded-2xl` 以上は使わない。
42
+
43
+ ## シャドウ
44
+
45
+ 基本的に使わない。ボーダーで区切りを表現する。
46
+
47
+ | 用途 | スタイル |
48
+ | ------------------------ | --------------------------------------------------------- |
49
+ | Card(shadow) | `shadow-sm`(`appearance="shadow"` 時) |
50
+ | Card(bordered) | `border border-border-mute`(`appearance="bordered"` 時) |
51
+ | Modal / Dialog / Tooltip | `shadow-md` |
52
+ | Dropdown / ListBox | `shadow-md` |
53
+ | Button | なし |
54
+
55
+ `shadow-xl` 以上は使わない。
56
+
57
+ ## レイアウトパターン
58
+
59
+ ### 余白で階層を作る
60
+
61
+ ```tsx
62
+ // Good: 余白の差で関連度を示す
63
+ <section className="mt-12">
64
+ <Heading level={2}>セクション</Heading>
65
+ <p className="mt-2">直接関連する説明</p>
66
+ <div className="mt-8">やや離れたコンテンツ</div>
67
+ </section>
68
+
69
+ // Bad: すべて同じ余白
70
+ <section className="mt-4">
71
+ <Heading level={2}>セクション</Heading>
72
+ <p className="mt-4">説明</p>
73
+ <div className="mt-4">コンテンツ</div>
74
+ </section>
75
+ ```
76
+
77
+ ### カードは万能ではない
78
+
79
+ すべてのコンテンツをカードに入れる必要はない。余白と Separator で十分なケースが多い。
80
+
81
+ ```tsx
82
+ import { Separator } from '@k8o/arte-odyssey/separator';
83
+
84
+ // Good: Separator で区切る
85
+ <div>
86
+ <section>コンテンツA</section>
87
+ <Separator className="my-8" />
88
+ <section>コンテンツB</section>
89
+ </div>
90
+
91
+ // 過剰: すべてカードに入れる
92
+ <Card>コンテンツA</Card>
93
+ <Card>コンテンツB</Card>
94
+ ```
95
+
96
+ ## やってはいけないこと
97
+
98
+ - `gap-1` や `p-1` のような極端に狭いスペーシング
99
+ - コンテンツの詰め込み(情報密度より余白を優先)
100
+ - ネストされたカード(Card in Card)
101
+ - 12 を超える z-index 値
@@ -0,0 +1,67 @@
1
+ # タイポグラフィ
2
+
3
+ ArteOdyssey のタイポグラフィは「読みやすさ」と「静けさ」を両立する。
4
+
5
+ ## フォントファミリー
6
+
7
+ 日本語最適化のフォントスタック。
8
+
9
+ ```css
10
+ font-family: 'Noto Sans JP', 'M PLUS 2', sans-serif;
11
+ ```
12
+
13
+ - **Inter / Roboto / Open Sans は使わない** — AI が生成した感が出る
14
+ - 日本語テキストが主体のため、和文フォントを優先
15
+
16
+ ## フォントサイズスケール
17
+
18
+ | Tailwind クラス | 値 | 用途 |
19
+ | --------------- | -------- | -------------------- |
20
+ | `text-xs` | 0.75rem | 注釈、キャプション |
21
+ | `text-sm` | 0.875rem | 補足テキスト、ラベル |
22
+ | `text-md` | 1rem | 本文(デフォルト) |
23
+ | `text-lg` | 1.125rem | 小見出し |
24
+ | `text-xl` | 1.25rem | 見出し |
25
+ | `text-2xl` | 1.5rem | 大見出し |
26
+ | `text-3xl` | 1.875rem | ページタイトル |
27
+
28
+ ## フォントウェイト
29
+
30
+ ウェイトは控えめに使う。太字の多用は「静けさ」を損なう。
31
+
32
+ | Tailwind クラス | 値 | 用途 |
33
+ | --------------- | --- | ---------------------------- |
34
+ | `font-normal` | 400 | 本文 |
35
+ | `font-medium` | 450 | 強調テキスト(控えめな強調) |
36
+ | `font-bold` | 700 | 見出し、ボタンラベル |
37
+
38
+ - `font-semibold` (600) や `font-extrabold` (800) は使わない
39
+ - `font-medium` が 450 であることに注意(一般的な 500 より軽い)
40
+
41
+ ## 行間
42
+
43
+ 日本語テキストは欧文より広い行間が必要。
44
+
45
+ - 本文: `leading-relaxed` (1.625) を推奨
46
+ - 見出し: `leading-tight` (1.25) か `leading-snug` (1.375)
47
+ - リスト内: デフォルトの `leading-normal` (1.5)
48
+
49
+ ## Heading コンポーネント
50
+
51
+ 見出しには `Heading` コンポーネントを使う。
52
+
53
+ ```tsx
54
+ import { Heading } from '@k8o/arte-odyssey/heading';
55
+
56
+ <Heading level={1}>ページタイトル</Heading>
57
+ <Heading level={2}>セクション見出し</Heading>
58
+ <Heading level={3}>サブセクション</Heading>
59
+ ```
60
+
61
+ ## やってはいけないこと
62
+
63
+ - 3種類以上のフォントウェイトを1画面で使う
64
+ - `text-3xl` より大きいサイズを使う(ページタイトル以外)
65
+ - `uppercase` や `tracking-widest` を日本語テキストに適用する
66
+ - テキストにグラデーションをかける
67
+ - フォントサイズだけで階層を作る(余白も活用する)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@k8o/arte-odyssey",
3
- "version": "4.1.0",
3
+ "version": "4.2.0",
4
4
  "description": "k8o's react ui library",
5
5
  "keywords": [
6
6
  "components",
@@ -20,7 +20,8 @@
20
20
  "url": "git+https://github.com/k35o/ArteOdyssey.git"
21
21
  },
22
22
  "files": [
23
- "dist/**"
23
+ "dist/**",
24
+ "docs/**"
24
25
  ],
25
26
  "type": "module",
26
27
  "sideEffects": [
@@ -45,7 +46,6 @@
45
46
  "clsx": "2.1.1",
46
47
  "lucide-react": "0.577.0",
47
48
  "motion": "12.36.0",
48
- "react-error-boundary": "6.1.1",
49
49
  "tailwind-merge": "3.5.0"
50
50
  },
51
51
  "devDependencies": {
@@ -1,2 +0,0 @@
1
- import { ErrorBoundary } from "react-error-boundary";
2
- export { ErrorBoundary };
@@ -1,2 +0,0 @@
1
- import { ErrorBoundary } from "react-error-boundary";
2
- export { ErrorBoundary };