SIGN IN SIGN UP

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.

52430 0 1 TypeScript
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
# Ionic Component Implementation Guide
- [Button States](#button-states)
* [Component Structure](#component-structure)
* [Disabled](#disabled)
* [Focused](#focused)
* [Hover](#hover)
* [Activated](#activated)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
* [Ripple Effect](#ripple-effect)
* [Example Components](#example-components)
* [References](#references)
- [Accessibility](#accessibility)
* [Checkbox](#checkbox)
* [Switch](#switch)
* [Accordion](#accordion)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
- [Rendering Anchor or Button](#rendering-anchor-or-button)
* [Example Components](#example-components-4)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
* [Component Structure](#component-structure-1)
- [Converting Scoped to Shadow](#converting-scoped-to-shadow)
- [RTL](#rtl)
feat: add ionic theme architecture (#29132) Issue number: Internal --------- <!-- 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. --> ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> Adds the base architecture to add a new theme configuration to Ionic Framework components. - Components can now specify an additional stylesheet for the `ionic` theme. - Developers can specify the `theme` and `mode` independently to control look and feel of a component. Test infrastructure has been updated to add support for testing the theme configuration with Playwright. - Existing `themes` test configuration has been renamed to `palettes` This PR is just the initial effort to decouple Ionic's architecture to separate look and feel and allow our dev team to start introducing the new component appearance to the UI. There will be additional changes required to completely add support for the Ionic theme. These changes are targeted against the `next` branch and are not expected to be used in a production environment at this time. ## 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 <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com> Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
2024-03-18 15:45:01 -04:00
- [Themes vs. Modes](#themes-vs-modes)
- [Adding New Components with Native Input Support](#adding-new-components-with-native-input-support)
* [Angular Integration](#angular-integration)
* [Angular Tests](#angular-tests)
* [Vue Integration](#vue-integration)
* [Vue Tests](#vue-tests)
* [React Integration](#react-integration)
* [React Tests](#react-tests)
* [Interface Exports](#interface-exports)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
## Button States
Any component that renders a button should have the following states: [`disabled`](#disabled), [`focused`](#focused), [`hover`](#hover), [`activated`](#activated). It should also have a [Ripple Effect](#ripple-effect) component added for Material Design.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
### Component Structure
#### JavaScript
A component that renders a native button should use the following structure:
```jsx
<Host>
<button class="button-native">
<span class="button-inner">
<slot></slot>
</span>
</button>
</Host>
```
Any other attributes and classes that are included are irrelevant to the button states, but it's important that this structure is followed and the classes above exist. In some cases they may be named something else that makes more sense, such as in item.
#### CSS
A mixin called `button-state()` has been added to make it easier to setup the states in each component.
```scss
@mixin button-state() {
@include position(0, 0, 0, 0);
position: absolute;
content: "";
opacity: 0;
}
```
The following styles should be set for the CSS to work properly. Note that the `button-state()` mixin is included in the `::after` pseudo element of the native button.
```scss
.button-native {
/**
* All other CSS in this selector is irrelevant to button states
* but the following are required styles
*/
position: relative;
overflow: hidden;
}
.button-native::after {
@include button-state();
}
.button-inner {
/**
* All other CSS in this selector is irrelevant to button states
* but the following are required styles
*/
position: relative;
z-index: 1;
}
```
### Disabled
The disabled state should be set via prop on all components that render a native button. Setting a disabled state will change the opacity or color of the button and remove click events from firing.
#### JavaScript
The `disabled` property should be set on the component:
```jsx
/**
* If `true`, the user cannot interact with the button.
*/
@Prop({ reflectToAttr: true }) disabled = false;
```
Then, the render function should add the [`aria-disabled`](https://www.w3.org/WAI/PF/aria/states_and_properties#aria-disabled) role to the host, a class that is the element tag name followed by `disabled`, and pass the `disabled` attribute to the native button:
```jsx
render() {
const { disabled } = this;
return (
<Host
aria-disabled={disabled ? 'true' : null}
class={{
'button-disabled': disabled
}}
>
<button disabled={disabled}>
<slot></slot>
</button>
</Host>
);
}
```
> [!NOTE]
> If the class being added was for `ion-back-button` it would be `back-button-disabled`.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
#### CSS
The following CSS _at the bare minimum_ should be added for the disabled class, but it should be styled to match the spec:
```css
:host(.button-disabled) {
cursor: default;
opacity: .5;
pointer-events: none;
}
```
#### User Customization
TODO
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
### Focused
The focused state should be enabled for elements with actions when tabbed to via the keyboard. This will only work inside of an `ion-app`. It usually changes the opacity or background of an element.
> [!WARNING]
> Do not use `:focus` because that will cause the focus to apply even when an element is tapped (because the element is now focused). Instead, we only want the focus state to be shown when it makes sense which is what the `.ion-focusable` utility mentioned below does.
> [!IMPORTANT]
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
> Make sure the component has the correct [component structure](#component-structure) before continuing.
#### JavaScript
The `ion-focusable` class needs to be set on an element that can be focused:
```jsx
render() {
return (
<Host class="ion-focusable">
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
<slot></slot>
</Host>
);
}
```
Once that is done, the element will get the `ion-focused` class added when the element is tabbed to.
#### CSS
Components should be written to include the following focused variables for styling:
```css
/**
* @prop --color-focused: Color of the button when tabbed to with the keyboard
* @prop --background-focused: Background of the button when tabbed to with the keyboard
* @prop --background-focused-opacity: Opacity of the background when tabbed to with the keyboard
*/
```
Style the `ion-focused` class based on the spec for that element:
```scss
:host(.ion-focused) .button-native {
color: var(--color-focused);
&::after {
background: var(--background-focused);
opacity: var(--background-focused-opacity);
}
}
```
> [!IMPORTANT]
> Order matters! Focused should be **before** the activated and hover states.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
#### User Customization
Setting the focused state on the `::after` pseudo-element allows the user to customize the focused state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on focus, or they can leave out `--background-focused-opacity` and the button will use the default focus opacity to match the spec.
```css
ion-button {
--background-focused: red;
--background-focused-opacity: 1;
}
```
#### When to use `.ion-focusable` versus `:focus-visible`
The [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible) pseudo-class mostly does the same thing as our JavaScript-driven utility. However, it does not work well with Shadow DOM components as the element that receives focus is typically inside of the Shadow DOM, but we usually want to set the `:focus-visible` state on the host so we can style other parts of the component.
Using other combinations such as `:has(:focus-visible)` does not work because `:has` does not pierce the Shadow DOM (as that would leak implementation details about the Shadow DOM contents). `:focus-within` does work with the Shadow DOM, but that has the same problem as `:focus` that was mentioned before. Unfortunately, a [`:focus-visible-within` pseudo-class does not exist yet](https://github.com/WICG/focus-visible/issues/151).
The `.ion-focusable` class should be used when you want to style Element A based on the state of Element B. For example, the Button component styles the host of the component (Element A) when the native `button` inside the Shadow DOM (Element B) has focus.
On the other hand, the `:focus-visible` pseudo-class can be used when you want to style the element based on its own state. For example, we could use `:focus-visible` to style the clear icon on Input when the icon itself is focused.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
### Hover
The [hover state](https://developer.mozilla.org/en-US/docs/Web/CSS/:hover) happens when a user moves their cursor on top of an element without pressing on it. It should not happen on mobile, only on desktop devices that support hover.
> [!NOTE]
> Some Android devices [incorrectly report their inputs](https://issues.chromium.org/issues/40855702) which can result in certain devices receiving hover events when they should not.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
> [!IMPORTANT]
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
> Make sure the component has the correct [component structure](#component-structure) before continuing.
#### CSS
Components should be written to include the following hover variables for styling:
```css
/**
* @prop --color-hover: Color of the button on hover
* @prop --background-hover: Background of the button on hover
* @prop --background-hover-opacity: Opacity of the background on hover
*/
```
Style the `:hover` based on the spec for that element:
```scss
@media (any-hover: hover) {
:host(:hover) .button-native {
color: var(--color-hover);
&::after {
background: var(--background-hover);
opacity: var(--background-hover-opacity);
}
}
}
```
> [!IMPORTANT]
> Order matters! Hover should be **before** the activated state.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
#### User Customization
Setting the hover state on the `::after` pseudo-element allows the user to customize the hover state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on hover, or they can leave out `--background-hover-opacity` and the button will use the default hover opacity to match the spec.
```css
ion-button {
--background-hover: red;
--background-hover-opacity: 1;
}
```
### Activated
The activated state should be enabled for elements with actions on "press". It usually changes the opacity or background of an element.
> [!WARNING]
>`:active` should not be used here as it is not received on mobile Safari unless the element has a `touchstart` listener (which we don't necessarily want to have to add to every element). From [Safari Web Content Guide](https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/AdjustingtheTextSize/AdjustingtheTextSize.html):
>
>> On iOS, mouse events are sent so quickly that the down or active state is never received. Therefore, the `:active` pseudo state is triggered only when there is a touch event set on the HTML element
> [!IMPORTANT]
> Make sure the component has the correct [component structure](#component-structure) before continuing.
#### JavaScript
The `ion-activatable` class needs to be set on an element that can be activated:
```jsx
render() {
return (
<Host class="ion-activatable">
<slot></slot>
</Host>
);
}
```
Once that is done, the element will get the `ion-activated` class added on press after a small delay. This delay exists so that the active state does not show up when an activatable element is tapped while scrolling.
In addition to setting that class, `ion-activatable-instant` can be set in order to have an instant press with no delay:
```jsx
<Host class="ion-activatable ion-activatable-instant">
```
#### CSS
```css
/**
* @prop --color-activated: Color of the button when pressed
* @prop --background-activated: Background of the button when pressed
* @prop --background-activated-opacity: Opacity of the background when pressed
*/
```
Style the `ion-activated` class based on the spec for that element:
```scss
:host(.ion-activated) .button-native {
color: var(--color-activated);
&::after {
background: var(--background-activated);
opacity: var(--background-activated-opacity);
}
}
```
> [!IMPORTANT]
> Order matters! Activated should be **after** the focused & hover states.
#### User Customization
Setting the activated state on the `::after` pseudo-element allows the user to customize the activated state without knowing what the default opacity is set at. A user can customize in the following ways to have a solid red background on press, or they can leave out `--background-activated-opacity` and the button will use the default activated opacity to match the spec.
```css
ion-button {
--background-activated: red;
--background-activated-opacity: 1;
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
}
```
### Ripple Effect
The ripple effect should be added to elements for Material Design. It *requires* the `ion-activatable` class to be set on the parent element to work, and relative positioning on the parent.
```jsx
render() {
feat: add ionic theme architecture (#29132) Issue number: Internal --------- <!-- 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. --> ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> Adds the base architecture to add a new theme configuration to Ionic Framework components. - Components can now specify an additional stylesheet for the `ionic` theme. - Developers can specify the `theme` and `mode` independently to control look and feel of a component. Test infrastructure has been updated to add support for testing the theme configuration with Playwright. - Existing `themes` test configuration has been renamed to `palettes` This PR is just the initial effort to decouple Ionic's architecture to separate look and feel and allow our dev team to start introducing the new component appearance to the UI. There will be additional changes required to completely add support for the Ionic theme. These changes are targeted against the `next` branch and are not expected to be used in a production environment at this time. ## 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 <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com> Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
2024-03-18 15:45:01 -04:00
const theme = getIonTheme(this);
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
return (
<Host
class={{
'ion-activatable': true,
}}
>
<button>
<slot></slot>
feat: add ionic theme architecture (#29132) Issue number: Internal --------- <!-- 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. --> ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> Adds the base architecture to add a new theme configuration to Ionic Framework components. - Components can now specify an additional stylesheet for the `ionic` theme. - Developers can specify the `theme` and `mode` independently to control look and feel of a component. Test infrastructure has been updated to add support for testing the theme configuration with Playwright. - Existing `themes` test configuration has been renamed to `palettes` This PR is just the initial effort to decouple Ionic's architecture to separate look and feel and allow our dev team to start introducing the new component appearance to the UI. There will be additional changes required to completely add support for the Ionic theme. These changes are targeted against the `next` branch and are not expected to be used in a production environment at this time. ## 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 <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com> Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
2024-03-18 15:45:01 -04:00
{theme === 'md' && <ion-ripple-effect></ion-ripple-effect>}
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
</button>
</Host>
);
```
The ripple effect can also accept a different `type`. By default it is `"bounded"` which will expand the ripple effect from the click position outwards. To add a ripple effect that always starts in the center of the element and expands in a circle, set the type to `"unbounded"`. An unbounded ripple will exceed the container, so add `overflow: hidden` to the parent to prevent this.
Make sure to style the ripple effect for that component to accept a color:
```css
ion-ripple-effect {
color: var(--ripple-color);
}
```
### Example Components
- [ion-button](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/button)
- [ion-back-button](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/back-button)
- [ion-menu-button](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/menu-button)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
### References
- [Material Design States](https://material.io/design/interaction/states.html)
- [iOS Buttons](https://developer.apple.com/design/human-interface-guidelines/ios/controls/buttons/)
## Accessibility
### Checkbox
#### Example Components
- [ion-checkbox](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/checkbox)
#### VoiceOver
In order for VoiceOver to work properly with a checkbox component there must be a native `input` with `type="checkbox"`, and `aria-checked` and `role="checkbox"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the checkbox is disabled, preventing iOS users from selecting it:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
/>
...
</Host>
);
}
```
#### NVDA
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="checkbox"
>
<input
type="checkbox"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
```
#### Labels
Labels should be passed directly to the component in the form of either visible text or an `aria-label`. The visible text can be set inside of a `label` element, and the `aria-label` can be set directly on the interactive element.
In the following example the `aria-label` can be inherited from the Host using the `inheritAttributes` or `inheritAriaAttributes` utilities. This allows developers to set `aria-label` on the host element since they do not have access to inside the shadow root.
> [!NOTE]
> Use `inheritAttributes` to specify which attributes should be inherited or `inheritAriaAttributes` to inherit all of the possible `aria` attributes.
```tsx
import { Prop } from '@stencil/core';
import { inheritAttributes } from '@utils/helpers';
import type { Attributes } from '@utils/helpers';
...
private inheritedAttributes: Attributes = {};
@Prop() labelText?: string;
componentWillLoad() {
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
}
render() {
return (
<Host>
<label>
{this.labelText}
<input type="checkbox" {...this.inheritedAttributes} />
</label>
</Host>
)
}
```
#### Hidden Input
A helper function to render a hidden input has been added, it can be added in the `render`:
```tsx
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
```
> This is required for the checkbox to work with forms.
#### Known Issues
When using VoiceOver on macOS, Chrome will announce the following when you are focused on a checkbox:
```
currently on a checkbox inside of a checkbox
```
This is a compromise we have to make in order for it to work with the other screen readers & Safari.
### Switch
#### Example Components
- [ion-toggle](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/toggle)
#### Voiceover
In order for VoiceOver to work properly with a switch component there must be a native `input` with `type="checkbox"` and `role="switch"`, and `aria-checked` and `role="switch"` **must** be on the host element. The `aria-hidden` attribute needs to be added if the switch is disabled, preventing iOS users from selecting it:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
/>
...
</Host>
);
}
```
#### NVDA
It is required to have `aria-checked` on the native input for checked to read properly and `disabled` to prevent tabbing to the input:
```tsx
render() {
const { checked, disabled } = this;
return (
<Host
aria-checked={`${checked}`}
aria-hidden={disabled ? 'true' : null}
role="switch"
>
<input
type="checkbox"
role="switch"
aria-checked={`${checked}`}
disabled={disabled}
/>
...
</Host>
);
}
```
#### Labels
Labels should be passed directly to the component in the form of either visible text or an `aria-label`. The visible text can be set inside of a `label` element, and the `aria-label` can be set directly on the interactive element.
In the following example the `aria-label` can be inherited from the Host using the `inheritAttributes` or `inheritAriaAttributes` utilities. This allows developers to set `aria-label` on the host element since they do not have access to inside the shadow root.
> [!NOTE]
> Use `inheritAttributes` to specify which attributes should be inherited or `inheritAriaAttributes` to inherit all of the possible `aria` attributes.
```tsx
import { Prop } from '@stencil/core';
import { inheritAttributes } from '@utils/helpers';
import type { Attributes } from '@utils/helpers';
...
private inheritedAttributes: Attributes = {};
@Prop() labelText?: string;
componentWillLoad() {
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
}
render() {
return (
<Host>
<label>
{this.labelText}
<input type="checkbox" role="switch" {...this.inheritedAttributes} />
</label>
</Host>
)
}
```
#### Hidden Input
A helper function to render a hidden input has been added, it can be added in the `render`:
```tsx
renderHiddenInput(true, el, name, (checked ? value : ''), disabled);
```
> This is required for the switch to work with forms.
#### Known Issues
When using VoiceOver on macOS or iOS, Chrome will announce the switch as a checked or unchecked `checkbox`:
```
You are currently on a switch. To select or deselect this checkbox, press Control-Option-Space.
```
There is a WebKit bug open for this: https://bugs.webkit.org/show_bug.cgi?id=196354
### Accordion
#### Example Components
- [ion-accordion](https://github.com/ionic-team/ionic-framework/tree/master/core/src/components/accordion)
- [ion-accordion-group](https://github.com/ionic-team/ionic-framework/tree/master/core/src/components/accordion-group)
#### NVDA
In order to use the arrow keys to navigate the accordions, users must be in "Focus Mode". Typically, NVDA automatically switches between Browse and Focus modes when inside of a form, but not every accordion needs a form.
You can either wrap your `ion-accordion-group` in a form, or manually toggle Focus Mode using NVDA's keyboard shortcut.
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
## Rendering Anchor or Button
Certain components can render an `<a>` or a `<button>` depending on the presence of an `href` attribute.
### Example Components
- [ion-button](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/button)
- [ion-card](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/card)
- [ion-fab-button](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/fab-button)
- [ion-item-option](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/item-option)
- [ion-item](https://github.com/ionic-team/ionic-framework/tree/main/core/src/components/item)
feat(components): improve button states and add new css properties (#19440) Before users had to know the exact opacity that the MD/iOS spec called for in order to change the hover or focused background color. This allows them to change the background without having to know the opacity. - changes apply to Action Sheet (Buttons), Back Button, Button, FAB Button, Item, Menu Button, Segment Button, Tab Button - greatly reduces the requirement by users to set the background hover, focused states for dark modes and custom themes, also eliminates the need to know what the hover opacity is for each based on the spec - updates the MD dark theme per their spec - adds a component guide for internal use changing Ionic components references #18279 fixes #20213 fixes #19965 BREAKING CHANGE: *Activated Class* The `activated` class that is automatically added to buttons on press has been renamed to `ion-activated`. This will be more consistent with our `ion-focused` class we add and also will reduce conflicts with user's CSS. *CSS Variables* The `--background-hover`, `--background-focused` and `--background-activated` CSS variables on components that render native buttons will now have an opacity automatically set. If you are setting any of these like the following: ``` --background-hover: rgba(44, 44, 44, 0.08); ``` You will likely not see a hover state anymore. It should be updated to only set the desired color: ``` --background-hover: rgba(44, 44, 44); ``` If the opacity desired is something other than what the spec asks for, use: ``` --background-hover: rgba(44, 44, 44); --background-hover-opacity: 1; ```
2020-01-23 16:57:47 -05:00
### Component Structure
#### JavaScript
In order to implement a component with a dynamic tag type, set the property that it uses to switch between them, we use `href`:
```jsx
/**
* Contains a URL or a URL fragment that the hyperlink points to.
* If this property is set, an anchor tag will be rendered.
*/
@Prop() href: string | undefined;
```
Then use that in order to render the tag:
```jsx
render() {
const TagType = href === undefined ? 'button' : 'a' as any;
return (
<Host>
<TagType>
<slot></slot>
</TagType>
</Host>
);
}
```
If the component can render an `<a>`, `<button>` or a `<div>` add in more properties such as a `button` attribute in order to check if it should render a button.
## Converting Scoped to Shadow
### CSS
There will be some CSS issues when converting to shadow. Below are some of the differences.
**Targeting host + slotted child**
```css
/* IN SCOPED */
:host(.ion-color)::slotted(ion-segment-button)
/* IN SHADOW*/
:host(.ion-color) ::slotted(ion-segment-button)
```
**Targeting host-context + host (with a :not)**
```css
/* IN SCOPED */
:host-context(ion-toolbar.ion-color):not(.ion-color) {
/* IN SHADOW */
:host-context(ion-toolbar.ion-color):host(:not(.ion-color)) {
```
**Targeting host-context + host (with a :not) > slotted child**
```css
/* IN SCOPED */
:host-context(ion-toolbar:not(.ion-color)):not(.ion-color)::slotted(ion-segment-button) {
/* IN SHADOW*/
:host-context(ion-toolbar:not(.ion-color)):host(:not(.ion-color)) ::slotted(ion-segment-button) {
```
## RTL
When you need to support both LTR and RTL modes, try to avoid using values such as `left` and `right`. For certain CSS properties, you can use the appropriate mixin to have this handled for you automatically.
For example, if you wanted `transform-origin` to be RTL-aware, you would use the `transform-origin` mixin:
```css
@include transform-origin(start, center);
```
This would output `transform-origin: left center` in LTR mode and `transform-origin: right center` in RTL mode.
These mixins depend on the `:host-context` pseudo-class when used inside of shadow components, which is not supported in WebKit. As a result, these mixins will not work in Safari for macOS and iOS when applied to shadow components.
To work around this, you should set an RTL class on the host of your component and set your RTL styles by targeting that class:
```tsx
<Host
class={{
'my-cmp-rtl': document.dir === 'rtl'
chore(docs): consolidate the developer resource files into a docs/ directory (#29266) Start your review here 👉 [docs/README.md](https://github.com/ionic-team/ionic-framework/blob/FW-6107/docs/README.md) ## What is the current behavior? Documentation files with information on how to contribute, component implementations, testing, etc. are scattered throughout various folders in this repository. ## What is the new behavior? Consolidates the documentation files into a root `docs/` directory for easier discovery and organization. `/docs` tree: ``` ├── _config.yml ├── component-guide.md ├── CONTRIBUTING.md ├── README.md ├── sass-guidelines.md ├── angular │   ├── README.md │   └── testing.md ├── core │   ├── README.md │   └── testing │   ├── README.md │   ├── api.md │   ├── best-practices.md │   ├── preview-changes.md │   └── usage-instructions.md ├── react │   ├── README.md │   └── testing.md ├── react-router │   ├── README.md │   └── testing.md ├── vue │   ├── README.md │   └── testing.md └── vue-router ├── README.md └── testing.md ``` **Migrates the following:** | Previous Location | New Location | | ----------------------------------------------------------- | ----------------------------------------- | | `.github/COMPONENT-GUIDE.md` | `docs/component-guide.md` | | `.github/CONTRIBUTING.md` | `docs/CONTRIBUTING.md` | | `core/scripts/README.md` | `docs/core/testing/preview-changes.md` | | `core/src/utils/test/playwright/docs/api.md` | `docs/core/testing/api.md` | | `core/src/utils/test/playwright/docs/best-practices.md` | `docs/core/testing/best-practices.md` | | `core/src/utils/test/playwright/docs/README.md` | `docs/core/testing/README.md` | | `core/src/utils/test/playwright/docs/usage-instructions.md` | `docs/core/testing/usage-instructions.md` | | `packages/angular/test/README.md` | `docs/angular/testing.md` | | `packages/react-router/test/README.md` | `docs/react-router/testing.md` | | `packages/react/test/README.md` | `docs/react/testing.md` | | `packages/react/test/base/README.md` | `docs/react/testing.md` | | `packages/vue/test/README.md` | `docs/vue/testing.md` | **Adds the following:** | File | Description | | ----------------------------- | ----------------------------------------------------------------------- | | `docs/sass-guidelines.md` | Sass Variable guidelines taken from `ionic-framework-design-documents` | | `docs/README.md` | Entry file that should link to all other files | | `docs/_config.yml` | Config file for use with GitHub pages | | `docs/core/README.md` | Description of core, links to contributing and testing | | `docs/angular/README.md` | Description of angular, links to contributing and testing | | `docs/react/README.md` | Description of react, links to contributing and testing | | `docs/react-router/README.md` | Description of react-router, links to contributing and testing | | `docs/vue/README.md` | Description of vue, links to contributing and testing | | `docs/vue-router/README.md` | Description of vue-router, links to contributing and testing | | `docs/vue-router/testing.md` | Testing file for vue-router, populated from vue-router's main README | **Does not** add any files for `angular-server`. This is because the README is essentially empty and there is no testing in that directory. I can add blank files if we want to have something to add to later. **Does not** migrate the content of the packages' root `README.md` files. These files are used for their npm package descriptions so we should not edit them. ## Hosting Documentation We can (and should) host these files using GitHub Pages. I have duplicated them in a personal repository to see how this would look: [docs-consolidation](https://brandyscarney.github.io/docs-consolidation/). Doing so will require some formatting fixes (see [Sass Guidelines](https://brandyscarney.github.io/docs-consolidation/sass-guidelines.html#-reusable-values)) so I did not publish them now but we can easily enable GitHub pages by toggling a setting in this repository. ## Other information - Verify that no documentation files were missed in the migration - You can use these commands to search for `*.md` files in a directory: - `find core/src -type f -name "*.md" -print` - `find packages/angular -type f -name "*.md" -not -path "**/node_modules/*" -print` - I did add some redirect links in some of the existing markdown files so they might still exist for that reason - We should probably break up the contributing + component guide documentation into smaller files, such as including best practices, but I wanted to get everything in the same place first - The contributing has sections on each of the packages that we could move to that package's docs folder: https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#core --------- Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com>
2024-04-08 15:06:26 -04:00
}}
>
...
</Host>
```
```css
:host {
transform-origin: left center;
}
:host(.my-cmp-rtl) {
transform-origin: right center;
}
```
feat: add ionic theme architecture (#29132) Issue number: Internal --------- <!-- 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. --> ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> Adds the base architecture to add a new theme configuration to Ionic Framework components. - Components can now specify an additional stylesheet for the `ionic` theme. - Developers can specify the `theme` and `mode` independently to control look and feel of a component. Test infrastructure has been updated to add support for testing the theme configuration with Playwright. - Existing `themes` test configuration has been renamed to `palettes` This PR is just the initial effort to decouple Ionic's architecture to separate look and feel and allow our dev team to start introducing the new component appearance to the UI. There will be additional changes required to completely add support for the Ionic theme. These changes are targeted against the `next` branch and are not expected to be used in a production environment at this time. ## 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 <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> --------- Co-authored-by: Maria Hutt <thetaPC@users.noreply.github.com> Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
2024-03-18 15:45:01 -04:00
## Themes vs. Modes
Themes and modes are two different concepts in Ionic. Themes refer to the "look" of the component, such as the stylesheet that is used. Modes refer to the "behavior" of the component, such as the platform specific behaviors on iOS and Android.
To detect the theme, you can use the `getIonTheme` function:
```tsx
const theme = getIonTheme(this);
return (
<Host class={theme}>
{theme === "md" && <ion-ripple-effect></ion-ripple-effect>}
</Host>
);
```
Theme can be both used for styling decisions and conditional rendering of elements. For example, the ripple effect is only used in the Material Design theme.
To detect the mode, you can use the `getIonMode` function:
```tsx
const mode = getIonMode(this);
if (mode === "ios") {
enableRubberBandScrolling();
}
```
Mode can be used for behavior tied to the platform the app is running on. For example, iOS has rubber band scrolling, while Android does not.
Use mode for functionality that remains consistent across all themes but is intended specifically for a certain platform.
Functionality that is applied only to a specific theme should use theme.
## Adding New Components with Native Input Support
When creating a new component that renders native input elements (such as `<input>` or `<textarea>`), there are several steps required to ensure proper form integration across all frameworks (Angular, React, and Vue).
### Angular Integration
#### Value Accessors
For Angular integration, you should use one of the existing value accessors based on your component's needs. Choose the one that most closely matches your component's behavior:
- For text input (handles string values): Use [`TextValueAccessorDirective`](/packages/angular/src/directives/control-value-accessors/text-value-accessor.ts) which handles `ion-input:not([type=number])`, `ion-input-otp[type=text]`, `ion-textarea`, and `ion-searchbar`
- For numeric input (converts string to number): Use [`NumericValueAccessorDirective`](/packages/angular/src/directives/control-value-accessors/numeric-value-accessor.ts) which handles `ion-input[type=number]`, `ion-input-otp:not([type=text])`, and `ion-range`
- For boolean input (handles true/false): Use [`BooleanValueAccessorDirective`](/packages/angular/src/directives/control-value-accessors/boolean-value-accessor.ts) which handles `ion-checkbox` and `ion-toggle`
- For select-like input (handles option selection): Use [`SelectValueAccessorDirective`](/packages/angular/src/directives/control-value-accessors/select-value-accessor.ts) which handles `ion-select`, `ion-radio-group`, `ion-segment`, and `ion-datetime`
These value accessors are already set up in the `@ionic/angular` package and handle all the necessary form integration. You don't need to create a new value accessor unless your component has unique requirements that aren't covered by these existing ones.
For example, if your component renders a text input, it should be included in the `TextValueAccessorDirective` selector in [`text-value-accessor.ts`](/packages/angular/src/directives/control-value-accessors/text-value-accessor.ts):
```diff
@Directive({
- selector: 'ion-input:not([type=number]),ion-input-otp[type=text],ion-textarea,ion-searchbar',
+ selector: 'ion-input:not([type=number]),ion-input-otp[type=text],ion-textarea,ion-searchbar,ion-new-component',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: TextValueAccessorDirective,
multi: true,
},
],
})
```
You'll also need to add your component's type to the value accessor's type definitions. For example, in the `TextValueAccessorDirective`, you would add your component's type to the `_handleInputEvent` method:
```diff
@HostListener('ionInput', ['$event.target'])
_handleInputEvent(
- el: HTMLIonInputElement | HTMLIonInputOtpElement | HTMLIonTextareaElement | HTMLIonSearchbarElement
+ el: HTMLIonInputElement | HTMLIonInputOtpElement | HTMLIonTextareaElement | HTMLIonSearchbarElement | HTMLIonNewComponentElement
): void {
this.handleValueChange(el, el.value);
}
```
If your component needs special handling for value changes, you'll also need to update the `registerOnChange` method. For example, if your component needs to handle numeric values:
```diff
registerOnChange(fn: (_: number | null) => void): void {
- if (this.el.nativeElement.tagName === 'ION-INPUT' || this.el.nativeElement.tagName === 'ION-INPUT-OTP') {
+ if (this.el.nativeElement.tagName === 'ION-INPUT' || this.el.nativeElement.tagName === 'ION-INPUT-OTP' || this.el.nativeElement.tagName === 'ION-NEW-COMPONENT') {
super.registerOnChange((value: string) => {
fn(value === '' ? null : parseFloat(value));
});
} else {
super.registerOnChange(fn);
}
}
```
#### Standalone Directive
For standalone components, create a directive in the [standalone package](/packages/angular/standalone/src/directives). Look at the implementation of the most similar existing component as a reference:
- For text/numeric inputs: See [ion-input](/packages/angular/standalone/src/directives/input.ts) or [ion-input-otp](/packages/angular/standalone/src/directives/input-otp.ts)
- For boolean inputs: See [ion-checkbox](/packages/angular/standalone/src/directives/checkbox.ts) or [ion-toggle](/packages/angular/standalone/src/directives/toggle.ts)
- For select-like inputs: See [ion-select](/packages/angular/standalone/src/directives/select.ts) or [ion-radio-group](/packages/angular/standalone/src/directives/radio-group.ts)
After creating the directive, you need to export it in two places:
1. First, add your component to the directives export group in [`packages/angular/standalone/src/directives/index.ts`](/packages/angular/standalone/src/directives/index.ts):
```typescript
export { IonNewComponent } from './new-component';
```
2. Then, add it to the main standalone package's index file in [`packages/angular/standalone/src/index.ts`](/packages/angular/standalone/src/index.ts):
```typescript
export {
IonCheckbox,
IonDatetime,
IonInput,
IonInputOtp,
IonNewComponent, // Add your new component here
// ... other components
} from './directives';
```
This ensures your component is properly exported and available for use in standalone Angular applications.
#### Output Target Configuration
Update the `angularOutputTarget` configuration in [`stencil.config.ts`](/core/stencil.config.ts) to exclude your new component from the generated proxies. This is necessary because value accessors for these components are manually implemented in the standalone package.
```typescript
angularOutputTarget({
// ... other config
excludeComponents: [
...excludeComponents,
// ... other excludes
/**
* Value Accessors are manually implemented in the `@ionic/angular/standalone` package.
*/
'ion-new-component'
]
})
```
### Angular Tests
Add tests for the new component to the existing Angular test files:
- **(Lazy) Inputs**
- [`inputs.component.html`](/packages/angular/test/base/src/app/lazy/inputs/inputs.component.html)
- [`inputs.component.ts`](/packages/angular/test/base/src/app/lazy/inputs/inputs.component.ts)
- [`inputs.spec.ts`](/packages/angular/test/base/e2e/src/lazy/inputs.spec.ts)
- **(Lazy) Form**
- [`form.component.html`](/packages/angular/test/base/src/app/lazy/form/form.component.html)
- [`form.component.ts`](/packages/angular/test/base/src/app/lazy/form/form.component.ts)
- [`form.spec.ts`](/packages/angular/test/base/e2e/src/lazy/form.spec.ts)
- **(Standalone) Value Accessors**
- [`value-accessors/`](/packages/angular/test/base/src/app/standalone/value-accessors)
- [`value-accessors.spec.ts`](/packages/angular/test/base/e2e/src/standalone/value-accessors.spec.ts)
These files contain tests for form integration and input behavior. Review how similar components are tested and add the new component to the relevant test files.
### Vue Integration
#### Output Target Configuration
Update the `vueOutputTarget` configuration in [`stencil.config.ts`](/core/stencil.config.ts):
- Add your new component to the appropriate `componentModels` array, based on its behavior:
- For boolean inputs, add to the array with `targetAttr: 'checked'` and `event: 'ion-change'`
- For select-like inputs, add to the array with `targetAttr: 'value'` and `event: 'ion-change'`
- For text/numeric inputs, add to the array with `targetAttr: 'value'` and `event: 'ion-input'`
For example, if your component is a text input, add it to:
```js
vueOutputTarget({
// ... other config
componentModels: [
// ... other models
{
elements: ['ion-input', 'ion-input-otp', 'ion-searchbar', 'ion-textarea', 'ion-range', 'ion-new-component'],
targetAttr: 'value',
event: 'ion-input',
}
],
}),
```
Look at similar components in the `componentModels` arrays to determine the correct placement.
### Vue Tests
- **Inputs**
- [`Inputs.vue`](/packages/vue/test/base/src/views/Inputs.vue)
- [`inputs.cy.js`](/packages/vue/test/base/tests/e2e/specs/inputs.cy.js)
These files contain tests for input behavior. Review how similar components are tested and add the new component to the relevant test files.
### React Integration
React components are automatically generated from the core component definitions. No additional configuration is needed.
### React Tests
- **Inputs**
- [`Inputs.tsx`](/packages/react/test/base/src/pages/Inputs.tsx)
- [`inputs.cy.ts`](/packages/react/test/base/tests/e2e/specs/components/inputs.cy.ts)
These files contain tests for input behavior. Review how similar components are tested and add the new component to the relevant test files.
### Interface Exports
Add your component's interfaces to the framework packages:
1. Angular ([`packages/angular/src/index.ts`](/packages/angular/src/index.ts)):
```typescript
export {
NewComponentCustomEvent,
NewComponentChangeEventDetail,
NewComponentInputEventDetail,
// ... other event interfaces
} from '@ionic/core';
```
2. React ([`packages/react/src/components/index.ts`](/packages/react/src/components/index.ts)):
```typescript
export {
NewComponentCustomEvent,
NewComponentChangeEventDetail,
NewComponentInputEventDetail,
// ... other event interfaces
} from '@ionic/core/components';
```
3. Vue ([`packages/vue/src/index.ts`](/packages/vue/src/index.ts)):
```typescript
export {
NewComponentCustomEvent,
NewComponentChangeEventDetail,
NewComponentInputEventDetail,
// ... other event interfaces
} from '@ionic/core/components';
```