@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 +2 -9
- package/dist/components/icons/base.d.mts +1 -1
- package/dist/components/icons/base.mjs +10 -1
- package/dist/components/index.d.mts +1 -2
- package/dist/components/index.mjs +1 -2
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +1 -2
- package/docs/GUIDE.md +232 -0
- package/docs/references/color.md +86 -0
- package/docs/references/components.md +449 -0
- package/docs/references/interaction-design.md +74 -0
- package/docs/references/spatial-design.md +101 -0
- package/docs/references/typography.md +67 -0
- package/package.json +3 -3
- package/dist/components/utility/error-boundary/index.d.mts +0 -2
- package/dist/components/utility/error-boundary/index.mjs +0 -2
package/README.md
CHANGED
|
@@ -66,15 +66,9 @@ function MyPage() {
|
|
|
66
66
|
}
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
## AI Agent
|
|
69
|
+
## AI Agent Documentation
|
|
70
70
|
|
|
71
|
-
ArteOdyssey
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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.
|
|
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": {
|