summaryrefslogtreecommitdiff
path: root/docs/core-concepts/astro-components.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/core-concepts/astro-components.md')
-rw-r--r--docs/core-concepts/astro-components.md208
1 files changed, 208 insertions, 0 deletions
diff --git a/docs/core-concepts/astro-components.md b/docs/core-concepts/astro-components.md
new file mode 100644
index 000000000..e6d80f976
--- /dev/null
+++ b/docs/core-concepts/astro-components.md
@@ -0,0 +1,208 @@
+---
+layout: ~/layouts/Main.astro
+title: Astro Components
+---
+
+
+
+## ✨ `.astro` Syntax
+
+Astro comes with its own server-side, component-based templating language. Think of it as HTML enhanced with the full power of JavaScript.
+
+Learning a new syntax can be intimidating, but the `.astro` format has been carefully designed with familiarity in mind. It borrows heavily from patterns you likely already know—components, Frontmatter, and JSX-like expressions. We're confident that this guide will help you feel comfortable writing `.astro` files in no time.
+
+---
+
+### The `.astro` format
+
+If you're already familiar with **HTML or JavaScript**, you'll likely feel comfortable with `.astro` files right away.
+
+Think of `.astro` as **component-oriented HTML**. Components are reusable, self-contained blocks of HTML and CSS that belong together.
+
+```html
+<!-- This is a valid Astro component -->
+<html lang="en">
+ <head>
+ <meta charset="UTF-8" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <title>Document</title>
+ </head>
+ <body>
+ <main>
+ <h1>Hello world!</h1>
+ </main>
+ </body>
+</html>
+```
+
+```html
+<!-- This is also a valid Astro component! -->
+<main>
+ <h1>Hello world!</h1>
+</main>
+```
+
+Developers have come up with a myriad of different techniques for composing blocks of HTML over the years, but far and away the most successful has been [JSX](https://reactjs.org/docs/introducing-jsx.html).
+
+We love JSX! In fact, `.astro` files borrow the highly-expressive expression syntax directly from JSX.
+
+```jsx
+<!-- This is an Astro component with expressions! -->
+<main>
+ <h1>Hello {name}!</h1>
+ <ul>
+ {items.map((item) => (
+ <li>{item}</li>
+ ))}
+ </ul>
+ <h2 data-hint={`Use JS template strings when you need to mix-in ${"variables"}.`}>So good!</h2>
+</main>
+```
+
+`.astro` files also borrow the concept of [Frontmatter](https://jekyllrb.com/docs/front-matter/) from Markdown. Instead of introducing a new HTML-oriented `import` and `export` syntax, `.astro` just uses JavaScript.
+
+```jsx
+---
+// This area is TypeScript (and therefore JavaScript)!
+import MyComponent from './MyComponent.astro'
+---
+
+<html lang="en">
+ <head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>Document</title>
+ </head>
+ <body>
+ <MyComponent></MyComponent>
+ </body>
+</html>
+```
+
+### Data and Props
+
+`.astro` components can define local variables inside of the Frontmatter script. These are automatically exposed to the content below.
+
+```jsx
+---
+let name = 'world';
+---
+
+<main>
+ <h1>Hello {name}!</h1>
+</main>
+```
+
+`.astro` components can also accept props when they are rendered. Public props are exposed on the `Astro.props` global.
+
+```jsx
+---
+const { greeting = 'Hello', name } = Astro.props;
+---
+
+<main>
+ <h1>{greeting} {name}!</h1>
+</main>
+```
+
+To define the props which your component accepts, you may export a TypeScript interface or type named `Props`.
+
+```tsx
+---
+export interface Props {
+ name: string;
+ greeting?: string;
+}
+
+const { greeting = 'Hello', name } = Astro.props;
+---
+
+<main>
+ <h1>{greeting} {name}!</h1>
+</main>
+```
+
+### Fragments
+
+At the top-level of an `.astro` file, you may render any number of elements.
+
+```html
+<!-- Look, no Fragment! -->
+<div id="a" />
+<div id="b" />
+<div id="c" />
+```
+
+Inside of an expression, you must wrap multiple elements in a Fragment. Fragments must open with `<>` and close with `</>`.
+
+```jsx
+<div>
+ {[0, 1, 2].map((id) => (
+ <>
+ <div id={`a-${id}`} />
+ <div id={`b-${id}`} />
+ <div id={`c-${id}`} />
+ </>
+ ))}
+</div>
+```
+
+### `.astro` versus `.jsx`
+
+`.astro` files can end up looking very similar to `.jsx` files, but there are a few key differences. Here's a comparison between the two formats.
+
+| Feature | Astro | JSX |
+| ---------------------------- | ------------------------------------------ | -------------------------------------------------- |
+| File extension | `.astro` | `.jsx` or `.tsx` |
+| User-Defined Components | `<Capitalized>` | `<Capitalized>` |
+| Expression Syntax | `{}` | `{}` |
+| Spread Attributes | `{...props}` | `{...props}` |
+| Boolean Attributes | `autocomplete` === `autocomplete={true}` | `autocomplete` === `autocomplete={true}` |
+| Inline Functions | `{items.map(item => <li>{item}</li>)}` | `{items.map(item => <li>{item}</li>)}` |
+| IDE Support | WIP - [VS Code][code-ext] | Phenomenal |
+| Requires JS import | No | Yes, `jsxPragma` (`React` or `h`) must be in scope |
+| Fragments | Automatic top-level, `<>` inside functions | Wrap with `<Fragment>` or `<>` |
+| Multiple frameworks per-file | Yes | No |
+| Modifying `<head>` | Just use `<head>` | Per-framework (`<Head>`, `<svelte:head>`, etc) |
+| Comment Style | `<!-- HTML -->` | `{/* JavaScript */}` |
+| Special Characters | `&nbsp;` | `{'\xa0'}` or `{String.fromCharCode(160)}` |
+| Attributes | `dash-case` | `camelCase` |
+
+### URL resolution
+
+It’s important to note that Astro **won’t** transform HTML references for you. For example, consider an `<img>` tag with a relative `src` attribute inside `src/pages/about.astro`:
+
+```html
+<!-- ❌ Incorrect: will try and load `/about/thumbnail.png` -->
+<img src="./thumbnail.png" />
+```
+
+Since `src/pages/about.astro` will build to `/about/index.html`, you may not have expected that image to live at `/about/thumbnail.png`. So to fix this, choose either of two options:
+
+#### Option 1: Absolute URLs
+
+```html
+<!-- ✅ Correct: references public/thumbnail.png -->
+<img src="/thumbnail.png" />
+```
+
+The recommended approach is to place files within `public/*`. This references a file it `public/thumbnail.png`, which will resolve to `/thumbnail.png` at the final build (since `public/` ends up at `/`).
+
+#### Option 2: Asset import references
+
+```jsx
+---
+// ✅ Correct: references src/thumbnail.png
+import thumbnailSrc from './thumbnail.png';
+---
+
+<img src={thumbnailSrc} />
+```
+
+If you’d prefer to organize assets alongside Astro components, you may import the file in JavaScript inside the component script. This works as intended but this makes `thumbnail.png` harder to reference in other parts of your app, as its final URL isn’t easily-predictable (unlike assets in `public/*`, where the final URL is guaranteed to never change).
+
+### TODO: Composition (Slots)
+
+[code-ext]: https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode
+
+