Issue number: resolves #29219 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> We got feedback that the current dark theme is a bit jarring when compared with native. In particular, devs are expecting the contrast to be white for many of these colors to match native iOS. Currently, text inside of a primary button is black on dark mode, but devs expect it to be white. Additionally, the dark mode colors appear to be too washed out when compared with their light mode counterparts. The team discussed this and we think we can find a way to make the colors more in line with what devs expect while still allowing for AA color contrast levels. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Adjusted the secondary and danger colors to be slightly more vibrant/inline with what developers expect in mobile apps while still meeting AA color contrast. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer for more information. --> ## Other information I intentionally did not change the contrast color, and I intentionally did not significantly change the vibrancy of each color token. I did some research into how the native platforms handle colors. I'll place this information here, because there are some subtle differences between web and native that make a difference. ### Material Design [Source](https://m2.material.io/design/color/dark-theme.html#ui-application) Material Design 2 calls for desaturated color tokens as well as flipping contrast colors. For example, a vibrant purple background with light text on light mode is a washed purple with dark text on dark mode. The colors in Ionic <=7 did not follow these patterns. The tokens in Ionic 8 now follows these patterns, so what we have in `main` means we are aligning closer with native MD than have in the past.  ### iOS [Source](https://developer.apple.com/design/human-interface-guidelines/accessibility#Color-and-effects) iOS is a bit tricky. On the docs, Apple references the WCAG color contrast formula (what Ionic follows). However, the table they present below is slightly different: | Text Size | Text Weight | Minimum Contrast Ratio | | - | - | - | | Up to 17 points | All | 4.5:1 | | 18 points and larger | All | 3:1 | | All | Bold | 3:1 | The last row is the main difference. WCAG states that text that is bold AND >=14pts (~18.66px) needs to meet a minimum contrast ratio of 3:1. Apple's guidelines state that any text that is bold (regardless of size) needs to meet a minimum contrast ratio of 3:1. In other words, **Apple is using different guidelines to choose colors which is why colored dark mode buttons on iOS typically use white text**. However, Apple is inconsistent in implementing its own guidelines. Consider the following red buttons in the Apple Music app. | Screenshot | Meets Web guidelines | Meets Apple guidelines | Notes | | - | - | - | - | | <img src="https://github.com/ionic-team/ionic-framework/assets/2721089/6bb0e0b3-c29e-4b96-9ad5-e45e59bf0415" width="300" /> | ❌ | ❌ | Text is not bold which makes it not meet either guidelines. | | <img src="https://github.com/ionic-team/ionic-framework/assets/2721089/8ce93b45-0b2b-4160-97a4-19852134684c" width="300" /> | ❌ | ✅ | Text is bold which makes it pass the Apple guidelines, but it's still too small to also pass the Web guidelines. | ### Ionic One of the things I tried is adjusting the base color to work well with white and black backgrounds. It's common to have a blue background with white text (such as a button) AND to have a blue link on a black background (such as an `a` element). This approach does not work well for the shade/tint colors used for hover/focus states. These colors also need to meet Web guidelines. Consider the following example: | Screenshot | Notes | Text/Link passes AA guidelines | Tint passes AA guidelines | | - | - | - | - | |  | This uses the same primary color found in the light palette | ❌ | ✅ | |  | This changes the base color such that the Text/Link passes with a 4.5:1 ratio | ✅ | ❌ | |  | This changes the base color such that the Tint passes with a 4:5:1 ratio | ❌ | ✅ | We also considered adjusting the `a` and `ion-text` colors to use the tint color. We decided against that because it a) felt a little odd given that tint is typically used for states (hover, focus, etc) and b) we were concerned that making this change would impose future restrictions on how this color palette can evolve. ### Conclusion While Ionic's colors don't exactly match the iOS colors, the reality is that we are a web-based tool, so we are going to be evaluated using web-based tools/standards. As a result, it's recommended that we align closer with the Web guidelines than Apple's guidelines. ## Testing Testing: Developers can look at the colors by opening http://localhost:3333/src/themes/test/colors In the video below, the first state is the dark theme in `main`. The second state is the proposed changes. | Visual Comparison | | - | | <video src="https://github.com/ionic-team/ionic-framework/assets/2721089/241fb1b6-212b-4f03-83cd-9558b9a53761"></video> |
@ionic/core
Ionic is an open source App Development Framework that makes it easy to build top quality Native and Progressive Web Apps with web technologies.
The Ionic Core package contains the Web Components that make up the reusable UI building blocks of Ionic Framework. These components are designed to be used in traditional frontend view libraries/frameworks (such as Stencil, React, Angular, or Vue), or on their own through traditional JavaScript in the browser.
Features
- Tiny, highly optimized components built with Stencil
- Styling for both iOS and Material Design
- No build or compiling required
- Simply add the static files to any project
- Lazy-loaded components without configuration
- Asynchronous rendering
- Theming through CSS Variables
How to use
Vanilla HTML
Easiest way to start using Ionic Core is by adding a script tag to the CDN:
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
<link href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" rel="stylesheet">
Any Ionic component added to the webpage will automatically load. This includes writing the component tag directly in HTML, or using JavaScript such as document.createElement('ion-toggle').
Additionally, within this package is a dist/ionic.js file and accompanying dist/ionic/ directory. These are the same files which are used by the CDN, and they're available in this package so they can be apart of an app's local development.
Framework Bindings
The @ionic/core package can be used in simple HTML, or by vanilla JavaScript without any framework at all. Ionic also has packages that make it easier to integrate Ionic into a framework's traditional ecosystem and patterns. (However, at the lowest-level framework bindings are still just using Ionic Core and Web Components).
Custom Elements Build
In addition to the default, self lazy-loading components built by Stencil, this package also comes with each component exported as a stand-alone custom element within @ionic/core/components. Each component extends HTMLElement, and does not lazy-load itself. Instead, this package is useful for projects already using a bundler such as Webpack or Rollup. While all components are available to be imported, the custom elements build also ensures bundlers only import what's used, and tree-shakes any unused components.
Below is an example of importing ion-badge, and initializing Ionic so it is able to correctly load the "mode", such as Material Design or iOS. Additionally, the initialize({...}) function can receive the Ionic config.
import { defineCustomElement } from "@ionic/core/components/ion-badge.js";
import { initialize } from "@ionic/core/components";
// Initializes the Ionic config and `mode` behavior
initialize();
// Defines the `ion-badge` web component
defineCustomElement();
Notice how we import from @ionic/core/components as opposed to @ionic/core. This helps bundlers pull in only the code that is needed.
The defineCustomElement function will automatically define the component as well as any child components that may be required.
For example, if you wanted to use ion-modal, you would do the following:
import { defineCustomElement } from "@ionic/core/components/ion-modal.js";
import { initialize } from "@ionic/core/components";
// Initializes the Ionic config and `mode` behavior
initialize();
// Defines the `ion-modal` and child `ion-backdrop` web components.
defineCustomElement();
The defineCustomElement function will define ion-modal, but it will also define ion-backdrop, which is a component that ion-modal uses internally.
Using Overlay Controllers
When using an overlay controller, developers will need to define the overlay component before it can be used. Below is an example of using modalController:
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';
import { initialize, modalController } from '@ionic/core/components';
initialize();
defineCustomElement();
const showModal = async () => {
const modal = await modalController.create({ ... });
...
}
How to contribute
Check out the CONTRIBUTE guide