diff --git a/docs/docs/hardware.mdx b/docs/docs/hardware.mdx
index 76a0a3cb..d2b6aa9d 100644
--- a/docs/docs/hardware.mdx
+++ b/docs/docs/hardware.mdx
@@ -6,12 +6,48 @@ sidebar_label: Supported Hardware
import HardwareList from "@site/src/components/hardware-list";
import Metadata from "@site/src/data/hardware-metadata.json";
+import Heading from "@theme/Heading";
+
+import { groupedMetadata } from "@site/src/components/hardware-utils";
+
+export const toc = [
+ {
+ value: "Onboard Controller Keyboards",
+ id: "onboard",
+ level: 2,
+ },
+ {
+ value: "Composite Keyboards",
+ id: "composite",
+ level: 2,
+ },
+ ...Object.values(groupedMetadata(Metadata).interconnects).map(
+ ({ interconnect }) => ({
+ value: `${interconnect.name} Interconnect`,
+ id: interconnect.id,
+ level: 3,
+ })
+ ),
+ {
+ value: "Other Hardware",
+ id: "other-hardware",
+ level: 2,
+ },
+ {
+ value: "Contributing",
+ id: "contributing",
+ level: 2,
+ },
+];
+
With the solid technical foundation of Zephyrâ„¢ RTOS, ZMK can support a wide diversity of hardware targets.
That being said, there are currently only a few specific [boards](/docs/faq#what-is-a-board)/[shields](faq.md#what-is-a-shield) that have been implemented and tested by the ZMK contributors.
-## Other Hardware
+
+ Other Hardware
+
In addition to the basic keyboard functionality, there is some initial support for additional keyboard hardware:
@@ -22,6 +58,8 @@ In addition to the basic keyboard functionality, there is some initial support f
Until detailed documentation is available, feel free to ask questions about how these are supported in the [Discord server](https://zmk.dev/community/discord/invite).
-## Contributing
+
+ Contributing
+
If you'd like to add support for a new keyboard shield, head over to the [New Keyboard Shield](development/new-shield.md) documentation.
diff --git a/docs/src/components/hardware-list.tsx b/docs/src/components/hardware-list.tsx
index e611f5cf..54034ada 100644
--- a/docs/src/components/hardware-list.tsx
+++ b/docs/src/components/hardware-list.tsx
@@ -1,11 +1,9 @@
import React from "react";
-import {
- Board,
- HardwareMetadata,
- Interconnect,
- Shield,
-} from "../hardware-metadata";
+import Heading from "@theme/Heading";
+
+import { HardwareMetadata } from "../hardware-metadata";
+import { groupedMetadata, InterconnectDetails } from "./hardware-utils";
interface HardwareListProps {
items: HardwareMetadata[];
@@ -53,12 +51,6 @@ function HardwareLineItem({ item }: { item: HardwareMetadata }) {
);
}
-interface InterconnectDetails {
- interconnect?: Interconnect;
- boards: Board[];
- shields: Shield[];
-}
-
function mapInterconnect({
interconnect,
boards,
@@ -70,15 +62,17 @@ function mapInterconnect({
return (
-
{interconnect.name} Interconnect
+
+ {interconnect.name} Interconnect
+
{interconnect.description &&
{interconnect.description}
}
-
Boards
+
Boards
-
Shields
+
Shields
{shields.map((s) => (
@@ -88,88 +82,41 @@ function mapInterconnect({
);
}
-interface GroupedMetadata {
- onboard: Board[];
- interconnects: Record;
-}
-
-function groupedBoard(agg: GroupedMetadata, board: Board) {
- if (board.features?.includes("keys")) {
- agg.onboard.push(board);
- } else if (board.exposes) {
- board.exposes.forEach((element) => {
- let ic = agg.interconnects[element] ?? {
- boards: [],
- shields: [],
- };
- ic.boards.push(board);
- agg.interconnects[element] = ic;
- });
- } else {
- console.error("Board without keys or interconnect");
- }
-
- return agg;
-}
-
-function groupedShield(agg: GroupedMetadata, shield: Shield) {
- shield.requires.forEach((id) => {
- let ic = agg.interconnects[id] ?? { boards: [], shields: [] };
- ic.shields.push(shield);
- agg.interconnects[id] = ic;
- });
-
- return agg;
-}
-
-function groupedInterconnect(agg: GroupedMetadata, item: Interconnect) {
- let ic = agg.interconnects[item.id] ?? { boards: [], shields: [] };
- ic.interconnect = item;
- agg.interconnects[item.id] = ic;
-
- return agg;
-}
-
function HardwareList({ items }: HardwareListProps) {
- let grouped = items.reduce(
- (agg, hm) => {
- switch (hm.type) {
- case "board":
- return groupedBoard(agg, hm);
- case "shield":
- return groupedShield(agg, hm);
- case "interconnect":
- return groupedInterconnect(agg, hm);
- }
- },
- { onboard: [] as Board[], interconnects: {} }
- );
+ let grouped = groupedMetadata(items);
return (
<>
- Keyboards
- Onboard Controller Keyboards
-
- Keyboards with onboard controllers are single PCBs that contain all the
- components of a keyboard, including the controller chip, switch
- footprints, etc.
-
-
- {grouped["onboard"]
- .sort((a, b) => a.name.localeCompare(b.name))
- .map((s) => (
-
- ))}
-
- Composite Keyboards
-
- Composite keyboards are composed of two main PCBs: a small controller
- board with exposed pads, and a larger keyboard PCB (a shield, in ZMK
- lingo) with switch footprints and a location where the controller is
- added. This location is called an interconnect. Multiple interconnects
- can be found below.
-
- {Object.values(grouped.interconnects).map(mapInterconnect)}
+
+
+ Onboard Controller Keyboards
+
+
+ Keyboards with onboard controllers are single PCBs that contain all
+ the components of a keyboard, including the controller chip, switch
+ footprints, etc.
+
+
+ {grouped["onboard"]
+ .sort((a, b) => a.name.localeCompare(b.name))
+ .map((s) => (
+
+ ))}
+
+
+
+
+ Composite Keyboards
+
+
+ Composite keyboards are composed of two main PCBs: a small controller
+ board with exposed pads, and a larger keyboard PCB (a shield, in ZMK
+ lingo) with switch footprints and a location where the controller is
+ added. This location is called an interconnect. Multiple interconnects
+ can be found below.
+
+ {Object.values(grouped.interconnects).map(mapInterconnect)}
+
>
);
}
diff --git a/docs/src/components/hardware-utils.ts b/docs/src/components/hardware-utils.ts
new file mode 100644
index 00000000..13ca5eb6
--- /dev/null
+++ b/docs/src/components/hardware-utils.ts
@@ -0,0 +1,70 @@
+import {
+ Board,
+ HardwareMetadata,
+ Interconnect,
+ Shield,
+} from "../hardware-metadata";
+
+export interface InterconnectDetails {
+ interconnect?: Interconnect;
+ boards: Board[];
+ shields: Shield[];
+}
+
+export interface GroupedMetadata {
+ onboard: Board[];
+ interconnects: Record;
+}
+
+function groupedBoard(agg: GroupedMetadata, board: Board) {
+ if (board.features?.includes("keys")) {
+ agg.onboard.push(board);
+ } else if (board.exposes) {
+ board.exposes.forEach((element) => {
+ let ic = agg.interconnects[element] ?? {
+ boards: [],
+ shields: [],
+ };
+ ic.boards.push(board);
+ agg.interconnects[element] = ic;
+ });
+ } else {
+ console.error("Board without keys or interconnect");
+ }
+
+ return agg;
+}
+
+function groupedShield(agg: GroupedMetadata, shield: Shield) {
+ shield.requires.forEach((id) => {
+ let ic = agg.interconnects[id] ?? { boards: [], shields: [] };
+ ic.shields.push(shield);
+ agg.interconnects[id] = ic;
+ });
+
+ return agg;
+}
+
+function groupedInterconnect(agg: GroupedMetadata, item: Interconnect) {
+ let ic = agg.interconnects[item.id] ?? { boards: [], shields: [] };
+ ic.interconnect = item;
+ agg.interconnects[item.id] = ic;
+
+ return agg;
+}
+
+export function groupedMetadata(items: HardwareMetadata[]) {
+ return items.reduce(
+ (agg, hm) => {
+ switch (hm.type) {
+ case "board":
+ return groupedBoard(agg, hm);
+ case "shield":
+ return groupedShield(agg, hm);
+ case "interconnect":
+ return groupedInterconnect(agg, hm);
+ }
+ },
+ { onboard: [] as Board[], interconnects: {} }
+ );
+}
diff --git a/docs/tsconfig.json b/docs/tsconfig.json
index 811eb183..589217e2 100644
--- a/docs/tsconfig.json
+++ b/docs/tsconfig.json
@@ -2,7 +2,7 @@
"extends": "@tsconfig/docusaurus/tsconfig.json",
"include": ["src/"],
"compilerOptions": {
- "jsx": "react",
+ "types": ["node", "@docusaurus/theme-classic"],
"moduleResolution": "Node",
"esModuleInterop": true,
"resolveJsonModule": true,