fix(select): do not collapse to width: 0 when placed in flex container (#28631)

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

We currently apply a workaround to `ion-select` so it can wrap correctly
inside of `ion-item`:
357b8b2beb/core/src/components/select/select.scss (L99-L103)

However, this causes issues when a parent element has `display: flex`
because the `ion-select` width becomes 0.

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

- In order to get the desired behavior, we need the `ion-select` (and
other elements in the default slot) to either truncate or wrap within
its own container and then have the entire container (i.e. the entire
`ion-select`) wrap to the next line once the container is too small.

To achieve this, I needed to set a min-width on `.item-inner` to define
the point at which the element should wrap to the next line. I also
changed the flex basis from `auto` to `0` which means the initial main
size of the flex item will be 0px. In reality, this will be
`--inner-min-width` since we also set `min-width:
var(--inner-min-width)`. I used `0` for simplicity but I can change this
to use the CSS variable if that's more clear. Since we also set
`flex-grow: 1` we indicate that the element can grow from that basis
(but it cannot shrink).

I chose `--inner-min-width: 4rem` to minimize the number of diffs. We
can certainly change this, but it may cause some diffs as certain
elements will start wrapping sooner. I also chose to use `rem` because
having a fixed min-width means that fewer characters are going to fit in
the same space as text scales.

I made this a CSS variable but left it undocumented. If developers need
a way of changing this `min-width` they can request it and we can easily
expose this variable. However, I think `4rem` is small enough that this
should be sufficient.

## 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. -->

The visual diffs here are correct. The table below shows the screenshot
group and an explanation for why the changes are correct.


| Path | Example | Details |
| - | - | - |
| `disabled` |
[Link](https://github.com/ionic-team/ionic-framework/pull/28631/files#diff-d529716f95f7a7aa82c88588104220775b728af67077f48cd47a8afa04423143)
| The searchbar is able to shrink slightly to fit on the same line as
the checkbox at the bottom. |
| `highlight` |
[Link](https://github.com/ionic-team/ionic-framework/pull/28631/files#diff-0b64f24c91393923701d1ced4e330a1c6b926d72ee461b8ab1e135e708be3457)
| We're changing how small the main content can get, so the input is
only wrapping once it gets to `--inner-min-width`. |
| `legacy/fill` |
[Link](https://github.com/ionic-team/ionic-framework/pull/28631/files#diff-2ef8dbfa5e69e2b96c3e1ed29ab962f08cf5ba2aaf2af773e40bd143e38a4bef)
| We're changing how small the main content can get, so the input is
only wrapping once it gets to `--inner-min-width`. |
| `slotted-inputs` |
[Link](https://github.com/ionic-team/ionic-framework/pull/28631/files#diff-2f173c7303969d6a6c58f30a618cebc3caf918d3761fc83df5642fd48dfabd7b)
| We're changing how small the main content can get, so the range is
only wrapping once it gets to `--inner-min-width`. |

`slotted-inputs` note: I'd argue many of these examples are not best
practices. For example, adding a range in the start slot and the end
slot is a bit unusual. I'm not aware of any native apps that implement
this pattern.

popover note: I [removed the `ion-item` from the `popover/test/async`
test](331fcb859c).
There was a diff because the min-width increased, but IMO that component
should not be used in the popover test since we want to test the
popover, not the item.

--------

Demo:

| `feature-7.6` | `branch` |
| - | - |
| <video
src="https://github.com/ionic-team/ionic-framework/assets/2721089/693d4947-fa33-460d-bc7f-7b96b6338032"></video>
| <video
src="https://github.com/ionic-team/ionic-framework/assets/2721089/df35ca73-87aa-4e76-9bb7-99f0f2810640"></video>
|

(In this demo I updated the `ion-select` to wrap within its own
container first instead of truncate. We may want to consider doing this
by default, but I think this is out of scope for this task)

---------

Co-authored-by: ionitron <hi@ionicframework.com>
Co-authored-by: Brandy Carney <brandy@ionic.io>
This commit is contained in:
Liam DeBeasi
2023-12-05 18:33:02 -05:00
committed by GitHub
parent 8c235fd30c
commit e71e7a0690
46 changed files with 30 additions and 24 deletions

View File

@ -51,6 +51,15 @@
* @prop --highlight-color-valid: The color of the highlight on the item when valid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
* @prop --highlight-color-invalid: The color of the highlight on the item when invalid. Only applies to inputs and textareas using the legacy form syntax. DEPRECATED: Highlights can be styled on `ion-input` or `ion-textarea` when using the modern form syntax.
*/
/**
* We change the minimum width as the
* font size changes. Using a fixed minimum
* width means that fewer and fewer characters
* can be displayed in the same space as the
* text grows.
*/
--inner-min-width: 4rem;
--border-radius: 0px;
--border-width: 0px;
--border-style: solid;
@ -80,15 +89,6 @@
position: relative;
// When an item containing a select is inside of a
// flex container the item will collapse to 0px
// width due to the select setting the width to 0px.
// By setting the flex property here, we are
// allowing the item to grow to fill the flex container.
// If the item is inside of a block container this
// property will be ignored.
flex: 1;
align-items: center;
justify-content: space-between;
@ -310,7 +310,7 @@ button, a {
// This flex property is required in order to make
// the elements wrap when there is a slotted start
// element and a label
flex: 1 0 auto;
flex: 1 0 0;
flex-direction: inherit;
@ -322,6 +322,15 @@ button, a {
align-items: inherit;
align-self: stretch;
/**
* The min-width defines when the
* content in the default slot should
* stop wrapping/truncating within its own
* container. At this point the entire
* container will wrap to the next line.
*/
min-width: var(--inner-min-width);
// Max width must be set to 100%, otherwise the
// elements will overflow this container instead
// of wrapping

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 240 KiB

After

Width:  |  Height:  |  Size: 228 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 KiB

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 197 KiB

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 230 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 238 KiB

After

Width:  |  Height:  |  Size: 234 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -40,9 +40,7 @@
popover.addEventListener('ionMount', () => {
popover.innerHTML = `
<div style="padding: 10px;">
<ion-list>
<ion-item>Item 1</ion-item>
</ion-list>
Popover Content
</div>
`;
});

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

View File

@ -92,14 +92,11 @@
// TODO FW-3194 - Remove the :not(.legacy-select) piece
//
// The flex and width properties are required here
// in order to allow the select to shrink inside of an item
// otherwise it always wraps to the next line even
// when it can shrink
// The flex property is required here in order to allow
// the select to shrink inside of an item otherwise it
// always wraps to the next line even when it can shrink
:host(.in-item:not(.legacy-select)) {
flex: 1 1 0;
width: 0;
}
// TODO FW-3194 - Remove this

View File

@ -45,11 +45,13 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
await page.setContent(
`
<div id="container" style="display: flex">
<ion-list>
<ion-item>
<ion-select label="Fruit" value="apple">
<ion-select-option value="apple">Apple</ion-select-option>
</ion-select>
</ion-item>
<ion-list>
</div>
`,
config

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB