@rdlabo/ionic-theme-ios26 0.0.2 → 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.
- package/.cursor/rules/css-compilation.mdc +34 -0
- package/.cursor/rules/demo-application.mdc +39 -0
- package/.cursor/rules/development-workflow.mdc +41 -0
- package/.cursor/rules/project-role.mdc +21 -0
- package/.github/FUNDING.yml +15 -0
- package/.husky/pre-commit +1 -0
- package/.lintstagedrc.yml +6 -0
- package/.prettierignore +3 -0
- package/FEEDBACK.md +25 -0
- package/README.md +58 -87
- package/USING_ION_ITEM_GROUP.md +58 -0
- package/build-sass.js +25 -0
- package/demo/ .cursor/rules/angular-20.mdc +136 -0
- package/demo/.browserslistrc +15 -0
- package/demo/.editorconfig +16 -0
- package/demo/.vscode/extensions.json +5 -0
- package/demo/.vscode/settings.json +3 -0
- package/demo/angular.json +141 -0
- package/demo/capacitor.config.ts +9 -0
- package/demo/eslint.config.js +47 -0
- package/demo/ionic.config.json +7 -0
- package/demo/karma.conf.js +44 -0
- package/demo/package-lock.json +20001 -0
- package/demo/package.json +60 -0
- package/demo/src/app/album/album-page.component.html +24 -0
- package/demo/src/app/album/album-page.component.scss +31 -0
- package/demo/src/app/album/album-page.component.spec.ts +21 -0
- package/demo/src/app/album/album-page.component.ts +24 -0
- package/demo/src/app/app.component.html +3 -0
- package/demo/src/app/app.component.ts +16 -0
- package/demo/src/app/app.config.ts +17 -0
- package/demo/src/app/app.routes.ts +8 -0
- package/demo/src/app/health/health-page.component.html +17 -0
- package/demo/src/app/health/health-page.component.scss +0 -0
- package/demo/src/app/health/health-page.component.spec.ts +21 -0
- package/demo/src/app/health/health-page.component.ts +14 -0
- package/demo/src/app/index/index-page.component.html +41 -0
- package/demo/src/app/index/index-page.component.scss +0 -0
- package/demo/src/app/index/index-page.component.spec.ts +21 -0
- package/demo/src/app/index/index-page.component.ts +102 -0
- package/demo/src/app/index/index.routes.ts +25 -0
- package/demo/src/app/index/pages/action-sheet/action-sheet.page.html +33 -0
- package/demo/src/app/index/pages/action-sheet/action-sheet.page.scss +0 -0
- package/demo/src/app/index/pages/action-sheet/action-sheet.page.spec.ts +17 -0
- package/demo/src/app/index/pages/action-sheet/action-sheet.page.ts +75 -0
- package/demo/src/app/index/pages/action-sheet/action-sheet.util.ts +28 -0
- package/demo/src/app/index/pages/alert/alert.page.html +33 -0
- package/demo/src/app/index/pages/alert/alert.page.scss +0 -0
- package/demo/src/app/index/pages/alert/alert.page.spec.ts +17 -0
- package/demo/src/app/index/pages/alert/alert.page.ts +75 -0
- package/demo/src/app/index/pages/alert/alert.util.ts +21 -0
- package/demo/src/app/index/pages/button/button.page.html +90 -0
- package/demo/src/app/index/pages/button/button.page.scss +0 -0
- package/demo/src/app/index/pages/button/button.page.spec.ts +17 -0
- package/demo/src/app/index/pages/button/button.page.ts +53 -0
- package/demo/src/app/index/pages/checkbox/checkbox.page.html +66 -0
- package/demo/src/app/index/pages/checkbox/checkbox.page.scss +0 -0
- package/demo/src/app/index/pages/checkbox/checkbox.page.spec.ts +17 -0
- package/demo/src/app/index/pages/checkbox/checkbox.page.ts +47 -0
- package/demo/src/app/settings/settings-page.component.html +120 -0
- package/demo/src/app/settings/settings-page.component.scss +33 -0
- package/demo/src/app/settings/settings-page.component.spec.ts +21 -0
- package/demo/src/app/settings/settings-page.component.ts +55 -0
- package/demo/src/app/tabs/tabs.page.html +23 -0
- package/demo/src/app/tabs/tabs.page.scss +9 -0
- package/demo/src/app/tabs/tabs.page.spec.ts +26 -0
- package/demo/src/app/tabs/tabs.page.ts +28 -0
- package/demo/src/app/tabs/tabs.routes.ts +41 -0
- package/demo/src/assets/.gitkeep +0 -0
- package/demo/src/favicon.ico +0 -0
- package/demo/src/global.scss +47 -0
- package/demo/src/index.html +24 -0
- package/demo/src/main.ts +5 -0
- package/demo/src/theme/theme-ios26.scss +25 -0
- package/demo/src/theme/variables.scss +2 -0
- package/demo/tsconfig.app.json +14 -0
- package/demo/tsconfig.json +30 -0
- package/demo/tsconfig.spec.json +17 -0
- package/package.json +38 -11
- package/prettier.config.js +18 -0
- package/screenshots/ios26.png +0 -0
- package/screenshots/why-ion-list-inset.png +0 -0
- package/src/components/ion-action-sheet.scss +42 -0
- package/src/components/ion-alert.scss +31 -0
- package/src/components/ion-button.scss +111 -0
- package/src/components/ion-card.scss +3 -0
- package/src/components/ion-fab.scss +16 -0
- package/src/components/ion-list.scss +33 -0
- package/src/components/ion-modal.scss +6 -0
- package/src/components/ion-popover.scss +21 -0
- package/src/components/ion-searchbar.scss +37 -0
- package/src/components/ion-segment.scss +10 -0
- package/src/components/ion-tabs.scss +47 -0
- package/src/components/ion-toast.scss +3 -0
- package/src/components/ion-toggle.scss +47 -0
- package/src/components-dark/ion-button.scss +28 -0
- package/src/components-dark/theme-dark.scss +14 -0
- package/src/ionic-theme-dark-class.scss +6 -0
- package/src/ionic-theme-dark-system.scss +8 -0
- package/src/ionic-theme-ios26.scss +32 -0
- package/src/md-ion-list-inset.scss +19 -0
- package/src/utils/api.scss +20 -0
- package/src/utils/default-variables.scss +10 -0
- package/src/utils/theme-list-inset.scss +92 -0
- package/src/utils/translucent.scss +70 -0
- package/tsconfig.json +5 -0
- package/css/ion-list-inset.css +0 -247
- package/css/ion-list-inset.css.map +0 -1
- package/css/ionic-theme-ios26.css +0 -349
- package/css/ionic-theme-ios26.css.map +0 -1
- package/fesm2022/rdlabo-ionic-theme-ios26.mjs +0 -4
- package/fesm2022/rdlabo-ionic-theme-ios26.mjs.map +0 -1
- package/index.d.ts +0 -3
- package/src/assets/ion-list-inset.scss +0 -198
- package/src/assets/ios-design/ion-button.scss +0 -68
- package/src/assets/ios-design/ion-popover.scss +0 -23
- package/src/assets/ios-design/ion-searchbar.scss +0 -44
- package/src/assets/ios-design/ion-segment.scss +0 -12
- package/src/assets/ios-design/ion-tabs.scss +0 -60
- package/src/assets/ios-design/ion-toggle.scss +0 -8
- package/src/assets/ios-design/ios-design-dark.scss +0 -28
- package/src/assets/ios-design.scss +0 -110
- 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
|
package/.prettierignore
ADDED
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,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A CSS theme library that applies iOS26 design system to Ionic applications.
|
|
4
4
|
|
|
5
|
+

|
|
6
|
+
|
|
5
7
|
DEMO is here: https://ionic-theme-ios26.netlify.app/
|
|
6
8
|
|
|
7
9
|
## Overview
|
|
@@ -10,130 +12,99 @@ This library provides CSS files to apply the iOS26 design system used in real pr
|
|
|
10
12
|
|
|
11
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.
|
|
12
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)
|
|
13
21
|
|
|
14
22
|
## Setup
|
|
15
23
|
|
|
16
24
|
> **⚠️ Warning**: This library is under development. API changes and breaking changes may occur before full-scale use.
|
|
17
25
|
|
|
18
|
-
### 1. Installation
|
|
19
|
-
|
|
20
26
|
```bash
|
|
21
27
|
npm install @rdlabo/ionic-theme-ios26
|
|
22
28
|
```
|
|
23
29
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
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:
|
|
27
31
|
|
|
28
32
|
```scss
|
|
29
|
-
@import '@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css';
|
|
30
|
-
@import '@rdlabo/ionic-theme-ios26/css/ion-list-inset.css';
|
|
33
|
+
@import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-ios26.min.css';
|
|
31
34
|
|
|
32
|
-
/* Required: Safe area configuration */
|
|
33
35
|
:root {
|
|
34
|
-
|
|
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));
|
|
35
42
|
}
|
|
36
43
|
```
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
### 3. Framework-specific Configuration Examples
|
|
45
|
+
## Important Notes
|
|
41
46
|
|
|
42
|
-
|
|
47
|
+
### Support Dark Mode
|
|
43
48
|
|
|
44
|
-
|
|
49
|
+
We support Ionic Dark Mode. More information is here: https://ionicframework.com/docs/theming/dark-mode
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
```
|
|
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' |
|
|
54
56
|
|
|
55
|
-
|
|
57
|
+
### `ion-back-button` は `ion-buttons` に入れないで使う必要があります
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
:root {
|
|
59
|
-
--max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
|
|
60
|
-
}
|
|
61
|
-
```
|
|
59
|
+
以下の条件を満たす時、Ionic Frameworkは `ion-back-button` をプログラムで生成して、アニメーションで表示します。
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
- 遷移前のページに `ion-header[collapse='condense']` を使用している
|
|
62
|
+
- 遷移後のページに、 `ion-buttons ion-back-button` がある
|
|
64
63
|
|
|
65
|
-
|
|
64
|
+
これはiOS26のUIではなく、このプログラムを避けるために以下の実装を行う必要があります。
|
|
66
65
|
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
|
|
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>
|
|
70
73
|
```
|
|
71
74
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```css
|
|
75
|
-
:root {
|
|
76
|
-
--max-safe-area: calc(max(10px, var(--ion-safe-area-bottom, 0px)) + var(--admob-safe-area, 0px));
|
|
77
|
-
}
|
|
78
|
-
```
|
|
75
|
+
### Using `ion-item-group`
|
|
79
76
|
|
|
80
|
-
|
|
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).
|
|
81
78
|
|
|
82
|
-
|
|
79
|
+
### You can also use the liquid glass mixin
|
|
83
80
|
|
|
84
|
-
|
|
85
|
-
import '@rdlabo/ionic-theme-ios26/css/ionic-theme-ios26.css';
|
|
86
|
-
import '@rdlabo/ionic-theme-ios26/css/ion-list-inset.css';
|
|
87
|
-
```
|
|
81
|
+
You can use the liquid glass mixin by importing SCSS files from the main package.
|
|
88
82
|
|
|
89
|
-
|
|
83
|
+
```scss
|
|
84
|
+
@use '@rdlabo/ionic-theme-ios26/src/utils/api';
|
|
90
85
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
--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;
|
|
94
88
|
}
|
|
95
89
|
```
|
|
96
90
|
|
|
91
|
+
## CSS Utility Classes
|
|
97
92
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
This library is currently in the development and consideration phase. We are working on the following tasks:
|
|
101
|
-
|
|
102
|
-
- [ ] API stabilization
|
|
103
|
-
- [ ] Documentation improvement
|
|
104
|
-
- [ ] Test coverage enhancement
|
|
105
|
-
- [ ] Performance optimization
|
|
106
|
-
- [ ] Community feedback collection
|
|
107
|
-
|
|
108
|
-
## Developer Information
|
|
109
|
-
|
|
110
|
-
### Build
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
ng build ionic-theme-ios26
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### Test
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
ng test
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
## License
|
|
123
|
-
|
|
124
|
-
MIT License
|
|
93
|
+
### .ios26-liquid-glass
|
|
125
94
|
|
|
126
|
-
|
|
95
|
+
Apply this class to components where you want to use the iOS26 design that is not automatically applied. Supported selectors are as follows:
|
|
127
96
|
|
|
128
|
-
|
|
97
|
+
- `ion-button`
|
|
98
|
+
- `ion-buttons.ios26-liquid-glass ion-button`
|
|
99
|
+
- `ion-button.ios26-liquid-glass`
|
|
129
100
|
|
|
130
|
-
-
|
|
131
|
-
- Feature requests
|
|
132
|
-
- Documentation improvements
|
|
133
|
-
- Code review participation
|
|
101
|
+
### .ios26-no-liquid-glass
|
|
134
102
|
|
|
135
|
-
|
|
103
|
+
Many components automatically have the iOS26 design applied, but apply this class when you don't want it. Supported selectors are as follows:
|
|
136
104
|
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
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
|
+

|
|
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
|