diff --git a/.changeset/press-feedback.md b/.changeset/press-feedback.md new file mode 100644 index 000000000..aa7ca5ee5 --- /dev/null +++ b/.changeset/press-feedback.md @@ -0,0 +1,10 @@ +--- +'8341-ui': patch +--- + +タッチでも押したことが伝わるよう、押している間の見た目(`active:`)を付けました。 + +- Link・Card(`href`)・Accordion・Checkbox / Radio / Switch(ラベルの文字を押しても出る)・入力欄・NotificationBanner の閉じるボタンに、マウスの hover と同じ見た目を `active:` でも付けた +- Button の hover と押した見た目を `enabled:` から `not-disabled:` に替えた。`buttonVariants` を `` に当てたとき、hover も押した見た目も出なかった +- テーマで端末のタップの塗り(`-webkit-tap-highlight-color`)を消した +- iOS Safari で `:active` を効かせるには、アプリで `document` に `touchstart` の受け手を置く(README) diff --git a/DESIGN.md b/DESIGN.md index 9eaa508a5..c74d54d42 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -185,7 +185,7 @@ DTCG では `{"colorSpace": "oklch", "components": [L, C, H], "hex": "#..."}` - import パスは shadcn 方式: `@/components/ui/{Name}/index`(ディレクトリ名は PascalCase)、`@/lib/{name}` - 独自のスタイルは `tv()` を `@/lib/tv` から import して書く。`tailwind-variants` の `tv` を直接使わない(独自のテーマ名を登録した `tv` でないと `text-fg text-body-md` の文字色が消える) - **フォーカスは `focus-ring` クラス**。見た目が 44px 未満の操作対象には `tap-target` -- コンポーネント自体を作る・直すときの規約(data 属性、`enabled:hover:`、`forced-colors:`、`'use client'` など)は [docs/rulebook/04-components.md](./docs/rulebook/04-components.md) +- コンポーネント自体を作る・直すときの規約(data 属性、`not-disabled:hover:`、`forced-colors:`、`'use client'` など)は [docs/rulebook/04-components.md](./docs/rulebook/04-components.md) ### Button diff --git a/README.md b/README.md index 11b519d63..0592e6490 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,16 @@ npx shadcn@latest add @8341/8341-base @8341/button @8341/form-field @8341/text-f あとは使うだけです。テーマは `` か `` でダークに切り替わり、どちらも無ければ OS の設定に従います。 テーマ(`styles/8341-ui.css`)はトークンを同梱しています。トークンが更新されたら `npx shadcn@latest add @8341/theme --overwrite` で取り込み直します。 +部品は押している間の見た目(`:active`)でタッチでも押したことを伝えます。iOS Safari は `touchstart` の受け手が無いと `:active` を当てないので、アプリの全画面に共通する枠(レイアウトなど)で一度だけ受け手を置きます。インラインの `ontouchstart` 属性は CSP で止まることがあるので、スクリプトで付けます。 + +```tsx +useEffect(() => { + const enableActive = () => undefined; + document.addEventListener('touchstart', enableActive, { passive: true }); + return () => document.removeEventListener('touchstart', enableActive); +}, []); +``` + ```tsx import { Button } from '@/components/ui/Button/index'; import { FormField } from '@/components/ui/FormField/index'; diff --git a/docs/improvement/log.md b/docs/improvement/log.md index 4e8c9fd6a..a71d1c3a1 100644 --- a/docs/improvement/log.md +++ b/docs/improvement/log.md @@ -4,6 +4,7 @@ | 日付 | 種別 | 内容 | 再発防止 | | ---------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| 2026-11-07 | 部品 | タッチで押したことが伝わるよう、hover だけだった部品(Link・Card・Accordion・Checkbox / Radio / Switch(ラベルを押しても出る)・入力欄・NotificationBanner の閉じる)に、hover と同じ見た目の `active:` を足した。ボタンの見た目(`buttonVariants`)をリンクに当てると `enabled:` が `` に当たらず hover も押した見た目も出なかったので、Button を `not-disabled:` に替えた。端末のタップの塗りは消した。bouzu(#84・#89)での知見 | クラス監査に `enabled-variant`(enabled: を禁止)と `hover-without-active`(hover: だけで active: が無い部品)を追加。Button・Link のテスト。iOS Safari の touchstart の受け手を README に記載 | | 2026-11-02 | 保守 | Node.js を 26.13.0(LTS Lithium)に更新。`devEngines` を `>=26.13.0`、`@types/node` を 26 系(`^26.6.6`)に合わせた。他の依存の版は変えていない | ADR-0020。CI は `.tool-versions` の版を使う | | 2026-10-23 | 保守 | 全体のリファクタリング。古い参照(存在しない make ターゲット・パス・README の節名)を直し、トークンを変えた後の手順を `make generate` に統一。Makefile と重複していた pnpm スクリプト、design-review に混ざっていたコードレビュー・Next.js の項目、使われていない関数と export を削除。DESIGN.md・ルールブック 04・06・CONTRIBUTING・factory.md の重複を正本へのリンクにし、トークンの CSS 化の規則を `packages/tokens/scripts/lib/css.ts` に集めて build.ts とスライドで共有 | 規則を 1 か所にしたので、tokens.css とスライドの値の書き方がずれない。重複していた手順は正本(Makefile・COMPONENT_STRUCTURE.md・06 章・ds-factory)だけに置いた | | 2026-10-23 | 機能 | 8341-ui を使うプロダクトに、DESIGN.md と design-principles を配るレジストリ item `@8341/design-md` を追加。DESIGN.md はコードから読み取れない考え方(プロダクトの前提・画面領域ごとの方向性・大事にすること・外した必須)と原則の必須の要約だけにし、トークンや部品の一覧は載せない | ADR-0019。原則の要約は `scripts/sync-product-design.ts` が docs/design-principles から生成し、`make check` で鮮度を検査。配布する原則のファイル一覧も registry.json の --check で追従 | diff --git a/docs/rulebook/02-accessibility.md b/docs/rulebook/02-accessibility.md index eb0876e7e..e29cf9ed1 100644 --- a/docs/rulebook/02-accessibility.md +++ b/docs/rulebook/02-accessibility.md @@ -21,7 +21,7 @@ | A11 | 動的に出す通知だけ `role="status"` / `role="alert"` を付ける | 4.1.3 | NotificationBanner の `live` | | A12 | `prefers-reduced-motion` で動きを止める | 2.3.3 | theme.css、`motion-reduce:` | | A13 | 強制カラーモード(Windows ハイコントラスト)で境界とフォーカスが消えない | 1.4.11 | 各コンポーネントの `forced-colors:`、e2e の forced-colors プロジェクト | -| A14 | hover で文字の太さ・大きさを変えない。無効状態に hover を効かせない(`enabled:hover:`) | — | レビュー(Tailwind v4 の `hover:` は自動で `@media (hover: hover)` に入る) | +| A14 | hover で文字の太さ・大きさを変えない。無効状態に hover を効かせない(`not-disabled:hover:`)。hover の見た目は `active:` にも付け、タッチでも押したことを伝える | — | クラス監査の `enabled-variant`・`hover-without-active`(Tailwind v4 の `hover:` は自動で `@media (hover: hover)` に入る) | | A15 | ストーリーはすべて axe の WCAG 2.2 AA ルールで違反ゼロ | — | Storybook addon-a11y(`test: 'error'`)+ addon-vitest | | A16 | 幅 320px で横スクロールが出ない。文字サイズ 200% で内容が切れない | 1.4.10, 1.4.4 | Playwright の e2e(手動・都度実行) | diff --git a/docs/rulebook/04-components.md b/docs/rulebook/04-components.md index f3d5d4279..bc5394d2d 100644 --- a/docs/rulebook/04-components.md +++ b/docs/rulebook/04-components.md @@ -37,7 +37,9 @@ - 状態は Base UI の data 属性で装飾する(`data-[checked]:`、`data-[invalid]:`、`data-[disabled]:`、`data-[highlighted]:`、`data-[panel-open]:`、`data-[starting-style]:`) - **フォーカスは `focus-ring`**(`@/lib/focus` の `focusRing`)。Base UI は `data-focus-visible` を付けないため `:focus-visible` で描く - 見た目が 44px 未満の操作対象には `tap-target` -- 無効状態に hover を効かせないよう `enabled:hover:` を使う(Tailwind v4 の `hover:` は自動で `@media (hover: hover)` に入る) +- 無効状態に hover と押した見た目を効かせないよう `not-disabled:hover:`・`not-disabled:active:` を使う。`enabled:` は `` に当たらず、ボタンの見た目(`buttonVariants`)をリンクに当てたときに何も出なくなる(クラス監査の `enabled-variant`) +- `hover:` を付けたら、同じ見た目かそれより濃い見た目を `active:` にも付ける。Tailwind v4 の `hover:` は自動で `@media (hover: hover)` に入り、タッチでは出ないので、押したことは `active:` だけが伝える(クラス監査の `hover-without-active`) +- ラベルの文字を押して操作する部品(Checkbox・Radio・Switch)は、ラベルに `group/*` を付け、`group-active/*:` で四角・丸・トラックにも押した見た目を出す - 強制カラーモードは `forced-colors:` で補う - 論理プロパティのクラスを使う(`ps-*`、`ms-*`、`border-s-*`) - クラス名を動的に組み立てない(`` `text-${size}` `` は Tailwind が検出できない)。variants に列挙する diff --git a/packages/ui/scripts/audit-classes.ts b/packages/ui/scripts/audit-classes.ts index ac2b72f58..1b882d507 100644 --- a/packages/ui/scripts/audit-classes.ts +++ b/packages/ui/scripts/audit-classes.ts @@ -14,6 +14,8 @@ * bare-read-only … read-only: は button や無効の input にも当たる。[&:read-only:not(:disabled,button)]: を使う * theme-var-ref … 任意値・手書き CSS からの Tailwind テーマ変数(--color-* / --spacing-* / --text-* など)の参照。 * @theme inline は使われた変数しか出力しないため未定義になりうる。常に存在する --8341-* を参照する + * enabled-variant … enabled: は に当たらない。ボタンの見た目をリンクに当てると hover も押した見た目も出ない。not-disabled: を使う + * hover-without-active … hover: を書いた部品に active: が無い。タッチでは hover が出ないので、押した見た目は active: で出す * warning * numeric-spacing … p-4 / gap-6 など数値の余白。semantic な余白(p-inset-md、gap-stack-md)を検討する */ @@ -57,6 +59,17 @@ export function auditClasses(): Finding[] { message: "フックを使っているのに 'use client' がありません", }); } + const classText = text.replace(/\/\/.*$/gm, ''); + if (/(? { const add = (rule: string, severity: Finding['severity'], message: string) => findings.push({ file: rel, line: i + 1, rule, severity, message }); @@ -77,6 +90,8 @@ export function auditClasses(): Finding[] { 'error', 'read-only: は button や無効の input にも当たります。[&:read-only:not(:disabled,button)]: を使ってください', ); + if (/(? に当たりません。not-disabled: を使ってください'); const palette = line.match(PALETTE); if (palette) add('tailwind-palette', 'error', `Tailwind 既定のパレットは使えません: ${palette[0]}(semantic の色を使う)`); diff --git a/packages/ui/src/components/ui/Accordion/index.tsx b/packages/ui/src/components/ui/Accordion/index.tsx index 693c65bf4..6fae1f805 100644 --- a/packages/ui/src/components/ui/Accordion/index.tsx +++ b/packages/ui/src/components/ui/Accordion/index.tsx @@ -10,7 +10,7 @@ export const accordionVariants = tv({ item: 'border-b border-border', header: 'm-0 text-body-md font-bold', trigger: [ - 'group/trigger flex min-h-target-min w-full cursor-pointer items-center rounded-xs border-0 bg-transparent px-inset-sm py-inset-md text-start font-bold text-fg hover:bg-muted', + 'group/trigger flex min-h-target-min w-full cursor-pointer items-center rounded-xs border-0 bg-transparent px-inset-sm py-inset-md text-start font-bold text-fg hover:bg-muted active:bg-muted', focusRing, ], icon: 'ms-gap-md shrink-0 text-icon-key transition-transform group-data-[panel-open]/trigger:rotate-180', diff --git a/packages/ui/src/components/ui/Button/index.test.tsx b/packages/ui/src/components/ui/Button/index.test.tsx index 7b5e82eee..de00a854b 100644 --- a/packages/ui/src/components/ui/Button/index.test.tsx +++ b/packages/ui/src/components/ui/Button/index.test.tsx @@ -1,9 +1,20 @@ import { render, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import { describe, expect, it, vi } from 'vite-plus/test'; -import { Button } from './index'; +import { Button, buttonVariants } from './index'; describe('Button', () => { + it('ボタンの見た目をリンクに当てても、押した見た目が出る(:enabled は a に当たらない)', () => { + render( + + 申請を始める + , + ); + const link = screen.getByRole('link', { name: '申請を始める' }); + expect(link).toHaveClass('not-disabled:active:bg-key-active'); + expect(link.className).not.toMatch(/(? { render(); expect(screen.getByRole('button')).toHaveAttribute('type', 'button'); diff --git a/packages/ui/src/components/ui/Button/index.tsx b/packages/ui/src/components/ui/Button/index.tsx index a4560afb2..5facd1b5d 100644 --- a/packages/ui/src/components/ui/Button/index.tsx +++ b/packages/ui/src/components/ui/Button/index.tsx @@ -28,16 +28,16 @@ export const buttonVariants = tv({ */ variant: { primary: { - root: 'border-key bg-key text-fg-on-key enabled:hover:border-key-hover enabled:hover:bg-key-hover enabled:active:border-key-active enabled:active:bg-key-active', + root: 'border-key bg-key text-fg-on-key not-disabled:hover:border-key-hover not-disabled:hover:bg-key-hover not-disabled:active:border-key-active not-disabled:active:bg-key-active', }, secondary: { - root: 'border-border-key bg-surface text-fg-key enabled:hover:bg-key-subtle enabled:active:bg-key-subtle-hover', + root: 'border-border-key bg-surface text-fg-key not-disabled:hover:bg-key-subtle not-disabled:active:bg-key-subtle-hover', }, tertiary: { - root: 'border-transparent bg-transparent text-fg-key underline underline-offset-[0.2em] enabled:hover:bg-key-subtle enabled:active:bg-key-subtle-hover disabled:border-transparent disabled:bg-transparent', + root: 'border-transparent bg-transparent text-fg-key underline underline-offset-[0.2em] not-disabled:hover:bg-key-subtle not-disabled:active:bg-key-subtle-hover disabled:border-transparent disabled:bg-transparent', }, danger: { - root: 'border-danger bg-danger text-fg-on-key enabled:hover:border-danger-hover enabled:hover:bg-danger-hover enabled:active:border-danger-active enabled:active:bg-danger-active', + root: 'border-danger bg-danger text-fg-on-key not-disabled:hover:border-danger-hover not-disabled:hover:bg-danger-hover not-disabled:active:border-danger-active not-disabled:active:bg-danger-active', }, }, /** sm は見た目 36px だが、タップ領域は 44px を確保する */ diff --git a/packages/ui/src/components/ui/Card/index.tsx b/packages/ui/src/components/ui/Card/index.tsx index a1e600bfe..30c4635f7 100644 --- a/packages/ui/src/components/ui/Card/index.tsx +++ b/packages/ui/src/components/ui/Card/index.tsx @@ -11,10 +11,11 @@ export const cardVariants = tv({ body: 'flex flex-1 flex-col gap-stack-sm p-inset-xl', eyebrow: 'm-0 text-body-sm text-fg-subtle', title: 'm-0 text-heading-xs', - link: 'text-fg-link underline decoration-1 underline-offset-[0.2em] outline-none after:absolute after:inset-0 after:content-[""] group-hover/card:decoration-(length:--8341-border-width-underline-hover)', // allow-outline-none: フォーカスはカード全体に focus-ring-within で描く + link: 'text-fg-link underline decoration-1 underline-offset-[0.2em] outline-none after:absolute after:inset-0 after:content-[""] group-hover/card:decoration-(length:--8341-border-width-underline-hover) group-active/card:decoration-(length:--8341-border-width-underline-hover)', // allow-outline-none: フォーカスはカード全体に focus-ring-within で描く content: '[&>p]:m-0', footer: 'flex items-center justify-between gap-gap-sm px-inset-xl pb-inset-xl text-fg-subtle', - arrow: 'ms-auto text-icon-key transition-transform group-hover/card:translate-x-gap-xs', + arrow: + 'ms-auto text-icon-key transition-transform group-hover/card:translate-x-gap-xs group-active/card:translate-x-gap-xs', }, variants: { variant: { @@ -22,7 +23,12 @@ export const cardVariants = tv({ filled: { root: 'border-transparent bg-subtle' }, }, interactive: { - true: { root: [focusRingWithin, 'hover:border-border-key hover:shadow-1'] }, + true: { + root: [ + focusRingWithin, + 'hover:border-border-key hover:shadow-1 active:border-border-key active:bg-subtle active:shadow-1', + ], + }, }, }, defaultVariants: { variant: 'outlined' }, diff --git a/packages/ui/src/components/ui/Checkbox/index.tsx b/packages/ui/src/components/ui/Checkbox/index.tsx index 4bbc8c4b1..ce0ce36cd 100644 --- a/packages/ui/src/components/ui/Checkbox/index.tsx +++ b/packages/ui/src/components/ui/Checkbox/index.tsx @@ -8,7 +8,7 @@ import { type VariantProps, tv } from '@/lib/tv'; export const choiceVariants = tv({ slots: { label: [ - 'flex w-fit cursor-pointer items-start gap-gap-sm text-body-md text-fg', + 'group/choice flex w-fit cursor-pointer items-start gap-gap-sm text-body-md text-fg', // 1 行の高さ(16px × 1.7)に上下の余白を足して 44px のタップ領域にする 'min-h-target-min py-[calc((var(--8341-size-target-min)-var(--8341-text-body-md-font-size)*var(--8341-text-body-md-line-height))/2)]', 'has-[[data-disabled]]:cursor-not-allowed has-[[data-disabled]]:text-fg-disabled', @@ -16,6 +16,8 @@ export const choiceVariants = tv({ control: [ 'group/control mt-[calc((var(--8341-text-body-md-font-size)*var(--8341-text-body-md-line-height)-var(--choice-box))/2)] inline-grid size-(--choice-box) shrink-0 place-items-center', 'border-2 border-border-input bg-surface hover:border-border-strong hover:bg-muted', + // ラベルの文字を押しても、四角や丸に押した見た目を出す + 'group-active/choice:not-data-[disabled]:border-border-strong group-active/choice:not-data-[disabled]:bg-muted', 'data-[invalid]:border-border-danger', 'data-[disabled]:border-border-disabled data-[disabled]:bg-disabled', focusRing, diff --git a/packages/ui/src/components/ui/FormField/index.tsx b/packages/ui/src/components/ui/FormField/index.tsx index f9eaf998d..8551dae30 100644 --- a/packages/ui/src/components/ui/FormField/index.tsx +++ b/packages/ui/src/components/ui/FormField/index.tsx @@ -14,7 +14,7 @@ export const controlVariants = tv({ 'block w-full rounded-md border border-border-input bg-surface px-inset-md py-inset-sm', // 16px 未満だと iOS Safari がフォーカス時に拡大するため、文字サイズは固定 'text-body-md leading-(--8341-text-dense-md-line-height) text-fg placeholder:text-fg-subtle', - 'transition-colors hover:border-border-strong focus-visible:border-border-strong', + 'transition-colors hover:border-border-strong active:border-border-strong focus-visible:border-border-strong', focusRing, // エラーは色に加えて線を太くし、形でも示す 'data-[invalid]:border-border-danger data-[invalid]:shadow-[inset_0_0_0_1px_var(--8341-color-border-danger)] aria-invalid:border-border-danger aria-invalid:shadow-[inset_0_0_0_1px_var(--8341-color-border-danger)]', diff --git a/packages/ui/src/components/ui/Link/index.test.tsx b/packages/ui/src/components/ui/Link/index.test.tsx index 27665831a..eb09073dc 100644 --- a/packages/ui/src/components/ui/Link/index.test.tsx +++ b/packages/ui/src/components/ui/Link/index.test.tsx @@ -12,4 +12,13 @@ describe('Link', () => { const link = screen.getByRole('link', { name: /外部サイト\s?(新しいタブで開きます)/ }); expect(link).toHaveAttribute('rel', expect.stringContaining('noopener')); }); + + it('押している間は、タッチでも見える色と下線の太さに変わる', () => { + render(単語帳); + const link = screen.getByRole('link', { name: '単語帳' }); + expect(link).toHaveClass( + 'active:text-fg-link-active', + 'active:decoration-(length:--8341-border-width-underline-hover)', + ); + }); }); diff --git a/packages/ui/src/components/ui/Link/index.tsx b/packages/ui/src/components/ui/Link/index.tsx index b53ff6f50..8b07f405f 100644 --- a/packages/ui/src/components/ui/Link/index.tsx +++ b/packages/ui/src/components/ui/Link/index.tsx @@ -6,12 +6,13 @@ import { tv } from '@/lib/tv'; * リンクの 5 状態: default / visited / hover / active / focus * - 下線は常に表示する(色だけで判別させない) * - hover では下線を太くするだけで、文字の太さ・大きさは変えない(レイアウトがずれないように) + * - active(押している間)は橙にし、下線も hover と同じ太さにする。タッチでは hover が出ないので、押したことはこれで伝える * - focus では背景も黄色にして、文中のリンクでも見失わないようにする */ export const linkVariants = tv({ base: [ 'rounded-xs text-fg-link underline decoration-1 underline-offset-[0.2em]', - 'visited:text-fg-link-visited hover:text-fg-link-hover hover:decoration-(length:--8341-border-width-underline-hover) active:text-fg-link-active', + 'visited:text-fg-link-visited hover:text-fg-link-hover hover:decoration-(length:--8341-border-width-underline-hover) active:text-fg-link-active active:decoration-(length:--8341-border-width-underline-hover)', // Tailwind v4 の outline-none は線種を none にするため使わず、:focus-visible で線種から指定する 'focus-visible:bg-focus-ring focus-visible:text-focus-text focus-visible:decoration-1 focus-visible:outline-solid', 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-focus-outline', diff --git a/packages/ui/src/components/ui/NotificationBanner/index.tsx b/packages/ui/src/components/ui/NotificationBanner/index.tsx index e01f37765..dabbc1d76 100644 --- a/packages/ui/src/components/ui/NotificationBanner/index.tsx +++ b/packages/ui/src/components/ui/NotificationBanner/index.tsx @@ -18,7 +18,7 @@ export const notificationBannerVariants = tv({ content: '[&>p]:m-0', actions: 'flex flex-wrap gap-gap-sm', close: [ - 'tap-target -m-inset-md inline-grid size-target-min shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent p-0 text-icon hover:bg-muted', + 'tap-target -m-inset-md inline-grid size-target-min shrink-0 cursor-pointer place-items-center rounded-md border-0 bg-transparent p-0 text-icon hover:bg-muted active:bg-muted', focusRing, ], }, diff --git a/packages/ui/src/components/ui/Switch/index.tsx b/packages/ui/src/components/ui/Switch/index.tsx index 17a464c6c..d8d6eb353 100644 --- a/packages/ui/src/components/ui/Switch/index.tsx +++ b/packages/ui/src/components/ui/Switch/index.tsx @@ -11,7 +11,7 @@ import { type VariantProps, tv } from '@/lib/tv'; export const switchVariants = tv({ slots: { label: [ - 'grid w-fit cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-x-gap-sm text-fg', + 'group/switch-label grid w-fit cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-x-gap-sm text-fg', // ラベル全体がタップ領域になる。トラックの見た目は 44px 未満でも行の高さで 44px を確保する 'min-h-target-min', 'has-[[data-disabled]]:cursor-not-allowed has-[[data-disabled]]:text-fg-disabled', @@ -23,6 +23,9 @@ export const switchVariants = tv({ 'hover:not-data-[disabled]:border-border-strong hover:not-data-[disabled]:bg-muted', 'data-[checked]:border-key data-[checked]:bg-key', 'data-[checked]:hover:not-data-[disabled]:border-key-hover data-[checked]:hover:not-data-[disabled]:bg-key-hover', + // ラベルの文字を押しても、トラックに押した見た目を出す。色は hover と同じ + 'group-active/switch-label:not-data-[disabled]:border-border-strong group-active/switch-label:not-data-[disabled]:bg-muted', + 'data-[checked]:group-active/switch-label:not-data-[disabled]:border-key-hover data-[checked]:group-active/switch-label:not-data-[disabled]:bg-key-hover', 'data-[invalid]:border-border-danger', 'data-[disabled]:border-border-disabled data-[disabled]:bg-disabled', 'data-[disabled]:data-[checked]:border-border-disabled data-[disabled]:data-[checked]:bg-disabled', @@ -31,10 +34,10 @@ export const switchVariants = tv({ ], thumb: [ 'grid size-(--switch-thumb) place-items-center rounded-full transition-[translate,background-color]', - 'bg-(--8341-color-border-input) group-hover/switch:not-data-[disabled]:bg-(--8341-color-border-strong)', + 'bg-(--8341-color-border-input) group-hover/switch:not-data-[disabled]:bg-(--8341-color-border-strong) group-active/switch-label:not-data-[disabled]:bg-(--8341-color-border-strong)', // オンでは白抜きのつまみにチェックを出す(色だけで状態を伝えない) 'data-[checked]:translate-x-(--switch-thumb) rtl:data-[checked]:-translate-x-(--switch-thumb)', - 'data-[checked]:bg-surface group-hover/switch:data-[checked]:not-data-[disabled]:bg-surface', + 'data-[checked]:bg-surface group-hover/switch:data-[checked]:not-data-[disabled]:bg-surface group-active/switch-label:data-[checked]:not-data-[disabled]:bg-surface', 'data-[disabled]:bg-(--8341-color-text-disabled) data-[disabled]:data-[checked]:bg-(--8341-color-text-disabled)', 'forced-colors:bg-[ButtonText] forced-colors:data-[checked]:bg-[Highlight] forced-colors:data-[disabled]:bg-[GrayText]', ], diff --git a/packages/ui/src/styles/theme.css b/packages/ui/src/styles/theme.css index 502a8d827..c864f1a0b 100644 --- a/packages/ui/src/styles/theme.css +++ b/packages/ui/src/styles/theme.css @@ -62,6 +62,8 @@ line-height: var(--8341-text-body-md-line-height); letter-spacing: var(--8341-text-body-md-letter-spacing); font-feature-settings: normal; + /* 押した見た目は各部品の active: で出す。端末の灰色や青のタップの塗りと重ねない */ + -webkit-tap-highlight-color: transparent; /* 和文の禁則を厳格に、単語途中の改行を避ける */ line-break: strict; overflow-wrap: anywhere;