diff --git a/.github/ISSUE_TEMPLATE/BUGS.yml b/.github/ISSUE_TEMPLATE/BUGS.yml
index 64dab21b75..18358ff125 100644
--- a/.github/ISSUE_TEMPLATE/BUGS.yml
+++ b/.github/ISSUE_TEMPLATE/BUGS.yml
@@ -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,13 +22,13 @@ 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
@@ -39,7 +36,7 @@ body:
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
diff --git a/.github/ISSUE_TEMPLATE/CONTENT.yml b/.github/ISSUE_TEMPLATE/CONTENT.yml
index 477a961eee..1b1ebe748d 100644
--- a/.github/ISSUE_TEMPLATE/CONTENT.yml
+++ b/.github/ISSUE_TEMPLATE/CONTENT.yml
@@ -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,7 +23,7 @@ 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:
@@ -33,11 +31,11 @@ body:
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
diff --git a/.github/ISSUE_TEMPLATE/REQUEST.yml b/.github/ISSUE_TEMPLATE/REQUEST.yml
index 55479fe1e9..f1aef4ba5a 100644
--- a/.github/ISSUE_TEMPLATE/REQUEST.yml
+++ b/.github/ISSUE_TEMPLATE/REQUEST.yml
@@ -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,7 +25,7 @@ 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:
@@ -35,7 +33,7 @@ body:
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:
@@ -43,4 +41,4 @@ body:
description: If you would like to suggest code samples please attach a working reproduction.
placeholder: "..."
validations:
- required: false
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index b105304437..06c2280099 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -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!"
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 1a6d7de3ac..b9f88f0cc9 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -4,6 +4,7 @@
- [ ] This PR references an issue (except for typos, broken links, or other minor problems)
### Description(required)
+
### Related issues & labels
diff --git a/.github/actions/install/action.yml b/.github/actions/install/action.yml
index 17ced68c17..049f92fbd4 100644
--- a/.github/actions/install/action.yml
+++ b/.github/actions/install/action.yml
@@ -5,9 +5,7 @@ runs:
using: composite
steps:
- name: Setup pnpm
- uses: pnpm/action-setup@v4
- with:
- version: 10
+ uses: pnpm/action-setup@v6
- name: Setup Node.js
uses: actions/setup-node@v6
diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml
new file mode 100644
index 0000000000..08192d60e4
--- /dev/null
+++ b/.github/workflows/autofix.yml
@@ -0,0 +1,31 @@
+name: autofix.ci
+
+on:
+ pull_request:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
+ cancel-in-progress: true
+
+permissions:
+ contents: write
+
+jobs:
+ autofix:
+ name: autofix
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v7.0.0
+ with:
+ fetch-depth: 0
+ - name: Setup Tools
+ uses: ./.github/actions/install
+ - name: Fix lint issues
+ run: pnpm lint:fix
+ - name: Fix formatting
+ run: pnpm format
+ - name: Apply fixes
+ uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27
+ with:
+ commit-message: "ci: apply automated fixes"
diff --git a/.github/workflows/orama_sync.yml b/.github/workflows/orama_sync.yml
index 30d83ee15e..510d513518 100644
--- a/.github/workflows/orama_sync.yml
+++ b/.github/workflows/orama_sync.yml
@@ -17,14 +17,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v4
- - uses: pnpm/action-setup@v3
- with:
- version: 9
+ uses: actions/checkout@v7
+ - uses: pnpm/action-setup@v6
- name: Setup Node.js
- uses: actions/setup-node@v4
+ uses: actions/setup-node@v6
with:
- node-version: 20.x
+ node-version: 24.x
cache: pnpm
- name: Install dependencies
run: pnpm i
@@ -32,4 +30,5 @@ jobs:
run: pnpm sync:orama
env:
ORAMA_PRIVATE_API_KEY: ${{ secrets.ORAMA_PRIVATE_API_KEY }}
- ORAMA_PRIVATE_INDEX_ID: ${{ secrets.ORAMA_PRIVATE_INDEX_ID }}
+ ORAMA_DATASOURCE_ID: ${{ secrets.ORAMA_DATASOURCE_ID }}
+ ORAMA_PROJECT_ID: ${{ secrets.ORAMA_PROJECT_ID }}
diff --git a/.github/workflows/static_checks.yml b/.github/workflows/static_checks.yml
index c71be85632..da45c4712c 100644
--- a/.github/workflows/static_checks.yml
+++ b/.github/workflows/static_checks.yml
@@ -18,14 +18,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
- name: Install tools & dependencies
uses: ./.github/actions/install
- - name: Generate virtual modules
- run: pnpm sync
-
- name: TypeScript check
run: pnpm check:types
@@ -33,10 +30,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
- uses: actions/checkout@v4
+ uses: actions/checkout@v7
- name: Install tools & dependencies
uses: ./.github/actions/install
- name: Lint code
run: pnpm check:lint
+
+ - name: Check formatting
+ run: pnpm exec prettier . --check
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000000..474a57d70d
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1,2 @@
+ignore-workspace-root-check=true
+auto-install-peers=false
diff --git a/.prettierignore b/.prettierignore
index 97ea5f2502..44ceb5a9c5 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,4 +1,5 @@
.solid
dist
*.min.*
-package-lock.json
\ No newline at end of file
+package-lock.json
+.github
diff --git a/.prettierrc b/.prettierrc
index 1d91c6a999..bfe5b02fa8 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -4,5 +4,5 @@
"semi": true,
"singleQuote": false,
"useTabs": true,
- "plugins": ["prettier-plugin-tailwindcss"]
+ "plugins": ["prettier-plugin-tailwindcss"]
}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 26b11b8c7d..1e94e9a229 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -133,13 +133,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
diff --git a/README.md b/README.md
index 04cb6e1eb1..3a195a4352 100644
--- a/README.md
+++ b/README.md
@@ -2,10 +2,9 @@
- Remove This Now!!! If you see this it means that markdown custom components - does work -
-); + export const pre = (props: ParentProps) => { return (
{props.children}
@@ -234,7 +224,7 @@ export const pre = (props: ParentProps) => {
export const code = (props: ParentProps) => {
return (
{props.children}
@@ -252,9 +242,6 @@ export const hr = (props: ParentProps) => {
export const response = (props: ParentProps) => {
return {props.children};
};
-// export const void = (props: ParentProps) => {
-// return {props.children};
-// }
export const unknown = (props: ParentProps) => {
return {props.children};
};
diff --git a/src/styles/expressive-code.css b/osmium/src/styles/expressive-code.css
similarity index 96%
rename from src/styles/expressive-code.css
rename to osmium/src/styles/expressive-code.css
index bbb58b687f..947113dfa2 100644
--- a/src/styles/expressive-code.css
+++ b/osmium/src/styles/expressive-code.css
@@ -1,3 +1,5 @@
+@reference "../tailwind.css"
+
.expressive-code-overrides .expressive-code {
@apply my-4 font-mono;
}
@@ -7,7 +9,7 @@
}
.expressive-code-overrides .expressive-code .frame.is-terminal .header {
- @apply border-x-0 border-b border-t-0 border-solid border-slate-600/20;
+ @apply border-x-0 border-t-0 border-b border-solid border-slate-600/20;
}
html .expressive-code-overrides .expressive-code pre {
diff --git a/src/styles/prism.css b/osmium/src/styles/prism.css
similarity index 62%
rename from src/styles/prism.css
rename to osmium/src/styles/prism.css
index e38bc887c9..6dcd53f713 100644
--- a/src/styles/prism.css
+++ b/osmium/src/styles/prism.css
@@ -1,5 +1,7 @@
+@reference "../tailwind.css"
+
pre[class*="language-"] {
- color: theme("colors.slate.50");
+ color: var(--color-slate-50);
}
.token.tag,
@@ -8,7 +10,7 @@ pre[class*="language-"] {
.token.selector .class,
.token.selector.class,
.token.function {
- color: theme("colors.pink.400");
+ color: var(--color-pink-400);
}
.token.attr-name,
@@ -16,32 +18,32 @@ pre[class*="language-"] {
.token.rule,
.token.pseudo-class,
.token.important {
- color: theme("colors.slate.300");
+ color: var(--color-slate-300);
}
.token.module {
- color: theme("colors.pink.400");
+ color: var(--color-pink-400);
}
.token.attr-value,
.token.class,
.token.string,
.token.property {
- color: theme("colors.sky.300");
+ color: var(--color-sky-300);
}
.token.punctuation,
.token.attr-equals {
- color: theme("colors.slate.500");
+ color: var(--color-slate-500);
}
.token.unit,
.language-css .token.function {
- color: theme("colors.teal.200");
+ color: var(--color-teal-200);
}
.token.comment,
.token.operator,
.token.combinator {
- color: theme("colors.slate.400");
+ color: var(--color-slate-400);
}
diff --git a/osmium/src/tailwind.css b/osmium/src/tailwind.css
new file mode 100644
index 0000000000..2816c32676
--- /dev/null
+++ b/osmium/src/tailwind.css
@@ -0,0 +1,61 @@
+@plugin "@tailwindcss/typography";
+@plugin "@kobalte/tailwindcss" {
+ prefix: kb;
+}
+
+@custom-variant dark (&:where([data-theme*='dark'], [data-theme*='dark'] *));
+
+@theme {
+ --text-xs: 0.75rem;
+ --text-xs--line-height: 1rem;
+
+ --text-sm: 0.875rem;
+ --text-sm--line-height: 1.5rem;
+
+ --text-base: 1rem;
+ --text-base--line-height: 2rem;
+
+ --text-lg: 1.125rem;
+ --text-lg--line-height: 1.75rem;
+
+ --text-xl: 1.25rem;
+ --text-xl--line-height: 2rem;
+
+ --text-2xl: 1.5rem;
+ --text-2xl--line-height: 2.5rem;
+
+ --text-3xl: 2rem;
+ --text-3xl--line-height: 2.5rem;
+
+ --text-4xl: 2.5rem;
+ --text-4xl--line-height: 3rem;
+
+ --text-5xl: 3rem;
+ --text-5xl--line-height: 3.5rem;
+
+ --text-6xl: 3.75rem;
+ --text-6xl--line-height: 1;
+
+ --text-7xl: 4.5rem;
+ --text-7xl--line-height: 1;
+
+ --text-8xl: 6rem;
+ --text-8xl--line-height: 1;
+
+ --text-9xl: 8rem;
+ --text-9xl--line-height: 1;
+
+ --font-sans: var(--font-geist);
+ --font-mono: var(--font-geist-mono);
+
+ --font-display: var(--font-geist);
+
+ --container-8xl: 88rem;
+}
+
+@layer utilities {
+ .font-display {
+ font-family: var(--font-geist);
+ font-feature-settings: "ss01";
+ }
+}
diff --git a/src/ui/button-link.tsx b/osmium/src/ui/button-link.tsx
similarity index 68%
rename from src/ui/button-link.tsx
rename to osmium/src/ui/button-link.tsx
index e9058e12d7..fb123291ad 100644
--- a/src/ui/button-link.tsx
+++ b/osmium/src/ui/button-link.tsx
@@ -1,20 +1,21 @@
-import { A, type RouterLinkProps } from "./i18n-anchor";
+import { ComponentProps, splitProps } from "solid-js";
-type ButtonLinkProps = RouterLinkProps & {
+type ButtonLinkProps = ComponentProps<"a"> & {
variant: "primary" | "secondary";
};
export const ButtonLink = (props: ButtonLinkProps) => {
+ const [localProps, otherProps] = splitProps(props, ["variant"]);
+
return (
-
);
};
diff --git a/src/ui/callout.tsx b/osmium/src/ui/callout.tsx
similarity index 95%
rename from src/ui/callout.tsx
rename to osmium/src/ui/callout.tsx
index 9878c4266a..1554e84d73 100644
--- a/src/ui/callout.tsx
+++ b/osmium/src/ui/callout.tsx
@@ -1,4 +1,3 @@
-import { Alert } from "@kobalte/core";
import { Icon } from "solid-heroicons";
import { mergeProps, type JSX, Show, untrack } from "solid-js";
import {
@@ -91,7 +90,7 @@ export function Callout(props: CalloutProps) {
const IconComponent = icons[iconType];
return (
-
{mergedProps.title}
-
+
{mergedProps.children}
-
+
);
}
diff --git a/osmium/src/ui/docs-layout.tsx b/osmium/src/ui/docs-layout.tsx
new file mode 100644
index 0000000000..fadf427fbc
--- /dev/null
+++ b/osmium/src/ui/docs-layout.tsx
@@ -0,0 +1,62 @@
+import { Show, JSX, createMemo } from "solid-js";
+import { Pagination } from "./pagination";
+import { EditPageLink } from "./edit-page-link";
+import { PageIssueLink } from "./page-issue-link";
+import { useOsmiumThemeFrontmatter } from "../frontmatter";
+import { useRouteConfig } from "../utils";
+import { useCurrentPageData } from "@kobalte/solidbase/client";
+
+interface DocsLayoutProps {
+ children: JSX.Element;
+}
+
+export const DocsLayout = (props: DocsLayoutProps) => {
+ const frontmatter = useOsmiumThemeFrontmatter();
+
+ const pageData = useCurrentPageData();
+ const config = useRouteConfig();
+
+ const formatter = createMemo(
+ () => new Intl.DateTimeFormat(undefined, config()?.lastUpdated || undefined)
+ );
+
+ const date = createMemo(
+ () =>
+ new Date(
+ Number.isNaN(pageData()?.lastUpdated)
+ ? 0
+ : (pageData()?.lastUpdated ?? 0)
+ )
+ );
+
+ return (
+
+
+ {(t) => (
+
+ {t()}
+
+ )}
+
+
+ {frontmatter()?.title}
+
+ {props.children}
+
+
+ Last updated:{" "}
+
+ {formatter().format(date())}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/ui/edit-page-link.tsx b/osmium/src/ui/edit-page-link.tsx
similarity index 61%
rename from src/ui/edit-page-link.tsx
rename to osmium/src/ui/edit-page-link.tsx
index 094d5579bf..a5c64c28bb 100644
--- a/src/ui/edit-page-link.tsx
+++ b/osmium/src/ui/edit-page-link.tsx
@@ -3,22 +3,19 @@ import { Icon } from "solid-heroicons";
import { pencilSquare } from "solid-heroicons/outline";
import { useCurrentPageData } from "@kobalte/solidbase/client";
-import { useI18n } from "~/i18n/i18n-context";
-
export const EditPageLink: Component = () => {
- const i18n = useI18n();
const data = useCurrentPageData();
return (
{(editLink) => (
-
- {i18n.t("contribute.edit")}
+
+ Edit this page
)}
diff --git a/src/ui/eraser-link/eraser-link.css b/osmium/src/ui/eraser-link/eraser-link.css
similarity index 100%
rename from src/ui/eraser-link/eraser-link.css
rename to osmium/src/ui/eraser-link/eraser-link.css
diff --git a/src/ui/eraser-link/index.tsx b/osmium/src/ui/eraser-link/index.tsx
similarity index 88%
rename from src/ui/eraser-link/index.tsx
rename to osmium/src/ui/eraser-link/index.tsx
index 76bdd6f46c..453edf2c98 100644
--- a/src/ui/eraser-link/index.tsx
+++ b/osmium/src/ui/eraser-link/index.tsx
@@ -55,7 +55,7 @@ const EraserLink = (
fallback={
{props.children}
@@ -67,6 +67,7 @@ const EraserLink = (
class="relative inline-block"
target="_blank"
rel="noopener noreferrer"
+ aria-label="View diagram on Eraser.io"
>
setIsLoaded(true)}
/>
{isLoaded() ? (
@@ -100,7 +101,7 @@ export default function EraserOrAnchor(props: ParentProps<{ href: string }>) {
fallback={
{props.children}
diff --git a/src/ui/image-links.tsx b/osmium/src/ui/image-link.tsx
similarity index 60%
rename from src/ui/image-links.tsx
rename to osmium/src/ui/image-link.tsx
index d287ce897d..e878fdcc92 100644
--- a/src/ui/image-links.tsx
+++ b/osmium/src/ui/image-link.tsx
@@ -1,5 +1,5 @@
-import { ParentComponent, Show, untrack } from "solid-js";
-import { A } from "~/ui/i18n-anchor";
+import { useLocale } from "@kobalte/solidbase/client";
+import { ParentComponent, untrack } from "solid-js";
/**
* @todo
@@ -24,19 +24,21 @@ export const logos: { [key: string]: { file: string; style?: string } } = {
uno: { file: "uno.svg" },
};
-export type ImageLinksProps = {
+export type ImageLinkProps = {
title: string;
logo: keyof typeof logos;
href: string;
};
-export const ImageLinks: ParentComponent = (props) => {
+export const ImageLink: ParentComponent = (props) => {
+ const locale = useLocale();
+
const logoImage = untrack(() => props.logo);
const { file, style } = logos[logoImage];
return (
-
+
@@ -49,26 +51,17 @@ export const ImageLinks: ParentComponent = (props) => {
/>
-
-
- {props.title}
-
+
-
-
- {props.title}
-
-
+
+ {props.title}
+
diff --git a/osmium/src/ui/layout.tsx b/osmium/src/ui/layout.tsx
new file mode 100644
index 0000000000..19dfe81a99
--- /dev/null
+++ b/osmium/src/ui/layout.tsx
@@ -0,0 +1,48 @@
+import { ParentComponent, Show } from "solid-js";
+
+import { MainNavigation } from "./layout/main-navigation";
+import { MainHeader } from "./layout/main-header";
+import { Hero } from "./layout/hero";
+import { DocsLayout } from "./docs-layout";
+import { SidePanel } from "./layout/side-panel";
+import { useOsmiumThemeFrontmatter } from "../frontmatter";
+
+export const Layout: ParentComponent<{ isError?: boolean }> = (props) => {
+ const frontmatter = useOsmiumThemeFrontmatter();
+
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/src/ui/layout/contribute.tsx b/osmium/src/ui/layout/contribute.tsx
similarity index 60%
rename from src/ui/layout/contribute.tsx
rename to osmium/src/ui/layout/contribute.tsx
index ad9ea2d56f..25dcd63e89 100644
--- a/src/ui/layout/contribute.tsx
+++ b/osmium/src/ui/layout/contribute.tsx
@@ -1,27 +1,24 @@
import { Component } from "solid-js";
-import { useI18n } from "~/i18n/i18n-context";
import { EditPageLink } from "../edit-page-link";
import { PageIssueLink } from "../page-issue-link";
export const Contribute: Component = () => {
- const i18n = useI18n();
-
return (
<>
- {i18n.t("contribute.title")}
+ Contribute
-
-
+
-
-
+
diff --git a/osmium/src/ui/layout/hero-code-snippet.tsx b/osmium/src/ui/layout/hero-code-snippet.tsx
new file mode 100644
index 0000000000..cd4e623bed
--- /dev/null
+++ b/osmium/src/ui/layout/hero-code-snippet.tsx
@@ -0,0 +1,3 @@
+export default function CodeSnippet() {
+ return TODO;
+}
diff --git a/osmium/src/ui/layout/hero.tsx b/osmium/src/ui/layout/hero.tsx
new file mode 100644
index 0000000000..78545b5f4c
--- /dev/null
+++ b/osmium/src/ui/layout/hero.tsx
@@ -0,0 +1,5 @@
+import { Component } from "solid-js";
+
+export const Hero: Component = () => {
+ return ;
+};
diff --git a/osmium/src/ui/layout/language-selector.tsx b/osmium/src/ui/layout/language-selector.tsx
new file mode 100644
index 0000000000..845d04f292
--- /dev/null
+++ b/osmium/src/ui/layout/language-selector.tsx
@@ -0,0 +1,60 @@
+import { Component, Show } from "solid-js";
+import { Icon } from "solid-heroicons";
+import { language } from "solid-heroicons/solid";
+import { ResolvedLocale, useLocale } from "@kobalte/solidbase/client";
+import { Select } from "@kobalte/core/select";
+import { OsmiumThemeConfig } from "../..";
+
+export const LanguageSelector: Component = () => {
+ const { locales, currentLocale, setLocale } = useLocale();
+
+ return (
+ 1}>
+ {(_) => {
+ return (
+
+ );
+ }}
+
+ );
+};
diff --git a/osmium/src/ui/layout/main-header.tsx b/osmium/src/ui/layout/main-header.tsx
new file mode 100644
index 0000000000..ccdff88385
--- /dev/null
+++ b/osmium/src/ui/layout/main-header.tsx
@@ -0,0 +1,139 @@
+import {
+ ComponentProps,
+ For,
+ Show,
+ createSignal,
+ onCleanup,
+ onMount,
+} from "solid-js";
+import { isServer } from "solid-js/web";
+
+import { ProjectLogo, GitHubIcon, DiscordIcon } from "../logo";
+import { ThemeSelector } from "./theme-selector";
+import { MobileNavigation } from "./mobile-navigation";
+import { LanguageSelector } from "./language-selector";
+
+import { clientOnly } from "@solidjs/start";
+import { useProject, useRouteConfig } from "../../utils";
+import { useOsmiumThemeState } from "../../context";
+
+const ClientSearch = clientOnly(() =>
+ import("../search").then((m) => ({ default: m.Search }))
+);
+
+interface NavLinkProps extends ComponentProps<"a"> {
+ active?: boolean;
+}
+
+function NavLink(props: NavLinkProps) {
+ return (
+
+ {props.children}
+
+ );
+}
+
+interface MainHeaderProps {}
+
+export function MainHeader(_props: MainHeaderProps) {
+ const [isScrolled, setIsScrolled] = createSignal(false);
+
+ const config = useRouteConfig();
+
+ const project = useProject();
+
+ const { setNavOpen } = useOsmiumThemeState();
+
+ if (!isServer) {
+ const onScroll = () => {
+ setIsScrolled(window.scrollY > 0);
+ };
+
+ onMount(() => {
+ onScroll();
+ window.addEventListener("scroll", onScroll, { passive: true });
+ });
+
+ onCleanup(() => {
+ window.removeEventListener("scroll", onScroll);
+ });
+ }
+
+ return (
+
+
+
+ );
+}
diff --git a/osmium/src/ui/layout/main-navigation.tsx b/osmium/src/ui/layout/main-navigation.tsx
new file mode 100644
index 0000000000..5565f89b4a
--- /dev/null
+++ b/osmium/src/ui/layout/main-navigation.tsx
@@ -0,0 +1,167 @@
+import { createMemo, createSignal, For, Show } from "solid-js";
+import { useBeforeLeave, useLocation, useMatch } from "@solidjs/router";
+import { Icon } from "solid-heroicons";
+import { chevronDown } from "solid-heroicons/solid";
+import { setIsOpen } from "./mobile-navigation";
+import {
+ SidebarItem,
+ SidebarItemLink,
+ useLocale,
+ useSidebar,
+} from "@kobalte/solidbase/client";
+import { Collapsible } from "@kobalte/core/collapsible";
+import { Tabs } from "@kobalte/core/tabs";
+import VersionSelector from "./version-selector";
+
+interface MainNavigationProps {}
+
+function ListItemLink(props: { item: SidebarItemLink; prefix?: string }) {
+ const location = useLocation();
+ const locale = useLocale();
+
+ const linkStyles = () =>
+ location.pathname === props.item.link.replace(/\\/g, "/")
+ ? "font-semibold text-blue-700 before:bg-blue-700 dark:before:bg-blue-200 dark:text-blue-300 before:block"
+ : "text-slate-700 before:hidden before:bg-blue-600 before:dark:bg-blue-200 hover:text-blue-700 hover:before:block dark:text-slate-300 ";
+ return (
+ -
+ setIsOpen(false)}
+ href={locale.applyPathPrefix(
+ `${props.prefix === "/" ? "" : (props.prefix ?? "")}${props.item.link === "/" ? "" : props.item.link}`
+ )}
+ class={`block w-full pl-3.5 before:pointer-events-none before:absolute before:top-1/2 before:-left-1 before:h-1.5 before:w-1.5 before:-translate-y-1/2 before:rounded-full hover:text-blue-700 lg:text-sm dark:hover:text-blue-300 ${linkStyles()}`}
+ >
+ {props.item.title}
+
+
+ );
+}
+
+function DirList(props: { items: SidebarItem[] }) {
+ return (
+
+ {(child) => {
+ if ("items" in child) {
+ return (
+ <>
+ -
+
+
+
+ {child.title}
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+ }
+
+ if ("link" in child) {
+ return ;
+ }
+
+ return "";
+ }}
+
+ );
+}
+
+export function MainNavigation(_props: MainNavigationProps) {
+ const isReference = useMatch(() => "*/reference/*?");
+
+ const initialTab = () => (isReference() ? "reference" : "learn");
+
+ const [selectedTab, setSelectedTab] = createSignal(initialTab());
+
+ const sidebar = useSidebar();
+
+ const sidebarEntries = createMemo(() => {
+ return sidebar().items.sort((a, b) => {
+ // @ts-expect-error: shorthand
+ return !!a.items - !!b.items;
+ });
+ });
+
+ /**
+ * Re-syncs the selected tab with the chosen route.
+ */
+ useBeforeLeave(({ to }) => {
+ if (typeof to === "number") return;
+
+ if (to.includes("/reference/")) {
+ setSelectedTab("reference");
+ } else {
+ setSelectedTab("learn");
+ }
+ });
+
+ return (
+
+ );
+}
diff --git a/src/ui/layout/mobile-navigation.tsx b/osmium/src/ui/layout/mobile-navigation.tsx
similarity index 70%
rename from src/ui/layout/mobile-navigation.tsx
rename to osmium/src/ui/layout/mobile-navigation.tsx
index 48c028eec1..fc10c5e331 100644
--- a/src/ui/layout/mobile-navigation.tsx
+++ b/osmium/src/ui/layout/mobile-navigation.tsx
@@ -4,38 +4,28 @@ import { bars_3, xMark } from "solid-heroicons/solid";
import { MainNavigation } from "./main-navigation";
import { createSignal } from "solid-js";
-interface Entry {
- title: string;
- path: string;
- children?: Entry[];
- mainNavExclude: boolean;
- isTranslated?: boolean;
-}
-
-interface NavProps {
- tree: {
- learn: Entry[];
- reference: Entry[];
- };
-}
+interface MobileNavigationProps {}
export const [isOpen, setIsOpen] = createSignal(false);
-export const MobileNavigation = (props: NavProps) => {
+export const MobileNavigation = (_props: MobileNavigationProps) => {
return (
-
-
+
+
-
+
-
+
diff --git a/src/ui/layout/side-panel.tsx b/osmium/src/ui/layout/side-panel.tsx
similarity index 100%
rename from src/ui/layout/side-panel.tsx
rename to osmium/src/ui/layout/side-panel.tsx
diff --git a/src/ui/layout/table-of-contents.tsx b/osmium/src/ui/layout/table-of-contents.tsx
similarity index 81%
rename from src/ui/layout/table-of-contents.tsx
rename to osmium/src/ui/layout/table-of-contents.tsx
index e8181b5036..6b8509de0f 100644
--- a/src/ui/layout/table-of-contents.tsx
+++ b/osmium/src/ui/layout/table-of-contents.tsx
@@ -6,14 +6,10 @@ import {
import { createEventListener } from "@solid-primitives/event-listener";
import { isServer } from "solid-js/web";
-import { useI18n } from "~/i18n/i18n-context";
-
export const TableOfContents = () => {
const data = useCurrentPageData();
const toc = () => data()?.toc;
- const i18n = useI18n();
-
const [currentSection, setCurrentSection] = createSignal();
const [headingElements, setHeadingElements] = createSignal<
@@ -53,13 +49,10 @@ export const TableOfContents = () => {
return (