Skip to content

Commit

Permalink
Add directives reference page (#282)
Browse files Browse the repository at this point in the history
* create page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* move hydration directives documentation to directives reference page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add fragment to directives reference page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add script and style tag directives

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add set:html and set:text

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add directives reference page to sidebar

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add hoist example & improve define:vars warning

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* update headings to be more uniform

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* create page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* move hydration directives documentation to directives reference page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add fragment to directives reference page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add script and style tag directives

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add set:html and set:text

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add directives reference page to sidebar

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* add hoist example & improve define:vars warning

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* update headings to be more uniform

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* Add is:raw

* Move is:raw

* Add scetion descriptions

* document global directive

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* document class:list directive

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* fix formatting

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* Add info about how class:list is passed to children.

* Add information to top of page

* Fix typo

* Clean up page a bit

* Add note about `class:list` not working with expressions

* make links to directives reference page consistet with the rest of the docs

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* update to be consistent with new script and style behavior ([#2961](withastro/astro#2961))

* move universal directives to the top of the page

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* change framework components page a little

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* better description at top of page

* add link to styling page

* add note about is:text being redundent

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* make is:raw description clearer

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* move warnings below example code

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* fix typo

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* another typo

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

* fix fragment from old draft

Signed-off-by: Zade Viggers <zade.viggers@gmail.com>

Co-authored-by: Fred K. Schott <fkschott@gmail.com>
  • Loading branch information
zadeviggers and FredKSchott authored Apr 12, 2022
1 parent 0be6fc2 commit 5c542c8
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 37 deletions.
3 changes: 2 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ export const SIDEBAR = {
{ text: 'Import Aliases', link: 'en/guides/aliases' },
{ text: 'Integrations', link: 'en/guides/integrations-guide' },
{ text: 'RSS', link: 'en/guides/rss' },
{ text: 'Server-side Rendering (SSR)', link: 'en/guides/server-side-rendering' },
{ text: 'TypeScript', link: 'en/guides/typescript' },
{ text: 'UI Frameworks', link: 'en/core-concepts/framework-components' },
{ text: 'Server-side Rendering (experimental)', link: 'en/guides/server-side-rendering' },

{ text: 'Reference', header: true, type: 'api' },
{
Expand All @@ -46,6 +46,7 @@ export const SIDEBAR = {
{ text: 'Integrations API', link: 'en/reference/integrations-reference' },
{ text: 'Adapter API (experimental)', link: 'en/reference/adapter-reference' },
{ text: 'Routing Rules', link: 'en/core-concepts/routing' },
{ text: 'Templating Directives', link: 'en/reference/directives-reference' },
// ADD: Astro Component Syntax
// ADD: Markdown Syntax
{ text: 'NPM Package Format', link: 'en/guides/publish-to-npm' },
Expand Down
4 changes: 3 additions & 1 deletion src/pages/en/core-concepts/astro-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ They can be used to style your components, and all style rules are automatically

To send JavaScript to the browser without [using a framework component](/en/core-concepts/framework-components) (React, Svelte, Vue, Preact, SolidJS, AlpineJS, Lit...) you can use a `<script>` tag in your Astro component template and send JavaScript to the browser that executes in the global scope.


```astro
<script>
// Will be rendered into the HTML exactly as written!
Expand All @@ -335,6 +334,9 @@ To send JavaScript to the browser without [using a framework component](/en/core
// Processed! Bundled! ESM imports work, even to npm packages.
</script>
```

📚 See our [directives reference](/en/reference/directives-reference#script-and-style-tags) page for more information about the directives available on `<script>` tags.

#### Loading External Scripts

**When to use this:** If your JavaScript file lives inside of `public/`.
Expand Down
2 changes: 2 additions & 0 deletions src/pages/en/core-concepts/component-hydration.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ Start importing the component JS at page load and hydrate when the import comple

If more than one renderer is included in the Astro [config](/en/reference/configuration-reference), `client:only` needs a hint to know which renderer to use for the component. For example, `client:only="react"` would make sure that the component is hydrated in the browser with the React renderer. For custom renderers not provided by `@astrojs`, use the full name of the renderer provided in your Astro config, i.e. `<client:only="my-custom-renderer" />`.

📚 See our [directives reference](/en/reference/directives-reference#ui-framework-components) page for more infomation on all of the `client:` directives.

## Can I Hydrate Astro Components?

[Astro components](/en/core-concepts/astro-components) (`.astro` files) are HTML-only templating components with no client-side runtime. If you try to hydrate an Astro component with a `client:` modifier, you will get an error.
Expand Down
36 changes: 2 additions & 34 deletions src/pages/en/core-concepts/framework-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,41 +78,9 @@ the user scrolls down and the component is visible on the page -->
### Available Hydration Directives

#### `client:load`
There are serveral hydration directives available for UI framework components: `client:load`, `client:idle`, `client:visible`, `client:media={QUERY}` and `client:only=" "`.

Start importing the component JS at page load.

💡 *Useful for immediately-visible UI elements that need to be interactive as soon as possible.*

#### `client:idle`

Start importing the component JS as soon as main thread is free.

💡 *Useful for items that don't need to be immediately interactive.*

#### `client:visible`

Start importing the component JS as soon as the element enters the viewport.

💡 *Useful for content lower down on the page.*

#### `client:media={QUERY}`

Start importing the component JS as soon as the browser matches the given media query.

💡 *Useful for sidebar toggles, or other elements that might be used only for certain screen sizes.*

> ⚠️ Remember, this directive only refers to making the component *interactive* at certain media queries. This does not affect the component being *rendered to the screen*, nor its *visibility*!
#### `client:only=" "`

Start importing the component JS at page load, similar to `client:load`.

>⚠️ This component will be **skipped** at build time, and to assist the client, you should specify which renderer to use from the array in your [`astro.config.mjs` configuration](/en/reference/configuration-reference).
>
> e.g. `<client:only="react" />` or `<client:only="my-custom-renderer" />`
💡 *Useful for components that are entirely dependent on client-side APIs.*
📚 See our [directives reference](/en/reference/directives-reference#ui-framework-components) page for a full description of these hydration directives, and their usage.

## Mixing Frameworks

Expand Down
2 changes: 1 addition & 1 deletion src/pages/en/guides/styling.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const backgroundColor = "rgb(24 121 78)";
<h1>Hello</h1>
```

Any *serializable* front matter variable is supported, including props passed to your component through `Astro.props`.
📚 See our [directives reference](/en/reference/directives-reference#definevarsvariables) page to learn more about `define:vars`.

## External Styles

Expand Down
218 changes: 218 additions & 0 deletions src/pages/en/reference/directives-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
---
layout: ~/layouts/MainLayout.astro
title: Directives Reference
---

Directives are special properties that can be passed to HTML elements, Astro components, And UI Framework components.

Directives are Astro-specific attributes, used in your `.astro` component to "direct" Astro as it renders your HTML template.

This page describes the options available for directing Astro to render different types of content on your page.

## Universally available directives

These directives are available on HTML elements, UI Framework components, Astro components, the works!

### `is:raw`

Instructs the Astro compiler to treat any children of that element as text. This means that all special Astro templating syntax will be ignored.

Used internally by the `<Markdown>` component.

For example, if you had a custom Katex component that converted some text to HTML, you could have users do this:

```astro
---
import Katex from '../components/Katex.astro';
---
<Katex is:raw>Some conflicting {syntax} here</Katex>
```

### `class:list`

Serializes a JavaScript expression to a string of CSS class names. Similar to the [clsx](https://github.com/lukeed/clsx) helper library.

The final `class` string is passed to the component/element as the `class` prop.

```astro
<!-- This -->
<span class:list={[ 'hello goodbye', { hello: true, world: true }, new Set([ 'hello', 'friend' ]) ]} />
<!-- Becomes -->
<span class="hello goodbye world friend"></span>
```

>⚠️ `class:list` will not be parsed if its value is not an expression.
>
> e.g. `<Component class:list="test" />` will not work.
## UI Framework components

These directives can be used on components from any of the UI Frameworks that Astro supports. Lean more about UI Framework components on their [dedicated page](/en/core-concepts/framework-components).

### `client:load`

Start importing the component JS at page load.

💡 *Useful for immediately-visible UI elements that need to be interactive as soon as possible.*

### `client:idle`

Start importing the component JS as soon as main thread is free.

💡 *Useful for items that don't need to be immediately interactive.*

### `client:visible`

Start importing the component JS as soon as the element enters the viewport.

💡 *Useful for content lower down on the page.*

### `client:media={QUERY}`

Start importing the component JS as soon as the browser matches the given media query.

💡 *Useful for sidebar toggles, or other elements that might be used only for certain screen sizes.*

> ⚠️ Remember, this directive only refers to making the component *interactive* at certain media queries. This does not affect the component being *rendered to the screen*, nor its *visibility*!
### `client:only=" "`

Start importing the component JS at page load, similar to `client:load`.

💡 *Useful for components that are entirely dependent on client-side APIs.*

>⚠️ This component will be **skipped** at build time, and to assist the client, you should specify which renderer to use from the array in your [`astro.config.mjs` configuration](/en/reference/configuration-reference).
>
> e.g. `<client:only="react" />` or `<client:only="my-custom-renderer" />`
## Script and Style tags

These directives can be used on HTML `<script>` and `<style>` tags.

### `define:vars={variables}`

Pass variables into a `<script>` or `<style>` tag. Any *serializable* front matter variable is supported, including props passed to your component through `Astro.props`.

```astro
---
const foregroundColor = "rgb(221 243 228)";
const backgroundColor = "rgb(24 121 78)";
const message = "Astro is awsome!";
---
<style define:vars={{ textColor: foregroundColor, backgroundColor }}>
h1 {
background-color: var(--backgroundColor);
color: var(--textColor);
}
</style>
<script define:vars={{ message }}>
alert(message);
</script>
```

>⚠️ Using `define:vars` on a `<script>` or `<style>` tag implies the `is:inline` directive, which means your scripts or styles won't be bundled and will be inlined directly into the HTML. See the [dedicated section](#isinline) on `is:inline` for more details.
### `is:inline`

Opt-out a `<script>` or `<stlye>` tag from being bundled.

This means that whatever you put in the tag is directly inlined into the page. In `<script>` tags, that means you can't use ESM imports to NPM modules.

The `is:inline` directive means that `<style>` and `<script>` tags:

- Will not be bundled into an external file.
- Will not be deduplicated—the element will appear as many times as it is rendered.
- Will be pre-processed, for example a `<style lang="sass">` attribute will still generate plain CSS.
- Will be rendered in the final output HTML where it is authored.

> ⚠️ The `is:inline` directive is implied whenever any attribute other than `src` is used on a `<script>` or `<style>` tag.
```astro
<style is:inline>
span { color: green; }
</style>
<script is:inline>
console.log('I am literally inlined here on the page');
</script>
<style>
@import './dep.css'; /* Vite imports supported, including npm packages! */
h1 { color: red; }
</style>
<script>
import cowsay from 'cowsay'; // Here too!
console.log(cowsay('I am bundled with the rest of the website JS!'));
</script>
```

### `is:global`

Make the contents of a `<style>` tag apply globaly on pages where the component is included by disabling Astro's CSS scoping system.

This is equivalent to wrapping all of the selectors within a `<style>` tag with `:global()`.

📚 See the [Styling & CSS](/en/guides/styling/#global-styles) page for more details about how global styles work.

```astro
<!-- This: -->
<style is:global>
a {
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
</style>
<!-- Is equivilent to this: -->
<style>
:global(a) {
text-decoration: none;
}
:global(a:hover) {
text-decoration: underline;
}
</style>
```

## HTML elements

These directives can be used on any HTML element, even the lowly `<div>`.

### `set:html={html}`

Inject an HTML string into an element without it being escaped.

```astro
---
const title = "Hello <strong>World</strong>"
---
<h1>{title}</h1> <!-- <h1>Hello &lt;strong&gt;World&lt;/strong&gt;</h1> -->
<h1 set:html={title} /> <!-- <h1>Hello <strong>World</strong></h1> -->
```

You can also use it on a `<Fragment>` to avoid adding a wrapper element.

```astro
---
const cmsContent = await fetchDataFromMyCMS();
---
<Fragment set:html={cmsContent}>
```

### `set:text={text}`

The opposite of `set:html`. `set:text` ensures that any HTML content passed to it is escaped.

This is the default behavior without using any directives though, so there aren't really any use cases for it other than making it clear that the content is being escaped properly.

```astro
---
const potentialyDangerousContent = await fetchUserGeneratedContent();
---
<Fragment set:text={potentialyDangerousContent}>
```

0 comments on commit 5c542c8

Please sign in to comment.