Skip to content
Open
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
114 changes: 98 additions & 16 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check

- [Development Workflow](#development-workflow)
- [Previewing Changes](#previewing-changes)
- [Checking Links](#checking-links)
- [Linting Documentation](#linting-documentation)
- [Spell Check](#spell-check)
- [Heading IDs](#heading-ids)
- [Using VS Code on Windows](#using-vs-code-on-windows)
- [Project Structure](#project-structure)
- [Directories](#directories)
- [Authoring Content](#authoring-content)
- [Admonitions](#admonitions)
- [Links and Headings](#links-and-headings)
- [Playgrounds](#playgrounds)
- [Reference Content](#reference-content)
- [Translation](#translation)
- [Reporting Issues](#reporting-issues)
Expand All @@ -28,16 +33,16 @@ Thanks for your interest in contributing to Ionic's documentation! :tada: Check

### Previewing Changes

In order to run the documentation locally, install the dependencies and run the development server:
In order to run the documentation locally, use Node.js 24 or later, install the dependencies and run the development server:

```sh
npm install
npm ci
npm start
```

#### GitHub Token

The documentation build requires a GitHub Personal Access Token to fetch Ionic Framework release notes. The build will still work locally without it (release notes will be empty), but it's required for Vercel preview and production builds.
The documentation build requires a GitHub Personal Access Token to fetch Ionic Framework release notes. The build still works locally without it, with an empty release notes page, but Vercel preview and production builds fail without it.

**Local Development:**

Expand Down Expand Up @@ -69,7 +74,17 @@ The documentation build requires a GitHub Personal Access Token to fetch Ionic F

3. Redeploy the project for the token to take effect

Without the token, the build will fail with an error message indicating the token is missing.
If the token is missing, Vercel builds fail with `GITHUB_TOKEN environment variable is required.`

### Checking Links

The development server does not check for broken links or anchors. Only a build does, and it fails on any it finds. Build the site before pushing a change that adds or moves links or headings:

```sh
npm run build:preview
```

This builds the English site only, the same build as a Vercel preview.

### Linting Documentation

Expand Down Expand Up @@ -107,7 +122,7 @@ npm run spellcheck
```mdx
{/* cspell:disable */}

<p>Everything inside of these comments will be ignored by the spell checkr. Proofread your own words carefully.</p>
<p>Everything inside of these comments will be ignored by the spell checker. Proofread your own words carefully.</p>

{/* cspell:enable */}
```
Expand All @@ -124,11 +139,25 @@ Comments disabling the next line or entire sections of documentation are useful

In general, we should try to avoid ignoring words unless they are technical terms that are used throughout the documentation and wouldn't necessarily make sense formatted as code.

### Heading IDs

Every heading in `docs/` needs an explicit ID, so that renaming the heading doesn't change its anchor and break links to it:

```mdx
## Basic Usage {/* #basic-usage */}
```

Run the following command to add IDs to any new headings, and then push the changes. CI fails if a heading is missing one.

```
npm run heading-ids
```

---

## Using VS Code on Windows

The Ionic docs were originally built in a Mac-based environment, so Mac-focused linting rules apply when committing changes. To contribute on Windows, do the following:
Prettier expects LF line endings, and CI fails if `npm run lint` changes any file. To contribute on Windows, do the following:

- Configure VS Code to read/save files using line breaks (LF) instead of carriage returns (CRLF). Set it globally by navigating to: Settings -> Text Editor -> Files -> Eol. Set to `\n`.
- Check that the Git setting `core.autocrlf` is set to `false`: run `git config -l | grep autocrlf`. Switch it to false using: `git config --global core.autocrlf false`.
Expand All @@ -140,14 +169,19 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c

### Directories

- `_templates/` - templates used by `npm run playground:new`
- `docs/` - content of the current version of the docs
- `plugins/` - local Docusaurus plugins, such as the one that generates the component API pages
- `scripts/` - build scripts used to generate markdown or json files
- `src/` - source code and content of the docs
- `src/` - source code of the site
- `components/` - components used across the site
- `global/` - components used globally
- `page/` - components used on a single page or in a limited scope
- `styles/` - global styles and variables
- `components/` - styles split out into the components they target
- `theme/` - Docusaurus theme components that have been swizzled
- `static/`
- `code/` - StackBlitz project templates used by the playgrounds
- `demos/` - self-contained demos, optionally presented by pages via `demoUrl` YAML frontmatter
- `usage/` - playgrounds that can be created by running `npm run playground:new` [(docs)](_templates/README.md#new-playground-template)
- `versioned_docs/` - versions of the docs created by the docusaurus versioning command
Expand All @@ -158,13 +192,31 @@ Ionic's documentation is built using [Docusaurus](https://docusaurus.io/). The c
The content of the Ionic docs is written as [Markdown](https://commonmark.org/) in `docs/`. Each Markdown file corresponds to a route unless explicitly changed in the frontmatter.

```
/docs/ => src/pages/index.md
/docs/intro/cli => src/pages/intro/cli.md
/docs/theming/advanced => src/pages/theming/advanced.md
/docs/theming => src/pages/theming.md
/docs => docs/index.mdx
/docs/intro/cli => docs/intro/cli.mdx
/docs/theming/basics => docs/theming/basics.mdx
/docs/v8/intro/cli => versioned_docs/version-v8/intro/cli.mdx
```

You can make copy edits to the site by [editing the Markdown files directly on GitHub](https://help.github.com/articles/editing-files-in-another-user-s-repository/). In your pull request, please explain what was missing from or inaccurate about the content.
`/docs` maps to `docs/index.mdx` through `slug: /` in its frontmatter. Older versions live in `versioned_docs/` and are served under their version, such as `/docs/v8/`.

Versions listed in [`versions.json`](versions.json) are actively maintained. If your change also applies to one of them, make the same change in its `versioned_docs/version-<name>/` folder. Versions listed in [`versionsArchived.json`](versionsArchived.json) are frozen deployments that are no longer built, so changes to their folders never reach the site.

Markdown links resolve within their own version, but JSX paths such as `<Link to>` and `useBaseUrl` do not. In an older version, prefix them with the version, such as `<Link to="/v8/api/note">`.

You can make copy edits to the site by [editing the Markdown files directly on GitHub](https://docs.github.com/en/repositories/working-with-files/managing-files/editing-files). In your pull request, please explain what was missing from or inaccurate about the content.

### Admonitions

Give an admonition a title with square brackets. The older `:::note My Title` form renders as plain text with no build error, so CI fails on it:

```mdx
:::note[My Title]

Content

:::
```

### Links and Headings

Expand All @@ -177,14 +229,40 @@ The build only checks links and anchors that go through Markdown or these compon

Markup inside code samples is exempt, since it's example code rather than part of the page.

### Playgrounds

A playground is the interactive example on a component page. It shows a live demo that switches between iOS and Material Design modes, the code for JavaScript, Angular, React and Vue, and a button to open the example in StackBlitz.

Each playground is a folder in `static/usage/<version>/<component>/<example>/`:

- `demo.html`: the live demo, so update it along with the framework code
- `javascript.md`, `react.md`, `vue.md` and `angular/`: the code shown for each framework
- `index.mdx`: renders the `Playground` component with those files

Run the following command to generate a playground, and then import its `index.mdx` into the page:

```
npm run playground:new
```

```mdx
import Basic from '@site/static/usage/v9/button/basic/index.mdx';

<Basic />
```

For the generator's prompts, refer to the [playground template docs](_templates/README.md#new-playground-template). For the `Playground` options, refer to its [README](src/components/global/Playground/README.md).

### Reference Content

The Markdown in `docs/` does not only contain manually written markdown files:

- Paths matching `/docs/api/*` are built from the [Ionic Framework](https://github.com/ionic-team/ionic) source code
- Paths matching `/docs/native/*` are built from the [Ionic Native](https://github.com/ionic-team/ionic-native) source code
- The properties, events, methods, and other API tables on `/docs/api/*` pages are built from the [Ionic Framework](https://github.com/ionic-team/ionic-framework) source code
- Paths matching `/docs/native/*` are built from the [Capacitor plugins](https://github.com/ionic-team/capacitor-plugins) READMEs
- Paths matching `/docs/cli/commands/*` are built from the [Ionic CLI](https://github.com/ionic-team/ionic-cli) source code

The `native/` and `cli/commands/` pages are generated when you run `npm start` or build the site, and they are not committed. To change them, edit the plugin's README in [capacitor-plugins](https://github.com/ionic-team/capacitor-plugins) or the command's source in [ionic-cli](https://github.com/ionic-team/ionic-cli).

## Translation

The Ionic docs have been translated into Japanese and are in the process of being translated into Chinese, French, Portuguese, and Spanish. We've chosen these languages because we believe they have the greatest number of developers where English-only documentation would be a barrier.
Expand All @@ -195,7 +273,7 @@ _Please submit translation issues to the Crowdin page and not the Ionic Docs Git

<!-- cspell:disable-next-line -->

The Japanese translation of the docs were built by an independent team, lead by [rdlabo](https://github.com/rdlabo) and can be found and contributed to on the [ionic-jp group's `ionic-docs` project page](https://github.com/ionic-jp/ionic-docs).
The Japanese translation of the docs were built by an independent team, led by [rdlabo](https://github.com/rdlabo) and can be found and contributed to on the [ionic-jp group's `ionic-docs` project page](https://github.com/ionic-jp/ionic-docs).

## Reporting Issues

Expand All @@ -206,7 +284,7 @@ If the issue you're reporting is a bug, please be sure it is an issue with the I
- Steps to reproduce
- Expected behavior
- OS and browser versions
- If possible, a demo repo or CodePen/CodeSandbox
- If possible, a demo repo or StackBlitz

> [!NOTE]
> Some [reference content](#reference-content) is pulled from other Ionic repos. In that case, please submit your issue on the docs repo with a link to the repo where the content lives.
Expand All @@ -217,6 +295,10 @@ If the issue you're reporting is a bug, please be sure it is an issue with the I

When submitting pull requests, please keep the scope of your change contained to a single feature or bug. When in doubt, err on the side of smaller pull requests. If your pull request is a new feature, we would recommend opening an issue first to come to an agreement about the feature before putting in significant time.

Title your pull request in the [Conventional Commits](https://www.conventionalcommits.org/) format, such as `docs(button): add an icon-only example`. Pull requests are squash merged, so the title becomes the commit message on `main`.

Each pull request gets a Vercel preview deployment. Use it to check your change on the built site.

---

## Deploying
Expand Down
11 changes: 6 additions & 5 deletions _templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ Some helpful docs links for updating/creating templates:

## Generation

To create a new playground, run `npm run playground:new`. This will walk you through some prompts to decide what files for the generator to create for the playground, and what their paths should be.
To create a new playground, run `npm run playground:new`. This will walk you through some prompts to decide what files for the generator to create for the playground, and what their paths should be:

The path defaults to `basic`. If there is already a basic playground, you'll want to input a different path for the playground.

The CSS option will add extra files if you need to include custom CSS in your playground.
- **Component or guide:** a component playground goes under the component's name, such as `button`. Any other playground goes under a guide section, such as `animations`, and starts with an `ion-card`.
- **Path:** the folder for the playground under that name, such as `basic` or `theming/colors`. Use `basic` for a component's first playground.
- **Version:** the Ionic Framework version the playground is for.
- **CSS:** adds extra files if you need to include custom CSS in your playground.

If you need a component for multiple versions of Ionic Framework, you (currently) need to run the generator once for each version.

## Usage

Once you've generated your playground, you need to add it to the main markdown file in the docs (e.g. [docs/api/button.mdx](../docs/api/button.mdx)) by doing something similar to the following example:
Once you've generated your playground, you need to add it to the main markdown file in the docs (e.g. [docs/api/button.mdx](../docs/api/button.mdx)). The generator prints the snippet to paste when it finishes, which looks similar to the following example:

```
## Feature
Expand Down
82 changes: 77 additions & 5 deletions src/components/global/Playground/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,50 @@ The Playground component renders a demo preview of a component experience with c

The Playground can be customized per example, to meet the requirements of the component or experience that you are trying to showcase.

## Basic Usage

Every playground needs `code` with a snippet for each framework, `src` pointing at its demo page, and `version` for the major version of Ionic the example uses. Without `version`, the playground renders nothing.

```tsx
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_example_component_html from './angular/example_component_html.md';
import angular_example_component_ts from './angular/example_component_ts.md';

<Playground
version="9"
code={{
javascript,
react,
vue,
angular: {
files: {
'src/app/example.component.html': angular_example_component_html,
'src/app/example.component.ts': angular_example_component_ts,
},
},
}}
src="usage/v9/button/basic/demo.html"
/>;
```

## Options

| Option | Description |
| ------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `size` | Height of the demo: `xsmall`, `small` (default), `medium`, `large`, `xlarge`, or any CSS height such as `300px`. |
| `mode` | Locks the demo to `ios` or `md` and disables the button for the other mode. |
| `devicePreview` | Renders the demo inside a device frame. Refer to [Device Frame](#show-example-within-a-device-frame-iphonepixel-5). |
| `showConsole` | Shows a console below the demo with anything the demo logs through `console.log`, `console.warn`, or `console.error`. |
| `includeIonContent` | Wraps the StackBlitz example in `ion-app` and `ion-content`. Defaults to `true`. Refer to [Ejecting](#ejecting-from-ionappioncontent-boilerplate). |
| `defaultFramework` | Framework tab to select when the reader has not picked one. Defaults to Angular when available. |
| `title` | Title of the generated StackBlitz project. |
| `description` | Description of the generated StackBlitz project. |

## Show example within a device frame (iPhone/Pixel 5)

By default, Playground examples will render in an empty container and fill the available space. Using the `devicePreview` flag, the Playground will render the demo experience within an iPhone device frame when on iOS mode and within a Pixel device frame when on MD.
Expand All @@ -14,7 +58,7 @@ By default, Playground examples will render in an empty container and fill the a

## Multiple File Examples

Playground supports single file and multi-file examples to show the required code to create a sample. To include multiple file examples for a single framework target, use the `files` option to specify the file location (in the StackBlitz generated project) and the file contents.
Playground supports single file and multi-file examples to show the required code to create a sample. To include multiple file examples for a single framework target, pass an object with a `files` option that maps each file location (in the StackBlitz generated project) to its contents.

You can mix multi-file and single file examples together in a single example:

Expand All @@ -29,10 +73,13 @@ import vue from './vue.md';
import javascript from './javascript.md';

<Playground
files={{
version="9"
code={{
angular: {
'src/app/example.component.html': angular_example_component_html,
'src/app/example.component.ts': angular_example_component_ts,
files: {
'src/app/example.component.html': angular_example_component_html,
'src/app/example.component.ts': angular_example_component_ts,
},
},
react: {
files: {
Expand All @@ -43,10 +90,35 @@ import javascript from './javascript.md';
javascript,
vue,
}}
src="usage/v9/component/feature/demo.html"
/>;
```

The file location is respective to the StackBlitz demo project. If you are unsure of the exact path, refer to the `stackblitz.utils.ts` method for each respective target. The path specified in `sdk.openProject` will coincide with the value used in the `files` configuration.
The file location is relative to the StackBlitz demo project. If you are unsure of the exact path, refer to the `files` object in the `open*Editor` function for each target in [`stackblitz.utils.ts`](./stackblitz.utils.ts).

## Adding Dependencies

To add npm packages to the StackBlitz project, pass `dependencies` alongside `files` for each framework that needs them. The key is the package name and the value is a semver range:

```tsx
<Playground
version="9"
code={{
react: {
files: {
'src/main.tsx': react_main_tsx,
},
dependencies: {
'@maskito/react': '^3.0.0',
'@maskito/core': '^3.0.0',
},
},
}}
src="usage/v9/input/mask/demo.html"
/>
```

The live demo does not install these packages, so `demo.html` has to load them itself, such as from a CDN.

## Creating a New Playground

Expand Down
Loading