From 8b1dc1371d1b32d7dded29cc1b64e54dd0410a9e Mon Sep 17 00:00:00 2001 From: rdlabo Date: Wed, 19 Aug 2026 13:18:44 +0900 Subject: [PATCH] docs: split README into package guides with omit markers Move theme guides into docs/ and keep demo/testing notes behind omit comments for GitHub. --- README.md | 230 +++------------------------------ USING_ION_ITEM_GROUP.md | 57 +------- docs/experimental-animation.md | 81 ++++++++++++ docs/features.md | 36 ++++++ docs/ios-18.md | 11 ++ docs/migration.md | 59 +++++++++ docs/using-ion-item-group.md | 56 ++++++++ package.json | 3 +- 8 files changed, 264 insertions(+), 269 deletions(-) create mode 100644 docs/experimental-animation.md create mode 100644 docs/features.md create mode 100644 docs/ios-18.md create mode 100644 docs/migration.md create mode 100644 docs/using-ion-item-group.md diff --git a/README.md b/README.md index 4f383b3b..94fd4591 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,7 @@ A CSS/JS theme library that applies iOS26 design system to Ionic applications. -**Documentation:** [Read the full documentation](https://docs.rdlabo.dev/projects/ionic-theme-ios26) - -![](screenshots/ios26.png) +![iOS 26 themed Ionic screens with Liquid Glass tab bar, lists, and controls](https://raw.githubusercontent.com/rdlabo-dev/ionic-theme-ios26/v2.3.2/screenshots/ios26.png) DEMO is here: https://ionic-theme-ios26.netlify.app/ @@ -16,7 +14,12 @@ I'm also working on the Android Design (Material Design 3) theme. Be sure to cat 👉️[rdlabo-dev/ionic-theme-md3](https://github.com/rdlabo-dev/ionic-theme-md3) -## Setup + +## Quick start + +After [Installation](#installation), import the theme CSS. Details are in Installation below. + +## Installation This is a CSS theme for extending your Ionic project. It does not work on its own, so use it together with the Ionic Framework. @@ -42,7 +45,7 @@ And import the theme in your project's main CSS file (e.g., `src/styles.scss`). /** * If you will use the design of ion-item-group with ion-list on Android as well, import it. - * More info: https://github.com/rdlabo-dev/ionic-theme-ios26/blob/main/USING_ION_ITEM_GROUP.md + * More info: ./docs/using-ion-item-group.md * Note: This is include `@rdlabo/ionic-theme-md3` * @import '@rdlabo/ionic-theme-ios26/dist/css/md-ion-list-inset.css'; */ @@ -88,217 +91,19 @@ createApp(App) }) ``` -## Important Notes - -### Using `ion-item-group` - -Under specific conditions, you need to use `ion-item-group`. - -```diff - - Label -+ - ... - ... -+ - -``` - -For details, please refer to [USING_ION_ITEM_GROUP.md](./USING_ION_ITEM_GROUP.md). - - -## Features - -### CSS Variables - -To customize the library's default styles to match your design, several CSS variables are provided. See this file for details: -https://github.com/rdlabo-dev/ionic-theme-ios26/blob/main/src/styles/default-variables.scss - -### `.ios26-disabled` Class - -Add the `.ios26-disabled` class to disable the iOS26 theme on specific components. - -```html - -iOS26 Design - - -Standard Ionic Design -``` - -### Liquid Glass Mixin - -Import the SCSS files from the main package to use the liquid glass mixin. - -```scss -@use '@rdlabo/ionic-theme-ios26/src/styles/utils/api.scss'; - -ion-textarea label.textarea-wrapper { - @include api.glass-background; -} -``` - -### Additional Design - -To achieve higher fidelity to iOS26 design, you can implement additional design provided by this library. For more details, please visit: - -https://ionic-theme-ios26.netlify.app/main/docs - - -## Experimental Animation - -__This feature is experimental. The library can be used without this feature.__ - - -### Sheet of Glass with `ion-tab-button` / `ion-segment-button` - -By registering `ion-tab-bar` / `ion-segment`, you can display animation effects on `ion-tab-button` / `ion-segment-button` - -[![Image from Gyazo](https://i.gyazo.com/fafd726b520827f042c76b6c73abd81c.gif)](https://gyazo.com/fafd726b520827f042c76b6c73abd81c) - -```js -import { registerTabBarEffect, registerSegmentEffect } from '@rdlabo/ionic-theme-ios26'; - -/** - * Register DOM elements. Effects are applied using Ionic Gesture and Ionic Animation. - */ -const registeredTabBarEffect = registerTabBarEffect(document.querySelector('ion-tab-bar')); -const registeredSegmentEffect = registerSegmentEffect(document.querySelector('ion-segment')); - -const destroy = () => { - /** - * If the registered DOM element is removed (e.g., due to page navigation), - * make sure to destroy the gesture and animation. This will also remove the event listeners. - * You can re-register them if needed. - */ - registeredTabBarEffect?.destroy(); - registeredSegmentEffect?.destroy(); -} -``` - -### TabBarSearchable: Searchable with `ion-tab-bar` and `ion-fab-button` - -Enable Searchable for the DOM structure with the specified markup inner `ion-tabs`. - -[![Image from Gyazo](https://i.gyazo.com/06bc63f4a474f9f19f5b1d865f5c2a85.gif)](https://gyazo.com/06bc63f4a474f9f19f5b1d865f5c2a85) - - -```html -... - - - - - - - - - - - - - - - - -``` - -```ts -import { attachTabBarSearchable, TabBarSearchableFunction, TabBarSearchableType } from '@rdlabo/ionic-theme-ios26'; - -let searchableFun: TabBarSearchableFunction | undefined; -const initialize = () => { - // attachTabBarSearchable has state. You should initialize per page. - searchableFun = attachTabBarSearchable( - document.querySelector('ion-tab-bar'), - document.querySelector('ion-fab-button'), - document.querySelector('ion-footer'), - ); -} - -const present = (event: Event) => { - searchableFun!(event, TabBarSearchableType.Enter); -} - -const dismiss = (event: Event) => { - searchableFun!(event, TabBarSearchableType.Leave); -} -``` +## Documentation -## Additional Information +Start with [Installation](#installation), then [Using ion-item-group](./docs/using-ion-item-group.md) when you use inset lists. -### How to prevent loading a theme file on iOS 18 - -If you want to load a theme file only when the user's device is running iOS 26 (and let users on iOS 18 use the default Ionic iOS theme), you can achieve this by adding a supports-condition to your `import`. - -```css -@import '@rdlabo/ionic-theme-ios26/dist/css/default-variables.css' supports(text-wrap: pretty); -@import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-ios26.css' supports(text-wrap: pretty); -@import '@rdlabo/ionic-theme-ios26/dist/css/md-remove-ios-class-effect.css' supports(text-wrap: pretty); -@import '@rdlabo/ionic-theme-ios26/dist/css/md-ion-list-inset.css' supports(text-wrap: pretty); -``` +- [Using ion-item-group](./docs/using-ion-item-group.md) — required markup for inset lists. +- [Features](./docs/features.md) — CSS variables, `.ios26-disabled`, liquid glass. +- [Experimental Animation](./docs/experimental-animation.md) — tab bar and searchable effects. +- [iOS 18](./docs/ios-18.md) — load the theme only on iOS 26. +- [Migration](./docs/migration.md) — selective component imports and dark mode. - -## Migration Support - -For gradual migration, you can selectively apply the iOS26 theme by importing individual components instead of the full theme file. - -```css -@import '@rdlabo/ionic-theme-ios26/dist/css/utils/translucent'; -@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-action-sheet'; -@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-alert'; -@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-breadcrumbs'; -@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-button'; -... -``` - -### Dark Mode with Individual Components - -When importing individual components with dark mode support, use SCSS instead of CSS. This is because the selectors differ between `Always`, `System`, and `Class` modes. - -> **Note**: Currently, only `ion-button` has separate dark mode styling applied. - -Always (Always Dark Mode): -```scss -@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; - -:root { - @include theme-dark.default-variables; -} -@include theme-dark.ion-button; -@include theme-dark.ion-fab; -@include theme-dark.ion-tabs; -@include theme-dark.ion-segment; -``` - -System (Follow System Settings): -```scss -@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; - -@media (prefers-color-scheme: dark) { - :root { - @include theme-dark.default-variables; - } - @include theme-dark.ion-button; - @include theme-dark.ion-fab; - @include theme-dark.ion-tabs; - @include theme-dark.ion-segment; -} -``` - -Class (Toggle with CSS Class): -```scss -@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; - -.ion-palette-dark { - @include theme-dark.default-variables; - @include theme-dark.ion-button; - @include theme-dark.ion-fab; - @include theme-dark.ion-tabs; - @include theme-dark.ion-segment; -} -``` + +**Full documentation:** [https://docs.rdlabo.dev/projects/ionic-theme-ios26](https://docs.rdlabo.dev/projects/ionic-theme-ios26) ## Development & Testing @@ -333,3 +138,4 @@ npm run test:e2e:debug # Update baseline screenshots (when intentionally changing UI) npm run test:e2e:update ``` + diff --git a/USING_ION_ITEM_GROUP.md b/USING_ION_ITEM_GROUP.md index c21e5449..06272e14 100644 --- a/USING_ION_ITEM_GROUP.md +++ b/USING_ION_ITEM_GROUP.md @@ -1,56 +1 @@ -# Using `ion-item-group` with iOS26 Theme - -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`. - -## When is `ion-item-group` required? - -It is only required when **both** of the following conditions are met: - -- You have enabled the `inset` property on `ion-list` - -Only when these conditions apply, you need to wrap your list items with `ion-item-group`. - -## Implementation Example - -```diff - - Label -+ - ... - ... -+ - -``` - -## Why is this change necessary? - -### Background: Challenges in iOS Design Reproduction - -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**. - -![](screenshots/why-ion-list-inset.png) - -### Solution: Background Color Separation - -To faithfully reproduce iOS design, this theme makes the following changes: - -- Set `ion-list` background color to transparent -- Delegate background color to `ion-item-group` - -This change allows `ion-list-header` to be treated as an independent element, achieving the native iOS appearance. - -## Using the Same Design with Material Design - -If you want to use the same design pattern with Material Design theme, import the following CSS: - -```css -@import '@rdlabo/ionic-theme-ios26/dist/css/md-ion-list-inset.css'; -``` - -This will apply the same `ion-item-group` pattern to the Material Design theme as well. - -## Summary - -- **Most cases**: You can use your existing Ionic code as-is -- **Specific conditions only**: `ion-item-group` is only required when setting using `inset` on `ion-list` -- **Purpose**: To accurately reproduce iOS 26's native design patterns +This guide now lives in [docs/using-ion-item-group.md](./docs/using-ion-item-group.md). diff --git a/docs/experimental-animation.md b/docs/experimental-animation.md new file mode 100644 index 00000000..fa3ea2a1 --- /dev/null +++ b/docs/experimental-animation.md @@ -0,0 +1,81 @@ +Optional gesture and animation helpers. The theme works without this feature. + +**This feature is experimental. The library can be used without this feature.** + +### Sheet of Glass with `ion-tab-button` / `ion-segment-button` + +By registering `ion-tab-bar` / `ion-segment`, you can display animation effects on `ion-tab-button` / `ion-segment-button` + +[![Sheet of Glass animation on ion-tab-button and ion-segment-button](https://i.gyazo.com/fafd726b520827f042c76b6c73abd81c.gif)](https://gyazo.com/fafd726b520827f042c76b6c73abd81c) + +```ts +import { registerTabBarEffect, registerSegmentEffect } from '@rdlabo/ionic-theme-ios26'; + +/** + * Register DOM elements. Effects are applied using Ionic Gesture and Ionic Animation. + */ +const tabBar = document.querySelector('ion-tab-bar'); +const segment = document.querySelector('ion-segment'); +const registeredTabBarEffect = tabBar ? registerTabBarEffect(tabBar) : undefined; +const registeredSegmentEffect = segment ? registerSegmentEffect(segment) : undefined; + +const destroy = () => { + /** + * If the registered DOM element is removed (e.g., due to page navigation), + * make sure to destroy the gesture and animation. This will also remove the event listeners. + * You can re-register them if needed. + */ + registeredTabBarEffect?.destroy(); + registeredSegmentEffect?.destroy(); +}; +``` + +### TabBarSearchable: Searchable with `ion-tab-bar` and `ion-fab-button` + +Enable Searchable for the DOM structure with the specified markup inner `ion-tabs`. + +[![TabBarSearchable animation expanding search from ion-fab-button into the tab bar](https://i.gyazo.com/06bc63f4a474f9f19f5b1d865f5c2a85.gif)](https://gyazo.com/06bc63f4a474f9f19f5b1d865f5c2a85) + +```html +... + + + + + + + + + + + + + + + +``` + +```ts +import { attachTabBarSearchable, TabBarSearchableType } from '@rdlabo/ionic-theme-ios26'; +import type { TabBarSearchableFunction } from '@rdlabo/ionic-theme-ios26'; + +let searchableFun: TabBarSearchableFunction | undefined; +const initialize = () => { + // attachTabBarSearchable has state. You should initialize per page. + const tabBar = document.querySelector('ion-tab-bar'); + const fabButton = document.querySelector('ion-fab-button'); + const footer = document.querySelector('ion-footer'); + if (!tabBar || !fabButton || !footer) { + return; + } + searchableFun = attachTabBarSearchable(tabBar, fabButton, footer); +}; + +const present = (event: Event) => { + searchableFun!(event, TabBarSearchableType.Enter); +}; + +const dismiss = (event: Event) => { + searchableFun!(event, TabBarSearchableType.Leave); +}; +``` diff --git a/docs/features.md b/docs/features.md new file mode 100644 index 00000000..b5baa954 --- /dev/null +++ b/docs/features.md @@ -0,0 +1,36 @@ +CSS variables, opt-out class, and the liquid glass mixin. See [Using ion-item-group](./using-ion-item-group.md) for list markup. + +### CSS Variables + +To customize the library's default styles to match your design, several CSS variables are provided. See this file for details: +https://github.com/rdlabo-dev/ionic-theme-ios26/blob/v2.3.2/src/styles/default-variables.scss + +### `.ios26-disabled` Class + +Add the `.ios26-disabled` class to disable the iOS26 theme on specific components. + +```html + +iOS26 Design + + +Standard Ionic Design +``` + +### Liquid Glass Mixin + +Import the SCSS files from the main package to use the liquid glass mixin. + +```scss +@use '@rdlabo/ionic-theme-ios26/src/styles/utils/api.scss'; + +ion-textarea label.textarea-wrapper { + @include api.glass-background; +} +``` + +### Additional Design + +To achieve higher fidelity to iOS26 design, you can implement additional design provided by this library. For more details, please visit: + +https://ionic-theme-ios26.netlify.app/main/docs diff --git a/docs/ios-18.md b/docs/ios-18.md new file mode 100644 index 00000000..8b4a7fce --- /dev/null +++ b/docs/ios-18.md @@ -0,0 +1,11 @@ +### How to prevent loading a theme file on iOS 18 + +If you want to load a theme file only when the user's device is running iOS 26 (and let users on iOS 18 use the default Ionic iOS theme), you can achieve this by adding a supports-condition to your `import`. + +```css +@import '@rdlabo/ionic-theme-ios26/dist/css/default-variables.css' supports(text-wrap: pretty); +@import '@rdlabo/ionic-theme-ios26/dist/css/ionic-theme-ios26.css' supports(text-wrap: pretty); +@import '@rdlabo/ionic-theme-ios26/dist/css/md-remove-ios-class-effect.css' + supports(text-wrap: pretty); +@import '@rdlabo/ionic-theme-ios26/dist/css/md-ion-list-inset.css' supports(text-wrap: pretty); +``` diff --git a/docs/migration.md b/docs/migration.md new file mode 100644 index 00000000..18ac6c4f --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,59 @@ +For gradual migration, you can selectively apply the iOS26 theme by importing individual components instead of the full theme file. + +```css +@import '@rdlabo/ionic-theme-ios26/dist/css/utils/translucent'; +@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-action-sheet'; +@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-alert'; +@import '@rdlabo/ionic-theme-ios26/dist/css/components/ion-button'; +... +``` + +### Dark Mode with Individual Components + +When importing individual components with dark mode support, use SCSS instead of CSS. This is because the selectors differ between `Always`, `System`, and `Class` modes. + +> **Note**: Currently, only `ion-button` has separate dark mode styling applied. + +Always (Always Dark Mode): + +```scss +@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; + +:root { + @include theme-dark.default-variables; +} +@include theme-dark.ion-button; +@include theme-dark.ion-fab; +@include theme-dark.ion-tabs; +@include theme-dark.ion-segment; +``` + +System (Follow System Settings): + +```scss +@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; + +@media (prefers-color-scheme: dark) { + :root { + @include theme-dark.default-variables; + } + @include theme-dark.ion-button; + @include theme-dark.ion-fab; + @include theme-dark.ion-tabs; + @include theme-dark.ion-segment; +} +``` + +Class (Toggle with CSS Class): + +```scss +@use '@rdlabo/ionic-theme-ios26/src/styles/utils/theme-dark'; + +.ion-palette-dark { + @include theme-dark.default-variables; + @include theme-dark.ion-button; + @include theme-dark.ion-fab; + @include theme-dark.ion-tabs; + @include theme-dark.ion-segment; +} +``` diff --git a/docs/using-ion-item-group.md b/docs/using-ion-item-group.md new file mode 100644 index 00000000..f340eea2 --- /dev/null +++ b/docs/using-ion-item-group.md @@ -0,0 +1,56 @@ +# Using `ion-item-group` with iOS26 Theme + +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`. + +## When is `ion-item-group` required? + +It is only required when the following condition is met: + +- You have enabled the `inset` property on `ion-list` + +Only when this condition applies, you need to wrap your list items with `ion-item-group`. + +## Implementation Example + +```diff + + Label ++ + ... + ... ++ + +``` + +## Why is this change necessary? + +### Background: Challenges in iOS Design Reproduction + +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**. + +![ion-list inset background comparison showing why ion-item-group is required](https://raw.githubusercontent.com/rdlabo-dev/ionic-theme-ios26/v2.3.2/screenshots/why-ion-list-inset.png) + +### Solution: Background Color Separation + +To faithfully reproduce iOS design, this theme makes the following changes: + +- Set `ion-list` background color to transparent +- Delegate background color to `ion-item-group` + +This change allows `ion-list-header` to be treated as an independent element, achieving the native iOS appearance. + +## Using the Same Design with Material Design + +If you want to use the same design pattern with Material Design theme, import the following CSS: + +```css +@import '@rdlabo/ionic-theme-ios26/dist/css/md-ion-list-inset.css'; +``` + +This will apply the same `ion-item-group` pattern to the Material Design theme as well. + +## Summary + +- **Most cases**: You can use your existing Ionic code as-is +- **Specific conditions only**: `ion-item-group` is only required when setting using `inset` on `ion-list` +- **Purpose**: To accurately reproduce iOS 26's native design patterns diff --git a/package.json b/package.json index 1cce83ee..1ef8e270 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "files": [ "dist", "src", - "package.json" + "package.json", + "docs" ], "scripts": { "build": "npm run build:css && npm run build:ts",