Skip to content

docs(content): add component playgrounds #2622

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

Merged
merged 14 commits into from
Oct 26, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
222 changes: 60 additions & 162 deletions docs/api/content.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,6 @@
---
title: "ion-content"
hide_table_of_contents: true
demoUrl: "/docs/demos/api/content/index.html"
demoSourceUrl: "https://github.com/ionic-team/ionic-docs/tree/main/static/demos/api/content/index.html"
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import TOCInline from '@theme/TOCInline';

import Props from '@site/static/auto-generated/content/props.md';
import Events from '@site/static/auto-generated/content/events.md';
import Methods from '@site/static/auto-generated/content/methods.md';
Expand All @@ -24,14 +17,6 @@ import EncapsulationPill from '@components/page/api/EncapsulationPill';

<EncapsulationPill type="shadow" />

<h2 className="table-of-contents__title">Contents</h2>

<TOCInline
toc={toc}
maxHeadingLevel={2}
/>



The content component provides an easy to use content area with some useful methods
to control the scrollable area. There should only be one content in a single
Expand All @@ -40,204 +25,117 @@ view.
Content, along with many other Ionic components, can be customized to modify its padding, margin, and more using the global styles provided in the [CSS Utilities](/docs/layout/css-utilities) or by individually styling it using CSS and the available [CSS Custom Properties](#css-custom-properties).


## Fixed Content
## Basic Usage

In order to place elements outside of the scrollable area, `slot="fixed"` can be added to the element. This will absolutely position the element placing it in the top left. In order to place the element in a different position, style it using [top, right, bottom, and left](https://developer.mozilla.org/en-US/docs/Web/CSS/position).
import Basic from '@site/static/usage/content/basic/index.md';

## Interfaces
<Basic />

### ScrollBaseDetail

```typescript
interface ScrollBaseDetail {
isScrolling: boolean;
}
```
## Header & Footer

### ScrollDetail
Content can be the only top-level component in a page, or it can be used alongside a [header](./header), [footer](./footer), or both. When used with a header or footer, it will adjust its size to fill the remaining height.

```typescript
interface ScrollDetail extends GestureDetail, ScrollBaseDetail {
scrollTop: number;
scrollLeft: number;
}
```

### ScrollBaseCustomEvent
import HeaderFooter from '@site/static/usage/content/header-footer/index.md';

While not required, this interface can be used in place of the `CustomEvent` interface for stronger typing on the `ionScrollStart` and `ionScrollEnd` events.

```typescript
interface ScrollBaseCustomEvent extends CustomEvent {
detail: ScrollBaseDetail;
target: HTMLIonContentElement;
}
```

### ScrollCustomEvent

While not required, this interface can be used in place of the `CustomEvent` interface for stronger typing on the `ionScroll` event.

```typescript
interface ScrollCustomEvent extends ScrollBaseCustomEvent {
detail: ScrollDetail;
}
```
<HeaderFooter />


## Fullscreen Content

By default, content fills the space between a [header](./header) and [footer](./footer) but does not go behind them. In certain cases, it may be desired to have the content scroll behind the header and footer, such as when the `translucent` property is set on either of them, or `opacity` is set on the toolbar. This can be achieved by setting the `fullscreen` property on the content to `true`.

## Usage
import Fullscreen from '@site/static/usage/content/fullscreen/index.md';

<Tabs groupId="framework" defaultValue="angular" values={[{ value: 'angular', label: 'Angular' }, { value: 'javascript', label: 'Javascript' }, { value: 'react', label: 'React' }, { value: 'stencil', label: 'Stencil' }, { value: 'vue', label: 'Vue' }]}>
<Fullscreen />

<TabItem value="angular">

```html
<ion-content
[scrollEvents]="true"
(ionScrollStart)="logScrollStart()"
(ionScroll)="logScrolling($event)"
(ionScrollEnd)="logScrollEnd()">
<h1>Main Content</h1>
## Fixed Content

<div slot="fixed">
<h1>Fixed Content</h1>
</div>
</ion-content>
```
To place elements outside of the scrollable area, assign them to the `fixed` slot. Doing so will [absolutely position](https://developer.mozilla.org/en-US/docs/Web/CSS/position#absolute_positioning) the element to the top left of the content. In order to change the position of the element, it can be styled using the [top, right, bottom, and left](https://developer.mozilla.org/en-US/docs/Web/CSS/position) CSS properties.

import Fixed from '@site/static/usage/content/fixed/index.md';

<Fixed />

</TabItem>
## Scroll Methods

Content provides [methods](#methods) that can be called to scroll the content to the bottom, top, or to a specific point. They can be passed a `duration` in order to smoothly transition instead of instantly changing the position.

<TabItem value="javascript">
import ScrollMethods from '@site/static/usage/content/scroll-methods/index.md';

```html
<ion-content>
<h1>Main Content</h1>
<ScrollMethods />

<div slot="fixed">
<h1>Fixed Content</h1>
</div>
</ion-content>
```
## Scroll Events

```javascript
var content = document.querySelector('ion-content');
content.scrollEvents = true;
content.addEventListener('ionScrollStart', () => console.log('scroll start'));
content.addEventListener('ionScroll', (ev) => console.log('scroll', ev.detail));
content.addEventListener('ionScrollEnd', () => console.log('scroll end'));
```
Scroll events are disabled by default for content due to performance. However, they can be enabled by setting `scrollEvents` to `true`. This is necessary before listening to any of the scroll [events](#events).

import ScrollEvents from '@site/static/usage/content/scroll-events/index.md';

</TabItem>
<ScrollEvents />


<TabItem value="react">
## Theming

```tsx
import React from 'react';
import { IonContent } from '@ionic/react';
### Colors

const ContentExample: React.FC = () => (
<IonContent
scrollEvents={true}
onIonScrollStart={() => {}}
onIonScroll={() => {}}
onIonScrollEnd={() => {}}>
<h1>Main Content</h1>
import Colors from '@site/static/usage/content/theming/colors/index.md';

<div slot="fixed">
<h1>Fixed Content</h1>
</div>
</IonContent>
);
```
<Colors />

### CSS Shadow Parts

</TabItem>
import CSSParts from '@site/static/usage/content/theming/css-shadow-parts/index.md';

<CSSParts />

<TabItem value="stencil">
### CSS Custom Properties

```tsx
import { Component, h } from '@stencil/core';
import CSSProps from '@site/static/usage/content/theming/css-properties/index.md';

@Component({
tag: 'content-example',
styleUrl: 'content-example.css'
})
export class ContentExample {
logScrollStart() {
console.log('Scroll start');
}
<CSSProps />

logScrolling(ev) {
console.log('Scrolling', ev);
}

logScrollEnd() {
console.log('Scroll end');
}
## Interfaces

render() {
return [
<ion-content
scrollEvents={true}
onIonScrollStart={() => this.logScrollStart()}
onIonScroll={(ev) => this.logScrolling(ev)}
onIonScrollEnd={() => this.logScrollEnd()}>
<h1>Main Content</h1>
### ScrollBaseDetail

<div slot="fixed">
<h1>Fixed Content</h1>
</div>
</ion-content>
];
}
```typescript
interface ScrollBaseDetail {
isScrolling: boolean;
}
```

### ScrollDetail

</TabItem>


<TabItem value="vue">

```html
<template>
<ion-content
:scroll-events="true"
@ionScrollStart="logScrollStart()"
@ionScroll="logScrolling($event)"
@ionScrollEnd="logScrollEnd()">
<h1>Main Content</h1>

<div slot="fixed">
<h1>Fixed Content</h1>
</div>
</ion-content>
</template>
```typescript
interface ScrollDetail extends GestureDetail, ScrollBaseDetail {
scrollTop: number;
scrollLeft: number;
}
```

<script>
import { IonContent } from '@ionic/vue';
import { defineComponent } from 'vue';
### ScrollBaseCustomEvent

export default defineComponent({
components: { IonContent }
});
</script>
While not required, this interface can be used in place of the `CustomEvent` interface for stronger typing on the `ionScrollStart` and `ionScrollEnd` events.

```typescript
interface ScrollBaseCustomEvent extends CustomEvent {
detail: ScrollBaseDetail;
target: HTMLIonContentElement;
}
```

### ScrollCustomEvent

While not required, this interface can be used in place of the `CustomEvent` interface for stronger typing on the `ionScroll` event.

</TabItem>
```typescript
interface ScrollCustomEvent extends ScrollBaseCustomEvent {
detail: ScrollDetail;
}
```

</Tabs>

## Properties
<Props />
Expand All @@ -255,4 +153,4 @@ export default defineComponent({
<CustomProps />

## Slots
<Slots />
<Slots />
12 changes: 12 additions & 0 deletions static/usage/content/basic/angular.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```html
<ion-content class="ion-padding">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>

<p>Here's a small text description for the content. Nothing more, nothing less.</p>
</ion-content>
```
29 changes: 29 additions & 0 deletions static/usage/content/basic/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Content</title>
<link rel="stylesheet" href="../../common.css" />
<script src="../../common.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@6/dist/ionic/ionic.esm.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core@6/css/ionic.bundle.css" />
</head>

<body>
<ion-app>
<ion-content class="ion-padding">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>

<p>Here's a small text description for the content. Nothing more, nothing less.</p>
</ion-content>
</ion-app>
</body>

</html>
13 changes: 13 additions & 0 deletions static/usage/content/basic/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Playground from '@site/src/components/global/Playground';

import javascript from './javascript.md';
import react from './react.md';
import vue from './vue.md';
import angular from './angular.md';

<Playground
code={{ javascript, react, vue, angular }}
src="usage/content/basic/demo.html"
includeIonContent={false}
devicePreview={true}
/>
12 changes: 12 additions & 0 deletions static/usage/content/basic/javascript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```html
<ion-content class="ion-padding">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>

<p>Here's a small text description for the content. Nothing more, nothing less.</p>
</ion-content>
```
20 changes: 20 additions & 0 deletions static/usage/content/basic/react.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
```tsx
import React from 'react';
import { IonContent } from '@ionic/react';

function Example() {
return (
<IonContent className="ion-padding">
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>

<p>Here's a small text description for the content. Nothing more, nothing less.</p>
</IonContent>
);
}
export default Example;
```
Loading