Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
| // -------------------------------------------------- | ||
|
|
||
| .action-sheet-button-label { | ||
| gap: 12px; |
There was a problem hiding this comment.
I decided to use the same value that ionic uses.
| <div class="alert-button-inner"> | ||
| <div class="alert-checkbox-icon"> | ||
| <div class="alert-checkbox-inner"></div> | ||
| {inputs.map((i) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
| <div class="alert-button-inner"> | ||
| <div class="alert-radio-icon"> | ||
| <div class="alert-radio-inner"></div> | ||
| {inputs.map((i) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
| */ | ||
| this.closeModal(); | ||
| } | ||
| {this.options.map((option, index) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
| onIonChange={(ev) => { | ||
| this.setChecked(ev); | ||
| this.callOptionHandler(ev); | ||
| return this.options.map((option, index) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
| /** | ||
| * Text that is placed underneath the option text to provide additional details about the option. | ||
| */ | ||
| @Prop() description?: string; |
There was a problem hiding this comment.
Description isn't being used here to display on the screen because ion-select-option isn't used to display the options, it's done through the respective interface. So description is passed to the interface.
| <slot name="start"></slot> | ||
| <slot></slot> | ||
| <slot name="end"></slot> |
There was a problem hiding this comment.
Slots aren't being used here to display on the screen because ion-select-option isn't used to display the options, it's done through the respective interface. So slots are passed to the interface and the rendering is done with a new utility.
Even though it's not used to display here, it's still useful to include here so the docs can generate that "slots" are available for the options.
| onIonChange={(ev) => { | ||
| this.setChecked(ev); | ||
| this.callOptionHandler(ev); | ||
| return options.map((option, index) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
| */ | ||
| this.dismissParentPopover(); | ||
| } | ||
| {options.map((option, index) => { |
There was a problem hiding this comment.
The only change is the addition of optionLabelOptions and renderOptionLabel
ShaneK
left a comment
There was a problem hiding this comment.
This is looking really good! Just some feedback on some things I noticed
|
|
||
| export interface ActionSheetButton<T = any> { | ||
| text?: string; | ||
| text?: string | HTMLElement; |
There was a problem hiding this comment.
Widening text from string to string | HTMLElement here affects all action-sheet consumers, not just select-driven ones. Same with AlertInput.label. Anyone calling actionSheetController.create() who does button.text.toLowerCase() or passes text to a string-typed function will get TS errors. Since this targets next, breaking changes are expected, but would it be cleaner to add a separate property (e.g., richText or contentElement) for the HTMLElement case? That way existing string usage stays untouched.
| <span class="action-sheet-button-inner"> | ||
| {b.icon && <ion-icon icon={b.icon} aria-hidden="true" lazy={false} class="action-sheet-icon" />} | ||
| {b.text} | ||
| {renderOptionLabel(optionLabelOptions, 'action-sheet-button-label')} |
There was a problem hiding this comment.
This changes the DOM structure for all action-sheet buttons, not just ones created through select. Previously {b.text} rendered directly inside .action-sheet-button-inner, now it's wrapped in <span class="action-sheet-button-label"><span>...</span></span>. Same thing happens in alert for radio/checkbox labels. Any app CSS targeting these internal elements will break. Should renderOptionLabel only wrap when rich content is actually present (when startContent/endContent/description exist), falling back to the original rendering for plain strings?
There was a problem hiding this comment.
I do understand that breaking changes are acceptable here and this may be intended. Just double checking that's what you're going for.
|
|
||
| // Clear previous content and clone new nodes | ||
| el.innerHTML = ''; | ||
| Array.from(content.childNodes).forEach((n) => el.appendChild(n.cloneNode(true))); |
There was a problem hiding this comment.
The select's closed-state display goes through sanitizeDOMString before innerHTML injection, but this overlay path clones nodes with cloneNode(true) without sanitization. Inline event handlers (onclick, onerror) on elements inside ion-select-option get faithfully cloned into the overlay DOM. The two rendering paths for the same content have different security postures.
| <script> | ||
| window.Ionic = { | ||
| config: { | ||
| innerHTMLTemplatesEnabled: true, |
There was a problem hiding this comment.
This window.Ionic = { config: { innerHTMLTemplatesEnabled: true } } replaces the entire config object that setContent already sets in the head (which includes mode and theme). I think it works by accident because md is the fallback on non-iOS platforms, but you're losing the explicit config. Should be merging instead: window.Ionic = window.Ionic || {}; window.Ionic.config = { ...window.Ionic.config, innerHTMLTemplatesEnabled: true };
| }, | ||
| startContent: startContent ?? undefined, | ||
| endContent: endContent ?? undefined, | ||
| description: option.description, |
There was a problem hiding this comment.
You're gating startContent/endContent behind this.customHTMLEnabled but description gets passed through regardless. Is that intentional? If someone has innerHTMLTemplatesEnabled set to false (the default), they'd still see descriptions in overlays but not the slot content. Feels like it should be consistent either way.
There was a problem hiding this comment.
It was intentional. Devs can only pass string text as a description. To me, it would feel weird that a dev would have to enable innerHTMLTemplatesEnabled when they only want to have a description (no start or end slots). It follows how other props are being handled.
| * spacing between the items without changing the display to prevent | ||
| * losing the ellipsis behavior. | ||
| */ | ||
| .select-text > * { |
There was a problem hiding this comment.
.select-text > * applies margin-inline-start to the first child too, which adds unwanted leading space. Should be .select-text > * + * or .select-text > *:not(:first-child) to only space between items. Same thing in the ionic theme file.
| // Ionic Select Popover | ||
| // -------------------------------------------------- | ||
|
|
||
| // Select Modal: Select Option |
There was a problem hiding this comment.
This says "Select Modal" but it's the select-popover file.
| <script> | ||
| window.Ionic = { | ||
| config: { | ||
| innerHTMLTemplatesEnabled: true, |
There was a problem hiding this comment.
Setting innerHTMLTemplatesEnabled: true globally here means all existing tests that navigate to this page now run with a different config than they were written for. Could the existing overlay open/dismiss and focus tests be affected? Would it be safer to create a separate test page for the rich content tests, or set the config per-test in page.setContent?
Issue number: resolves #29890
What is the current behavior?
Select only allows plain text to be passed within it's options.
What is the new behavior?
ion-select-optionion-select-optionion-select-optionDoes this introduce a breaking change?
Other information
Preview