Skip to content

Commit 18b02b3

Browse files
feat(radio): display as block when justify or alignment properties are defined (#29801)
- Change the radio's `display` property to `block` when the `justify` or `alignment` property is set. - Set the default `justify-content` style to `space-between` so that a radio with `width: 100%` set without `justify` or `alignment` set will still have the same default - Modifies the `label-placement` e2e test to remove the explicit width as setting the property will make them full-width - Adds two examples to the `label-placement` e2e test of labels that do not have `justify` set but use `width: 100%` to ensure they are working as expected without it - Adds one example to the `label-placement` e2e test of a long label that uses `justify` to ensure it still wraps properly
1 parent 0332c8c commit 18b02b3

File tree

181 files changed

+120
-44
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+120
-44
lines changed

core/api.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,10 +1319,10 @@ ion-progress-bar,part,stream
13191319
ion-progress-bar,part,track
13201320

13211321
ion-radio,shadow
1322-
ion-radio,prop,alignment,"center" | "start",'center',false,false
1322+
ion-radio,prop,alignment,"center" | "start" | undefined,undefined,false,false
13231323
ion-radio,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
13241324
ion-radio,prop,disabled,boolean,false,false,false
1325-
ion-radio,prop,justify,"end" | "space-between" | "start",'space-between',false,false
1325+
ion-radio,prop,justify,"end" | "space-between" | "start" | undefined,undefined,false,false
13261326
ion-radio,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
13271327
ion-radio,prop,mode,"ios" | "md",undefined,false,false
13281328
ion-radio,prop,name,string,this.inputId,false,false

core/src/components.d.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2248,9 +2248,9 @@ export namespace Components {
22482248
}
22492249
interface IonRadio {
22502250
/**
2251-
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
2251+
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL. Setting this property will change the radio `display` to `block`.
22522252
*/
2253-
"alignment": 'start' | 'center';
2253+
"alignment"?: 'start' | 'center';
22542254
/**
22552255
* The color to use from your application's color palette. Default options are: `"primary"`, `"secondary"`, `"tertiary"`, `"success"`, `"warning"`, `"danger"`, `"light"`, `"medium"`, and `"dark"`. For more information on colors, see [theming](/docs/theming/basics).
22562256
*/
@@ -2260,9 +2260,9 @@ export namespace Components {
22602260
*/
22612261
"disabled": boolean;
22622262
/**
2263-
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements.
2263+
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements. Setting this property will change the radio `display` to `block`.
22642264
*/
2265-
"justify": 'start' | 'end' | 'space-between';
2265+
"justify"?: 'start' | 'end' | 'space-between';
22662266
/**
22672267
* Where to place the label relative to the radio. `"start"`: The label will appear to the left of the radio in LTR and to the right in RTL. `"end"`: The label will appear to the right of the radio in LTR and to the left in RTL. `"fixed"`: The label has the same behavior as `"start"` except it also has a fixed width. Long text will be truncated with ellipses ("..."). `"stacked"`: The label will appear above the radio regardless of the direction. The alignment of the label can be controlled with the `alignment` property.
22682268
*/
@@ -6939,7 +6939,7 @@ declare namespace LocalJSX {
69396939
}
69406940
interface IonRadio {
69416941
/**
6942-
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
6942+
* How to control the alignment of the radio and label on the cross axis. `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL. `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL. Setting this property will change the radio `display` to `block`.
69436943
*/
69446944
"alignment"?: 'start' | 'center';
69456945
/**
@@ -6951,7 +6951,7 @@ declare namespace LocalJSX {
69516951
*/
69526952
"disabled"?: boolean;
69536953
/**
6954-
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements.
6954+
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements. Setting this property will change the radio `display` to `block`.
69556955
*/
69566956
"justify"?: 'start' | 'end' | 'space-between';
69576957
/**

core/src/components/radio/radio.scss

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ input {
9090
flex-grow: 1;
9191

9292
align-items: center;
93+
justify-content: space-between;
9394

9495
height: inherit;
9596

@@ -165,6 +166,20 @@ input {
165166
align-items: center;
166167
}
167168

169+
// Justify Content & Align Items
170+
// ---------------------------------------------
171+
172+
// The radio should be displayed as block when either justify
173+
// or alignment is set; otherwise, these properties will have no
174+
// visible effect.
175+
:host(.radio-justify-space-between),
176+
:host(.radio-justify-start),
177+
:host(.radio-justify-end),
178+
:host(.radio-alignment-start),
179+
:host(.radio-alignment-center) {
180+
display: block;
181+
}
182+
168183
// Radio Label Placement - Start
169184
// ----------------------------------------------------------------
170185

core/src/components/radio/radio.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,17 @@ export class Radio implements ComponentInterface {
9090
* on the left in RTL.
9191
* `"space-between"`: The label and radio will appear on opposite
9292
* ends of the line with space between the two elements.
93+
* Setting this property will change the radio `display` to `block`.
9394
*/
94-
@Prop() justify: 'start' | 'end' | 'space-between' = 'space-between';
95+
@Prop() justify?: 'start' | 'end' | 'space-between';
9596

9697
/**
9798
* How to control the alignment of the radio and label on the cross axis.
9899
* `"start"`: The label and control will appear on the left of the cross axis in LTR, and on the right side in RTL.
99100
* `"center"`: The label and control will appear at the center of the cross axis in both LTR and RTL.
101+
* Setting this property will change the radio `display` to `block`.
100102
*/
101-
@Prop() alignment: 'start' | 'center' = 'center';
103+
@Prop() alignment?: 'start' | 'center';
102104

103105
/**
104106
* Emitted when the radio button has focus.
@@ -223,8 +225,8 @@ export class Radio implements ComponentInterface {
223225
'in-item': inItem,
224226
'radio-checked': checked,
225227
'radio-disabled': disabled,
226-
[`radio-justify-${justify}`]: true,
227-
[`radio-alignment-${alignment}`]: true,
228+
[`radio-justify-${justify}`]: justify !== undefined,
229+
[`radio-alignment-${alignment}`]: alignment !== undefined,
228230
[`radio-label-placement-${labelPlacement}`]: true,
229231
// Focus and active styling should not apply when the radio is in an item
230232
'ion-activatable': !inItem,

core/src/components/radio/test/basic/index.html

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,12 @@
1515

1616
<style>
1717
ion-radio {
18-
display: block;
1918
margin-bottom: 8px;
2019
}
20+
21+
hr {
22+
background: #ddd;
23+
}
2124
</style>
2225
</head>
2326

@@ -31,17 +34,28 @@
3134

3235
<ion-content class="ion-padding">
3336
<div id="radios">
34-
<ion-radio-group>
35-
<ion-radio value="radio" justify="start" label-placement="end">Unchecked</ion-radio>
36-
</ion-radio-group>
37+
<ion-radio-group> <ion-radio value="radio" label-placement="end">Unchecked</ion-radio> </ion-radio-group
38+
><br />
3739
<ion-radio-group value="radio">
38-
<ion-radio value="radio" justify="start" label-placement="end">Checked</ion-radio>
39-
</ion-radio-group>
40+
<ion-radio value="radio" label-placement="end">Checked</ion-radio> </ion-radio-group
41+
><br />
4042
<ion-radio-group>
41-
<ion-radio value="radio" justify="start" label-placement="end" disabled>Disabled</ion-radio>
42-
</ion-radio-group>
43+
<ion-radio value="radio" label-placement="end" disabled>Disabled</ion-radio> </ion-radio-group
44+
><br />
45+
<ion-radio-group value="radio">
46+
<ion-radio value="radio" label-placement="end" disabled>Disabled, Checked</ion-radio> </ion-radio-group
47+
><br />
48+
49+
<hr />
50+
51+
<ion-radio-group value="radio"> <ion-radio value="radio">Default width</ion-radio> </ion-radio-group><br />
52+
53+
<ion-radio-group value="radio">
54+
<ion-radio value="radio" style="width: 200px">Specified width </ion-radio> </ion-radio-group
55+
><br />
56+
4357
<ion-radio-group value="radio">
44-
<ion-radio value="radio" justify="start" label-placement="end" disabled>Disabled, Checked</ion-radio>
58+
<ion-radio value="radio" style="width: 100%">Full-width </ion-radio>
4559
</ion-radio-group>
4660
</div>
4761
</ion-content>

core/src/components/radio/test/label-placement/index.html

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,6 @@
3535
padding: 0;
3636
}
3737
}
38-
39-
ion-radio {
40-
width: 100%;
41-
}
4238
</style>
4339
</head>
4440

core/src/components/radio/test/label-placement/radio.e2e.ts

Lines changed: 68 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,55 @@ import { expect } from '@playwright/test';
22
import { configs, test } from '@utils/test/playwright';
33

44
/**
5-
* By default ion-radio only takes up
6-
* as much space as it needs. Justification is
7-
* used for when the radio takes up the full
8-
* line (such as in an ion-item). As a result,
9-
* we set the width of the radio so we can
10-
* see the justification results.
5+
* By default ion-radio only takes up as much space
6+
* as it needs. Justification is used for when the
7+
* radio should take up the full line (such as in an
8+
* ion-item or when it has 100% width).
119
*/
12-
1310
configs().forEach(({ title, screenshot, config }) => {
1411
test.describe(title('radio: label'), () => {
12+
test.describe('radio: default placement', () => {
13+
test('should render a space between justification with a full width radio', async ({ page }) => {
14+
await page.setContent(
15+
`
16+
<ion-radio-group value="1">
17+
<ion-radio value="1" style="width: 100%">
18+
Label
19+
</ion-radio>
20+
</ion-radio-group>
21+
`,
22+
config
23+
);
24+
25+
const radio = page.locator('ion-radio');
26+
await expect(radio).toHaveScreenshot(screenshot(`radio-label-full-width`));
27+
});
28+
29+
test('should truncate long labels with ellipses', async ({ page }) => {
30+
// radio needs to be full width to truncate properly
31+
// because it is not inside of an `ion-app` in tests
32+
await page.setContent(
33+
`
34+
<ion-radio-group value="1">
35+
<ion-radio value="1" style="width: 100%">
36+
Long Label Long Label Long Label Long Label Long Label Long Label
37+
</ion-radio>
38+
</ion-radio-group>
39+
`,
40+
config
41+
);
42+
43+
const radio = page.locator('ion-radio');
44+
await expect(radio).toHaveScreenshot(screenshot(`radio-label-long-label`));
45+
});
46+
});
47+
1548
test.describe('radio: start placement', () => {
1649
test('should render a start justification with label in the start position', async ({ page }) => {
1750
await page.setContent(
1851
`
1952
<ion-radio-group value="1">
20-
<ion-radio label-placement="start" justify="start" style="width: 200px" value="1">Label</ion-radio>
53+
<ion-radio label-placement="start" justify="start" value="1">Label</ion-radio>
2154
</ion-radio-group>
2255
`,
2356
config
@@ -30,7 +63,7 @@ configs().forEach(({ title, screenshot, config }) => {
3063
await page.setContent(
3164
`
3265
<ion-radio-group value="1">
33-
<ion-radio label-placement="start" justify="end" style="width: 200px" value="1">Label</ion-radio>
66+
<ion-radio label-placement="start" justify="end" value="1">Label</ion-radio>
3467
</ion-radio-group>
3568
`,
3669
config
@@ -43,7 +76,7 @@ configs().forEach(({ title, screenshot, config }) => {
4376
await page.setContent(
4477
`
4578
<ion-radio-group value="1">
46-
<ion-radio label-placement="start" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
79+
<ion-radio label-placement="start" justify="space-between" value="1">Label</ion-radio>
4780
</ion-radio-group>
4881
`,
4982
config
@@ -52,14 +85,30 @@ configs().forEach(({ title, screenshot, config }) => {
5285
const radio = page.locator('ion-radio');
5386
await expect(radio).toHaveScreenshot(screenshot(`radio-label-start-justify-space-between`));
5487
});
88+
89+
test('should truncate long labels with ellipses', async ({ page }) => {
90+
await page.setContent(
91+
`
92+
<ion-radio-group value="1">
93+
<ion-radio value="1" label-placement="start" justify="start">
94+
Long Label Long Label Long Label Long Label Long Label Long Label
95+
</ion-radio>
96+
</ion-radio-group>
97+
`,
98+
config
99+
);
100+
101+
const radio = page.locator('ion-radio');
102+
await expect(radio).toHaveScreenshot(screenshot(`radio-label-start-justify-start-long-label`));
103+
});
55104
});
56105

57106
test.describe('radio: end placement', () => {
58107
test('should render a start justification with label in the end position', async ({ page }) => {
59108
await page.setContent(
60109
`
61110
<ion-radio-group value="1">
62-
<ion-radio label-placement="end" justify="start" style="width: 200px" value="1">Label</ion-radio>
111+
<ion-radio label-placement="end" justify="start" value="1">Label</ion-radio>
63112
</ion-radio-group>
64113
`,
65114
config
@@ -72,7 +121,7 @@ configs().forEach(({ title, screenshot, config }) => {
72121
await page.setContent(
73122
`
74123
<ion-radio-group value="1">
75-
<ion-radio label-placement="end" justify="end" style="width: 200px" value="1">Label</ion-radio>
124+
<ion-radio label-placement="end" justify="end" value="1">Label</ion-radio>
76125
</ion-radio-group>
77126
`,
78127
config
@@ -85,7 +134,7 @@ configs().forEach(({ title, screenshot, config }) => {
85134
await page.setContent(
86135
`
87136
<ion-radio-group value="1">
88-
<ion-radio label-placement="end" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
137+
<ion-radio label-placement="end" justify="space-between" value="1">Label</ion-radio>
89138
</ion-radio-group>
90139
`,
91140
config
@@ -101,7 +150,7 @@ configs().forEach(({ title, screenshot, config }) => {
101150
await page.setContent(
102151
`
103152
<ion-radio-group value="1">
104-
<ion-radio label-placement="fixed" justify="start" style="width: 200px" value="1">This is a long label</ion-radio>
153+
<ion-radio label-placement="fixed" justify="start" value="1">This is a long label</ion-radio>
105154
</ion-radio-group>
106155
`,
107156
config
@@ -114,7 +163,7 @@ configs().forEach(({ title, screenshot, config }) => {
114163
await page.setContent(
115164
`
116165
<ion-radio-group value="1">
117-
<ion-radio label-placement="fixed" justify="end" style="width: 200px" value="1">This is a long label</ion-radio>
166+
<ion-radio label-placement="fixed" justify="end" value="1">This is a long label</ion-radio>
118167
</ion-radio-group>
119168
`,
120169
config
@@ -127,7 +176,7 @@ configs().forEach(({ title, screenshot, config }) => {
127176
await page.setContent(
128177
`
129178
<ion-radio-group value="1">
130-
<ion-radio label-placement="fixed" justify="space-between" style="width: 200px" value="1">This is a long label</ion-radio>
179+
<ion-radio label-placement="fixed" justify="space-between" value="1">This is a long label</ion-radio>
131180
</ion-radio-group>
132181
`,
133182
config
@@ -142,7 +191,7 @@ configs().forEach(({ title, screenshot, config }) => {
142191
await page.setContent(
143192
`
144193
<ion-radio-group value="1">
145-
<ion-radio label-placement="stacked" alignment="start" style="width: 200px" value="1">This is a long label</ion-radio>
194+
<ion-radio label-placement="stacked" alignment="start" value="1">This is a long label</ion-radio>
146195
</ion-radio-group>
147196
`,
148197
config
@@ -156,7 +205,7 @@ configs().forEach(({ title, screenshot, config }) => {
156205
await page.setContent(
157206
`
158207
<ion-radio-group value="1">
159-
<ion-radio label-placement="stacked" alignment="center" style="width: 200px" value="1">This is a long label</ion-radio>
208+
<ion-radio label-placement="stacked" alignment="center" value="1">This is a long label</ion-radio>
160209
</ion-radio-group>
161210
`,
162211
config
@@ -174,7 +223,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config, screen
174223
test('long label should truncate', async ({ page }) => {
175224
await page.setContent(
176225
`
177-
<ion-radio label-placement="stacked" alignment="start" style="width: 200px">Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications</ion-radio>
226+
<ion-radio label-placement="stacked" alignment="start">Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications</ion-radio>
178227
`,
179228
config
180229
);

0 commit comments

Comments
 (0)