Skip to content

Commit e360ac8

Browse files
docs(range): add new parts for dual knobs to css shadow parts section (#4420)
Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com>
1 parent 4080b0d commit e360ac8

File tree

9 files changed

+634
-117
lines changed

9 files changed

+634
-117
lines changed

docs/api/range.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ import CSSProps from '@site/static/usage/v8/range/theming/css-properties/index.m
124124

125125
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.
126126

127+
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.
128+
127129
import CSSParts from '@site/static/usage/v8/range/theming/css-shadow-parts/index.md';
128130

129131
<CSSParts />
Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,114 @@
11
```css
2-
ion-range::part(tick) {
3-
background: #a2d2ff;
2+
/* Shared styles for all ranges */
3+
ion-range {
4+
--knob-size: 34px;
45
}
56

6-
ion-range::part(tick-active) {
7-
background: #bde0fe;
7+
ion-range::part(knob) {
8+
background: #fff;
9+
10+
box-sizing: border-box;
811
}
912

10-
ion-range::part(pin) {
11-
display: inline-flex;
12-
align-items: center;
13-
justify-content: center;
13+
/* Hide the Material Design indicator */
14+
ion-range::part(knob)::before {
15+
display: none;
16+
}
1417

15-
background: #ffafcc;
18+
ion-range::part(pin) {
1619
color: #fff;
17-
1820
border-radius: 50%;
19-
transform: scale(1.01);
21+
}
22+
23+
ion-range::part(tick),
24+
ion-range::part(tick-active) {
25+
height: 8px;
26+
top: 17px;
27+
}
2028

21-
top: -20px;
29+
/* Single Knob Range */
30+
#range-single::part(bar),
31+
#range-single::part(tick) {
32+
background: #bed4ff;
33+
}
2234

23-
min-width: 28px;
24-
height: 28px;
25-
transition: transform 120ms ease, background 120ms ease;
35+
#range-single::part(bar-active),
36+
#range-single::part(tick-active) {
37+
background: #40a2fd;
2638
}
2739

28-
ion-range::part(pin)::before {
29-
content: none;
40+
#range-single::part(knob) {
41+
border: 4px solid #40a2fd;
3042
}
3143

32-
ion-range::part(knob) {
33-
background: #ffc8dd;
44+
#range-single::part(knob pressed) {
45+
background: #bed4ff;
46+
}
47+
48+
#range-single::part(pin),
49+
#range-single::part(pin)::before {
50+
background: #40a2fd;
51+
}
52+
53+
/* Dual Knobs (A/B) Range */
54+
#range-a-b::part(bar-active) {
55+
background: #1ea9ca;
56+
}
57+
58+
#range-a-b::part(knob-a) {
59+
border: 4px solid #0f8fd6;
60+
}
61+
62+
#range-a-b::part(knob-a pressed) {
63+
background: #cfeefe;
64+
}
65+
66+
#range-a-b::part(pin-a),
67+
#range-a-b::part(pin-a)::before {
68+
background: #0f8fd6;
69+
}
70+
71+
#range-a-b::part(knob-b) {
72+
border: 4px solid #2dc2bd;
73+
}
74+
75+
#range-a-b::part(knob-b pressed) {
76+
background: #d4f5f3;
77+
}
78+
79+
#range-a-b::part(pin-b),
80+
#range-a-b::part(pin-b)::before {
81+
background: #2dc2bd;
82+
}
83+
84+
/* Dual Knobs (Lower/Upper) Range */
85+
#range-lower-upper::part(bar-active) {
86+
background: linear-gradient(to right, #0059ff 0%, #b77bff 100%);
87+
}
88+
89+
#range-lower-upper::part(knob-lower) {
90+
border: 4px solid #0059ff;
91+
}
92+
93+
#range-lower-upper::part(knob-lower pressed) {
94+
background: #bed4ff;
95+
}
96+
97+
#range-lower-upper::part(pin-lower),
98+
#range-lower-upper::part(pin-lower)::before {
99+
background: #0059ff;
100+
}
101+
102+
#range-lower-upper::part(knob-upper) {
103+
border: 4px solid #b77bff;
34104
}
35105

36-
ion-range::part(bar) {
37-
background: #a2d2ff;
106+
#range-lower-upper::part(knob-upper pressed) {
107+
background: #f1e5ff;
38108
}
39109

40-
ion-range::part(bar-active) {
41-
background: #bde0fe;
110+
#range-lower-upper::part(pin-upper),
111+
#range-lower-upper::part(pin-upper)::before {
112+
background: #b77bff;
42113
}
43114
```

static/usage/v8/range/theming/css-shadow-parts/angular/example_component_html.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
```html
2+
<h2>Single Knob</h2>
23
<ion-range
4+
id="range-single"
35
aria-label="Custom range"
46
[min]="0"
57
[max]="10"
@@ -8,4 +10,26 @@
810
[ticks]="true"
911
[snaps]="true"
1012
></ion-range>
13+
14+
<h2>Dual Knobs (A/B)</h2>
15+
<ion-range
16+
id="range-a-b"
17+
aria-label="Custom dual knob range with A/B styling"
18+
[min]="0"
19+
[max]="10"
20+
[value]="{lower: 3, upper: 7}"
21+
[dualKnobs]="true"
22+
[pin]="true"
23+
></ion-range>
24+
25+
<h2>Dual Knobs (Lower/Upper)</h2>
26+
<ion-range
27+
id="range-lower-upper"
28+
aria-label="Custom dual knob range with lower/upper styling"
29+
[min]="0"
30+
[max]="10"
31+
[value]="{lower: 3, upper: 7}"
32+
[dualKnobs]="true"
33+
[pin]="true"
34+
></ion-range>
1135
```

static/usage/v8/range/theming/css-shadow-parts/demo.html

Lines changed: 131 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,50 +9,126 @@
99
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@8/dist/ionic/ionic.esm.js"></script>
1010
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css" />
1111
<style>
12+
.container {
13+
flex-direction: column;
14+
}
15+
16+
/* Shared styles for all ranges */
1217
ion-range {
18+
--knob-size: 34px;
19+
20+
width: 100%;
1321
max-width: 320px;
22+
23+
margin-bottom: 24px;
1424
}
1525

16-
ion-range::part(tick) {
17-
background: #a2d2ff;
26+
ion-range::part(knob) {
27+
background: #fff;
28+
29+
box-sizing: border-box;
1830
}
1931

20-
ion-range::part(tick-active) {
21-
background: #bde0fe;
32+
/* Hide the Material Design indicator */
33+
ion-range::part(knob)::before {
34+
display: none;
2235
}
2336

2437
ion-range::part(pin) {
25-
display: inline-flex;
26-
align-items: center;
27-
justify-content: center;
28-
29-
background: #ffafcc;
3038
color: #fff;
31-
3239
border-radius: 50%;
33-
transform: scale(1.01);
40+
}
3441

35-
top: -20px;
42+
ion-range::part(tick),
43+
ion-range::part(tick-active) {
44+
height: 8px;
45+
top: 17px;
46+
}
3647

37-
min-width: 28px;
38-
height: 28px;
39-
transition: transform 120ms ease, background 120ms ease;
48+
/* Single Knob Range */
49+
#range-single::part(bar),
50+
#range-single::part(tick) {
51+
background: #bed4ff;
4052
}
4153

42-
ion-range::part(pin)::before {
43-
content: none;
54+
#range-single::part(bar-active),
55+
#range-single::part(tick-active) {
56+
background: #40a2fd;
4457
}
4558

46-
ion-range::part(knob) {
47-
background: #ffc8dd;
59+
#range-single::part(knob) {
60+
border: 4px solid #40a2fd;
61+
}
62+
63+
#range-single::part(knob pressed) {
64+
background: #bed4ff;
65+
}
66+
67+
#range-single::part(pin),
68+
#range-single::part(pin)::before {
69+
background: #40a2fd;
70+
}
71+
72+
/* Dual Knobs (A/B) Range */
73+
#range-a-b::part(bar-active) {
74+
background: #1ea9ca;
75+
}
76+
77+
#range-a-b::part(knob-a) {
78+
border: 4px solid #0f8fd6;
79+
}
80+
81+
#range-a-b::part(knob-a pressed) {
82+
background: #cfeefe;
83+
}
84+
85+
#range-a-b::part(pin-a),
86+
#range-a-b::part(pin-a)::before {
87+
background: #0f8fd6;
88+
}
89+
90+
#range-a-b::part(knob-b) {
91+
border: 4px solid #2dc2bd;
4892
}
4993

50-
ion-range::part(bar) {
51-
background: #a2d2ff;
94+
#range-a-b::part(knob-b pressed) {
95+
background: #d4f5f3;
5296
}
5397

54-
ion-range::part(bar-active) {
55-
background: #bde0fe;
98+
#range-a-b::part(pin-b),
99+
#range-a-b::part(pin-b)::before {
100+
background: #2dc2bd;
101+
}
102+
103+
/* Dual Knobs (Lower/Upper) Range */
104+
#range-lower-upper::part(bar-active) {
105+
background: linear-gradient(to right, #0059ff 0%, #b77bff 100%);
106+
}
107+
108+
#range-lower-upper::part(knob-lower) {
109+
border: 4px solid #0059ff;
110+
}
111+
112+
#range-lower-upper::part(knob-lower pressed) {
113+
background: #bed4ff;
114+
}
115+
116+
#range-lower-upper::part(pin-lower),
117+
#range-lower-upper::part(pin-lower)::before {
118+
background: #0059ff;
119+
}
120+
121+
#range-lower-upper::part(knob-upper) {
122+
border: 4px solid #b77bff;
123+
}
124+
125+
#range-lower-upper::part(knob-upper pressed) {
126+
background: #f1e5ff;
127+
}
128+
129+
#range-lower-upper::part(pin-upper),
130+
#range-lower-upper::part(pin-upper)::before {
131+
background: #b77bff;
56132
}
57133
</style>
58134
</head>
@@ -61,7 +137,9 @@
61137
<ion-app>
62138
<ion-content>
63139
<div class="container">
140+
<h2>Single Knob</h2>
64141
<ion-range
142+
id="range-single"
65143
aria-label="Custom range"
66144
min="0"
67145
max="10"
@@ -70,8 +148,38 @@
70148
ticks="true"
71149
snaps="true"
72150
></ion-range>
151+
152+
<h2>Dual Knobs (A/B)</h2>
153+
<ion-range
154+
id="range-a-b"
155+
aria-label="Custom dual knob range with A/B styling"
156+
min="0"
157+
max="10"
158+
dual-knobs="true"
159+
pin="true"
160+
></ion-range>
161+
162+
<h2>Dual Knobs (Lower/Upper)</h2>
163+
<ion-range
164+
id="range-lower-upper"
165+
aria-label="Custom dual knob range with lower/upper styling"
166+
min="0"
167+
max="10"
168+
dual-knobs="true"
169+
pin="true"
170+
></ion-range>
73171
</div>
74172
</ion-content>
75173
</ion-app>
174+
175+
<script>
176+
const ranges = document.querySelectorAll('ion-range[dual-knobs]');
177+
ranges.forEach((range) => {
178+
range.value = {
179+
lower: 3,
180+
upper: 7,
181+
};
182+
});
183+
</script>
76184
</body>
77185
</html>

static/usage/v8/range/theming/css-shadow-parts/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import angular_example_component_ts from './angular/example_component_ts.md';
1313

1414
<Playground
1515
version="8"
16+
size="550px"
1617
code={{
1718
javascript,
1819
react: {

0 commit comments

Comments
 (0)