Skip to content

update formating, linting, and some dependencies #1117

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 9 commits into from
Mar 10, 2025
Merged
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
45 changes: 0 additions & 45 deletions .eslintrc.json

This file was deleted.

17 changes: 7 additions & 10 deletions .github/ISSUE_TEMPLATE/BUGS.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
name: "Bug Report 🪲"
description: Report an issue or possible bug with the functionality of the Solid docs website. (Not related to the content of the site.)
title: "[Bug]: "
labels: [
"bug",
"pending review"
]
assignees:
- danieljcafonso
- atilafassina
labels: ["bug", "pending review"]
assignees:
- danieljcafonso
- atilafassina

body:
- type: textarea
@@ -25,21 +22,21 @@ body:
description: Please indicate on which page(s) the issue occurs.
placeholder: https://docs.solidjs.com/concepts/intro-to-reactivity
validations:
required: true
required: true
- type: textarea
id: expected
attributes:
label: "🤔 Expected Behavior"
description: Please describe what the expected behavior should be.
placeholder: When on this page, I expected . . .
placeholder: When on this page, I expected . . .
validations:
required: true
- type: textarea
id: current
attributes:
label: "👀 Current Behavior"
description: Please describe what the current behavior is.
placeholder: But instead, on this page I'm noticing . . .
placeholder: But instead, on this page I'm noticing . . .
validations:
required: true
- type: input
14 changes: 6 additions & 8 deletions .github/ISSUE_TEMPLATE/CONTENT.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
name: "Content Report 📄"
title: "[Content]:"
description: Report an issue with existing content.
labels: [
"improve documentation", "pending review"
]
assignees:
- ladybluenotes
labels: ["improve documentation", "pending review"]
assignees:
- ladybluenotes
body:
- type: markdown
attributes:
@@ -25,19 +23,19 @@ body:
description: Please provide the URL of the page(s) affected.
placeholder: https://docs.solidjs.com/concepts/intro-to-reactivity
validations:
required: true
required: true
- type: textarea
id: generalDesc
attributes:
label: "📋 Description of content that is out-of-date or incorrect"
description: Let us know what's wrong!
placeholder: "..."
validations:
required: true
required: true
- type: textarea
id: incorrectContent
attributes:
label: "🖥️ Reproduction in StackBlitz (if reporting incorrect content or code samples)"
description: If you are reporting incorrect content or code samples, you can also attach a reproduction in stackblitz.
validations:
required: false
required: false
6 changes: 2 additions & 4 deletions .github/ISSUE_TEMPLATE/OTHER.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
name: "Other Report 🌐"
title: "[Other]:"
description: Report something else we should know about the docs site!
labels: [
"pending review"
]
labels: ["pending review"]
body:
- type: textarea
id: issue
@@ -12,4 +10,4 @@ body:
description: Please describe the problem with the documentation in detail.
placeholder: "..."
validations:
required: true
required: true
14 changes: 6 additions & 8 deletions .github/ISSUE_TEMPLATE/REQUEST.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
name: "Request 💡"
title: "[Request]:"
description: Share an idea.
labels: [
"request", "pending review"
]
labels: ["request", "pending review"]
assignees:
- ladybluenotes
- ladybluenotes
body:
- type: markdown
attributes:
@@ -14,7 +12,7 @@ body:
id: request-topic
attributes:
label: "What is this request related to?"
options:
options:
- Request
- Styling
- Feature
@@ -27,20 +25,20 @@ body:
description: Please provide the URL of the page(s) or section this idea is related to.
placeholder: https://docs.solidjs.com/concepts/intro-to-reactivity
validations:
required: false
required: false
- type: textarea
id: generalDesc
attributes:
label: "📋 General description or bullet points"
description: Please provide a general description or bullet points about what you would like to see added.
placeholder: "..."
validations:
required: true
required: true
- type: textarea
id: example
attributes:
label: "🖥️ Reproduction of code samples in StackBlitz"
description: If you would like to suggest code samples please attach a working reproduction.
placeholder: "..."
validations:
required: false
required: false
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -2,4 +2,4 @@ blank_issues_enabled: true
contact_links:
- name: Support & Community 💁
url: https://discord.com/invite/solidjs
about: 'This issue tracker is not for support questions. Our Discord server hosts the community of Solid users. Come join us to discuss Solid or find assistance!'
about: "This issue tracker is not for support questions. Our Discord server hosts the community of Solid users. Come join us to discuss Solid or find assistance!"
1 change: 1 addition & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@
- [ ] This PR references an issue (except for typos, broken links, or other minor problems)

### Description(required)

<!-- Provide a detailed description of the changes in this PR. Why is it necessary, and what does it do? -->

### Related issues & labels
21 changes: 21 additions & 0 deletions .github/actions/install/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Install Tools & Dependencies
description: Installs pnpm, Node.js & package dependencies

runs:
using: composite
steps:
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- name: Install dependencies
run: pnpm install
shell: bash
21 changes: 21 additions & 0 deletions .github/workflows/format.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Install Tools & Dependencies
description: Installs pnpm, Node.js & package dependencies

runs:
using: composite
steps:
- name: Setup pnpm
uses: pnpm/action-setup@v4
with:
version: 9
run_install: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm

- name: Install dependencies
run: pnpm install
shell: bash
69 changes: 18 additions & 51 deletions .github/workflows/static_checks.yml
Original file line number Diff line number Diff line change
@@ -2,70 +2,37 @@ name: 🔍 Lint / Type Checks

on:
push:
branches: [main]
branches:
- main

pull_request:
branches: [main]
branches:
- main

jobs:
setup:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- run: pnpm i
- uses: actions/cache/save@v4
with:
path: |
node_modules
~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}

typecheck:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Check out code
uses: actions/checkout@v4

- name: Install tools & dependencies
uses: ./.github/actions/install

- name: Generate virtual modules
run: pnpm sync

- name: TypeScript check
run: pnpm check:types

lint:
needs: setup
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- uses: actions/cache/restore@v4
with:
path: |
node_modules
~/.pnpm-store
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
- name: Check out code
uses: actions/checkout@v4

- name: Install tools & dependencies
uses: ./.github/actions/install

- name: ESLint check
run: pnpm check:lint
1 change: 0 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": false,
56 changes: 19 additions & 37 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -2,27 +2,21 @@

Thank you for helping us make this project great and being a part of the Solid community!

We welcome contributions from anyone, regardless of your skill level.
We are happy to help with guidance on PRs, technical writing, and turning features into realities.
We welcome contributions from anyone, regardless of your skill level. We are happy to help with guidance on PRs, technical writing, and turning features into realities.

> **New to contributing?**
> Take a look at [this GitHub guide](https://docs.github.com/en/get-started/start-your-journey/hello-world) to learn how to use Git and GitHub to contribute to open-source.
> **New to contributing?** Take a look at [this GitHub guide](https://docs.github.com/en/get-started/start-your-journey/hello-world) to learn how to use Git and GitHub to contribute to open-source.
If you're new to Solid, we ask that you check out our [Writing Guide](https://github.com/solidjs/solid-docs-next/blob/main/WRITING.md).

## Types of contributions

There are many ways to contribute to the Solid's documentation!

The Solid Docs website is built on Solid!
Maintaining it requires not only written content and Solid code maintenance, but it also needs to address accessibility (a11y), CSS, UI, and UX concerns.
We also aim to make our documentation available in several languages, so we need help translating the entire site.
The Solid Docs website is built on Solid! Maintaining it requires not only written content and Solid code maintenance, but it also needs to address accessibility (a11y), CSS, UI, and UX concerns. We also aim to make our documentation available in several languages, so we need help translating the entire site.

You can help out by leaving review comments on [PRs](https://github.com/solidjs/solid-docs-next/pulls) and adding ideas in existing GitHub [issues ](https://github.com/solidjs/solid-docs-next/issues) and [discussions](https://github.com/solidjs/solid-docs-next/discussions).

Every PR, especially translation PRs, will need reviewers.
Reviewing PRs and leaving comments, suggestions, or even saying "Looks good!" can be a great way to get started on contributing alongside our Docs team.
It's also a great way to learn more about Solid!
Every PR, especially translation PRs, will need reviewers. Reviewing PRs and leaving comments, suggestions, or even saying "Looks good!" can be a great way to get started on contributing alongside our Docs team. It's also a great way to learn more about Solid!

We encourage you to:

@@ -71,8 +65,7 @@ We use labels as a way to organize and categorize our issues. Here are some comm

## Start a discussion

Discussions are a place within this repository where we can have open-ended conversations.
It's the perfect place for Q&A, sharing ideas, community engagement, and connecting with other members.
Discussions are a place within this repository where we can have open-ended conversations. It's the perfect place for Q&A, sharing ideas, community engagement, and connecting with other members.

Feel free to start a [new discussion](https://github.com/solidjs/solid-docs-next/discussions) on any topic related to our docs!

@@ -87,25 +80,22 @@ Feel free to start a [new discussion](https://github.com/solidjs/solid-docs-n

> If you've never submitted a pull request on GitHub before, check out [this overview on how to open a PR](https://opensource.guide/how-to-contribute/#opening-a-pull-request).
PRs are the heart of collaboration on GitHub.
When you open a pull request, you are putting forward your suggested changes, inviting us to review it, and requesting for these changes to be merged into our main branch.
PRs are the heart of collaboration on GitHub. When you open a pull request, you are putting forward your suggested changes, inviting us to review it, and requesting for these changes to be merged into our main branch.

Here's how to effectively contribute via a PR:

- **Understand the Scope**: Before creating a PR, ensure it addresses an existing issue. Remember to link your PR to the issue it solves for easy tracking and understanding.
- **Singular Focus**: Each PR should address a single issue or enhancement. Want to propose a larger change? Reach out to us on [Discord](https://discord.com/invite/solidjs) and let's discuss the best way forward!
- **Drafts for Early Feedback**: If you're seeking early feedback but aren't quite finished with your changes, consider creating a draft PR. Simply prefix your PR title with `**[Draft]**`. This way, you can get input on your work-in-progress.
- **Quality over Quantity**: Strive for the quality of your contribution rather than the quantity. A well-thought-out, cleanly coded, and thoroughly tested PR is much more valuable than a hastily done large one.
Contributing via PRs not only enhances the project, but also allows you to be a part of the active community, sharing ideas, learning, and growing with the project.
- **Quality over Quantity**: Strive for the quality of your contribution rather than the quantity. A well-thought-out, cleanly coded, and thoroughly tested PR is much more valuable than a hastily done large one. Contributing via PRs not only enhances the project, but also allows you to be a part of the active community, sharing ideas, learning, and growing with the project.

> Existing PRs and Issues need reviewing, triaging, and feedback, too! You can make valuable contributions by commenting, suggesting, testing, researching, brainstorming and generally helping in all areas!
### Writing a PR

> Need help making a PR? [Join us on Discord](https://discord.com/invite/solidjs), we'll be more than happy to help you out!
Contributions to the documentation site are made by editing the docs repository.
You can do this directly on GitHub.com or by creating a copy of the repository locally, making your changes there, and contributing back to our repository.
Contributions to the documentation site are made by editing the docs repository. You can do this directly on GitHub.com or by creating a copy of the repository locally, making your changes there, and contributing back to our repository.

#### Examples of helpful PRs

@@ -115,11 +105,9 @@ You can do this directly on GitHub.com or by creating a copy of the repository l

### Edit this page via GitHub

Every page on [docs.solidjs.com](https://docs.solidjs.com/) has an **Edit this page** link at the bottom.
You can click on that button to edit the source code for that page in **GitHub**.
Every page on [docs.solidjs.com](https://docs.solidjs.com/) has an **Edit this page** link at the bottom. You can click on that button to edit the source code for that page in **GitHub**.

After you make your changes, click **Commit changes**.
This will automatically create a [fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) of the docs in your GitHub account with the changes.
After you make your changes, click **Commit changes**. This will automatically create a [fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks) of the docs in your GitHub account with the changes.

Once you have committed your edits within your fork, follow the prompts to create a **pull request** and submit your changes for review.

@@ -133,13 +121,13 @@ Though it is not a hard requirement, we'd deeply appreciate if you could recomme

1. Create a dictionary file in `src/i18n/dictionaries/{locale}/ui.ts`. The name should follow our locale convention.

- language (ISO 639-1 - set 1): https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
- country code(optional) (ISO 3166-1 alpha-2): https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
- E.g.: Canadian French would be: `fr-ca`
- language (ISO 639-1 - set 1): https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes
- country code(optional) (ISO 3166-1 alpha-2): https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
- E.g.: Canadian French would be: `fr-ca`

2. Add the `import` and language information to the objects in the barrel file: `./src/i18n/dictionaries/index.ts`. So it will be identified by the routing system, and an entry its added to the language dropdown.
3. Add the language to the `array` in `./scripts/collections/index.mjs` so internal files are created.
4. Add the important UI translations to `./src/i18n/dictionaries/{locale}/ui.ts`
4. Add the important UI translations to `./src/i18n/dictionaries/{locale}/ui.ts`
5. Add at least the index page `./src/routes/{locale}/index.mdx`, so others and yourself could see things in action.

#### Adding translations to a supported language
@@ -153,13 +141,11 @@ To translate a new entry to an existing language, go to `src/routes/{locale}` an

Once you have made your changes using your preferred method, you're ready to create a 'pull request'.

This will let the Solid docs team know you have some changes you would like to propose.
At this point, we can give you feedback and possibly request changes.
This will let the Solid docs team know you have some changes you would like to propose. At this point, we can give you feedback and possibly request changes.

[Read more about making a pull request in GitHub's docs.](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project#making-a-pull-request)

Please include a clear title.
The description will have some pre-filled questions that we would like you to answer.
Please include a clear title. The description will have some pre-filled questions that we would like you to answer.

Every pull request generates a preview of the site, including your proposed changes, using **Netlify** for anyone to see.

@@ -171,21 +157,17 @@ The docs site will be automatically updated whenever pull requests are merged.

### Forks

On GitHub, you will need a 'fork' of this repository to work on.
This is your own copy of the code base where you can make changes. You can read more about forks in [GitHub's documentation](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project).
On GitHub, you will need a 'fork' of this repository to work on. This is your own copy of the code base where you can make changes. You can read more about forks in [GitHub's documentation](https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project).

Not sure how to get started with GitHub, forks, pull requests, or want a refresher?
You can watch this video series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github).
Not sure how to get started with GitHub, forks, pull requests, or want a refresher? You can watch this video series: [How to Contribute to an Open Source Project on GitHub](https://egghead.io/courses/how-to-contribute-to-an-open-source-project-on-github).

#### Creating a fork

To create your copy, click the `Fork` button at the top right of any page in this repository.

#### Maintaining a fork

When you first create your fork, it will be an exact copy of this repository.
Over time, our docs will change as they are updated, but your fork won’t automatically stay up-to-date.
Here are some ways to keep your fork in sync with this repo:
When you first create your fork, it will be an exact copy of this repository. Over time, our docs will change as they are updated, but your fork won’t automatically stay up-to-date. Here are some ways to keep your fork in sync with this repo:

##### Update through GitHub UI

57 changes: 15 additions & 42 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,75 +2,49 @@

Welcome to Solid's documentation!

This is the repo for [docs.solidjs.com](https://docs.solidjs.com/). This repo
contains all the source code that we use to build our docs.
This is the repo for [docs.solidjs.com](https://docs.solidjs.com/). This repo contains all the source code that we use to build our docs.

[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/solidjs/solid-docs-next)
[![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/github/solidjs/solid-docs-next/)
[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/solidjs/solid-docs-next)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/solidjs/solid-docs-next) [![Open with CodeSandbox](https://assets.codesandbox.io/github/button-edit-lime.svg)](https://codesandbox.io/p/github/solidjs/solid-docs-next/) [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/solidjs/solid-docs-next)

## What is Solid?

Solid is a JavaScript framework used for building high-performance
user-interfaces. Using a reactive approach and component-based architecture, we
want to empower developers in creating efficient and scalable web applications.
Solid is a JavaScript framework used for building high-performance user-interfaces. Using a reactive approach and component-based architecture, we want to empower developers in creating efficient and scalable web applications.

## Thank you for being here!

You can help make our docs better for the community! Your feedback is welcomed.
In addition, any editing, translating, designing, and developing skills are
welcomed. We are grateful to welcome you into our community!
You can help make our docs better for the community! Your feedback is welcomed. In addition, any editing, translating, designing, and developing skills are welcomed. We are grateful to welcome you into our community!

If you want to see how you can contribute, check out our
[How You Can Help](#how-you-can-help) section.
If you want to see how you can contribute, check out our [How You Can Help](#how-you-can-help) section.

## Chat with us

You can learn more about Solid, get support, and meet other devs and
contributors in our [Discord community](https://discord.com/invite/solidjs).
You can learn more about Solid, get support, and meet other devs and contributors in our [Discord community](https://discord.com/invite/solidjs).

## Raise an issue

Have you noticed something is missing, confusing, or is wrong in our
documentation?
Have you noticed something is missing, confusing, or is wrong in our documentation?

Check to see if it has
[already been mentioned ](https://github.com/solidjs/solid-docs-next/issues)
and, if not,
[create an issue](https://github.com/solidjs/solid-docs-next/issues/new/choose)
to bring it to our attention!
Check to see if it has [already been mentioned ](https://github.com/solidjs/solid-docs-next/issues) and, if not, [create an issue](https://github.com/solidjs/solid-docs-next/issues/new/choose) to bring it to our attention!

## Share an idea

Do you think something could be better? Have an idea you feel could make the
docs better?
Do you think something could be better? Have an idea you feel could make the docs better?

Discussion threads are where you can offer feedback on things that might not be
problems that need addressing, but are ideas to be explored.
Discussion threads are where you can offer feedback on things that might not be problems that need addressing, but are ideas to be explored.

Join us in the
[Discussions section](https://github.com/solidjs/solid-docs-next/discussions/280)
where we can brainstorm these ideas, ask questions, and share goals!
Join us in the [Discussions section](https://github.com/solidjs/solid-docs-next/discussions/280) where we can brainstorm these ideas, ask questions, and share goals!

## Suggest a fix or contribute

Have you found a typo, broken link, or another item with an obvious quick fix?

If you can see what the problem is, and you know how to fix it, you can make a
PR (pull request) with the change and contribute to the docs repo yourself.
If you can see what the problem is, and you know how to fix it, you can make a PR (pull request) with the change and contribute to the docs repo yourself.

If you're looking to make a larger contribution, please see our
[CONTRIBUTING.md](https://github.com/solidjs/solid-docs-next/blob/main/CONTRIBUTING.md)
first!
If you're looking to make a larger contribution, please see our [CONTRIBUTING.md](https://github.com/solidjs/solid-docs-next/blob/main/CONTRIBUTING.md) first!

## Running the Site Locally

At the moment, we recommend running the site locally through either
[CodeSandbox](https://codesandbox.io/p/github/solidjs/solid-docs-next/),
[Gitpod](https://gitpod.io/#https://github.com/solidjs/solid-docs-next), or
[StackBlitz](https://stackblitz.com/github/solidjs/solid-docs-next). These are
the quickest and easiest way to browse and edit the project files and run the
site locally.
At the moment, we recommend running the site locally through either [CodeSandbox](https://codesandbox.io/p/github/solidjs/solid-docs-next/), [Gitpod](https://gitpod.io/#https://github.com/solidjs/solid-docs-next), or [StackBlitz](https://stackblitz.com/github/solidjs/solid-docs-next). These are the quickest and easiest way to browse and edit the project files and run the site locally.

The app uses [pnpm](https://pnpm.io) as the package manager and it runs on Node.js `v18+`.

@@ -90,7 +64,6 @@ This will start your the app at [localhost:3000](http://localhost:3000) or the n

### Collections and virtual modules

The builds an [Astro](https://docs.astro.build/en/guides/content-collections/) inspired collection navigation, it will bring all routes and generate a couple of files at `/.solid`.
These files are exposed to your app via [Vite virtual modules](https://vitejs.dev/guide/api-plugin#virtual-modules-convention). This task is perform via our `sync` script (`pnpm sync`), ran before every build.
The builds an [Astro](https://docs.astro.build/en/guides/content-collections/) inspired collection navigation, it will bring all routes and generate a couple of files at `/.solid`. These files are exposed to your app via [Vite virtual modules](https://vitejs.dev/guide/api-plugin#virtual-modules-convention). This task is perform via our `sync` script (`pnpm sync`), ran before every build.

If changes are made to the navigation (new entry, or repositioning entry), it is necessary to restart the server for changes to take effect.
160 changes: 42 additions & 118 deletions WRITING.md

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions app.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineConfig } from "@solidjs/start/config";
import eslint from "vite-plugin-eslint";

Check failure on line 2 in app.config.ts

GitHub Actions / typecheck

Could not find a declaration file for module 'vite-plugin-eslint'. '/home/runner/work/solid-docs/solid-docs/node_modules/.pnpm/vite-plugin-eslint@1.8.1_eslint@9.22.0_jiti@2.4.2__vite@6.2.1_@types+node@22.9.0_jiti@2.4.2_terser@5.34.1_yaml@2.6.0_/node_modules/vite-plugin-eslint/dist/index.mjs' implicitly has an 'any' type.

import { createWithSolidBase, defineTheme } from "@kobalte/solidbase/config";

@@ -58,7 +59,7 @@
},
},
vite: {
plugins: [docsData(), heroCodeSnippet()],
plugins: [docsData(), heroCodeSnippet(), eslint()],
},
},
{
@@ -68,7 +69,7 @@
editPath: "https://github.com/solidjs/solid-docs/edit/main/:path",
markdown: {
expressiveCode: {
themes: ["min-light", "material-theme-ocean"],
themes: ["github-light-default", "material-theme-ocean"],
themeCssSelector: (theme) => `[data-theme="${theme.type}"]`,
frames: false,
styleOverrides: {
85 changes: 85 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import typescriptEslint from "@typescript-eslint/eslint-plugin";
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import path from "node:path";
import { fileURLToPath } from "node:url";
import js from "@eslint/js";
import { FlatCompat } from "@eslint/eslintrc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});

export default [
{
ignores: ["**/node_modules/", "**/dist/"],
},
...compat.extends(
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:solid/typescript",
"plugin:mdx/recommended",
),
{
plugins: {
"@typescript-eslint": typescriptEslint,
},

languageOptions: {
globals: {
...globals.browser,
},

parser: tsParser,
ecmaVersion: "latest",
sourceType: "script",
},
rules: {
"@typescript-eslint/no-unused-vars": [
"error",
{
args: "all",
argsIgnorePattern: "^_",
caughtErrors: "all",
caughtErrorsIgnorePattern: "^_",
destructuredArrayIgnorePattern: "^_",
varsIgnorePattern: "^_",
ignoreRestSiblings: true,
},
],
},
},
{
files: ["**/*.mdx"],
extends: ["plugin:mdx/recommended"],
settings: {
"mdx/code-blocks": true,
},
extensions: ["mdx"],
overrides: [
{
files: ["*.mdx"],
extends: ["plugin:mdx/overrides"],
},
{
files: "**/*.mdx",
extends: "plugin:mdx/code-blocks",
},
],
},
{
files: ["**/.eslintrc.{js,cjs}"],
languageOptions: {
globals: {
...globals.node,
},

ecmaVersion: 5,
sourceType: "commonjs",
},
},
];
57 changes: 0 additions & 57 deletions lunaria.config.json

This file was deleted.

4 changes: 0 additions & 4 deletions lunaria/styles.css

This file was deleted.

40 changes: 23 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
@@ -8,20 +8,20 @@
"sync": "node scripts/collections/index.mjs",
"sync:orama": "pnpm build && node scripts/sync-orama.mjs",
"dev": "pnpm sync && vinxi dev",
"build": "pnpm sync && pnpm build:sitemap && pnpm build:lunaria && NODE_OPTIONS=\"--max-old-space-size=8192\" vinxi build",
"build": "pnpm sync && pnpm build:sitemap && vinxi build",
"build:sitemap": "node scripts/generateSitemap.js",
"start": "vinxi start",
"e2e": "npx playwright test",
"build:lunaria": "lunaria build",
"preview:lunaria": "lunaria preview",
"check:lint": "eslint .",
"check:types": "tsc --noEmit"
"check:lint": "pnpm dlx eslint",
"check:types": "tsc --noEmit",
"check:format": "prettier . --check",
"format": "prettier . --write"
},
"dependencies": {
"@kobalte/core": "^0.13.9",
"@kobalte/solidbase": "^0.0.16",
"@kobalte/solidbase": "^0.0.23",
"@lunariajs/core": "^0.0.31",
"@oramacloud/client": "^1.3.15",
"@oramacloud/client": "^1.3.16",
"@solid-primitives/event-listener": "^2.3.3",
"@solid-primitives/marker": "^0.1.0",
"@solid-primitives/media": "^2.2.9",
@@ -30,10 +30,12 @@
"@solidjs/start": "^1.1.1",
"@vinxi/plugin-mdx": "^3.7.2",
"dotenv": "^16.4.5",
"eslint-mdx": "^3.2.0",
"eslint-plugin-mdx": "^3.2.0",
"glob": "^10.4.5",
"gray-matter": "^4.0.3",
"postcss": "^8.4.47",
"shiki": "^1.17.6",
"postcss": "^8.5.3",
"shiki": "^1.22.0",
"sitemap": "^7.1.2",
"solid-heroicons": "^3.2.4",
"solid-js": "^1.9.5",
@@ -43,22 +45,26 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@eslint/eslintrc": "^3.3.0",
"@eslint/js": "^9.22.0",
"@kobalte/tailwindcss": "^0.9.0",
"@orama/crawly": "^0.0.4",
"@tailwindcss/typography": "^0.5.15",
"@types/node": "^22.9.0",
"@typescript-eslint/eslint-plugin": "^8.7.0",
"@typescript-eslint/parser": "^8.7.0",
"@typescript-eslint/eslint-plugin": "^8.26.0",
"@typescript-eslint/parser": "^8.26.0",
"autoprefixer": "^10.4.20",
"eslint": "^8.57.1",
"eslint-plugin-solid": "^0.13.2",
"eslint": "^9.22.0",
"eslint-plugin-solid": "^0.14.5",
"globals": "^16.0.0",
"prettier": "3.2.5",
"tailwindcss": "^3.4.11",
"typescript": "^5.6.2",
"vite": "^6.1.1"
"tailwindcss": "^3.4.14",
"typescript": "^5.8.2",
"vite": "^6.2.1",
"vite-plugin-eslint": "^1.8.1"
},
"engines": {
"node": ">=18",
"packageManager": "pnpm@8"
"pnpm": ">=9"
}
}
2,165 changes: 1,589 additions & 576 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions scripts/collections/build-file-tree.mjs
Original file line number Diff line number Diff line change
@@ -3,14 +3,15 @@ import matter from "gray-matter";
import fs from "fs/promises";
import { getDirData } from "./utils/get-dir-data.mjs";
import { COLLECTIONS_ROOT } from "./index.mjs";
import { cwd } from "process";

/**
*
* @param {string} entry
* @returns
*/
export async function buildFileTree(entry = COLLECTIONS_ROOT) {
const entryPath = path.resolve(process.cwd(), entry);
const entryPath = path.resolve(cwd(), entry);
const parentSegment = path.parse(entryPath).dir;
try {
const stats = await fs.stat(entryPath);
@@ -56,7 +57,8 @@ export async function buildFileTree(entry = COLLECTIONS_ROOT) {
path:
"/" +
path
.relative(path.join(process.cwd(), COLLECTIONS_ROOT), entryPath)
.relative(path.join(cwd(), COLLECTIONS_ROOT), entryPath)
// eslint-disable-next-line
.replace(/\index\.mdx?/, "")
.replace(/\.mdx?/, ""),
slug: path.basename(entryPath, path.extname(entryPath)),
5 changes: 3 additions & 2 deletions scripts/collections/utils/create-dir.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { existsSync } from "fs";
import fs from "fs/promises";
import path from "path";
import { cwd } from "process";

export async function createSolidCollectionDir() {
const collectionDir = path.resolve(process.cwd(), ".solid");
const collectionDir = path.resolve(cwd(), ".solid");

if (!existsSync(collectionDir)) {
fs.mkdir(path.resolve(process.cwd(), ".solid"));
fs.mkdir(path.resolve(cwd(), ".solid"));
}
}
3 changes: 2 additions & 1 deletion scripts/collections/utils/get-dir-data.mjs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import fs from "fs/promises";
import path from "path";
import { sectionData } from "../schemas.mjs";
import { languages } from "../index.mjs";
import { cwd } from "process";

/**
*
@@ -17,7 +18,7 @@ function formatDirPath(path) {
return path;
}

export async function getDirData(dirPath = process.cwd()) {
export async function getDirData(dirPath = cwd()) {
const dir = formatDirPath(dirPath);
try {
const data = JSON.parse(
4 changes: 3 additions & 1 deletion scripts/create-i18n-entries.mjs
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@ import { existsSync } from "fs";
import path from "path";
import { COLLECTIONS_ROOT } from "./collections/index.mjs";
import { getFrontMatterData } from "./collections/utils/get-frontmatter.mjs";
import { cwd } from "process";

/**
* @typedef {Object} DocsEntry
* @property {string} type - The type of reference.
@@ -32,7 +34,7 @@ async function buildSectionList(entryList = [], locale, project = "") {
? entry.path + "index"
: entry.path;
const i18nEntryPath = path.join(
process.cwd(),
cwd(),
COLLECTIONS_ROOT,
project,
locale,
5 changes: 4 additions & 1 deletion scripts/create-i18n-tree.mjs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import { existsSync } from "fs";
import path from "path";
import { COLLECTIONS_ROOT } from "./collections/index.mjs";
import { getFrontMatterData } from "./collections/utils/get-frontmatter.mjs";
import { cwd } from "process";

/**
* @typedef {Object} Leaf
@@ -31,6 +32,8 @@ import { getFrontMatterData } from "./collections/utils/get-frontmatter.mjs";
*
* @param {Branch["children"]} children
*/

// eslint-disable-next-line
function traverseTree(children) {
for (const child of children) {
if (child.type === "section") {
@@ -62,7 +65,7 @@ export async function createI18nTree(entryList, locale, project = "") {
});
} else {
const i18nEntryPath = path.join(
process.cwd(),
cwd(),
COLLECTIONS_ROOT,
project,
locale,
5 changes: 3 additions & 2 deletions scripts/sync-orama.mjs
Original file line number Diff line number Diff line change
@@ -2,9 +2,10 @@ import { readFileSync } from "node:fs";
import { globSync } from "glob";
import { generalPurposeCrawler } from "@orama/crawly";
import "dotenv/config";
import { env } from "process";

const ORAMA_PRIVATE_API_KEY = process.env.ORAMA_PRIVATE_API_KEY;
const ORAMA_PRIVATE_INDEX_ID = process.env.ORAMA_PRIVATE_INDEX_ID;
const ORAMA_PRIVATE_API_KEY = env.ORAMA_PRIVATE_API_KEY;
const ORAMA_PRIVATE_INDEX_ID = env.ORAMA_PRIVATE_INDEX_ID;

const baseURL = new URL("../dist", import.meta.url).pathname;
const HTMLFiles = globSync("**/*.html", { cwd: baseURL });
215 changes: 142 additions & 73 deletions src/middleware/legacy-routes-redirect.ts
Original file line number Diff line number Diff line change
@@ -6,87 +6,152 @@ import { type FetchEvent } from "@solidjs/start/server";
* {origin: destination}
*/
const LEGACY_ROUTES = {

// api reference
"/references/api-reference/basic-reactivity/createEffect": "/reference/basic-reactivity/create-effect",
"/references/api-reference/basic-reactivity/createMemo": "/reference/basic-reactivity/create-memo",
"/references/api-reference/basic-reactivity/createResource": "/reference/basic-reactivity/create-resource",
"/references/api-reference/basic-reactivity/createSignal": "/reference/basic-reactivity/create-signal",
"/references/api-reference/component-apis/children": "/reference/component-apis/children",
"/references/api-reference/component-apis/createContext": "/reference/component-apis/create-context",
"/references/api-reference/component-apis/createUniqueId": "/reference/component-apis/create-unique-id",
"/references/api-reference/component-apis/lazy": "/reference/component-apis/lazy",
"/references/api-reference/component-apis/useContext": "/reference/component-apis/use-context",
"/references/api-reference/control-flow/Dynamic": "/reference/components/dynamic",
"/references/api-reference/control-flow/ErrorBoundary": "/reference/components/error-boundary",
"/references/api-reference/basic-reactivity/createEffect":
"/reference/basic-reactivity/create-effect",
"/references/api-reference/basic-reactivity/createMemo":
"/reference/basic-reactivity/create-memo",
"/references/api-reference/basic-reactivity/createResource":
"/reference/basic-reactivity/create-resource",
"/references/api-reference/basic-reactivity/createSignal":
"/reference/basic-reactivity/create-signal",
"/references/api-reference/component-apis/children":
"/reference/component-apis/children",
"/references/api-reference/component-apis/createContext":
"/reference/component-apis/create-context",
"/references/api-reference/component-apis/createUniqueId":
"/reference/component-apis/create-unique-id",
"/references/api-reference/component-apis/lazy":
"/reference/component-apis/lazy",
"/references/api-reference/component-apis/useContext":
"/reference/component-apis/use-context",
"/references/api-reference/control-flow/Dynamic":
"/reference/components/dynamic",
"/references/api-reference/control-flow/ErrorBoundary":
"/reference/components/error-boundary",
"/references/api-reference/control-flow/For": "/reference/components/for",
"/references/api-reference/control-flow/Index": "/reference/components/index-component",
"/references/api-reference/control-flow/Portal": "/reference/components/portal",
"/references/api-reference/control-flow/Index":
"/reference/components/index-component",
"/references/api-reference/control-flow/Portal":
"/reference/components/portal",
"/references/api-reference/control-flow/Show": "/reference/components/show",
"/references/api-reference/control-flow/Suspense": "/reference/components/suspense",
"/references/api-reference/control-flow/SuspenseList": "/reference/components/suspense-list",
"/references/api-reference/control-flow/Switch-and-Match": "/reference/components/switch-and-match",
"/references/api-reference/lifecycles/onCleanup": "/reference/lifecycle/on-cleanup",
"/references/api-reference/lifecycles/onError": "/reference/reactive-utilities/catch-error",
"/references/api-reference/lifecycles/onMount": "/reference/lifecycle/on-mount",
"/references/api-reference/reactive-utilities/batch": "/reference/reactive-utilities/batch",
"/references/api-reference/reactive-utilities/catchError": "/reference/reactive-utilities/catch-error",
"/references/api-reference/reactive-utilities/createRoot": "/reference/reactive-utilities/create-root",
"/references/api-reference/reactive-utilities/from": "/reference/reactive-utilities/from",
"/references/api-reference/reactive-utilities/getOwner": "/reference/reactive-utilities/get-owner",
"/references/api-reference/reactive-utilities/indexArray": "/reference/reactive-utilities/index-array",
"/references/api-reference/reactive-utilities/mapArray": "/reference/reactive-utilities/map-array",
"/references/api-reference/reactive-utilities/mergeProps": "/reference/reactive-utilities/merge-props",
"/references/api-reference/reactive-utilities/observable": "/reference/reactive-utilities/observable",
"/references/api-reference/reactive-utilities/on": "/reference/reactive-utilities/on",
"/references/api-reference/reactive-utilities/regularstartTransition": "/reference/reactive-utilities/start-transition",
"/references/api-reference/reactive-utilities/runWithOwner": "/reference/reactive-utilities/run-with-owner",
"/references/api-reference/reactive-utilities/splitProps": "/reference/reactive-utilities/split-props",
"/references/api-reference/reactive-utilities/untrack": "/reference/reactive-utilities/untrack",
"/references/api-reference/reactive-utilities/useTransition": "/reference/reactive-utilities/use-transition",
"/references/api-reference/control-flow/Suspense":
"/reference/components/suspense",
"/references/api-reference/control-flow/SuspenseList":
"/reference/components/suspense-list",
"/references/api-reference/control-flow/Switch-and-Match":
"/reference/components/switch-and-match",
"/references/api-reference/lifecycles/onCleanup":
"/reference/lifecycle/on-cleanup",
"/references/api-reference/lifecycles/onError":
"/reference/reactive-utilities/catch-error",
"/references/api-reference/lifecycles/onMount":
"/reference/lifecycle/on-mount",
"/references/api-reference/reactive-utilities/batch":
"/reference/reactive-utilities/batch",
"/references/api-reference/reactive-utilities/catchError":
"/reference/reactive-utilities/catch-error",
"/references/api-reference/reactive-utilities/createRoot":
"/reference/reactive-utilities/create-root",
"/references/api-reference/reactive-utilities/from":
"/reference/reactive-utilities/from",
"/references/api-reference/reactive-utilities/getOwner":
"/reference/reactive-utilities/get-owner",
"/references/api-reference/reactive-utilities/indexArray":
"/reference/reactive-utilities/index-array",
"/references/api-reference/reactive-utilities/mapArray":
"/reference/reactive-utilities/map-array",
"/references/api-reference/reactive-utilities/mergeProps":
"/reference/reactive-utilities/merge-props",
"/references/api-reference/reactive-utilities/observable":
"/reference/reactive-utilities/observable",
"/references/api-reference/reactive-utilities/on":
"/reference/reactive-utilities/on",
"/references/api-reference/reactive-utilities/regularstartTransition":
"/reference/reactive-utilities/start-transition",
"/references/api-reference/reactive-utilities/runWithOwner":
"/reference/reactive-utilities/run-with-owner",
"/references/api-reference/reactive-utilities/splitProps":
"/reference/reactive-utilities/split-props",
"/references/api-reference/reactive-utilities/untrack":
"/reference/reactive-utilities/untrack",
"/references/api-reference/reactive-utilities/useTransition":
"/reference/reactive-utilities/use-transition",
"/references/api-reference/rendering/DEV": "/reference/rendering/dev",
"/references/api-reference/rendering/hydrate": "/reference/rendering/hydrate",
"/references/api-reference/rendering/HydrationScript": "/reference/rendering/hydration-script",
"/references/api-reference/rendering/isServer": "/reference/rendering/is-server",
"/references/api-reference/rendering/HydrationScript":
"/reference/rendering/hydration-script",
"/references/api-reference/rendering/isServer":
"/reference/rendering/is-server",
"/references/api-reference/rendering/render": "/reference/rendering/render",
"/references/api-reference/rendering/renderToStream": "/reference/rendering/render-to-stream",
"/references/api-reference/rendering/renderToString": "/reference/rendering/render-to-string",
"/references/api-reference/rendering/renderToStringAsync": "/reference/rendering/render-to-string-async",
"/references/api-reference/secondary-primitives/createComputed": "/reference/secondary-primitives/create-computed",
"/references/api-reference/secondary-primitives/createDeferred": "/reference/secondary-primitives/create-deferred",
"/references/api-reference/secondary-primitives/createReaction": "/reference/secondary-primitives/create-reaction",
"/references/api-reference/secondary-primitives/createRenderEffect": "/reference/secondary-primitives/create-render-effect",
"/references/api-reference/secondary-primitives/createSelector": "/reference/secondary-primitives/create-selector",
"/references/api-reference/special-jsx-attributes/attr_": "/reference/jsx-attributes/attr",
"/references/api-reference/special-jsx-attributes/classList": "/reference/jsx-attributes/classlist",
"/references/api-reference/special-jsx-attributes/innerHTML-or-textContent": "/reference/jsx-attributes/innerhtml",
"/references/api-reference/special-jsx-attributes/on_": "/reference/jsx-attributes/on_",
"/references/api-reference/special-jsx-attributes/on_-and-oncapture_": "/reference/jsx-attributes/on",
"/references/api-reference/rendering/renderToStream":
"/reference/rendering/render-to-stream",
"/references/api-reference/rendering/renderToString":
"/reference/rendering/render-to-string",
"/references/api-reference/rendering/renderToStringAsync":
"/reference/rendering/render-to-string-async",
"/references/api-reference/secondary-primitives/createComputed":
"/reference/secondary-primitives/create-computed",
"/references/api-reference/secondary-primitives/createDeferred":
"/reference/secondary-primitives/create-deferred",
"/references/api-reference/secondary-primitives/createReaction":
"/reference/secondary-primitives/create-reaction",
"/references/api-reference/secondary-primitives/createRenderEffect":
"/reference/secondary-primitives/create-render-effect",
"/references/api-reference/secondary-primitives/createSelector":
"/reference/secondary-primitives/create-selector",
"/references/api-reference/special-jsx-attributes/attr_":
"/reference/jsx-attributes/attr",
"/references/api-reference/special-jsx-attributes/classList":
"/reference/jsx-attributes/classlist",
"/references/api-reference/special-jsx-attributes/innerHTML-or-textContent":
"/reference/jsx-attributes/innerhtml",
"/references/api-reference/special-jsx-attributes/on_":
"/reference/jsx-attributes/on_",
"/references/api-reference/special-jsx-attributes/on_-and-oncapture_":
"/reference/jsx-attributes/on",

"/references/api-reference/special-jsx-attributes/once": "/reference/jsx-attributes/once",
"/references/api-reference/special-jsx-attributes/prop_": "/reference/jsx-attributes/prop",
"/references/api-reference/special-jsx-attributes/ref": "/reference/jsx-attributes/ref",
"/references/api-reference/special-jsx-attributes/style": "/reference/jsx-attributes/style",
"/references/api-reference/special-jsx-attributes/use_": "/reference/jsx-attributes/use",
"/references/api-reference/stores/store-utilities": "/concepts/stores#store-utilities",
"/references/api-reference/special-jsx-attributes/once":
"/reference/jsx-attributes/once",
"/references/api-reference/special-jsx-attributes/prop_":
"/reference/jsx-attributes/prop",
"/references/api-reference/special-jsx-attributes/ref":
"/reference/jsx-attributes/ref",
"/references/api-reference/special-jsx-attributes/style":
"/reference/jsx-attributes/style",
"/references/api-reference/special-jsx-attributes/use_":
"/reference/jsx-attributes/use",
"/references/api-reference/stores/store-utilities":
"/concepts/stores#store-utilities",
"/references/api-reference/stores/using-stores": "/concepts/stores",

// deployment
"/guides/how-to-guides/deployment": "/guides/deploying-your-app",
"/guides/how-to-guides/deployment/deploying-to-cloudflare": "/guides/deployment-options/cloudflare",
"/guides/how-to-guides/deployment/deploying-to-firebase": "/guides/deployment-options/firebase",
"/guides/how-to-guides/deployment/deploying-to-flightcontrol": "/guides/deployment-options/aws-via-flightcontrol",
"/guides/how-to-guides/deployment/deploying-to-netlify": "/guides/deployment-options/netlify",
"/guides/how-to-guides/deployment/deploying-to-railway": "/guides/deployment-options/railway",
"/guides/how-to-guides/deployment/deploying-to-vercel": "/guides/deployment-options/vercel",
"/guides/how-to-guides/deployment/deploying-to-cloudflare":
"/guides/deployment-options/cloudflare",
"/guides/how-to-guides/deployment/deploying-to-firebase":
"/guides/deployment-options/firebase",
"/guides/how-to-guides/deployment/deploying-to-flightcontrol":
"/guides/deployment-options/aws-via-flightcontrol",
"/guides/how-to-guides/deployment/deploying-to-netlify":
"/guides/deployment-options/netlify",
"/guides/how-to-guides/deployment/deploying-to-railway":
"/guides/deployment-options/railway",
"/guides/how-to-guides/deployment/deploying-to-vercel":
"/guides/deployment-options/vercel",

// styling
"/guides/how-to-guides/styling-in-solid": "/guides/styling-your-components",
"/guides/how-to-guides/styling-in-solid/sass": "/guides/styling-components/sass",
"/guides/how-to-guides/styling-in-solid/less": "/guides/styling-components/less",
"/guides/how-to-guides/styling-in-solid/tailwind-css": "/guides/styling-components/tailwind",
"/guides/how-to-guides/styling-in-solid/css-modules": "/guides/styling-components/css-modules",
"/guides/how-to-guides/styling-in-solid/unocss": "/guides/styling-components/uno",
"/guides/how-to-guides/styling-in-solid/sass":
"/guides/styling-components/sass",
"/guides/how-to-guides/styling-in-solid/less":
"/guides/styling-components/less",
"/guides/how-to-guides/styling-in-solid/tailwind-css":
"/guides/styling-components/tailwind",
"/guides/how-to-guides/styling-in-solid/css-modules":
"/guides/styling-components/css-modules",
"/guides/how-to-guides/styling-in-solid/unocss":
"/guides/styling-components/uno",

// trailing slash removal
"/routing/migration/": "/routing/migration",
@@ -97,17 +162,21 @@ const LEGACY_ROUTES = {
"/guides/foundations/typescript-for-solid": "/configuration/typescript",
"/guides/foundations/understanding-components": "/concepts/components/basics",
"/guides/foundations/why-solid": "/#advantages-of-using-solid",
"/guides/how-to-guides/routing-in-solid/solid-router": "/routing/installation-and-setup",
"/guides/tutorials/getting-started-with-solid/installing-solid": "/quick-start",
"/guides/how-to-guides/routing-in-solid/solid-router":
"/routing/installation-and-setup",
"/guides/tutorials/getting-started-with-solid/installing-solid":
"/quick-start",
"/references/concepts/reactivity": "/concepts/intro-to-reactivity",
"/references/concepts/reactivity/tracking": "/concepts/intro-to-reactivity#subscribers",
"/references/concepts/reactivity/tracking":
"/concepts/intro-to-reactivity#subscribers",
"/references/concepts/ssr/async-ssr": "/guides/fetching-data",
"/references/concepts/ssr/simple-client-fetching-ssr": "/guides/fetching-data",
"/references/concepts/state-management/context": "/guides/complex-state-management#state-sharing",
"/references/concepts/ssr/simple-client-fetching-ssr":
"/guides/fetching-data",
"/references/concepts/state-management/context":
"/guides/complex-state-management#state-sharing",

// solid-docs-next moves/new location for old pages/solid api updates
"/reference/jsx-attributes/on-and-oncapture": "/reference/jsx-attributes/on",

} as const;

function isLegacyRoute(path: string): path is keyof typeof LEGACY_ROUTES {
76 changes: 22 additions & 54 deletions src/routes/advanced-concepts/fine-grained-reactivity.mdx
Original file line number Diff line number Diff line change
@@ -2,40 +2,31 @@
title: Fine-grained reactivity
---

Reactivity ensures automatic responses to data changes, eliminating the need for manual updates to the user interface (UI).
By connecting UI elements to the underlying data, updates become automated.
In a fine-grained reactive system an application will now have the ability to make highly _targeted and specific_ updates.
Reactivity ensures automatic responses to data changes, eliminating the need for manual updates to the user interface (UI). By connecting UI elements to the underlying data, updates become automated. In a fine-grained reactive system an application will now have the ability to make highly _targeted and specific_ updates.

An example of this can be seen in the contrast between Solid and [React](https://react.dev/).
In Solid, updates are made to the targeted attribute that needs to be changed, avoiding broader and, sometimes unnecessary, updates.
In contrast, React would re-execute an entire component for a change in the single attribute, which can be less efficient.
An example of this can be seen in the contrast between Solid and [React](https://react.dev/). In Solid, updates are made to the targeted attribute that needs to be changed, avoiding broader and, sometimes unnecessary, updates. In contrast, React would re-execute an entire component for a change in the single attribute, which can be less efficient.

Because of the fine-grained reactive system, unnecessary recalculations are avoided.
Through targeting only the areas of an application that have changed the user experience becomes smoother and more optimized.
Because of the fine-grained reactive system, unnecessary recalculations are avoided. Through targeting only the areas of an application that have changed the user experience becomes smoother and more optimized.

**Note:** If you're new to the concept of reactivity and want to learn the basics, consider starting with our [intro to reactivity guide](/concepts/intro-to-reactivity).

## Reactive primitives

In Solid's reactivity system, there are two key elements: signals and observers.
These core elements serve as the foundation for more specialized reactive features:
In Solid's reactivity system, there are two key elements: signals and observers. These core elements serve as the foundation for more specialized reactive features:

- [Stores](/concepts/stores) which are [proxies](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) that create, read, and write signals under the hood.
- [Memos](/concepts/derived-values/memos) resemble [effects](/concepts/effects) but are distinct in that they _return_ a signal and optimize computations through caching.
They update based on the behavior of effects, but are more ideal for computational optimization.
- [Memos](/concepts/derived-values/memos) resemble [effects](/concepts/effects) but are distinct in that they _return_ a signal and optimize computations through caching. They update based on the behavior of effects, but are more ideal for computational optimization.
- [Resources](/guides/fetching-data), building on the concept of memos, convert the asynchronicity of network requests into synchronicity, where the results are embedded within a signal.
- Render effects are a tailored type of effect that initiate immediately, specifically designed for managing the rendering process.

### Understanding signals

[Signals](/concepts/signals) are like mutable variables that can point to a value now and another in the future.
They are made up of two primary functions:
[Signals](/concepts/signals) are like mutable variables that can point to a value now and another in the future. They are made up of two primary functions:

- **Getter**: how to read the current value of a signal.
- **Setter**: a way to modify or update a signal's value.

In Solid, the [`createSignal`](/reference/basic-reactivity/create-signal) function can be used to create a signal.
This function returns the getter and setter as a pair in a two-element array, called a tuple.
In Solid, the [`createSignal`](/reference/basic-reactivity/create-signal) function can be used to create a signal. This function returns the getter and setter as a pair in a two-element array, called a tuple.

```js
import { createSignal } from "solid-js";
@@ -53,8 +44,7 @@ Here, `count` serves as the getter, and `setCount` functions as the setter.

### Effects

[Effects](/concepts/effects) are functions that are triggered when the signals they depend on point to a different value.
They can be thought of as automated responders where any changes in the signal's value will trigger the effect to run.
[Effects](/concepts/effects) are functions that are triggered when the signals they depend on point to a different value. They can be thought of as automated responders where any changes in the signal's value will trigger the effect to run.

```jsx
import { createSignal, createEffect } from "solid-js";
@@ -72,8 +62,7 @@ The effect takes a function that is called whenever _any_ of the signals it reli

To grasp the concept of reactivity, it is often helpful to construct a reactive system from scratch.

The following example will follow the observer pattern, where data entities (signals) will maintain a list of their subscribers (effects).
This is a way to notify subscribers whenever a signal they observe changes.
The following example will follow the observer pattern, where data entities (signals) will maintain a list of their subscribers (effects). This is a way to notify subscribers whenever a signal they observe changes.

Here is a basic code outline to begin:

@@ -116,8 +105,7 @@ function createSignal(initialValue) {
// ..
```

This allows you to retrieve the current value through the getter and make any changes via the setter.
At this stage, reactivity is not present, however.
This allows you to retrieve the current value through the getter and make any changes via the setter. At this stage, reactivity is not present, however.

### `createEffect`

@@ -178,19 +166,14 @@ function createEffect(fn) {
//..
```

A variable is used to hold a reference to the current executing subscriber function.
This is used to determine which effects are dependent on which signals.
A variable is used to hold a reference to the current executing subscriber function. This is used to determine which effects are dependent on which signals.

Inside `createSignal`, the initial value is stored and a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is used to store any subscriber functions that are dependent on the signal.
This function will then return two functions for the signal:
Inside `createSignal`, the initial value is stored and a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is used to store any subscriber functions that are dependent on the signal. This function will then return two functions for the signal:

- The `getter` function checks to see if the current subscriber function is being accessed and, if it is, adds it to the list of subscribers before returning the _current_ value of the signal.
- The `setter` function evaluated the new value against the old value, notifying the dependent functions only when the signal has been updated.

When creating the `createEffect` function, a reference to any previous subscribers is initialized to handle any possible nested effects present.
The current subscriber is then passed to the given function, which is run immediately.
During this run, if the effect accesses any signals it is then registered as a subscriber to those signals.
The current subscriber, once the given function has been run, will be reset to its previous value so that, if there are any nested effects, they are operated correctly.
When creating the `createEffect` function, a reference to any previous subscribers is initialized to handle any possible nested effects present. The current subscriber is then passed to the given function, which is run immediately. During this run, if the effect accesses any signals it is then registered as a subscriber to those signals. The current subscriber, once the given function has been run, will be reset to its previous value so that, if there are any nested effects, they are operated correctly.

### Validating the reactive system

@@ -214,12 +197,9 @@ This will display the incremented count value on the console at one-second inter

## Managing lifecycles in a reactive system

In reactive systems, various elements, often referred to as "nodes", are interconnected.
These nodes can be signals, effects, or other reactive primitives.
They serve as the individual units that collectively make up the reactive behavior of the system.
In reactive systems, various elements, often referred to as "nodes", are interconnected. These nodes can be signals, effects, or other reactive primitives. They serve as the individual units that collectively make up the reactive behavior of the system.

When a node changes, the system will re-evaluate the parts connected to that node.
This can result in updates, additions, or removals of these connections, which affect the overall behavior of the system.
When a node changes, the system will re-evaluate the parts connected to that node. This can result in updates, additions, or removals of these connections, which affect the overall behavior of the system.

Now, consider a scenario where a condition influences the data used to calculate an output:

@@ -247,19 +227,15 @@ console.log("4. Turn on displayTemp");
setDisplayTemp(true);
```

In this example, the `createMemo` primitive is used to cache the state of a computation.
This means the computation doesn't have to be re-run if its dependencies remain unchanged.
In this example, the `createMemo` primitive is used to cache the state of a computation. This means the computation doesn't have to be re-run if its dependencies remain unchanged.

The `displayTemperature` memo has an early return condition based on the value of `displayTemp`.
When `displayTemp` is false, the memo returns a message saying "Temperature display is off," and as a result, `temperature` and `unit` are not tracked.
The `displayTemperature` memo has an early return condition based on the value of `displayTemp`. When `displayTemp` is false, the memo returns a message saying "Temperature display is off," and as a result, `temperature` and `unit` are not tracked.

If the `unit` is changed while `displayTemp` is false, however, the effect won't trigger since none of the memo's current dependencies (`displayTemp` in this case) have changed.

### Synchronous nature of effect tracking

The reactivity system described above operates synchronously.
This operation has implications for how effects and their dependencies are tracked.
Specifically, the system registers the subscriber, runs the effect function, and then unregisters the subscriber — all in a linear, synchronous sequence.
The reactivity system described above operates synchronously. This operation has implications for how effects and their dependencies are tracked. Specifically, the system registers the subscriber, runs the effect function, and then unregisters the subscriber — all in a linear, synchronous sequence.

Consider the following example:

@@ -271,20 +247,12 @@ createEffect(() => {
});
```

The `createEffect` function in this example, initiates a `setTimeout` to delay the console log.
Because the system is synchronous, it doesn't wait for this operation to complete.
By the time the `count` getter is triggered within the `setTimeout`, the global scope no longer has a registered subscriber.
As a result, this `count` signal will not add the callback as a subscriber which leads to potential issues with tracking the changes to `count`.
The `createEffect` function in this example, initiates a `setTimeout` to delay the console log. Because the system is synchronous, it doesn't wait for this operation to complete. By the time the `count` getter is triggered within the `setTimeout`, the global scope no longer has a registered subscriber. As a result, this `count` signal will not add the callback as a subscriber which leads to potential issues with tracking the changes to `count`.

### Handling asynchronous effects

While the basic reactivity system is synchronous, frameworks like Solid offer more advanced features to handle asynchronous scenarios.
For example, the `on` function provides a way to manually specify the dependencies of an effect.
This is particularly useful for to make sure asynchronous operations are correctly tied into the reactive system.
While the basic reactivity system is synchronous, frameworks like Solid offer more advanced features to handle asynchronous scenarios. For example, the `on` function provides a way to manually specify the dependencies of an effect. This is particularly useful for to make sure asynchronous operations are correctly tied into the reactive system.

Solid also introduces the concept of resources for managing asynchronous operations.
Resources are specialized reactive primitives that convert the asynchronicity of operations like network requests into synchronicity, embedding the results within a signal.
The system can then track asynchronous operations and their state, keeping the UI up-to-date when the operation completes or its' state changes.
Solid also introduces the concept of resources for managing asynchronous operations. Resources are specialized reactive primitives that convert the asynchronicity of operations like network requests into synchronicity, embedding the results within a signal. The system can then track asynchronous operations and their state, keeping the UI up-to-date when the operation completes or its' state changes.

Using resources in Solid can assist in complex scenarios when multiple asynchronous operations are involved and the completion may affect different parts of the reactive system.
By integrating resources into the system, you can ensure that dependencies are correctly tracked and that the UI remains consistent with the underlying asynchronous data.
Using resources in Solid can assist in complex scenarios when multiple asynchronous operations are involved and the completion may affect different parts of the reactive system. By integrating resources into the system, you can ensure that dependencies are correctly tracked and that the UI remains consistent with the underlying asynchronous data.
74 changes: 22 additions & 52 deletions src/routes/concepts/components/basics.mdx
Original file line number Diff line number Diff line change
@@ -3,8 +3,7 @@ title: Basics
order: 4
---

Components are the building blocks of Solid applications.
These units are reusable and can be combined to create more complex applications.
Components are the building blocks of Solid applications. These units are reusable and can be combined to create more complex applications.

Components are functions that return [JSX](/concepts/understanding-jsx) elements:

@@ -14,8 +13,7 @@ function MyComponent() {
}
```

A component can be as simple as a single element or as complex as a full page.
They can also be nested within each other to create more intricate applications:
A component can be as simple as a single element or as complex as a full page. They can also be nested within each other to create more intricate applications:

```tsx
function App() {
@@ -29,10 +27,7 @@ function App() {

## Component trees

A web page is displayed by rendering a component tree, which is a hierarchical structure of components.
At the top of the tree is the primary application component, which is the root of the tree.
Child components are nested within the primary component, and those components can have their own child components.
This nesting can continue as needed.
A web page is displayed by rendering a component tree, which is a hierarchical structure of components. At the top of the tree is the primary application component, which is the root of the tree. Child components are nested within the primary component, and those components can have their own child components. This nesting can continue as needed.

A simple application may have a component tree that looks like this:

@@ -41,8 +36,7 @@ App // primary application component
└── MyComponent // child component
```

When an application grows, the component tree can become more complex.
For example, a more complex application may have a component tree that looks like this:
When an application grows, the component tree can become more complex. For example, a more complex application may have a component tree that looks like this:

```json
App
@@ -62,34 +56,23 @@ App
└── Footer
```

In nesting components, you can create a hierarchy of components that can be reused throughout the application.
This allows for a more modular approach to building applications, as components can be reused in different contexts.
In nesting components, you can create a hierarchy of components that can be reused throughout the application. This allows for a more modular approach to building applications, as components can be reused in different contexts.

## Component lifecycles

Components have a lifecycle that defines how they are created, updated, and destroyed.
A Solid component's lifecycle is different from other frameworks, as it is tied to the [concept of reactivity](/concepts/intro-to-reactivity).
Components have a lifecycle that defines how they are created, updated, and destroyed. A Solid component's lifecycle is different from other frameworks, as it is tied to the [concept of reactivity](/concepts/intro-to-reactivity).

Where frameworks may re-run components on every state change, a Solid component's lifecycle is tied to its initial run.
What this means is that a Solid component is only run once, when it is first rendered into the DOM.
After that, the component is not re-run, even if the application's state changes.
Where frameworks may re-run components on every state change, a Solid component's lifecycle is tied to its initial run. What this means is that a Solid component is only run once, when it is first rendered into the DOM. After that, the component is not re-run, even if the application's state changes.

When the Solid component renders, it sets up a reactive system that monitors for state changes.
When a state change occurs, the component will update the relevant areas without re-running the entire component.
By bypassing the full component lifecycle on every state change, Solid has a more predictable behavior compared to frameworks that re-run functions on every update.
When the Solid component renders, it sets up a reactive system that monitors for state changes. When a state change occurs, the component will update the relevant areas without re-running the entire component. By bypassing the full component lifecycle on every state change, Solid has a more predictable behavior compared to frameworks that re-run functions on every update.

Since the component's logic is not continuously visited, getting this setup right is important when working with Solid.

### Initialization & configuration

When a component is first rendered into the DOM, the component function is executed.
This is where you will set up the component's state and side-effects.
This includes setting up [signals](/concepts/signals), [stores](/concepts/stores), [effects](/concepts/effects), and other reactive elements.
Since the logic in the component function is not continuously visited, it is important to set up the component correctly from the outset.
When a component is first rendered into the DOM, the component function is executed. This is where you will set up the component's state and side-effects. This includes setting up [signals](/concepts/signals), [stores](/concepts/stores), [effects](/concepts/effects), and other reactive elements. Since the logic in the component function is not continuously visited, it is important to set up the component correctly from the outset.

Each component instance is independent of other instances, meaning that each component has its own state and side-effects.
Through establishing proper dependencies, you can ensure that the component is set up correctly.
This allows for components to be reused in different contexts without affecting each other.
Each component instance is independent of other instances, meaning that each component has its own state and side-effects. Through establishing proper dependencies, you can ensure that the component is set up correctly. This allows for components to be reused in different contexts without affecting each other.

```tsx
function MyComponent() {
@@ -106,12 +89,9 @@ function MyComponent() {
}
```

When this component is rendered into the DOM, the function body is executed.
This includes creating the `count` signal and executing the `console.log(count())` statement, which will log the current value of `count` to the console.
In addition, the component's JSX is returned, which will be rendered into the DOM.
When this component is rendered into the DOM, the function body is executed. This includes creating the `count` signal and executing the `console.log(count())` statement, which will log the current value of `count` to the console. In addition, the component's JSX is returned, which will be rendered into the DOM.

After the component is rendered, the `console.log` statement will not be executed again, even if the component's state changes.
However, because the component's JSX is reactive, each press of the button will update the DOM with the new value of `count`.
After the component is rendered, the `console.log` statement will not be executed again, even if the component's state changes. However, because the component's JSX is reactive, each press of the button will update the DOM with the new value of `count`.

In essence, Solid splits the concerns:

@@ -120,9 +100,7 @@ In essence, Solid splits the concerns:

### Conditional rendering

To display different content based on state or other criteria, you can use conditional rendering.
Given that the component function is only executed once, conditional statements must be placed within the return statement.
This design ensures that conditional paths are clear and immediately understood.
To display different content based on state or other criteria, you can use conditional rendering. Given that the component function is only executed once, conditional statements must be placed within the return statement. This design ensures that conditional paths are clear and immediately understood.

```tsx
function MyComponent() {
@@ -144,11 +122,10 @@ function MyComponent() {
}
```

This example uses a [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator) to conditionally render different content based on the value of `count`.
When `count` is greater than 5, the component will display `"Count limit reached"`.
Otherwise, it will display the current count with an increment button.
This example uses a [ternary operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_operator) to conditionally render different content based on the value of `count`. When `count` is greater than 5, the component will display `"Count limit reached"`. Otherwise, it will display the current count with an increment button.

:::info

To simplify conditional rendering, Solid provides built-in [control-flow](/concepts/control-flow/conditional-rendering) components like [`Show`](/concepts/control-flow/conditional-rendering#show), which create a more readable conditional rendering experience.

```tsx
@@ -177,18 +154,15 @@ To simplify conditional rendering, Solid provides built-in [control-flow](/conce

## Importing and exporting

For components to be reusable, they need to be exported from one module and imported into another.
This allows for components to be shared and used where needed.
For components to be reusable, they need to be exported from one module and imported into another. This allows for components to be shared and used where needed.

### Exporting components

Once defined, a component can be [exported](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export) to make it available for use in other parts of your application.
There are two ways to export a component: [named exports](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#named_exports) and [default exports](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#default_exports).
Once defined, a component can be [exported](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export) to make it available for use in other parts of your application. There are two ways to export a component: [named exports](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#named_exports) and [default exports](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#default_exports).

**Named export:**

Named exports allow for multiple components to be exported from a single file.
To export a component, you must use the `export` keyword before the function definition or specify the name of the component to export in curly braces (`{}`).
Named exports allow for multiple components to be exported from a single file. To export a component, you must use the `export` keyword before the function definition or specify the name of the component to export in curly braces (`{}`).

```typescript
export function MyComponent() {
@@ -206,8 +180,7 @@ export { MyComponent }

**Default export:**

Default exports specify a single component to export from a file.
This is done by using the `default` keyword.
Default exports specify a single component to export from a file. This is done by using the `default` keyword.

```typescript
// MyComponent.ts
@@ -218,8 +191,7 @@ export default function MyComponent() {

### Importing components

To use a component in another file or component, it must be [imported](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import).
To import a component, you must specify the path to the file containing the component and the name of the component to import.
To use a component in another file or component, it must be [imported](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import). To import a component, you must specify the path to the file containing the component and the name of the component to import.

**Named import:**

@@ -238,8 +210,7 @@ function App() {
}
```

This is the preferred way to import components, as it allows for better code readability and maintainability.
Additionally, it allows for multiple components to be imported from the same file.
This is the preferred way to import components, as it allows for better code readability and maintainability. Additionally, it allows for multiple components to be imported from the same file.

```tsx
// App.ts
@@ -274,8 +245,7 @@ function App() {

### Importing Solid and its utilities

To use Solid, you must import the Solid library.
The reactive primitives and utilities are exported from Solid's main module.
To use Solid, you must import the Solid library. The reactive primitives and utilities are exported from Solid's main module.

```tsx
import { createSignal } from "solid-js";
46 changes: 17 additions & 29 deletions src/routes/concepts/components/class-style.mdx
Original file line number Diff line number Diff line change
@@ -10,8 +10,7 @@ Similar to HTML, Solid uses `class` and `style` attributes to style elements via

## Inline styling

The `style` attribute allows you to style a single element and define CSS variables dynamically during runtime.
To use it, you can pass either a string or an object.
The `style` attribute allows you to style a single element and define CSS variables dynamically during runtime. To use it, you can pass either a string or an object.

```tsx
// String
@@ -21,25 +20,20 @@ To use it, you can pass either a string or an object.
<div style={{ color: "red" }}>This is a red div</div>
```

When using an object, the keys represent the CSS property names, and the values represent the CSS property values.
The keys must be in dash-case, and the values must be strings.
When using an object, the keys represent the CSS property names, and the values represent the CSS property values. The keys must be in dash-case, and the values must be strings.

<EraserLink
href="https://app.eraser.io/workspace/maDvFw5OryuPJOwSLyK9?elements=PgkKTGxuuOtDiQ_1KDA5dw"
preview="https://app.eraser.io/workspace/maDvFw5OryuPJOwSLyK9/preview?elements=PgkKTGxuuOtDiQ_1KDA5dw&type=embed"
/>

While inline styles are useful for rapid prototyping, they are not recommended for production use.
This is because they are not reusable, and they can be difficult to maintain over time.
While inline styles are useful for rapid prototyping, they are not recommended for production use. This is because they are not reusable, and they can be difficult to maintain over time.

## Classes

The `class` attribute allows you to style one or more elements through CSS rules.
This provides a more structured approach to styling, as it allows you to reuse styles across multiple elements.
The `class` attribute allows you to style one or more elements through CSS rules. This provides a more structured approach to styling, as it allows you to reuse styles across multiple elements.

Classes are defined in CSS files, which are then imported into the component files that use them.
You can import these files using the `import` statement at the top of your component file.
Once imported into a component, the classes are scoped to that component and any of its children.
Classes are defined in CSS files, which are then imported into the component files that use them. You can import these files using the `import` statement at the top of your component file. Once imported into a component, the classes are scoped to that component and any of its children.

```jsx
import "./Card.css";
@@ -51,8 +45,7 @@ function Card() {

### Dynamic styling

Dynamic styling provides a way to change the appearance of a component based on state or other factors like user inputs.
This is useful for creating components that can adapt to different scenarios without having to create multiple versions of the same component:
Dynamic styling provides a way to change the appearance of a component based on state or other factors like user inputs. This is useful for creating components that can adapt to different scenarios without having to create multiple versions of the same component:

```tsx
const [theme, setTheme] = createSignal("light");
@@ -62,8 +55,7 @@ const [theme, setTheme] = createSignal("light");
</div>;
```

[Props](/concepts/components/props) are another way to change styles.
By passing props to components, you can adapt styles based on the component's usage or the data it receives:
[Props](/concepts/components/props) are another way to change styles. By passing props to components, you can adapt styles based on the component's usage or the data it receives:

```tsx
function ThemedButton(props) {
@@ -77,34 +69,30 @@ function ThemedButton(props) {

### `classList`

When you want to apply multiple classes to an element, you can use the [`classList` attribute](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList).
To use it, you can pass either a string or an object where the keys represent the class names and the values represent a boolean expression.
When the value is `true`, the class is applied; when `false`, it is removed.
When you want to apply multiple classes to an element, you can use the [`classList` attribute](https://developer.mozilla.org/en-US/docs/Web/API/Element/classList). To use it, you can pass either a string or an object where the keys represent the class names and the values represent a boolean expression. When the value is `true`, the class is applied; when `false`, it is removed.

```tsx
const [current, setCurrent] = createSignal("foo");

<button
classList={{ "selected" : current() === "foo" }}
classList={{ selected: current() === "foo" }}
onClick={() => setCurrent("foo")}
>
foo
</button>;
```

`classList` is often more efficient than `class` when handling multiple conditional classes.
This is because `classList` selectively toggles only the classes that require alteration, while `class` will be re-evaluated each time.
For a single conditional class, using `class` might be simpler but as the number of conditional classes increases, `classList` offers a more readable and declarative approach.
`classList` is often more efficient than `class` when handling multiple conditional classes. This is because `classList` selectively toggles only the classes that require alteration, while `class` will be re-evaluated each time. For a single conditional class, using `class` might be simpler but as the number of conditional classes increases, `classList` offers a more readable and declarative approach.

:::info
While it is possible, mixing `class` and `classList` can introduce unexpected errors.
If both are reactive when the `class` value changes, Solid will set the entire `class` attribute.
This will remove any classes set by `classList`.
:::info

To avoid this, the `class` attribute should be set to a static string or nothing.
Alternatively, `class` can be set to a static computed value (e.g. `class={baseClass()}`), but then it must be put before any `classList` attributes.
While it is possible, mixing `class` and `classList` can introduce unexpected errors. If both are reactive when the `class` value changes, Solid will set the entire `class` attribute. This will remove any classes set by `classList`.

To avoid this, the `class` attribute should be set to a static string or nothing.
Alternatively, `class` can be set to a static computed value (e.g. `class={baseClass()}`), but then it must be put before any `classList` attributes.

Additionally, since `classList` is a pseudo-attribute, it doesn't work in prop spreads like `<div {...props} />` or in `<Dynamic>`.

Additionally, since `classList` is a pseudo-attribute, it doesn't work in prop spreads like `<div {...props} />` or in `<Dynamic>`.
:::

For a guide on how to style your components, see [Styling Your Components](/guides/styling-your-components), where we cover the different ways to style your components using libraries such as [Tailwind CSS](https://tailwindcss.com/).
46 changes: 14 additions & 32 deletions src/routes/concepts/components/event-handlers.mdx
Original file line number Diff line number Diff line change
@@ -10,8 +10,7 @@ Solid provides two ways to add event listeners to the browser:
- [`on:__`](/reference/jsx-attributes/on): adds an event listener to the `element`. This is also known as a _native event_.
- [`on__`](/reference/jsx-attributes/on_): adds an event listener to the `document` and dispatches it to the `element`. This can be referred to as a _delegated event_.

Delegated events flow through the [_component tree_](/concepts/components/basics#component-trees), and save some resources by performing better on commonly used events.
Native events, however, flow through the _DOM tree_, and provide more control over the behavior of the event.
Delegated events flow through the [_component tree_](/concepts/components/basics#component-trees), and save some resources by performing better on commonly used events. Native events, however, flow through the _DOM tree_, and provide more control over the behavior of the event.

## Using events

@@ -25,15 +24,13 @@ To add an event handler, prefix the event name with either `on` or `on:`, and as
<div on:scroll={handleScroll}>... very long text ...</div>
```

Delegated events are **not case sensitive**, therefore using delegated event handlers in Solid can be written using camelCase or all lowercase.
Note that while delegated events can be written both ways, native events _are_ case sensitive.
Delegated events are **not case sensitive**, therefore using delegated event handlers in Solid can be written using camelCase or all lowercase. Note that while delegated events can be written both ways, native events _are_ case sensitive.

```tsx
<button onclick={handleClick}>Click me</button>
```

For any other events, such as custom events or events you wish _not_ to be delegated, the `on:` attribute will add an event listener as-is.
This is what makes the event listener case sensitive.
For any other events, such as custom events or events you wish _not_ to be delegated, the `on:` attribute will add an event listener as-is. This is what makes the event listener case sensitive.

```tsx
<button on:Custom-Event={handleClick}>Click me</button>
@@ -43,8 +40,7 @@ For typing standard or custom events using `on:`, the TypeScript page has a sect

## Binding events

To optimize event handlers, you can pass an array as the event handler, replacing the function.
When doing this, the second item passed into the array is supplied as the handler's first argument:
To optimize event handlers, you can pass an array as the event handler, replacing the function. When doing this, the second item passed into the array is supplied as the handler's first argument:

```tsx
const handler = (data, event) => {
@@ -60,30 +56,23 @@ By binding events in this way, Solid avoids the overhead of using JavaScript's [

### Dynamic handlers

An event handler does not form part of the reactive system.
If you were to pass the handler as a signal, it will not respond to the changes of that signal.
In other words, events do not dynamically update, and the bindings are not reactive.
This is because attaching and detaching listeners is a resource-intensive task.
An event handler does not form part of the reactive system. If you were to pass the handler as a signal, it will not respond to the changes of that signal. In other words, events do not dynamically update, and the bindings are not reactive. This is because attaching and detaching listeners is a resource-intensive task.

Since event handlers are called like a standard function, you can design them to call a reactive source, if needed.

In the following example, `handleClick` represents a prop that has the flexibility to adopt any function.
As a result, there is no requirement for these functions to be reactive.
In the following example, `handleClick` represents a prop that has the flexibility to adopt any function. As a result, there is no requirement for these functions to be reactive.

```tsx
<div onClick={() => props.handleClick?.()} />
```

## Event delegation

Instead of attaching event listeners to every individual element, Solid uses _synthetic event delegation_, through the [`on__`](/reference/jsx-attributes/on_) form .
In this method event listeners are attached to the `document` element, and dispatch events to the relevant elements as they bubble up.
Instead of attaching event listeners to every individual element, Solid uses _synthetic event delegation_, through the [`on__`](/reference/jsx-attributes/on_) form . In this method event listeners are attached to the `document` element, and dispatch events to the relevant elements as they bubble up.

By keeping the number of event listeners to a minimum, events can be captured more effectively.
This is especially useful when working with a large number of elements, such as in a table or list.
By keeping the number of event listeners to a minimum, events can be captured more effectively. This is especially useful when working with a large number of elements, such as in a table or list.

Supported events such as `click`, `input` and `keydown` are just a few examples that are optimized in this way.
To view the full list see the [references below](#list-of-delegated-events).
Supported events such as `click`, `input` and `keydown` are just a few examples that are optimized in this way. To view the full list see the [references below](#list-of-delegated-events).

If you need to attach an event listener to an element that is not supported by Solid's event delegation, such as a custom event in a [custom element](https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_custom_elements), you can use the [`on:__`](/reference/jsx-attributes/on) form.

@@ -95,23 +84,19 @@ If you need to attach an event listener to an element that is not supported by S

While delegated events provide some performance enhancements, there are tradeoffs.

Event delegation is designed for event propagation through the JSX Tree, rather than the DOM Tree.
This can differ from the previous expectations of how events work and flow.
Event delegation is designed for event propagation through the JSX Tree, rather than the DOM Tree. This can differ from the previous expectations of how events work and flow.

Some things to keep in mind include:

- Delegated event listeners are added _once_ per event type and handle all future events of that type.
This means that delegated event listeners remain active even if the element that added them and its handler is removed.
For example, if a `div` listens for `mousemove` and is later removed, the `mousemove` events will still be dispatched to the `document` in case a different element is also listening for mouse moves.
- Delegated event listeners are added _once_ per event type and handle all future events of that type. This means that delegated event listeners remain active even if the element that added them and its handler is removed. For example, if a `div` listens for `mousemove` and is later removed, the `mousemove` events will still be dispatched to the `document` in case a different element is also listening for mouse moves.

```tsx
<div onMouseMove={handleCustomEvent} />
```

:::tip[Occasional Events]

Rather than using delegated events for events that happen infrequently, **native events** are a better solution.
Since these events happen in specific circumstances, they do not benefit from the performance improvements you get with event delegation.
Rather than using delegated events for events that happen infrequently, **native events** are a better solution. Since these events happen in specific circumstances, they do not benefit from the performance improvements you get with event delegation.

```tsx
<div on:mousemove={handleCustomEvent} />
@@ -121,9 +106,7 @@ Since these events happen in specific circumstances, they do not benefit from th

- `event.stopPropagation()` does not work as expected since events are attached to the `document` rather than the `element`.

With cases like this, a native event is recommended.
As an example, using a native event would stop the following event from reaching the `div native` handler, which is _not_ the case for delegated events.
You can [view this example in the Solid Playground](https://playground.solidjs.com/anonymous/c5346f84-01e4-4080-8ace-4443ffd0bb10).
With cases like this, a native event is recommended. As an example, using a native event would stop the following event from reaching the `div native` handler, which is _not_ the case for delegated events. You can [view this example in the Solid Playground](https://playground.solidjs.com/anonymous/c5346f84-01e4-4080-8ace-4443ffd0bb10).

```tsx
onMount(() => {
@@ -171,8 +154,7 @@ button

[See how this solution differs in the Solid Playground](https://playground.solidjs.com/anonymous/9e2deddc-2e83-4ac2-8ee0-49c7c3a45d11).

- [Portals](/concepts/control-flow/portal) propagate events following the _component tree_ and not the _DOM tree_, making them easier to use.
This means when a `Portal` gets attached to the `body`, any events will propagate up to the `container`.
- [Portals](/concepts/control-flow/portal) propagate events following the _component tree_ and not the _DOM tree_, making them easier to use. This means when a `Portal` gets attached to the `body`, any events will propagate up to the `container`.

```tsx
<div class="container" onInput={() => console.log("portal key press")}>
35 changes: 10 additions & 25 deletions src/routes/concepts/components/props.mdx
Original file line number Diff line number Diff line change
@@ -2,8 +2,7 @@
title: Props
---

Props are a way to pass state from a parent component to a child component.
These read-only properties are passed to components as attributes within JSX and are accessible within the component via the `props` object:
Props are a way to pass state from a parent component to a child component. These read-only properties are passed to components as attributes within JSX and are accessible within the component via the `props` object:

```tsx
function App() {
@@ -26,9 +25,7 @@ function MyComponent(props) {

## `mergeProps`

[`mergeProps`](/reference/reactive-utilities/merge-props) is a Solid utility function designed to merge multiple potentially reactive objects together.
It behaves similar to [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) but will retain the reactivity of the properties being merged.
This helps ensure that when individual properties within the merged object change, their reactivity is not lost.
[`mergeProps`](/reference/reactive-utilities/merge-props) is a Solid utility function designed to merge multiple potentially reactive objects together. It behaves similar to [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) but will retain the reactivity of the properties being merged. This helps ensure that when individual properties within the merged object change, their reactivity is not lost.

```typescript
import { mergeProps } from "solid-js";
@@ -43,16 +40,13 @@ function MyComponent(props) {
// Usage: <MyComponent defaultName="Ryan Carniato" />
```

When merging props, if there is no existing value for a property, the value from the first object will be used.
However, if a value already exists, it will be used instead, all while retaining the reactivity of the property.
When merging props, if there is no existing value for a property, the value from the first object will be used. However, if a value already exists, it will be used instead, all while retaining the reactivity of the property.

## Destructuring props

Props are read-only so that child components do not directly modify the data passed by the parent.
This also encourages one-way data flow, a pattern often seen to promote more predictable data management.
Props are read-only so that child components do not directly modify the data passed by the parent. This also encourages one-way data flow, a pattern often seen to promote more predictable data management.

With Solid, destructuring props is not recommended as it can break reactivity.
Instead, you should access props directly from the `props` object, or wrap them in a function to ensure they are always up-to-date:
With Solid, destructuring props is not recommended as it can break reactivity. Instead, you should access props directly from the `props` object, or wrap them in a function to ensure they are always up-to-date:

```typescript
function MyComponent(props) {
@@ -64,11 +58,9 @@ function MyComponent(props) {

### `splitProps`

[`splitProps`](/reference/reactive-utilities/split-props) is a utility function designed to help split a single props object into multiple sets of props, retaining the reactivity of the individual properties.
It provides a way to destructure props without breaking reactivity.
[`splitProps`](/reference/reactive-utilities/split-props) is a utility function designed to help split a single props object into multiple sets of props, retaining the reactivity of the individual properties. It provides a way to destructure props without breaking reactivity.

`splitProps` gives you the ability to define one or more arrays of keys that you wish to extract into separate props objects, all while retaining the reactivity of the individual properties.
It will return an array of props objects related to each set of keys, plus an additional props object containing any remaining keys.
`splitProps` gives you the ability to define one or more arrays of keys that you wish to extract into separate props objects, all while retaining the reactivity of the individual properties. It will return an array of props objects related to each set of keys, plus an additional props object containing any remaining keys.

When passing props to child components, you can use `splitProps` to split the props into multiple groups, and then pass each group to the appropriate child component:

@@ -96,9 +88,7 @@ function ParentComponent(props) {

## Passing props to children

In most instances, simply using `props` within JSX will work without any issues.
However, there are some cases where accessing `props.children` multiple times can introduce problems and unexpected behaviours, such as repeated creation of child components or elements.
For instances like these, Solid provides a [`children`](/reference/component-apis/children) helper that ensures you always get the right child components without anything unwanted happening.
In most instances, simply using `props` within JSX will work without any issues. However, there are some cases where accessing `props.children` multiple times can introduce problems and unexpected behaviours, such as repeated creation of child components or elements. For instances like these, Solid provides a [`children`](/reference/component-apis/children) helper that ensures you always get the right child components without anything unwanted happening.

```typescript
import { children } from "solid-js";
@@ -112,11 +102,6 @@ function ColoredList(props) {

## Prop drilling

Prop drilling is a term used to describe the process of passing props through multiple layers of components.
While it can be a useful pattern, it can also lead to problems.
When components are nested deeply, passing props through each component can become difficult to manage.
Additionally, this can lead to components receiving props that they do not need, unnecessary re-renders, and trouble refactoring.
Prop drilling is a term used to describe the process of passing props through multiple layers of components. While it can be a useful pattern, it can also lead to problems. When components are nested deeply, passing props through each component can become difficult to manage. Additionally, this can lead to components receiving props that they do not need, unnecessary re-renders, and trouble refactoring.

Since components in Solid do not own state, props are not needed to pass state between components, but may be used.
Because of this, there may be times when you need to pass props through multiple layers of components.
A common solution to this problem is to use [Context](/concepts/context) to pass state to deeply nested components without having to pass props through each component in between.
Since components in Solid do not own state, props are not needed to pass state between components, but may be used. Because of this, there may be times when you need to pass props through multiple layers of components. A common solution to this problem is to use [Context](/concepts/context) to pass state to deeply nested components without having to pass props through each component in between.
Loading