Conversation
Establish the 3-layer token architecture for the MD3 theme: 1. Source colors (--md-sys-source-*) map to the Ionic palette and are overridable for Material You / dynamic color. 2. MD3 color roles (--md-sys-color-*) form the public API. 3. Components will consume roles, never raw Ionic variables. Also add shape, typescale, motion, state and elevation tokens, plus dark-palette overrides. color-mix() is used as a CSS-only fallback adapter, not a canonical tonal palette generator. Legacy --token-elevation-* and --token-expressive-* are kept as aliases for backwards compatibility. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
ion-button: - Map Ionic fills to MD3 variants: solid -> filled, outline -> outlined, clear -> text, plus new button-elevated and button-tonal. - Use --md-sys-color-* for fills, state layers and typography. - Apply --md-sys-shape-corner-full by default, --md-sys-shape-corner-small for button-square. - Keep small / large sizing and icon-only sizing from the existing theme. ion-toolbar: - Surface background / on-surface text via --md-sys-color-*. - Add opt-in toolbar-small / toolbar-medium / toolbar-large variants. - Preserve existing insets and icon-only button back-fill behavior. No !important used; all changes rely on CSS custom properties and selectors that respect the md3-disabled opt-out. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- ion-card: default to M3 "filled" (surface-container-highest), add card-elevated (surface-container-low + elevation-1) and card-outlined (surface + outline-variant border) variants. - ion-chip: surface-container-low background, on-surface text and M3 state layer opacities. - ion-fab: primary-container / on-primary-container, M3 shape and elevation tokens. All changes go through CSS custom properties and avoid !important. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- ion-searchbar: surface-container-highest input with on-surface / on- surface-variant colors and extra-large corner radius. - ion-segment: outlined segmented button group with secondary-container selection, shared borders and pill-shaped first/last buttons. - ion-tabs: bottom navigation bar on surface-container, 80px height, active icon on a secondary-container pill. - ion-toggle: M3 switch using surface-container-highest track, primary checked track, outline handle and on-primary checked handle. All changes go through CSS custom properties. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- ion-list: use md-sys outline-variant for divider color, extra-small shape tokens and standard motion easing for floating labels. - ion-range: apply M3 slider color roles (surface-container-highest track, primary active track, on-primary thumb, inverse-surface pin) and motion tokens while preserving the existing 4dp bar / halo shape logic. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…dal, Popover, Toast) Apply M3 surface, shape, elevation and color roles to the overlay components while keeping Ionic layout and safe-area behavior. - Alert: surface-container-highest with extra-large radius, primary / destructive button colors. - Action Sheet: surface-container-low with bottom extra-large radius, destructive option color. - Loading: surface-container-highest wrapper. - Modal: level-3 shadow and extra-large radius for desktop / sheet. - Popover: surface-container with medium radius. - Toast: inverse-surface / inverse-on-surface snackbar with inverse-primary action color and extra-small corners. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- ion-content: surface / on-surface. - ion-datetime: surface-container-highest background and on-surface title. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
| --background: var(--md-sys-color-primary); | ||
| --color: var(--md-sys-color-on-primary); |
There was a problem hiding this comment.
🟡 Ionic の色指定が MD3 の固定色に置き換わる
color 属性付きボタンにも primary 背景と文字色が常に適用されます。同じ固定指定を持つ toolbar、card、chip、content、FAB、toggle でも指定色が表示されません。
Learn more
Ionic は color 属性から .ion-color と --ion-color-base / --ion-color-contrast を設定します。今回、文書側のコンポーネント規則が --background と --color を直接指定するため、その公開 API より MD3 の固定ロールが優先されます。デモにも color="success" の button と toggle、color="primary" の toolbar と card など、影響を受ける既存利用があります。
Example: <ion-button color="success" fill="solid">Save</ion-button> は success 色になるべきですが、常に --md-sys-color-primary と --md-sys-color-on-primary で描画されます。
Recommended fix: 各コンポーネントで .ion-color の場合は --ion-color-base / --ion-color-contrast を使う上書きを追加してください。button の outline/clear、toggle の checked 状態、toolbar、card、chip、content、FAB など、固定ロールを設定した全コンポーネントを同じ方針で監査してください。
Was this helpful? React with 👍 or 👎 to provide feedback.
| &:first-of-type { | ||
| --border-radius: var(--md-sys-shape-corner-full) 0 0 var(--md-sys-shape-corner-full); | ||
| } | ||
|
|
||
| &:last-of-type { | ||
| --border-radius: 0 var(--md-sys-shape-corner-full) var(--md-sys-shape-corner-full) 0; | ||
| --border-width: 0; |
There was a problem hiding this comment.
🟡 RTL のセグメント外枠が逆側で丸くなる
RTL では先頭ボタンが右端へ移動しても、左角だけが丸められます。外角が四角くなり、内側の継ぎ目が丸く表示されます。
Learn more
first-of-type と last-of-type は DOM 順を参照しますが、セグメントの視覚順は RTL で反転します。現在の border-radius は物理的な左・右を固定しているため、DOM 上の先頭要素に左側の角丸を付け続けます。
Example: DOM 順が A、B、C の場合、RTL では A が右端、C が左端です。現在は A の左角と C の右角が丸くなり、どちらもグループ内側に現れます。
Recommended fix: :dir(rtl) で first/last の半径を反転するか、論理方向に対応する方法で開始側・終了側の角丸を指定してください。区切り線の辺も RTL で外周と重複しないよう同時に確認してください。
Was this helpful? React with 👍 or 👎 to provide feedback.
| // switches to dark mode. These overrides adapt the derived Material roles | ||
| // for dark surfaces while preserving Ionic colors as the theme source. | ||
|
|
||
| html.ion-palette-dark { |
There was a problem hiding this comment.
🟡 system・always ダークモードでダーク用トークンが適用されない
ダーク補正は html.ion-palette-dark だけに限定されています。dark.system.css と dark.always.css では、MD3 コンテナ色がライト用の混合率のまま残ります。
Learn more
Ionic は class 方式以外に、常時適用する dark.always.css と OS 設定に従う dark.system.css を提供しています。リポジトリのデモ設定にも両方式が選択肢として残っていますが、ここでは class 方式のセレクターだけを検出します。その結果、基礎の Ionic 変数は暗色へ変わっても、surface-container などは 2–8% のライト用比率を使い続けます。
Example: dark.system.css を読み込み、OS をダークへ切り替えると --ion-background-color は暗くなります。しかし --md-sys-color-surface-container-highest は 8% のままで、期待するダーク用 20% へ変わりません。
Recommended fix: class、always、system の各公式方式に対応するスコープで同じダークロールを定義してください。system 方式には対応する prefers-color-scheme 条件を使い、Ionic の適用条件と同期させてください。
Was this helpful? React with 👍 or 👎 to provide feedback.
| --md-sys-color-inverse-surface: var(--ion-color-dark, #e6e0e9); | ||
| --md-sys-color-inverse-on-surface: var(--ion-color-dark-contrast, #1d1b20); | ||
| --md-sys-color-inverse-primary: var(--ion-color-primary-tint, #d0bcff); |
There was a problem hiding this comment.
🟡 ダークモードの inverse ロールが反転しない
ダークパレットでも --ion-color-dark は暗色のため、inverse surface は暗いままです。toast はライト時と同じ暗色背景になり、inverse 配色へ反転しません。
Learn more
CSS var() のフォールバックは変数が未定義の場合だけ使われます。Ionic は --ion-color-dark と --ion-color-dark-contrast を通常定義するため、ここに書かれた明色・暗色のフォールバックは選ばれません。
Example: ダークパレットで --ion-color-dark: #222428、その contrast が白なら、toast は暗色背景と白文字のままです。期待される inverse surface は明色背景と暗色文字です。
Recommended fix: ダークスコープでは明色パレットの base/contrast を inverse surface/on-surface に割り当ててください。カスタム Ionic パレットでも対になる色を維持できることを確認してください。
| --md-sys-color-inverse-surface: var(--ion-color-dark, #e6e0e9); | |
| --md-sys-color-inverse-on-surface: var(--ion-color-dark-contrast, #1d1b20); | |
| --md-sys-color-inverse-primary: var(--ion-color-primary-tint, #d0bcff); | |
| --md-sys-color-inverse-surface: var(--ion-color-light, #e6e0e9); | |
| --md-sys-color-inverse-on-surface: var(--ion-color-light-contrast, #1d1b20); | |
| --md-sys-color-inverse-primary: var(--ion-color-primary-tint, #d0bcff); |
Was this helpful? React with 👍 or 👎 to provide feedback.
| --token-elevation-6: var(--md-sys-elevation-level-4); | ||
| --token-elevation-8: var(--md-sys-elevation-level-5); | ||
| --token-elevation-12: var(--md-sys-elevation-level-5); |
|
📊 Ionic 9 Playwright Test Report View the detailed Ionic 9 report: https://rdlabo-dev.github.io/ionic-theme-md3/pr-47/ Ionic 8 runs against the same screenshots in a separate matrix job. View both results in the workflow run. |
Devin Review feedback on PR #47: - Add `.ion-color` overrides to Button, Card, Chip, FAB, Toggle and Toolbar so the Ionic `color` attribute (via `--ion-color-base` / `--ion-color-contrast`) is honored on top of MD3 tokens. - Fix `ion-card` setting the `color` property directly, which would override the Ionic `.ion-color` rule. - Restore the original legacy `--token-elevation-8` and `--token-elevation-12` values; keep 0/1/3 mapped to M3 levels and 6 mapped to M3 level 5. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Playwright test resultsDetails
Failed testschromium › screenshot.spec.ts › Screenshot Tests - All Routes › should match screenshot for action-sheet:all |
9a50498 to
91d8809
Compare
Restore the iOS/Ionic button shape (pill, circular icon-only, square variant) while keeping MD3 color roles and typography. - Add the :not(.button-round) selector back so toolbar rules do not override --border-radius. - Use 999px / 12px directly instead of MD3 shape tokens. - Revert icon sizes to the iOS defaults (24/20/24). Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Use --ion-color-light for the item border so the inset list group keeps its iOS card-like shape without a dark MD3 outline between items. Color (surface background, notes) remains MD3. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
iOS is essentially the default light implementation, so keep ion-content background as the platform default rather than forcing --md-sys-color-surface. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- Restore Ionic/main shape values (border-radius, height, spacing, handle radius, etc.) for action-sheet, alert, card, chip, fab, list, loading, modal, popover, range, searchbar, segment, tabs, toast, toggle, toolbar. - Keep MD3 color, typography, elevation, and state tokens where they only affect color. - Remove non-Ionic MD3-only variants (button-elevated/tonal, card-elevated/outlined, toolbar size variants) so defaults stay predictable. - Keep Ionic color="..." and md3-disabled behavior intact. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
✅ Screenshots have been updated successfully! The new screenshots have been committed to this PR. |
Android の ion-list[inset] では divider が背景色と同一なので、 --border-color を item background と同じ値にした。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Ionic のデフォルト形状(bar-height/knob サイズ等)を維持しつつ、 色トークンだけ MD3 を当てるようにした。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
❌ Failed to update screenshots. Please check the workflow run for details. |
|
/update-screenshots |
|
❌ Failed to update screenshots. Please check the workflow run for details. |
ion-range を Ionic 標準形状に戻したため、rtl.spec.ts の 固定ピクセル値 / カスタム transform 期待値を標準形状に合わせた。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
❌ Failed to update screenshots. Please check the workflow run for details. |
getComputedStyle はパーセーセンテージを px に解決するため、 fixture width 200px に対して 50% = 100px を期待するようにした。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
✅ Screenshots have been updated successfully! The new screenshots have been committed to this PR. |
…ples - iOS27 と同じく role: 'preferred' に対応する MD3 スタイルを追加 - alert: filled primary pill - action-sheet: filled primary row - destructive は既存の error 色を維持 - demo に preferred / destructive が両方表示されるようにボタンを更新 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
✅ Screenshots have been updated successfully! The new screenshots have been committed to this PR. |
.alert-wrapper の focus outline が黒い縁取りとして見えていた。 MD3 ダイアログにそのような縁取りは存在しないため outline: none を追加。 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
✅ Screenshots have been updated successfully! The new screenshots have been committed to this PR. |
- destructive / preferred のアイコンが --color を見ており、 テキスト色 (--button-color) だけ変更しても icon に反映されていなかった - --button-color と --color の両方を設定し、アイコンも含めて統一 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
/update-screenshots |
|
✅ Screenshots have been updated successfully! The new screenshots have been committed to this PR. |
|
/update-screenshots |
|
ℹ️ No screenshot changes detected. The current screenshots are already up to date. |
Summary
src/styles/default-variables.scss.--md-sys-*tokens.button-elevated,button-tonal) and shape option (button-square).toolbar-small,toolbar-medium,toolbar-large).card-elevated,card-outlined).Design principles
!important.--token-*aliases kept indefault-variables.scssfor backward compatibility..md3-disabledopt-out and themode="md"boundary.Test plan
npm run buildpassesnpm run lintpassesGenerated with Devin