fix(list): remove border from last item with item-sliding (#28439)

Issue number: resolves #28435

---------

<!-- 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?
<!-- Please describe the current behavior that you are modifying. -->

The item in the last item-sliding still has a border in an inset list.

## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->

- Item in last item-sliding no longer has a border

I originally only added `ion-item-sliding:last-of-type ion-item` but I
discovered that the original `ion-item:last-child` causes items in
item-sliding where the item is the last element in the item-sliding
container to not have a border, so the original fix was incomplete.

I added comments as to what each line does and why we didn't just do
`ion-item:last-child`.

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->


## Other information

<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->

--------

Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Brandy Carney <brandyscarney@users.noreply.github.com>
This commit is contained in:
Liam DeBeasi
2023-11-03 10:37:45 -04:00
committed by GitHub
parent 00c3a4431a
commit cafafcc9d1
21 changed files with 215 additions and 5 deletions

View File

@ -19,12 +19,25 @@
@include border-radius($list-inset-ios-border-radius); @include border-radius($list-inset-ios-border-radius);
} }
.list-ios.list-inset ion-item:last-child { /**
* These selectors ensure the last item in the list
* has the correct border.
* We need to consider the following scenarios:
1. The only item in a list.
2. The last item in a list as long as it is not the only item.
3. The item in the last item-sliding in a list.
* Note that we do not select ion-item:last-of-type
* because that will cause the borders to disappear on
* items in an item-sliding when the item is the last
* element in the item-sliding container.
*/
.list-ios.list-inset ion-item:only-child,
.list-ios.list-inset ion-item:not(:only-of-type):last-of-type,
.list-ios.list-inset ion-item-sliding:last-of-type ion-item {
--border-width: 0; --border-width: 0;
--inner-border-width: 0; --inner-border-width: 0;
} }
.list-ios.list-inset + ion-list.list-inset { .list-ios.list-inset + ion-list.list-inset {
@include margin(0, null, null, null); @include margin(0, null, null, null);
} }

View File

@ -23,12 +23,50 @@
@include border-radius($list-inset-md-border-radius); @include border-radius($list-inset-md-border-radius);
} }
.list-md.list-inset ion-item:first-child { /**
* These selectors ensure the first item in the list
* has the correct radius.
* We need to consider the following scenarios:
1. The first item in a list as long as it is not the only item.
2. The item in the first item-sliding in a list.
* Note that we do not select "ion-item-sliding ion-item:first-of-type"
* because that will cause the borders to disappear on
* items in an item-sliding when the item is the first
* element in the item-sliding container.
*/
.list-md.list-inset ion-item:not(:only-of-type):first-of-type,
.list-md.list-inset ion-item-sliding:first-of-type ion-item {
--border-radius: #{$list-inset-md-border-radius $list-inset-md-border-radius 0 0}; --border-radius: #{$list-inset-md-border-radius $list-inset-md-border-radius 0 0};
} }
.list-md.list-inset ion-item:last-child { /**
--border-radius: #{0 0 $list-inset-md-border-radius, $list-inset-md-border-radius}; * These selectors ensure the last item in the list
* has the correct radius and border.
* We need to consider the following scenarios:
1. The last item in a list as long as it is not the only item.
2. The item in the last item-sliding in a list.
* Note that we do not select "ion-item-sliding ion-item:last-of-type"
* because that will cause the borders to disappear on
* items in an item-sliding when the item is the last
* element in the item-sliding container.
*/
.list-md.list-inset ion-item:not(:only-of-type):last-of-type,
.list-md.list-inset ion-item-sliding:last-of-type ion-item {
--border-radius: #{0 0 $list-inset-md-border-radius $list-inset-md-border-radius};
--border-width: 0;
--inner-border-width: 0;
}
/**
* The only item in a list should have a border radius
* on all corners.
* We target :only-child instead of :only-of-type
* otherwise borders will disappear on items inside of
* ion-item-sliding because the item will be the only
* one of its type inside of the ion-item-sliding group.
*/
.list-md.list-inset ion-item:only-child {
--border-radius: #{$list-inset-md-border-radius};
--border-width: 0; --border-width: 0;
--inner-border-width: 0; --inner-border-width: 0;
} }

View File

@ -26,3 +26,162 @@ configs().forEach(({ title, screenshot, config }) => {
}); });
}); });
}); });
/**
* Padding and border color ensures the bottom border can be easily seen if it regresses.
* The background color ensures that any border radius values can be seen.
*/
configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('list: lines with children'), () => {
test('only item in inset list should not have line', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/28435',
});
await page.setContent(
`
<style>
#container {
padding: 10px;
background: #0088cc;
}
ion-item {
--border-color: red;
}
</style>
<div id="container">
<ion-list inset="true">
<ion-item>
<ion-label>Item 0</ion-label>
</ion-item>
</ion-list>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot('inset-list-only-item-no-lines'));
});
test('last item in inset list with end options should not have line', async ({ page }) => {
test.info().annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/28435',
});
await page.setContent(
`
<style>
#container {
padding: 10px;
background: #0088cc;
}
ion-item {
--border-color: red;
}
</style>
<div id="container">
<ion-list inset="true">
<ion-item-sliding>
<ion-item>
<ion-label>Item 0</ion-label>
</ion-item>
<ion-item-options slot="end">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
<ion-item-sliding>
<ion-item>
<ion-label>Item 1</ion-label>
</ion-item>
<ion-item-options slot="end">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
<ion-item-sliding>
<ion-item>
<ion-label>Item 2</ion-label>
</ion-item>
<ion-item-options slot="end">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
</ion-item-sliding>
</ion-list>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot('inset-list-end-options-no-lines'));
});
test('last item in inset list with start options should not have line', async ({ page }) => {
await page.setContent(
`
<style>
#container {
padding: 10px;
background: #0088cc;
}
ion-item {
--border-color: red;
}
</style>
<div id="container">
<ion-list inset="true">
<ion-item-sliding>
<ion-item-options slot="start">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
<ion-item>
<ion-label>Item 0</ion-label>
</ion-item>
</ion-item-sliding>
<ion-item-sliding>
<ion-item-options slot="start">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
<ion-item>
<ion-label>Item 1</ion-label>
</ion-item>
</ion-item-sliding>
<ion-item-sliding>
<ion-item-options slot="start">
<ion-item-option color="warning">
<ion-icon slot="icon-only" name="pin"></ion-icon>
</ion-item-option>
</ion-item-options>
<ion-item>
<ion-label>Item 2</ion-label>
</ion-item>
</ion-item-sliding>
</ion-list>
</div>
`,
config
);
const container = page.locator('#container');
await expect(container).toHaveScreenshot(screenshot('inset-list-start-options-no-lines'));
});
});
});