mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-15 17:42:15 +08:00
feat(content): add fixedSlotPlacement prop (#29233)
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. --> Content in the `fixed` slot is always placed after the main content in the DOM. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - A new `fixedSlotPlacement` prop on Content allows developers to place fixed content either before or after the main content in the DOM ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#footer for more information. --> ## Other information Dev build: `8.0.0-dev.11712072527.1dd97c66` <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> ⚠️This feature will not be part of the v8.0 release. As a result, do not merge this into `feature-8.0`. However, I am putting this PR up based off `feature-8.0` so it can get reviewed by the team. --------- Co-authored-by: Liam DeBeasi <liamdebeasi@users.noreply.github.com>
This commit is contained in:

committed by
Liam DeBeasi

parent
0f5d1c02d2
commit
90a7e70a1c
@ -361,6 +361,7 @@ ion-col,css-prop,--ion-grid-columns
|
|||||||
|
|
||||||
ion-content,shadow
|
ion-content,shadow
|
||||||
ion-content,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
ion-content,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||||
|
ion-content,prop,fixedSlotPlacement,"after" | "before",'after',false,false
|
||||||
ion-content,prop,forceOverscroll,boolean | undefined,undefined,false,false
|
ion-content,prop,forceOverscroll,boolean | undefined,undefined,false,false
|
||||||
ion-content,prop,fullscreen,boolean,false,false,false
|
ion-content,prop,fullscreen,boolean,false,false,false
|
||||||
ion-content,prop,scrollEvents,boolean,false,false,false
|
ion-content,prop,scrollEvents,boolean,false,false,false
|
||||||
|
8
core/src/components.d.ts
vendored
8
core/src/components.d.ts
vendored
@ -762,6 +762,10 @@ export namespace Components {
|
|||||||
* 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).
|
* 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).
|
||||||
*/
|
*/
|
||||||
"color"?: Color;
|
"color"?: Color;
|
||||||
|
/**
|
||||||
|
* Controls where the fixed content is placed relative to the main content in the DOM. This can be used to control the order in which fixed elements receive keyboard focus. For example, if a FAB in the fixed slot should receive keyboard focus before the main page content, set this property to `'before'`.
|
||||||
|
*/
|
||||||
|
"fixedSlotPlacement": 'after' | 'before';
|
||||||
/**
|
/**
|
||||||
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce. If the content exceeds the bounds of ionContent, nothing will change. Note, this does not disable the system bounce on iOS. That is an OS level setting.
|
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce. If the content exceeds the bounds of ionContent, nothing will change. Note, this does not disable the system bounce on iOS. That is an OS level setting.
|
||||||
*/
|
*/
|
||||||
@ -5482,6 +5486,10 @@ declare namespace LocalJSX {
|
|||||||
* 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).
|
* 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).
|
||||||
*/
|
*/
|
||||||
"color"?: Color;
|
"color"?: Color;
|
||||||
|
/**
|
||||||
|
* Controls where the fixed content is placed relative to the main content in the DOM. This can be used to control the order in which fixed elements receive keyboard focus. For example, if a FAB in the fixed slot should receive keyboard focus before the main page content, set this property to `'before'`.
|
||||||
|
*/
|
||||||
|
"fixedSlotPlacement"?: 'after' | 'before';
|
||||||
/**
|
/**
|
||||||
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce. If the content exceeds the bounds of ionContent, nothing will change. Note, this does not disable the system bounce on iOS. That is an OS level setting.
|
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce. If the content exceeds the bounds of ionContent, nothing will change. Note, this does not disable the system bounce on iOS. That is an OS level setting.
|
||||||
*/
|
*/
|
||||||
|
@ -75,6 +75,15 @@ export class Content implements ComponentInterface {
|
|||||||
*/
|
*/
|
||||||
@Prop() fullscreen = false;
|
@Prop() fullscreen = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controls where the fixed content is placed relative to the main content
|
||||||
|
* in the DOM. This can be used to control the order in which fixed elements
|
||||||
|
* receive keyboard focus.
|
||||||
|
* For example, if a FAB in the fixed slot should receive keyboard focus before
|
||||||
|
* the main page content, set this property to `'before'`.
|
||||||
|
*/
|
||||||
|
@Prop() fixedSlotPlacement: 'after' | 'before' = 'after';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce.
|
* If `true` and the content does not cause an overflow scroll, the scroll interaction will cause a bounce.
|
||||||
* If the content exceeds the bounds of ionContent, nothing will change.
|
* If the content exceeds the bounds of ionContent, nothing will change.
|
||||||
@ -423,7 +432,7 @@ export class Content implements ComponentInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { isMainContent, scrollX, scrollY, el } = this;
|
const { fixedSlotPlacement, isMainContent, scrollX, scrollY, el } = this;
|
||||||
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
const rtl = isRTL(el) ? 'rtl' : 'ltr';
|
||||||
const mode = getIonMode(this);
|
const mode = getIonMode(this);
|
||||||
const forceOverscroll = this.shouldForceOverscroll();
|
const forceOverscroll = this.shouldForceOverscroll();
|
||||||
@ -446,6 +455,9 @@ export class Content implements ComponentInterface {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div ref={(el) => (this.backgroundContentEl = el)} id="background-content" part="background"></div>
|
<div ref={(el) => (this.backgroundContentEl = el)} id="background-content" part="background"></div>
|
||||||
|
|
||||||
|
{fixedSlotPlacement === 'before' ? <slot name="fixed"></slot> : null}
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class={{
|
class={{
|
||||||
'inner-scroll': true,
|
'inner-scroll': true,
|
||||||
@ -467,7 +479,7 @@ export class Content implements ComponentInterface {
|
|||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<slot name="fixed"></slot>
|
{fixedSlotPlacement === 'after' ? <slot name="fixed"></slot> : null}
|
||||||
</Host>
|
</Host>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
31
core/src/components/content/test/content.spec.ts
Normal file
31
core/src/components/content/test/content.spec.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { newSpecPage } from '@stencil/core/testing';
|
||||||
|
|
||||||
|
import { Content } from '../content';
|
||||||
|
|
||||||
|
describe('content: fixed slot placement', () => {
|
||||||
|
it('should should fixed slot after content', async () => {
|
||||||
|
const page = await newSpecPage({
|
||||||
|
components: [Content],
|
||||||
|
html: '<ion-content></ion-content>',
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = page.body.querySelector('ion-content')!;
|
||||||
|
const fixedSlot = content.shadowRoot!.querySelector('slot[name="fixed"]')!;
|
||||||
|
const scrollEl = content.shadowRoot!.querySelector('[part="scroll"]')!;
|
||||||
|
|
||||||
|
expect(fixedSlot.nextElementSibling).not.toBe(scrollEl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should should fixed slot before content', async () => {
|
||||||
|
const page = await newSpecPage({
|
||||||
|
components: [Content],
|
||||||
|
html: `<ion-content fixed-slot-placement="before"></ion-content>`,
|
||||||
|
});
|
||||||
|
|
||||||
|
const content = page.body.querySelector('ion-content')!;
|
||||||
|
const fixedSlot = content.shadowRoot!.querySelector('slot[name="fixed"]')!;
|
||||||
|
const scrollEl = content.shadowRoot!.querySelector('[part="scroll"]')!;
|
||||||
|
|
||||||
|
expect(fixedSlot.nextElementSibling).toBe(scrollEl);
|
||||||
|
});
|
||||||
|
});
|
@ -592,7 +592,7 @@ export declare interface IonCol extends Components.IonCol {}
|
|||||||
|
|
||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
inputs: ['color', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
inputs: ['color', 'fixedSlotPlacement', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
||||||
methods: ['getScrollElement', 'scrollToTop', 'scrollToBottom', 'scrollByPoint', 'scrollToPoint']
|
methods: ['getScrollElement', 'scrollToTop', 'scrollToBottom', 'scrollByPoint', 'scrollToPoint']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
@ -600,7 +600,7 @@ export declare interface IonCol extends Components.IonCol {}
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['color', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
inputs: ['color', 'fixedSlotPlacement', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
||||||
})
|
})
|
||||||
export class IonContent {
|
export class IonContent {
|
||||||
protected el: HTMLElement;
|
protected el: HTMLElement;
|
||||||
|
@ -659,7 +659,7 @@ export declare interface IonCol extends Components.IonCol {}
|
|||||||
|
|
||||||
@ProxyCmp({
|
@ProxyCmp({
|
||||||
defineCustomElementFn: defineIonContent,
|
defineCustomElementFn: defineIonContent,
|
||||||
inputs: ['color', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
inputs: ['color', 'fixedSlotPlacement', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
||||||
methods: ['getScrollElement', 'scrollToTop', 'scrollToBottom', 'scrollByPoint', 'scrollToPoint']
|
methods: ['getScrollElement', 'scrollToTop', 'scrollToBottom', 'scrollByPoint', 'scrollToPoint']
|
||||||
})
|
})
|
||||||
@Component({
|
@Component({
|
||||||
@ -667,7 +667,7 @@ export declare interface IonCol extends Components.IonCol {}
|
|||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
template: '<ng-content></ng-content>',
|
template: '<ng-content></ng-content>',
|
||||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||||
inputs: ['color', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
inputs: ['color', 'fixedSlotPlacement', 'forceOverscroll', 'fullscreen', 'scrollEvents', 'scrollX', 'scrollY'],
|
||||||
standalone: true
|
standalone: true
|
||||||
})
|
})
|
||||||
export class IonContent {
|
export class IonContent {
|
||||||
|
@ -262,6 +262,7 @@ export const IonCol = /*@__PURE__*/ defineContainer<JSX.IonCol>('ion-col', defin
|
|||||||
export const IonContent = /*@__PURE__*/ defineContainer<JSX.IonContent>('ion-content', defineIonContent, [
|
export const IonContent = /*@__PURE__*/ defineContainer<JSX.IonContent>('ion-content', defineIonContent, [
|
||||||
'color',
|
'color',
|
||||||
'fullscreen',
|
'fullscreen',
|
||||||
|
'fixedSlotPlacement',
|
||||||
'forceOverscroll',
|
'forceOverscroll',
|
||||||
'scrollX',
|
'scrollX',
|
||||||
'scrollY',
|
'scrollY',
|
||||||
|
Reference in New Issue
Block a user