Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(radio): display as block when justify or alignment properties are defined #29801

Merged
merged 6 commits into from
Aug 29, 2024
Merged
Show file tree
Hide file tree
Changes from 5 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
4 changes: 2 additions & 2 deletions core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1319,10 +1319,10 @@ ion-progress-bar,part,stream
ion-progress-bar,part,track

ion-radio,shadow
ion-radio,prop,alignment,"center" | "start",'center',false,false
ion-radio,prop,alignment,"center" | "start" | undefined,undefined,false,false
ion-radio,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
ion-radio,prop,disabled,boolean,false,false,false
ion-radio,prop,justify,"end" | "space-between" | "start",'space-between',false,false
ion-radio,prop,justify,"end" | "space-between" | "start" | undefined,undefined,false,false
ion-radio,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
ion-radio,prop,mode,"ios" | "md",undefined,false,false
ion-radio,prop,name,string,this.inputId,false,false
Expand Down
12 changes: 6 additions & 6 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2248,9 +2248,9 @@ export namespace Components {
}
interface IonRadio {
/**
* 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.
* 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`.
*/
"alignment": 'start' | 'center';
"alignment"?: 'start' | 'center';
/**
* 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).
*/
Expand All @@ -2260,9 +2260,9 @@ export namespace Components {
*/
"disabled": boolean;
/**
* 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.
* 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`.
*/
"justify": 'start' | 'end' | 'space-between';
"justify"?: 'start' | 'end' | 'space-between';
/**
* 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.
*/
Expand Down Expand Up @@ -6939,7 +6939,7 @@ declare namespace LocalJSX {
}
interface IonRadio {
/**
* 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.
* 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`.
*/
"alignment"?: 'start' | 'center';
/**
Expand All @@ -6951,7 +6951,7 @@ declare namespace LocalJSX {
*/
"disabled"?: boolean;
/**
* 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.
* 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`.
*/
"justify"?: 'start' | 'end' | 'space-between';
/**
Expand Down
15 changes: 15 additions & 0 deletions core/src/components/radio/radio.scss
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ input {
flex-grow: 1;

align-items: center;
justify-content: space-between;

height: inherit;

Expand Down Expand Up @@ -165,6 +166,20 @@ input {
align-items: center;
}

// Justify Content & Align Items
// ---------------------------------------------

// The radio should be displayed as block when either justify
// or alignment is set; otherwise, these properties will have no
// visible effect.
:host(.radio-justify-space-between),
:host(.radio-justify-start),
:host(.radio-justify-end),
:host(.radio-alignment-start),
:host(.radio-alignment-center) {
display: block;
}

// Radio Label Placement - Start
// ----------------------------------------------------------------

Expand Down
10 changes: 6 additions & 4 deletions core/src/components/radio/radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,17 @@ export class Radio implements ComponentInterface {
* 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`.
*/
@Prop() justify: 'start' | 'end' | 'space-between' = 'space-between';
@Prop() justify?: 'start' | 'end' | 'space-between';

/**
* 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`.
*/
@Prop() alignment: 'start' | 'center' = 'center';
@Prop() alignment?: 'start' | 'center';

/**
* Emitted when the radio button has focus.
Expand Down Expand Up @@ -223,8 +225,8 @@ export class Radio implements ComponentInterface {
'in-item': inItem,
'radio-checked': checked,
'radio-disabled': disabled,
[`radio-justify-${justify}`]: true,
[`radio-alignment-${alignment}`]: true,
[`radio-justify-${justify}`]: justify !== undefined,
[`radio-alignment-${alignment}`]: alignment !== undefined,
[`radio-label-placement-${labelPlacement}`]: true,
// Focus and active styling should not apply when the radio is in an item
'ion-activatable': !inItem,
Expand Down
32 changes: 23 additions & 9 deletions core/src/components/radio/test/basic/index.html
brandyscarney marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@

<style>
ion-radio {
display: block;
margin-bottom: 8px;
}

hr {
background: #ddd;
}
</style>
</head>

Expand All @@ -31,17 +34,28 @@

<ion-content class="ion-padding">
<div id="radios">
<ion-radio-group>
<ion-radio value="radio" justify="start" label-placement="end">Unchecked</ion-radio>
</ion-radio-group>
<ion-radio-group> <ion-radio value="radio" label-placement="end">Unchecked</ion-radio> </ion-radio-group
><br />
<ion-radio-group value="radio">
<ion-radio value="radio" justify="start" label-placement="end">Checked</ion-radio>
</ion-radio-group>
<ion-radio value="radio" label-placement="end">Checked</ion-radio> </ion-radio-group
><br />
<ion-radio-group>
<ion-radio value="radio" justify="start" label-placement="end" disabled>Disabled</ion-radio>
</ion-radio-group>
<ion-radio value="radio" label-placement="end" disabled>Disabled</ion-radio> </ion-radio-group
><br />
<ion-radio-group value="radio">
<ion-radio value="radio" label-placement="end" disabled>Disabled, Checked</ion-radio> </ion-radio-group
><br />

<hr />

<ion-radio-group value="radio"> <ion-radio value="radio">Default width</ion-radio> </ion-radio-group><br />

<ion-radio-group value="radio">
<ion-radio value="radio" style="width: 200px">Specified width </ion-radio> </ion-radio-group
><br />

<ion-radio-group value="radio">
<ion-radio value="radio" justify="start" label-placement="end" disabled>Disabled, Checked</ion-radio>
<ion-radio value="radio" style="width: 100%">Full-width </ion-radio>
</ion-radio-group>
</div>
</ion-content>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 0 additions & 4 deletions core/src/components/radio/test/label-placement/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,6 @@
padding: 0;
}
}

ion-radio {
width: 100%;
}
</style>
</head>

Expand Down
87 changes: 68 additions & 19 deletions core/src/components/radio/test/label-placement/radio.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,55 @@ import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

/**
* By default ion-radio only takes up
* as much space as it needs. Justification is
* used for when the radio takes up the full
* line (such as in an ion-item). As a result,
* we set the width of the radio so we can
* see the justification results.
* By default ion-radio only takes up as much space
* as it needs. Justification is used for when the
* radio should take up the full line (such as in an
* ion-item or when it has 100% width).
*/

configs().forEach(({ title, screenshot, config }) => {
test.describe(title('radio: label'), () => {
test.describe('radio: default placement', () => {
test('should render a space between justification with a full width radio', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio value="1" style="width: 100%">
Label
</ion-radio>
</ion-radio-group>
`,
config
);

const radio = page.locator('ion-radio');
await expect(radio).toHaveScreenshot(screenshot(`radio-label-full-width`));
});

test('should truncate long labels with ellipses', async ({ page }) => {
// radio needs to be full width to truncate properly
// because it is not inside of an `ion-app` in tests
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio value="1" style="width: 100%">
Long Label Long Label Long Label Long Label Long Label Long Label
</ion-radio>
</ion-radio-group>
`,
config
);

const radio = page.locator('ion-radio');
await expect(radio).toHaveScreenshot(screenshot(`radio-label-long-label`));
});
});

test.describe('radio: start placement', () => {
test('should render a start justification with label in the start position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="start" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="start" justify="start" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -30,7 +63,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="end" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="start" justify="end" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -43,7 +76,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="start" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="start" justify="space-between" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -52,14 +85,30 @@ configs().forEach(({ title, screenshot, config }) => {
const radio = page.locator('ion-radio');
await expect(radio).toHaveScreenshot(screenshot(`radio-label-start-justify-space-between`));
});

test('should truncate long labels with ellipses', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio value="1" label-placement="start" justify="start">
Long Label Long Label Long Label Long Label Long Label Long Label
</ion-radio>
</ion-radio-group>
`,
config
);

const radio = page.locator('ion-radio');
await expect(radio).toHaveScreenshot(screenshot(`radio-label-start-justify-start-long-label`));
});
});

test.describe('radio: end placement', () => {
test('should render a start justification with label in the end position', async ({ page }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="start" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="end" justify="start" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -72,7 +121,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="end" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="end" justify="end" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -85,7 +134,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="end" justify="space-between" style="width: 200px" value="1">Label</ion-radio>
<ion-radio label-placement="end" justify="space-between" value="1">Label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -101,7 +150,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="start" style="width: 200px" value="1">This is a long label</ion-radio>
<ion-radio label-placement="fixed" justify="start" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -114,7 +163,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="end" style="width: 200px" value="1">This is a long label</ion-radio>
<ion-radio label-placement="fixed" justify="end" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -127,7 +176,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="fixed" justify="space-between" style="width: 200px" value="1">This is a long label</ion-radio>
<ion-radio label-placement="fixed" justify="space-between" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -142,7 +191,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="stacked" alignment="start" style="width: 200px" value="1">This is a long label</ion-radio>
<ion-radio label-placement="stacked" alignment="start" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -156,7 +205,7 @@ configs().forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<ion-radio-group value="1">
<ion-radio label-placement="stacked" alignment="center" style="width: 200px" value="1">This is a long label</ion-radio>
<ion-radio label-placement="stacked" alignment="center" value="1">This is a long label</ion-radio>
</ion-radio-group>
`,
config
Expand All @@ -174,7 +223,7 @@ configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config, screen
test('long label should truncate', async ({ page }) => {
await page.setContent(
`
<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>
<ion-radio label-placement="stacked" alignment="start">Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications Enable Notifications</ion-radio>
`,
config
);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading