Skip to content

feat(item-divider): add recipe and tokens#31009

Open
thetaPC wants to merge 19 commits intoionic-modularfrom
FW-6841
Open

feat(item-divider): add recipe and tokens#31009
thetaPC wants to merge 19 commits intoionic-modularfrom
FW-6841

Conversation

@thetaPC
Copy link
Contributor

@thetaPC thetaPC commented Mar 11, 2026

Issue number: internal


What is the current behavior?

Component styles for ion-item-divider are fragmented across multiple files (ios, md). The ionic theme uses the md styles. Developers were restricted to those themes and how those themes structured the logic and styles.

What is the new behavior?

  • Unified Style Architecture: Combined theme-specific styling into a single item-divider.scss file that consumes CSS variables, ensuring a single source of truth for component logic.
  • Anchor-Edge model: expanded the property-first approach into an anchor-edge model to account for the amount of slot usage
  • Defined TypeScript Interface: Added item-divider.interfaces.ts
  • Defined Shared Base Defaults: Added defaults that are being used regardless of theme
  • Defined Shared Theme Defaults: Added defaults that are being used per theme
  • Updated Test Page: Updated the dividers test page to include more cases

Does this introduce a breaking change?

  • Yes
  • No

This PR introduces a breaking change to how IonItemDivider is styled. Existing manual CSS overrides targeting internal item divider structures or old token names will no longer work due to the shift to thew new token hierarchy and a unified base SCSS file.

Migration Path:

  1. Token Updates: Update any custom theme configurations to match the new nested structure.

  2. CSS Overrides: Ensure selectors align with the new slotted element logic and variable names (e.g., --ion-item-divider-background).

--background should no longer be used. Setting the value, IonDivider.background, within the tokens file should be used to change the background.

  1. Theme classes: Remove any instances that target the theme classes: ion-divider.md

Other information

This PR significantly improves the developer experience for theming. By moving logic into default.tokens.ts and away from hardcoded SCSS functions, designers and developers can now override styles (like the size on a slotted avatar) purely through token configuration.

Preview

@vercel
Copy link

vercel bot commented Mar 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ionic-framework Ready Ready Preview, Comment Mar 13, 2026 6:56pm

Request Review

// Slotted Content
// --------------------------------------------------

::slotted(h1) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My following comment applies to all the slotted headers:

I noticed that the margins are being overridden by a high level style for headers. I'm not sure when the margins declared in the item divider ever get applied. This is also being overridden in main. Can we just get rid of the slotted header styles?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noticed that color functions were never used.

Comment on lines +256 to +257
// TODO(FW-6862): separate width and height tokens for thumbnails
--size: var(--ion-item-divider-thumbnail-width);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To maximize customization, we should split the size into height and width.

* @prop --size: Size of the thumbnail
*/
--size: 48px;
--size: 48px; // TODO(FW-6862): separate width and height tokens for thumbnails
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To maximize customization, we should split the size into height and width.

Comment on lines +18 to +19
width: var(--size, 48px);
height: var(--size, 48px);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're using --ion-item-divider-thumbnail-width to let dividers control thumbnail sizes. The problem is that if a theme doesn't provide this token, the CSS breaks instead of falling back. We can't use revert-layer because the 'original' size we want to return to is actually another variable, not a fixed value. The cleanest fix is to just bake the default 48px right into the variable's fallback.


:host([slot="start"]) {
@include mixins.margin(
var(--ion-item-divider-leading-anchor-margin-top, revert-layer),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

revert-layer is being used so that if we don't provide a modular CSS variable, we give the component permission to just keep doing whatever it was doing originally.

Comment on lines +23 to +40
leading?: {
// Targets `:host([slot="start"])`
anchor?: {
margin?: IonMargin;
};

// Targets `::slotted([slot="start"])`
edge?: {
margin?: IonMargin;
};
};

trailing?: {
// Targets `::slotted([slot="end"])`
edge?: {
margin?: IonMargin;
};
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Naming Convention: Anchors & Edges

To maintain consistency with the Ionic Modular architecture established in ion-chip, this component adopts a shared spatial vocabulary. While chips use DOM order (:first-child), dividers use named slots (slot="start/end"). The following naming convention bridges that gap:

  • Anchors (:host): Refers to the component's own placement within a parent container.
    • leading-anchor: Targets :host([slot="start"]).
    • trailing-anchor: Targets :host([slot="end"]).
  • Edges (::slotted): Refers to content placed at the boundaries of the component itself.
    • leading-edge: Targets ::slotted([slot="start"]).
    • trailing-edge: Targets ::slotted([slot="end"]).

Why this matters:
This mirrors the leading (:first-child) and trailing (:last-child) pattern used in chips. By using leading/trailing instead of left/right or start/end, we create a less confusing structure that developers can use with ease.

Comment on lines +65 to +73
default?: {
color?: string;
};

semantic?: {
default?: {
color?: string;
};
};
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This follows the same structure established in chip when it came to default vs semantic colors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added:

  • Item divider with icons at the start and end slot
  • Item divider with a thumbnail at the start
  • Item divider with paragrahs

import { colors as baseColors } from '../base/shared.tokens';

export const components = {
item: {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Item divider depends on the values set on item. This file was created to keep track of those values and other components that need to be shared with each other.

@thetaPC thetaPC marked this pull request as ready for review March 13, 2026 21:49
@thetaPC thetaPC requested a review from a team as a code owner March 13, 2026 21:49
@thetaPC thetaPC requested review from BenOsodrac and ShaneK and removed request for BenOsodrac March 13, 2026 21:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

package: angular @ionic/angular package package: core @ionic/core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant