Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api/range.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@ import CSSProps from '@site/static/usage/v8/range/theming/css-properties/index.m

Range includes [CSS Shadow Parts](#css-shadow-parts) to allow complete customization of specific element nodes within the Range component. CSS Shadow Parts offer the most customization capabilities and are the recommended approach when requiring advance styling with the Range component.

When `dualKnobs` is enabled, additional Shadow Parts are exposed to allow each knob to be styled independently. These are available in two forms: **static identity parts** (`A` and `B`) and **dynamic position parts** (`lower` and `upper`). The A and B parts always refer to the same physical knobs, even if the knobs cross. In contrast, the lower and upper parts reflect the current value position and automatically swap if the knobs cross. This allows styling by consistent identity or by relative value within the range.

import CSSParts from '@site/static/usage/v8/range/theming/css-shadow-parts/index.md';

<CSSParts />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,43 +1,114 @@
```css
ion-range::part(tick) {
background: #a2d2ff;
/* Shared styles for all ranges */
ion-range {
--knob-size: 34px;
}

ion-range::part(tick-active) {
background: #bde0fe;
ion-range::part(knob) {
background: #fff;

box-sizing: border-box;
}

ion-range::part(pin) {
display: inline-flex;
align-items: center;
justify-content: center;
/* Hide the Material Design indicator */
ion-range::part(knob)::before {
display: none;
}

background: #ffafcc;
ion-range::part(pin) {
color: #fff;

border-radius: 50%;
transform: scale(1.01);
}

ion-range::part(tick),
ion-range::part(tick-active) {
height: 8px;
top: 17px;
}

top: -20px;
/* Single Knob Range */
#range-single::part(bar),
#range-single::part(tick) {
background: #bed4ff;
}

min-width: 28px;
height: 28px;
transition: transform 120ms ease, background 120ms ease;
#range-single::part(bar-active),
#range-single::part(tick-active) {
background: #40a2fd;
}

ion-range::part(pin)::before {
content: none;
#range-single::part(knob) {
border: 4px solid #40a2fd;
}

ion-range::part(knob) {
background: #ffc8dd;
#range-single::part(knob pressed) {
background: #bed4ff;
}

#range-single::part(pin),
#range-single::part(pin)::before {
background: #40a2fd;
}

/* Dual Knobs (A/B) Range */
#range-a-b::part(bar-active) {
background: #1ea9ca;
}

#range-a-b::part(knob-a) {
border: 4px solid #0f8fd6;
}

#range-a-b::part(knob-a pressed) {
background: #cfeefe;
}

#range-a-b::part(pin-a),
#range-a-b::part(pin-a)::before {
background: #0f8fd6;
}

#range-a-b::part(knob-b) {
border: 4px solid #2dc2bd;
}

#range-a-b::part(knob-b pressed) {
background: #d4f5f3;
}

#range-a-b::part(pin-b),
#range-a-b::part(pin-b)::before {
background: #2dc2bd;
}

/* Dual Knobs (Lower/Upper) Range */
#range-lower-upper::part(bar-active) {
background: linear-gradient(to right, #0059ff 0%, #b77bff 100%);
}

#range-lower-upper::part(knob-lower) {
border: 4px solid #0059ff;
}

#range-lower-upper::part(knob-lower pressed) {
background: #bed4ff;
}

#range-lower-upper::part(pin-lower),
#range-lower-upper::part(pin-lower)::before {
background: #0059ff;
}

#range-lower-upper::part(knob-upper) {
border: 4px solid #b77bff;
}

ion-range::part(bar) {
background: #a2d2ff;
#range-lower-upper::part(knob-upper pressed) {
background: #f1e5ff;
}

ion-range::part(bar-active) {
background: #bde0fe;
#range-lower-upper::part(pin-upper),
#range-lower-upper::part(pin-upper)::before {
background: #b77bff;
}
```
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
```html
<h2>Single Knob</h2>
<ion-range
id="range-single"
aria-label="Custom range"
[min]="0"
[max]="10"
Expand All @@ -8,4 +10,26 @@
[ticks]="true"
[snaps]="true"
></ion-range>

<h2>Dual Knobs (A/B)</h2>
<ion-range
id="range-a-b"
aria-label="Custom dual knob range with A/B styling"
[min]="0"
[max]="10"
[value]="{lower: 3, upper: 7}"
[dualKnobs]="true"
[pin]="true"
></ion-range>

<h2>Dual Knobs (Lower/Upper)</h2>
<ion-range
id="range-lower-upper"
aria-label="Custom dual knob range with lower/upper styling"
[min]="0"
[max]="10"
[value]="{lower: 3, upper: 7}"
[dualKnobs]="true"
[pin]="true"
></ion-range>
```
154 changes: 131 additions & 23 deletions static/usage/v8/range/theming/css-shadow-parts/demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,126 @@
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@8/dist/ionic/ionic.esm.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css" />
<style>
.container {
flex-direction: column;
}

/* Shared styles for all ranges */
ion-range {
--knob-size: 34px;

width: 100%;
max-width: 320px;

margin-bottom: 24px;
}

ion-range::part(tick) {
background: #a2d2ff;
ion-range::part(knob) {
background: #fff;

box-sizing: border-box;
}

ion-range::part(tick-active) {
background: #bde0fe;
/* Hide the Material Design indicator */
ion-range::part(knob)::before {
display: none;
}

ion-range::part(pin) {
display: inline-flex;
align-items: center;
justify-content: center;

background: #ffafcc;
color: #fff;

border-radius: 50%;
transform: scale(1.01);
}

top: -20px;
ion-range::part(tick),
ion-range::part(tick-active) {
height: 8px;
top: 17px;
}

min-width: 28px;
height: 28px;
transition: transform 120ms ease, background 120ms ease;
/* Single Knob Range */
#range-single::part(bar),
#range-single::part(tick) {
background: #bed4ff;
}

ion-range::part(pin)::before {
content: none;
#range-single::part(bar-active),
#range-single::part(tick-active) {
background: #40a2fd;
}

ion-range::part(knob) {
background: #ffc8dd;
#range-single::part(knob) {
border: 4px solid #40a2fd;
}

#range-single::part(knob pressed) {
background: #bed4ff;
}

#range-single::part(pin),
#range-single::part(pin)::before {
background: #40a2fd;
}

/* Dual Knobs (A/B) Range */
#range-a-b::part(bar-active) {
background: #1ea9ca;
}

#range-a-b::part(knob-a) {
border: 4px solid #0f8fd6;
}

#range-a-b::part(knob-a pressed) {
background: #cfeefe;
}

#range-a-b::part(pin-a),
#range-a-b::part(pin-a)::before {
background: #0f8fd6;
}

#range-a-b::part(knob-b) {
border: 4px solid #2dc2bd;
}

ion-range::part(bar) {
background: #a2d2ff;
#range-a-b::part(knob-b pressed) {
background: #d4f5f3;
}

ion-range::part(bar-active) {
background: #bde0fe;
#range-a-b::part(pin-b),
#range-a-b::part(pin-b)::before {
background: #2dc2bd;
}

/* Dual Knobs (Lower/Upper) Range */
#range-lower-upper::part(bar-active) {
background: linear-gradient(to right, #0059ff 0%, #b77bff 100%);
}

#range-lower-upper::part(knob-lower) {
border: 4px solid #0059ff;
}

#range-lower-upper::part(knob-lower pressed) {
background: #bed4ff;
}

#range-lower-upper::part(pin-lower),
#range-lower-upper::part(pin-lower)::before {
background: #0059ff;
}

#range-lower-upper::part(knob-upper) {
border: 4px solid #b77bff;
}

#range-lower-upper::part(knob-upper pressed) {
background: #f1e5ff;
}

#range-lower-upper::part(pin-upper),
#range-lower-upper::part(pin-upper)::before {
background: #b77bff;
}
</style>
</head>
Expand All @@ -61,7 +137,9 @@
<ion-app>
<ion-content>
<div class="container">
<h2>Single Knob</h2>
<ion-range
id="range-single"
aria-label="Custom range"
min="0"
max="10"
Expand All @@ -70,8 +148,38 @@
ticks="true"
snaps="true"
></ion-range>

<h2>Dual Knobs (A/B)</h2>
<ion-range
id="range-a-b"
aria-label="Custom dual knob range with A/B styling"
min="0"
max="10"
dual-knobs="true"
pin="true"
></ion-range>

<h2>Dual Knobs (Lower/Upper)</h2>
<ion-range
id="range-lower-upper"
aria-label="Custom dual knob range with lower/upper styling"
min="0"
max="10"
dual-knobs="true"
pin="true"
></ion-range>
</div>
</ion-content>
</ion-app>

<script>
const ranges = document.querySelectorAll('ion-range[dual-knobs]');
ranges.forEach((range) => {
range.value = {
lower: 3,
upper: 7,
};
});
</script>
</body>
</html>
1 change: 1 addition & 0 deletions static/usage/v8/range/theming/css-shadow-parts/index.md
Copy link
Contributor

Choose a reason for hiding this comment

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

I really wish we had a show more/less on the code blocks.

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking that too 😂

Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import angular_example_component_ts from './angular/example_component_ts.md';

<Playground
version="8"
size="550px"
code={{
javascript,
react: {
Expand Down
Loading