@rdlabo/ionic-theme-ios26 0.0.1 → 0.0.3

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.
Files changed (120) hide show
  1. package/.cursor/rules/css-compilation.mdc +34 -0
  2. package/.cursor/rules/demo-application.mdc +39 -0
  3. package/.cursor/rules/development-workflow.mdc +41 -0
  4. package/.cursor/rules/project-role.mdc +21 -0
  5. package/.github/FUNDING.yml +15 -0
  6. package/.husky/pre-commit +1 -0
  7. package/.lintstagedrc.yml +6 -0
  8. package/.prettierignore +3 -0
  9. package/FEEDBACK.md +25 -0
  10. package/README.md +60 -83
  11. package/USING_ION_ITEM_GROUP.md +58 -0
  12. package/build-sass.js +25 -0
  13. package/demo/ .cursor/rules/angular-20.mdc +136 -0
  14. package/demo/.browserslistrc +15 -0
  15. package/demo/.editorconfig +16 -0
  16. package/demo/.vscode/extensions.json +5 -0
  17. package/demo/.vscode/settings.json +3 -0
  18. package/demo/angular.json +141 -0
  19. package/demo/capacitor.config.ts +9 -0
  20. package/demo/eslint.config.js +47 -0
  21. package/demo/ionic.config.json +7 -0
  22. package/demo/karma.conf.js +44 -0
  23. package/demo/package-lock.json +20001 -0
  24. package/demo/package.json +60 -0
  25. package/demo/src/app/album/album-page.component.html +24 -0
  26. package/demo/src/app/album/album-page.component.scss +31 -0
  27. package/demo/src/app/album/album-page.component.spec.ts +21 -0
  28. package/demo/src/app/album/album-page.component.ts +24 -0
  29. package/demo/src/app/app.component.html +3 -0
  30. package/demo/src/app/app.component.ts +16 -0
  31. package/demo/src/app/app.config.ts +17 -0
  32. package/demo/src/app/app.routes.ts +8 -0
  33. package/demo/src/app/health/health-page.component.html +17 -0
  34. package/demo/src/app/health/health-page.component.scss +0 -0
  35. package/demo/src/app/health/health-page.component.spec.ts +21 -0
  36. package/demo/src/app/health/health-page.component.ts +14 -0
  37. package/demo/src/app/index/index-page.component.html +41 -0
  38. package/demo/src/app/index/index-page.component.scss +0 -0
  39. package/demo/src/app/index/index-page.component.spec.ts +21 -0
  40. package/demo/src/app/index/index-page.component.ts +102 -0
  41. package/demo/src/app/index/index.routes.ts +25 -0
  42. package/demo/src/app/index/pages/action-sheet/action-sheet.page.html +33 -0
  43. package/demo/src/app/index/pages/action-sheet/action-sheet.page.scss +0 -0
  44. package/demo/src/app/index/pages/action-sheet/action-sheet.page.spec.ts +17 -0
  45. package/demo/src/app/index/pages/action-sheet/action-sheet.page.ts +75 -0
  46. package/demo/src/app/index/pages/action-sheet/action-sheet.util.ts +28 -0
  47. package/demo/src/app/index/pages/alert/alert.page.html +33 -0
  48. package/demo/src/app/index/pages/alert/alert.page.scss +0 -0
  49. package/demo/src/app/index/pages/alert/alert.page.spec.ts +17 -0
  50. package/demo/src/app/index/pages/alert/alert.page.ts +75 -0
  51. package/demo/src/app/index/pages/alert/alert.util.ts +21 -0
  52. package/demo/src/app/index/pages/button/button.page.html +90 -0
  53. package/demo/src/app/index/pages/button/button.page.scss +0 -0
  54. package/demo/src/app/index/pages/button/button.page.spec.ts +17 -0
  55. package/demo/src/app/index/pages/button/button.page.ts +53 -0
  56. package/demo/src/app/index/pages/checkbox/checkbox.page.html +66 -0
  57. package/demo/src/app/index/pages/checkbox/checkbox.page.scss +0 -0
  58. package/demo/src/app/index/pages/checkbox/checkbox.page.spec.ts +17 -0
  59. package/demo/src/app/index/pages/checkbox/checkbox.page.ts +47 -0
  60. package/demo/src/app/settings/settings-page.component.html +120 -0
  61. package/demo/src/app/settings/settings-page.component.scss +33 -0
  62. package/demo/src/app/settings/settings-page.component.spec.ts +21 -0
  63. package/demo/src/app/settings/settings-page.component.ts +55 -0
  64. package/demo/src/app/tabs/tabs.page.html +23 -0
  65. package/demo/src/app/tabs/tabs.page.scss +9 -0
  66. package/demo/src/app/tabs/tabs.page.spec.ts +26 -0
  67. package/demo/src/app/tabs/tabs.page.ts +28 -0
  68. package/demo/src/app/tabs/tabs.routes.ts +41 -0
  69. package/demo/src/assets/.gitkeep +0 -0
  70. package/demo/src/favicon.ico +0 -0
  71. package/demo/src/global.scss +47 -0
  72. package/demo/src/index.html +24 -0
  73. package/demo/src/main.ts +5 -0
  74. package/demo/src/theme/theme-ios26.scss +25 -0
  75. package/demo/src/theme/variables.scss +2 -0
  76. package/demo/tsconfig.app.json +14 -0
  77. package/demo/tsconfig.json +30 -0
  78. package/demo/tsconfig.spec.json +17 -0
  79. package/package.json +38 -11
  80. package/prettier.config.js +18 -0
  81. package/screenshots/ios26.png +0 -0
  82. package/screenshots/why-ion-list-inset.png +0 -0
  83. package/src/components/ion-action-sheet.scss +42 -0
  84. package/src/components/ion-alert.scss +31 -0
  85. package/src/components/ion-button.scss +111 -0
  86. package/src/components/ion-card.scss +3 -0
  87. package/src/components/ion-fab.scss +16 -0
  88. package/src/components/ion-list.scss +33 -0
  89. package/src/components/ion-modal.scss +6 -0
  90. package/src/components/ion-popover.scss +21 -0
  91. package/src/components/ion-searchbar.scss +37 -0
  92. package/src/components/ion-segment.scss +10 -0
  93. package/src/components/ion-tabs.scss +47 -0
  94. package/src/components/ion-toast.scss +3 -0
  95. package/src/components/ion-toggle.scss +47 -0
  96. package/src/components-dark/ion-button.scss +28 -0
  97. package/src/components-dark/theme-dark.scss +14 -0
  98. package/src/ionic-theme-dark-class.scss +6 -0
  99. package/src/ionic-theme-dark-system.scss +8 -0
  100. package/src/ionic-theme-ios26.scss +32 -0
  101. package/src/md-ion-list-inset.scss +19 -0
  102. package/src/utils/api.scss +20 -0
  103. package/src/utils/default-variables.scss +10 -0
  104. package/src/utils/theme-list-inset.scss +92 -0
  105. package/src/utils/translucent.scss +70 -0
  106. package/tsconfig.json +5 -0
  107. package/css/ionic-theme-ios26.css +0 -422
  108. package/css/ionic-theme-ios26.css.map +0 -1
  109. package/fesm2022/rdlabo-ionic-theme-ios26.mjs +0 -4
  110. package/fesm2022/rdlabo-ionic-theme-ios26.mjs.map +0 -1
  111. package/index.d.ts +0 -3
  112. package/src/assets/ion-button.scss +0 -77
  113. package/src/assets/ion-popover.scss +0 -23
  114. package/src/assets/ion-searchbar.scss +0 -42
  115. package/src/assets/ion-segment.scss +0 -12
  116. package/src/assets/ion-tabs.scss +0 -60
  117. package/src/assets/ios-design-dark.scss +0 -28
  118. package/src/assets/ios-design.scss +0 -131
  119. package/src/assets/ios-talk-room.scss +0 -50
  120. package/src/assets/ios-variables.scss +0 -38
@@ -0,0 +1,34 @@
1
+ ---
2
+ description: SCSS to CSS compilation process and build workflow
3
+ globs: *.scss,*.css,package.json
4
+ ---
5
+
6
+ # CSS Compilation Process
7
+
8
+ ## ビルドプロセス
9
+
10
+ ### ソースファイル
11
+ - **入力**: `src/` ディレクトリ内のSCSSファイル
12
+ - **メインファイル**: [src/ionic-theme-ios26.scss](mdc:src/ionic-theme-ios26.scss)
13
+
14
+ ### 出力ファイル
15
+ - **出力**: `dist/css/` ディレクトリ内のCSSファイル
16
+ - **生成ファイル**:
17
+ - [dist/css/ionic-theme-ios26.min.css](mdc:dist/css/ionic-theme-ios26.min.css): メインCSSファイル(圧縮版)
18
+ - [dist/css/ionic-theme-ios26.min.css.map](mdc:dist/css/ionic-theme-ios26.min.css.map): ソースマップ
19
+ - [dist/css/md-ion-list-inset.min.css](mdc:dist/css/md-ion-list-inset.min.css): インセットリスト専用CSS(圧縮版)
20
+ - [dist/css/md-ion-list-inset.min.css.map](mdc:dist/css/md-ion-list-inset.min.css.map): ソースマップ
21
+
22
+ ## コンパイル時の注意事項
23
+
24
+ 1. **依存関係**: [package.json](mdc:package.json)でビルドツールの依存関係を確認
25
+ 2. **ソースマップ**: 開発時のデバッグ用にソースマップファイルも生成
26
+ 3. **最適化**: 本番用にはCSSの最適化(minify)を検討
27
+ 4. **テスト**: コンパイル後は`demo/`アプリケーションで動作確認
28
+
29
+ ## ファイル構造の一貫性
30
+
31
+ - SCSSファイルは`src/`に配置
32
+ - コンパイル後のCSSファイルは`dist/css/`に配置
33
+ - デモアプリケーションは`demo/`に配置
34
+ - スクリーンショットなどのリソースは`screenshots/`に配置
@@ -0,0 +1,39 @@
1
+ ---
2
+ description: Angular demo application structure and usage
3
+ globs: demo/**/*
4
+ ---
5
+
6
+ # Demo Application (Angular)
7
+
8
+ ## デモアプリケーションの目的
9
+
10
+ `demo/` ディレクトリには、Ionic iOS26テーマの動作確認用のAngularアプリケーションが含まれています。
11
+
12
+ ## 主要なコンポーネント
13
+
14
+ ### ページコンポーネント
15
+ - [album-page.component](mdc:demo/src/app/album/): アルバムページ(リスト表示の確認)
16
+ - [health-page.component](mdc:demo/src/app/health/): ヘルスページ(ヘルス関連UIの確認)
17
+ - [settings-page.component](mdc:demo/src/app/settings/): 設定ページ(設定UIの確認)
18
+ - [simple-page.component](mdc:demo/src/app/simple/): シンプルページ(基本的なコンポーネントの確認)
19
+
20
+ ### ナビゲーション
21
+ - [tabs.page](mdc:demo/src/app/tabs/): タブベースのナビゲーション
22
+
23
+ ## テーマファイル
24
+
25
+ - [demo/src/theme/theme-ios26.scss](mdc:demo/src/theme/theme-ios26.scss): デモアプリ用のテーマ設定
26
+ - [demo/src/global.scss](mdc:demo/src/global.scss): グローバルスタイル
27
+
28
+ ## 使用方法
29
+
30
+ 1. **開発サーバー起動**: `cd demo && npm start` または `ionic serve`
31
+ 2. **テーマ確認**: 各ページでiOS26テーマの適用状況を確認
32
+ 3. **スタイル調整**: `src/` のSCSSファイルを編集後、デモアプリで確認
33
+
34
+ ## 設定ファイル
35
+
36
+ - [demo/angular.json](mdc:demo/angular.json): Angular CLI設定
37
+ - [demo/package.json](mdc:demo/package.json): デモアプリの依存関係
38
+ - [demo/ionic.config.json](mdc:demo/ionic.config.json): Ionic設定
39
+ - [demo/capacitor.config.ts](mdc:demo/capacitor.config.ts): Capacitor設定
@@ -0,0 +1,41 @@
1
+ ---
2
+ description: Development workflow and directory structure guidelines
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Development Workflow
7
+
8
+ ## ディレクトリ構造の詳細
9
+
10
+ ### src/ ディレクトリ
11
+ - **src/components/**: 個別のIonicコンポーネント用のSCSSファイル
12
+ - [ion-button.scss](mdc:src/components/ion-button.scss): ボタンスタイル
13
+ - [ion-list.scss](mdc:src/components/ion-list.scss): リストスタイル
14
+ - [ion-popover.scss](mdc:src/components/ion-popover.scss): ポップオーバースタイル
15
+ - [ion-searchbar.scss](mdc:src/components/ion-searchbar.scss): 検索バースタイル
16
+ - [ion-tabs.scss](mdc:src/components/ion-tabs.scss): タブスタイル
17
+ - [ion-toggle.scss](mdc:src/components/ion-toggle.scss): トグルスタイル
18
+
19
+ - **src/utils/**: ユーティリティファイル
20
+ - [api.scss](mdc:src/utils/api.scss): API関連ユーティリティ
21
+ - [theme-dark.scss](mdc:src/utils/theme-dark.scss): ダークテーマ用ユーティリティ
22
+ - [theme-list-inset.scss](mdc:src/utils/theme-list-inset.scss): インセットリスト用ユーティリティ
23
+ - [translucent.scss](mdc:src/utils/translucent.scss): 半透明効果用ユーティリティ
24
+
25
+ - **src/**: ルートレベルのファイル
26
+ - [default-variables.scss](mdc:src/default-variables.scss): デフォルト変数定義
27
+ - [md-ion-list-inset.scss](mdc:src/md-ion-list-inset.scss): Material Design用インセットリスト
28
+
29
+ - **src/ionic-theme-ios26.scss**: メインのSCSSファイル(全てのコンポーネントを統合)
30
+
31
+ ### demo/ ディレクトリ
32
+ - Angular 20ベースのデモアプリケーション
33
+ - 各ページコンポーネントでテーマの動作確認
34
+ - [demo/src/theme/theme-ios26.scss](mdc:demo/src/theme/theme-ios26.scss): デモアプリ用テーマファイル
35
+
36
+ ## 開発時の注意事項
37
+
38
+ 1. **SCSSファイルの編集**: `src/` ディレクトリ内のSCSSファイルを編集
39
+ 2. **コンパイル**: 変更後は適切なビルドコマンドでCSSファイルを生成
40
+ 3. **確認**: `demo/` アプリケーションでスタイルの動作確認
41
+ 4. **ドキュメント**: READMEは英語で記述(OSS配布のため)
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Ionic iOS26 Theme Library Project Overview
3
+ alwaysApply: true
4
+ ---
5
+
6
+ # Ionic iOS26 Theme Library Project
7
+
8
+ このプロジェクトは、Ionic FrameworkをiOS26のルックアンドフィールにするためのCSSライブラリです。OSSで配布するため、READMEの記述は基本的に英語になります。
9
+
10
+ ## プロジェクト構造
11
+
12
+ - **src/**: コンパイル前のSCSSファイルが配置されます
13
+ - **css/**: コンパイル後のCSSファイルが配置されます
14
+ - **demo/**: 開発と確認に用いるAngularプロジェクトです
15
+
16
+ ## 主要なファイル
17
+
18
+ - [package.json](mdc:package.json): プロジェクトの依存関係とビルドスクリプト
19
+ - [src/ionic-theme-ios26.scss](mdc:src/ionic-theme-ios26.scss): メインのSCSSファイル
20
+ - [demo/](mdc:demo/): Angularデモアプリケーション
21
+ - [README.md](mdc:README.md): プロジェクトの説明(英語)
@@ -0,0 +1,15 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: rdlabo
4
+ patreon: # Replace with a single Patreon username
5
+ open_collective: # Replace with a single Open Collective username
6
+ ko_fi: # Replace with a single Ko-fi username
7
+ tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8
+ community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9
+ liberapay: # Replace with a single Liberapay username
10
+ issuehunt: # Replace with a single IssueHunt username
11
+ lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
12
+ polar: # Replace with a single Polar username
13
+ buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
14
+ thanks_dev: # Replace with a single thanks.dev username
15
+ custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
@@ -0,0 +1 @@
1
+ npx lint-staged
@@ -0,0 +1,6 @@
1
+ "*.ts":
2
+ - prettier --parser typescript --write
3
+ "*.html":
4
+ - prettier --parser angular --write
5
+ "*.scss":
6
+ - prettier --parser scss --write
@@ -0,0 +1,3 @@
1
+ node_modules
2
+ dist
3
+ www
package/FEEDBACK.md ADDED
@@ -0,0 +1,25 @@
1
+ ## feat(): ion-config new property for disable ion-back-button Animation
2
+
3
+ 遷移前画面で `collapse` を使っており、遷移後画面で `ion-buttons ion-back-button` を指定している場合、iOS18以前のアニメーション処理が行われます。これは、iOS26以降では不要なので、無効化できるプロパティが必要です。
4
+
5
+ https://github.com/ionic-team/ionic-framework/blob/3b80473f2fd5ad4da5a9f5d66f783a69909c8965/core/src/utils/transition/ios.transition.ts#L333C31-L337
6
+ - enteringBackButtonTextAnimation
7
+ - enteringBackButtonIconAnimation
8
+ - enteringBackButtonAnimation
9
+
10
+ 現在、 `ion-buttons > ion-back-button` をセレクタする関係上、 `ion-back-button` を `ion-buttons` の中にいれない対応をとっています。。
11
+
12
+ # feat(): ion-content[fullscreen=true] will have .content-fullscreen class
13
+
14
+ iOS26の上下セーフエリアのぼかしを入れるため、ion-contentがfullscreen設定されているかのclassが必要です。
15
+ 以下のようなセレクターの指定を行いたいです。
16
+
17
+ ```css
18
+ .ion-page:has(ion-header.header-translucent) ion-content.content-fullscreen {
19
+ }
20
+
21
+ .ion-page:has(ion-header.footer-translucent) ion-content.content-fullscreen {
22
+ }
23
+ ```
24
+
25
+ 現在、 `translucent` な要素を使っている場合はfullscreenを指定している前提で実装していますが、これは確実ではありません。
package/README.md CHANGED
@@ -2,132 +2,109 @@
2
2
 
3
3
  A CSS theme library that applies iOS26 design system to Ionic applications.
4
4
 
5
+ ![](screenshots/ios26.png)
6
+
7
+ DEMO is here: https://ionic-theme-ios26.netlify.app/
8
+
5
9
  ## Overview
6
10
 
7
11
  This library provides CSS files to apply the iOS26 design system used in real projects to Ionic applications. It customizes the appearance and behavior of Ionic components based on the latest iOS26 design guidelines.
8
12
 
9
13
  > **⚠️ Under Development**: This library is currently in the development and consideration phase as an OSS project, based on files copied from real projects. We are working on API stability and documentation improvement before full-scale use.
10
14
 
15
+ ## 💖 Support This Project
16
+
17
+ Enjoying this project? Your support helps keep it alive and growing!
18
+ Sponsoring means you directly contribute to new features, improvements, and maintenance.
19
+
20
+ [Become a Sponsor →](https://github.com/sponsors/rdlabo)
11
21
 
12
22
  ## Setup
13
23
 
14
24
  > **⚠️ Warning**: This library is under development. API changes and breaking changes may occur before full-scale use.
15
25
 
16
- ### 1. Installation
17
-
18
26
  ```bash
19
27
  npm install @rdlabo/ionic-theme-ios26
20
28
  ```
21
29
 
22
- ### 2. CSS File Import (Required)
23
-
24
- Import the theme in your project's main CSS file (e.g., `src/styles.scss`) and set the `--max-safe-area` variable:
30
+ And import the theme in your project's main CSS file (e.g., `src/styles.scss`) and set the `--ios26-floating-safe-area-bottom` variable:
25
31
 
26
32
  ```scss
27
- @import '@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css';
33
+ @import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-ios26.min.css';
28
34
 
29
- /* Required: Safe area configuration */
30
35
  :root {
31
- --max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
36
+ /*
37
+ * This is default value. If you should change value, update this variable.
38
+ * ex) Using admob banner ad.
39
+ * --ios26-floating-safe-area-bottom: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
40
+ */
41
+ --ios26-floating-safe-area-bottom: max(10px, var(--ion-safe-area-bottom, 0px));
32
42
  }
33
43
  ```
34
44
 
35
- > **Important**: The theme will not work correctly without the `--max-safe-area` setting. This configuration is mandatory.
45
+ ## Important Notes
36
46
 
37
- ### 3. Framework-specific Configuration Examples
47
+ ### Support Dark Mode
38
48
 
39
- #### For Angular Projects
49
+ We support Ionic Dark Mode. More information is here: https://ionicframework.com/docs/theming/dark-mode
40
50
 
41
- Add CSS file to `angular.json`:
51
+ | Mode | Code |
52
+ |-----------|------------------------------------------------------------------------------|
53
+ | Always | Overwrite library colors on the :root selector. |
54
+ | System | @import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-dark-system.min.css' |
55
+ | CSS Class | @import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-dark-class.min.css' |
42
56
 
43
- ```json
44
- {
45
- "styles": [
46
- "node_modules/@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css"
47
- ]
48
- }
49
- ```
57
+ ### `ion-back-button` は `ion-buttons` に入れないで使う必要があります
50
58
 
51
- **Required**: Set `--max-safe-area` in `src/styles.scss`:
59
+ 以下の条件を満たす時、Ionic Frameworkは `ion-back-button` をプログラムで生成して、アニメーションで表示します。
52
60
 
53
- ```scss
54
- :root {
55
- --max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
56
- }
57
- ```
58
-
59
- #### For React Projects
61
+ - 遷移前のページに `ion-header[collapse='condense']` を使用している
62
+ - 遷移後のページに、 `ion-buttons ion-back-button` がある
60
63
 
61
- Import CSS file in `index.js` or `App.js`:
64
+ これはiOS26のUIではなく、このプログラムを避けるために以下の実装を行う必要があります。
62
65
 
63
- ```javascript
64
- import '@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css';
66
+ ```diff
67
+ <ion-header>
68
+ - <ion-buttons slot="start">
69
+ - <ion-back-button></ion-back-button>
70
+ - </ion-buttons>
71
+ + <ion-back-button slot=start></ion-back-button>
72
+ </ion-header>
65
73
  ```
66
74
 
67
- **Required**: Set `--max-safe-area` in main CSS file:
75
+ ### Using `ion-item-group`
68
76
 
69
- ```css
70
- :root {
71
- --max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
72
- }
73
- ```
77
+ Under specific conditions, you need to use `ion-item-group`. For details, please refer to [USING_ION_ITEM_GROUP.md](./USING_ION_ITEM_GROUP.md).
74
78
 
75
- #### For Vue.js Projects
79
+ ### You can also use the liquid glass mixin
76
80
 
77
- Import CSS file in `main.js`:
81
+ You can use the liquid glass mixin by importing SCSS files from the main package.
78
82
 
79
- ```javascript
80
- import '@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css';
81
- ```
82
-
83
- **Required**: Set `--max-safe-area` in main CSS file:
83
+ ```scss
84
+ @use '@rdlabo/ionic-theme-ios26/src/utils/api';
84
85
 
85
- ```css
86
- :root {
87
- --max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
86
+ ion-textarea label.textarea-wrapper {
87
+ @include api.glass-background;
88
88
  }
89
89
  ```
90
90
 
91
+ ## CSS Utility Classes
91
92
 
92
- ## Development Status
93
-
94
- This library is currently in the development and consideration phase. We are working on the following tasks:
95
-
96
- - [ ] API stabilization
97
- - [ ] Documentation improvement
98
- - [ ] Test coverage enhancement
99
- - [ ] Performance optimization
100
- - [ ] Community feedback collection
101
-
102
- ## Developer Information
103
-
104
- ### Build
105
-
106
- ```bash
107
- ng build ionic-theme-ios26
108
- ```
109
-
110
- ### Test
111
-
112
- ```bash
113
- ng test
114
- ```
115
-
116
- ## License
117
-
118
- MIT License
93
+ ### .ios26-liquid-glass
119
94
 
120
- ## Contributing
95
+ Apply this class to components where you want to use the iOS26 design that is not automatically applied. Supported selectors are as follows:
121
96
 
122
- This project is under development. We welcome feedback and suggestions:
97
+ - `ion-button`
98
+ - `ion-buttons.ios26-liquid-glass ion-button`
99
+ - `ion-button.ios26-liquid-glass`
123
100
 
124
- - Issue reporting
125
- - Feature requests
126
- - Documentation improvements
127
- - Code review participation
101
+ ### .ios26-no-liquid-glass
128
102
 
129
- ## Support
103
+ Many components automatically have the iOS26 design applied, but apply this class when you don't want it. Supported selectors are as follows:
130
104
 
131
- - **Under Development**: No formal support is provided
132
- - **Feedback**: Please report issues on GitHub Issues page
133
- - **Community**: Participate in developer community discussions
105
+ - `ion-button`
106
+ - `ion-header > ion-toolbar > ion-buttons.ios26-no-liquid-glass > ion-button`
107
+ - `ion-header > ion-toolbar > ion-buttons.ios26-no-liquid-glass > ion-back-button`
108
+ - `ion-header > ion-toolbar > ion-buttons > ion-button.ios26-no-liquid-glass`
109
+ - `ion-header > ion-toolbar > ion-buttons > ion-back-button.ios26-no-liquid-glass`
110
+ - `ion-popover.ios26-no-liquid-glass`
@@ -0,0 +1,58 @@
1
+ # Using `ion-item-group` with iOS26 Theme
2
+
3
+ This theme aims to bring Ionic Framework applications as close as possible to iOS 26 design. In most cases, you can use your existing Ionic code as-is, but **only under specific conditions**, you need to add `ion-item-group`.
4
+
5
+ ## When is `ion-item-group` required?
6
+
7
+ It is only required when **both** of the following conditions are met:
8
+
9
+ - You have enabled the `inset` property on `ion-list`
10
+
11
+ Only when these conditions apply, you need to wrap your list items with `ion-item-group`.
12
+
13
+ ## Implementation Example
14
+
15
+ ```diff
16
+ <ion-content color="light">
17
+ <ion-list inset=true>
18
+ <ion-list-header><ion-label>Label</ion-label></ion-list-header>
19
+ + <ion-item-group>
20
+ <ion-item>...</ion-item>
21
+ <ion-item>...</ion-item>
22
+ + </ion-item-group>
23
+ </ion-list>
24
+ </ion-content>
25
+ ```
26
+
27
+ ## Why is this change necessary?
28
+
29
+ ### Background: Challenges in iOS Design Reproduction
30
+
31
+ By default in Ionic Framework, `ion-list` has a background color, and `ion-list-header` is treated as part of the list. However, with this structure, it's impossible to accurately reproduce **iOS's native design patterns**.
32
+
33
+ ![](screenshots/why-ion-list-inset.png)
34
+
35
+ ### Solution: Background Color Separation
36
+
37
+ To faithfully reproduce iOS design, this theme makes the following changes:
38
+
39
+ - Set `ion-list` background color to transparent
40
+ - Delegate background color to `ion-item-group`
41
+
42
+ This change allows `ion-list-header` to be treated as an independent element, achieving the native iOS appearance.
43
+
44
+ ## Using the Same Design with Material Design
45
+
46
+ If you want to use the same design pattern with Material Design theme, import the following CSS:
47
+
48
+ ```css
49
+ @import '@rdlabo/ionic-theme-ios26/css/md-ion-list-inset.css';
50
+ ```
51
+
52
+ This will apply the same `ion-item-group` pattern to the Material Design theme as well.
53
+
54
+ ## Summary
55
+
56
+ - **Most cases**: You can use your existing Ionic code as-is
57
+ - **Specific conditions only**: `ion-item-group` is only required when setting using `inset` on `ion-list`
58
+ - **Purpose**: To accurately reproduce iOS 26's native design patterns
package/build-sass.js ADDED
@@ -0,0 +1,25 @@
1
+ const { execSync } = require('child_process');
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+
5
+ const srcDir = path.resolve(__dirname, 'src');
6
+ const outDir = path.resolve(__dirname, 'dist/css');
7
+
8
+ // 出力先ディレクトリがなければ作る
9
+ if (!fs.existsSync(outDir)) {
10
+ fs.mkdirSync(outDir, { recursive: true });
11
+ }
12
+
13
+ // src ディレクトリの .scss ファイルを取得
14
+ const scssFiles = fs.readdirSync(srcDir).filter(f => f.endsWith('.scss'));
15
+
16
+ scssFiles.forEach(file => {
17
+ const srcPath = path.join(srcDir, file);
18
+ const fileName = path.basename(file, '.scss');
19
+ const outPath = path.join(outDir, `${fileName}.min.css`);
20
+
21
+ console.log(`Building ${srcPath} → ${outPath}`);
22
+ execSync(`npx sass ${srcPath} ${outPath} --style=compressed`, { stdio: 'inherit' });
23
+ });
24
+
25
+ console.log('All SCSS files compiled successfully!');
@@ -0,0 +1,136 @@
1
+ ---
2
+ description: This rule provides comprehensive best practices and coding standards for Angular development, focusing on modern TypeScript, standalone components, signals, and performance optimizations.
3
+ globs: ["**/*.{ts,html,scss,css}"]
4
+ ---
5
+
6
+ # Angular Best Practices
7
+
8
+ This project adheres to modern Angular best practices, emphasizing maintainability, performance, accessibility, and scalability.
9
+
10
+ ## TypeScript Best Practices
11
+
12
+ * **Strict Type Checking:** Always enable and adhere to strict type checking. This helps catch errors early and improves code quality.
13
+ * **Prefer Type Inference:** Allow TypeScript to infer types when they are obvious from the context. This reduces verbosity while maintaining type safety.
14
+ * **Bad:**
15
+ ```typescript
16
+ let name: string = 'Angular';
17
+ ```
18
+ * **Good:**
19
+ ```typescript
20
+ let name = 'Angular';
21
+ ```
22
+ * **Avoid `any`:** Do not use the `any` type unless absolutely necessary as it bypasses type checking. Prefer `unknown` when a type is uncertain and you need to handle it safely.
23
+
24
+ ## Angular Best Practices
25
+
26
+ * **Standalone Components:** Always use standalone components, directives, and pipes. Avoid using `NgModules` for new features or refactoring existing ones.
27
+ * **Implicit Standalone:** When creating standalone components, you do not need to explicitly set `standalone: true` inside the `@Component`, `@Directive` and `@Pipe` decorators, as it is implied by default.
28
+ * **Bad:**
29
+ ```typescript
30
+ @Component({
31
+ standalone: true,
32
+ // ...
33
+ })
34
+ export class MyComponent {}
35
+ ```
36
+ * **Good:**
37
+ ```typescript
38
+ @Component({
39
+ // `standalone: true` is implied
40
+ // ...
41
+ })
42
+ export class MyComponent {}
43
+ ```
44
+ * **Signals for State Management:** Utilize Angular Signals for reactive state management within components and services.
45
+ * **Lazy Loading:** Implement lazy loading for feature routes to improve initial load times of your application.
46
+ * **NgOptimizedImage:** Use `NgOptimizedImage` for all static images to automatically optimize image loading and performance.
47
+ * **Host bindings:** Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead.
48
+
49
+ ## Components
50
+
51
+ * **Single Responsibility:** Keep components small, focused, and responsible for a single piece of functionality.
52
+ * **`input()` and `output()` Functions:** Prefer `input()` and `output()` functions over the `@Input()` and `@Output()` decorators for defining component inputs and outputs.
53
+ * **Old Decorator Syntax:**
54
+ ```typescript
55
+ @Input() userId!: string;
56
+ @Output() userSelected = new EventEmitter<string>();
57
+ ```
58
+ * **New Function Syntax:**
59
+ ```typescript
60
+ import { input, output } from '@angular/core';
61
+
62
+ // ...
63
+ userId = input<string>('');
64
+ userSelected = output<string>();
65
+ ```
66
+ * **`computed()` for Derived State:** Use the `computed()` function from `@angular/core` for derived state based on signals.
67
+ * **`ChangeDetectionStrategy.OnPush`:** Always set `changeDetection: ChangeDetectionStrategy.OnPush` in the `@Component` decorator for performance benefits by reducing unnecessary change detection cycles.
68
+ * **Inline Templates:** Prefer inline templates (template: `...`) for small components to keep related code together. For larger templates, use external HTML files.
69
+ * **Reactive Forms:** Prefer Reactive forms over Template-driven forms for complex forms, validation, and dynamic controls due to their explicit, immutable, and synchronous nature.
70
+ * **No `ngClass` / `NgClass`:** Do not use the `ngClass` directive. Instead, use native `class` bindings for conditional styling.
71
+ * **Bad:**
72
+ ```html
73
+ <section [ngClass]="{'active': isActive}"></section>
74
+ ```
75
+ * **Good:**
76
+ ```html
77
+ <section [class.active]="isActive"></section>
78
+ <section [class]="{'active': isActive}"></section>
79
+ <section [class]="myClasses"></section>
80
+ ```
81
+ * **No `ngStyle` / `NgStyle`:** Do not use the `ngStyle` directive. Instead, use native `style` bindings for conditional inline styles.
82
+ * **Bad:**
83
+ ```html
84
+ <section [ngStyle]="{'font-size': fontSize + 'px'}"></section>
85
+ ```
86
+ * **Good:**
87
+ ```html
88
+ <section [style.font-size.px]="fontSize"></section>
89
+ <section [style]="myStyles"></section>
90
+ ```
91
+
92
+ ## State Management
93
+
94
+ * **Signals for Local State:** Use signals for managing local component state.
95
+ * **`computed()` for Derived State:** Leverage `computed()` for any state that can be derived from other signals.
96
+ * **Pure and Predictable Transformations:** Ensure state transformations are pure functions (no side effects) and predictable.
97
+ * **Signal value updates:** Do NOT use `mutate` on signals, use `update` or `set` instead.
98
+
99
+ ## Templates
100
+
101
+ * **Simple Templates:** Keep templates as simple as possible, avoiding complex logic directly in the template. Delegate complex logic to the component's TypeScript code.
102
+ * **Native Control Flow:** Use the new built-in control flow syntax (`@if`, `@for`, `@switch`) instead of the older structural directives (`*ngIf`, `*ngFor`, `*ngSwitch`).
103
+ * **Old Syntax:**
104
+ ```html
105
+ <section *ngIf="isVisible">Content</section>
106
+ <section *ngFor="let item of items">{{ item }}</section>
107
+ ```
108
+ * **New Syntax:**
109
+ ```html
110
+ @if (isVisible) {
111
+ <section>Content</section>
112
+ }
113
+ @for (item of items; track item.id) {
114
+ <section>{{ item }}</section>
115
+ }
116
+ ```
117
+ * **Async Pipe:** Use the `async` pipe to handle observables in templates. This automatically subscribes and unsubscribes, preventing memory leaks.
118
+
119
+ ## Services
120
+
121
+ * **Single Responsibility:** Design services around a single, well-defined responsibility.
122
+ * **`providedIn: 'root'`:** Use the `providedIn: 'root'` option when declaring injectable services to ensure they are singletons and tree-shakable.
123
+ * **`inject()` Function:** Prefer the `inject()` function over constructor injection when injecting dependencies, especially within `provide` functions, `computed` properties, or outside of constructor context.
124
+ * **Old Constructor Injection:**
125
+ ```typescript
126
+ constructor(private myService: MyService) {}
127
+ ```
128
+ * **New `inject()` Function:**
129
+ ```typescript
130
+ import { inject } from '@angular/core';
131
+
132
+ export class MyComponent {
133
+ private myService = inject(MyService);
134
+ // ...
135
+ }
136
+ ```
@@ -0,0 +1,15 @@
1
+ # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2
+ # For additional information regarding the format and rule options, please see:
3
+ # https://github.com/browserslist/browserslist#queries
4
+
5
+ # For the full list of supported browsers by the Angular framework, please see:
6
+ # https://angular.dev/reference/versions#browser-support
7
+
8
+ # You can see what browsers were selected by your queries by running:
9
+ # npx browserslist
10
+
11
+ Chrome >=107
12
+ Firefox >=106
13
+ Edge >=107
14
+ Safari >=16.1
15
+ iOS >=16.1
@@ -0,0 +1,16 @@
1
+ # Editor configuration, see https://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ charset = utf-8
6
+ indent_style = space
7
+ indent_size = 2
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.ts]
12
+ quote_type = single
13
+
14
+ [*.md]
15
+ max_line_length = off
16
+ trim_trailing_whitespace = false
@@ -0,0 +1,5 @@
1
+ {
2
+ "recommendations": [
3
+ "Webnative.webnative"
4
+ ]
5
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "typescript.preferences.autoImportFileExcludePatterns": ["@ionic/angular/common", "@ionic/angular"]
3
+ }