Skip to content

Commit 175dc92

Browse files
feat(range): adding custom styling for ionic theme (#29979)
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? No ionic theme custom implementation existed for the ion-range component. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - Added ionic theme specific styling (based on the ios styling) for the range according to UX requirements. ## 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/docs/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. --> ![image](https://github.com/user-attachments/assets/1b78cba4-0f0f-45d4-abdc-d48cdb917ea2)
1 parent b046f37 commit 175dc92

19 files changed

+305
-64
lines changed

core/src/components/range/range.scss renamed to core/src/components/range/range.common.scss

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import "../../themes/native/native.globals";
1+
@import "../../themes/mixins";
22
@import "./range.vars.scss";
33

44
// Range
@@ -18,18 +18,14 @@
1818
* @prop --pin-background: Background of the range pin (only available in MD mode)
1919
* @prop --pin-color: Color of the range pin (only available in MD mode)
2020
*/
21-
--knob-handle-size: calc(var(--knob-size) * 2);
2221

2322
display: flex;
2423
position: relative;
2524

2625
flex: 3;
2726
align-items: center;
2827

29-
font-family: $font-family-base;
30-
3128
user-select: none;
32-
z-index: $z-index-item-input;
3329
}
3430

3531
:host(.range-disabled) {
@@ -40,10 +36,6 @@
4036
flex: initial;
4137
}
4238

43-
::slotted(ion-icon[slot]) {
44-
font-size: 24px;
45-
}
46-
4739
.range-slider {
4840
position: relative;
4941

@@ -214,8 +206,6 @@
214206
* only the label would show and users
215207
* would not be able to see the range.
216208
*/
217-
max-width: 200px;
218-
219209
text-overflow: ellipsis;
220210

221211
white-space: nowrap;
@@ -254,15 +244,6 @@
254244
flex-direction: row;
255245
}
256246

257-
:host(.range-label-placement-start) .label-text-wrapper {
258-
/**
259-
* The margin between the label and
260-
* the range should be on the end
261-
* when the label sits at the start.
262-
*/
263-
@include margin(0, $form-control-label-margin, 0, 0);
264-
}
265-
266247
// Range Label Placement - End
267248
// ----------------------------------------------------------------
268249

@@ -274,27 +255,9 @@
274255
flex-direction: row-reverse;
275256
}
276257

277-
/**
278-
* The margin between the label and
279-
* the range should be on the start
280-
* when the label sits at the end.
281-
*/
282-
:host(.range-label-placement-end) .label-text-wrapper {
283-
@include margin(0, 0, 0, $form-control-label-margin);
284-
}
285-
286258
// Range Label Placement - Fixed
287259
// ----------------------------------------------------------------
288260

289-
:host(.range-label-placement-fixed) .label-text-wrapper {
290-
/**
291-
* The margin between the label and
292-
* the range should be on the end
293-
* when the label sits at the start.
294-
*/
295-
@include margin(0, $form-control-label-margin, 0, 0);
296-
}
297-
298261
/**
299262
* Label is on the left of the range in LTR and
300263
* on the right in RTL. Label also has a fixed width.
@@ -321,26 +284,4 @@
321284

322285
:host(.range-label-placement-stacked) .label-text-wrapper {
323286
@include transform-origin(start, top);
324-
@include transform(scale(#{$form-control-label-stacked-scale}));
325-
326-
/**
327-
* The margin between the label and
328-
* the range should be on the bottom
329-
* when the label sits on top.
330-
*/
331-
@include margin(null, 0, $form-control-label-margin, 0);
332-
333-
/**
334-
* Label text should not extend
335-
* beyond the bounds of the range.
336-
*/
337-
max-width: calc(100% / #{$form-control-label-stacked-scale});
338-
}
339-
340-
:host(.in-item.range-label-placement-stacked) .label-text-wrapper {
341-
@include margin($range-item-label-margin-top, null, $form-control-label-margin, null);
342-
}
343-
344-
:host(.in-item.range-label-placement-stacked) .native-wrapper {
345-
@include margin(null, null, $range-item-label-margin-bottom, null);
346287
}
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
@use "../../themes/ionic/ionic.globals.scss" as globals;
2+
@import "./range.common";
3+
4+
// Ionic Range
5+
// --------------------------------------------------
6+
7+
:host {
8+
--knob-border-radius: #{globals.$ion-border-radius-full};
9+
--knob-background: #{globals.$ion-primitives-base-white};
10+
--knob-box-shadow: none;
11+
--knob-size: #{globals.$ion-scale-600};
12+
--knob-handle-size: #{globals.$ion-scale-1000};
13+
--bar-height: #{globals.$ion-scale-200};
14+
--bar-background: #{globals.$ion-primitives-neutral-100};
15+
--bar-background-active: #{globals.ion-color(primary, base)};
16+
--bar-border-radius: #{globals.$ion-border-radius-400};
17+
--height: #{globals.$ion-scale-1000};
18+
19+
@include globals.typography(globals.$ion-body-md-regular);
20+
21+
z-index: globals.$ion-z-index-100;
22+
}
23+
24+
:host(.range-item-start-adjustment) {
25+
@include padding(null, null, null, globals.$ion-space-600);
26+
}
27+
28+
:host(.range-item-end-adjustment) {
29+
@include padding(null, globals.$ion-space-600, null, null);
30+
}
31+
32+
:host(.ion-color) .range-bar-active,
33+
:host(.ion-color) .range-tick-active {
34+
background: globals.current-color(base);
35+
}
36+
37+
::slotted(ion-icon[slot]) {
38+
font-size: globals.$ion-font-size-600;
39+
}
40+
41+
::slotted([slot="start"]) {
42+
@include margin(0, globals.$ion-space-400, 0, 0);
43+
}
44+
45+
::slotted([slot="end"]) {
46+
@include margin(0, 0, 0, globals.$ion-space-400);
47+
}
48+
49+
::slotted([slot="label"]) {
50+
max-width: globals.$ion-scale-5000;
51+
}
52+
53+
:host(.range-has-pin:not(.range-label-placement-stacked)) {
54+
/**
55+
* The pin should not overlap any elements that are
56+
* above the range. By adding padding to the top of the
57+
* range, it provides a buffer for the pin to move into
58+
* when it is pressed.
59+
*
60+
* The padding is not included when the label is stacked
61+
* because the pin is below the label.
62+
* It still requires a buffer to prevent the pin from
63+
* overlapping the range. The buffer is added to the
64+
* bottom of the range label instead of the host.
65+
*/
66+
@include padding(calc(globals.$ion-space-200 + globals.dynamic-font(12px)), null, null, null);
67+
}
68+
69+
:host(.range-has-pin.range-label-placement-stacked) .label-text-wrapper {
70+
/**
71+
* The pin should not overlap the stacked label. By adding
72+
* margin to the bottom of the label, it provides a buffer
73+
* for the pin to move into when it is pressed.
74+
*/
75+
@include margin(null, null, calc(globals.$ion-space-200 + globals.dynamic-font(12px)), null);
76+
}
77+
78+
.range-bar-active {
79+
bottom: 0;
80+
81+
width: auto;
82+
83+
background: var(--bar-background-active);
84+
85+
&.has-ticks {
86+
@include border-radius(0);
87+
@include margin(null, calc(-1 * globals.$ion-scale-100 * 0.5), null, calc(-1 * globals.$ion-scale-100 * 0.5));
88+
}
89+
}
90+
91+
.range-tick {
92+
@include margin-horizontal(calc(globals.$ion-scale-100 * -0.5), null);
93+
@include border-radius(globals.$ion-border-radius-0);
94+
95+
position: absolute;
96+
top: calc((var(--height) * 0.5) - (globals.$ion-scale-300 * 0.5));
97+
98+
width: globals.$ion-scale-100;
99+
height: globals.$ion-scale-300;
100+
101+
background: globals.$ion-primitives-neutral-100;
102+
pointer-events: none;
103+
}
104+
105+
.range-tick-active {
106+
background: var(--bar-background-active);
107+
}
108+
109+
.range-pin {
110+
@include transform(translate3d(0, 100%, 0), scale(0.01));
111+
@include padding(globals.$ion-space-200, globals.$ion-space-200, globals.$ion-space-200, globals.$ion-space-200);
112+
113+
min-width: globals.$ion-scale-700;
114+
115+
transition: transform 120ms ease;
116+
117+
background: transparent;
118+
119+
font-size: globals.dynamic-font(12px);
120+
121+
text-align: center;
122+
}
123+
124+
.range-knob {
125+
border-width: globals.$ion-border-size-025;
126+
border-style: globals.$ion-border-style-solid;
127+
border-color: globals.ion-color(primary, base);
128+
box-sizing: border-box;
129+
}
130+
131+
/**
132+
* The -100% ensures the pin sits on top
133+
* of the range-knob-handle container.
134+
* We apply 11px so that the pin
135+
* text is closer to the knob inside of the container.
136+
* We also apply the 11px here instead of using "top"
137+
* otherwise the pin text will translate below the knob
138+
* when the text is scaled.
139+
*/
140+
.range-knob-pressed .range-pin,
141+
.range-knob-handle.ion-focused .range-pin {
142+
transform: translate3d(0, calc(-100% + 11px), 0) scale(1);
143+
}
144+
145+
// Ionic Range: Disabled (based on iOS Range)
146+
// --------------------------------------------------
147+
// When the range is disabled, the entire range,
148+
// range label, any slotted labels, and any slotted
149+
// icons need to receive the same opacity.
150+
151+
:host(.range-disabled) {
152+
opacity: 0.3;
153+
}
154+
155+
// Range Label Placement - Start
156+
// ----------------------------------------------------------------
157+
158+
:host(.range-label-placement-start) .label-text-wrapper {
159+
/**
160+
* The margin between the label and
161+
* the range should be on the end
162+
* when the label sits at the start.
163+
*/
164+
@include margin(0, globals.$ion-space-400, 0, 0);
165+
}
166+
167+
// Range Label Placement - End
168+
// ----------------------------------------------------------------
169+
170+
:host(.range-label-placement-end) .label-text-wrapper {
171+
/**
172+
* The margin between the label and
173+
* the range should be on the start
174+
* when the label sits at the end.
175+
*/
176+
@include margin(0, 0, 0, globals.$ion-space-400);
177+
}
178+
179+
// Range Label Placement - Fixed
180+
// ----------------------------------------------------------------
181+
182+
:host(.range-label-placement-fixed) .label-text-wrapper {
183+
/**
184+
* The margin between the label and
185+
* the range should be on the end
186+
* when the label sits at the start.
187+
*/
188+
@include margin(0, globals.$ion-space-400, 0, 0);
189+
}
190+
191+
// Range Label Placement - Stacked
192+
// ----------------------------------------------------------------
193+
194+
:host(.range-label-placement-stacked) .label-text-wrapper {
195+
@include transform(scale(0.75));
196+
197+
/**
198+
* The margin between the label and
199+
* the range should be on the bottom
200+
* when the label sits on top.
201+
*/
202+
@include margin(null, 0, globals.$ion-space-400, 0);
203+
204+
/**
205+
* Label text should not extend
206+
* beyond the bounds of the range.
207+
*/
208+
max-width: calc(100% / 0.75);
209+
}
210+
211+
:host(.in-item.range-label-placement-stacked) .label-text-wrapper {
212+
@include margin(globals.$ion-space-250, null, globals.$ion-space-400, null);
213+
}
214+
215+
:host(.in-item.range-label-placement-stacked) .native-wrapper {
216+
@include margin(null, null, globals.$ion-space-0, null);
217+
}

core/src/components/range/range.ios.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import "./range";
1+
@import "./range.native";
22
@import "./range.ios.vars";
33

44
// iOS Range

core/src/components/range/range.md.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@import "./range";
1+
@import "./range.native";
22
@import "./range.md.vars";
33

44
// Material Design Range

0 commit comments

Comments
 (0)