diff --git a/src/components/BoardDropdown/BoardDropdown.jsx b/src/components/BoardDropdown/BoardDropdown.jsx index 44b55c8..61e6c18 100644 --- a/src/components/BoardDropdown/BoardDropdown.jsx +++ b/src/components/BoardDropdown/BoardDropdown.jsx @@ -16,6 +16,7 @@ const BoardDropdown = () => { const handleBoardChange = (selectedBoard) => { // Verwende die setBoard-Funktion direkt, um das Board im Store zu aktualisieren useBoardStore.setState({ board: selectedBoard }); + console.log(selectedBoard, useBoardStore((state) => state.board)) // Hier kannst du weitere Aktionen ausführen, wenn sich das Board ändert }; diff --git a/src/theme/BoardDropdown/BoardDropdown.jsx b/src/theme/BoardDropdown/BoardDropdown.jsx new file mode 100644 index 0000000..44b55c8 --- /dev/null +++ b/src/theme/BoardDropdown/BoardDropdown.jsx @@ -0,0 +1,53 @@ +// BoardDropdown.jsx + +import React, { useState } from "react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@site/src/components/ui/select"; +import { useBoardStore } from "@site/src/lib/stores/store"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faMicrochip } from "@fortawesome/free-solid-svg-icons"; +const BoardDropdown = () => { + const board = useBoardStore((state) => state.board); + const handleBoardChange = (selectedBoard) => { + // Verwende die setBoard-Funktion direkt, um das Board im Store zu aktualisieren + useBoardStore.setState({ board: selectedBoard }); + // Hier kannst du weitere Aktionen ausführen, wenn sich das Board ändert + }; + + return ( + + ); +}; + +export default BoardDropdown; diff --git a/src/theme/Navbar/ColorModeToggle/index.js b/src/theme/Navbar/ColorModeToggle/index.js new file mode 100644 index 0000000..a506863 --- /dev/null +++ b/src/theme/Navbar/ColorModeToggle/index.js @@ -0,0 +1,22 @@ +import React from 'react'; +import {useColorMode, useThemeConfig} from '@docusaurus/theme-common'; +import ColorModeToggle from '@theme/ColorModeToggle'; +import styles from './styles.module.css'; +export default function NavbarColorModeToggle({className}) { + const navbarStyle = useThemeConfig().navbar.style; + const disabled = useThemeConfig().colorMode.disableSwitch; + const {colorMode, setColorMode} = useColorMode(); + if (disabled) { + return null; + } + return ( + + ); +} diff --git a/src/theme/Navbar/ColorModeToggle/styles.module.css b/src/theme/Navbar/ColorModeToggle/styles.module.css new file mode 100644 index 0000000..7bd077a --- /dev/null +++ b/src/theme/Navbar/ColorModeToggle/styles.module.css @@ -0,0 +1,3 @@ +.darkNavbarColorModeToggle:hover { + background: var(--ifm-color-gray-800); +} diff --git a/src/theme/Navbar/Content/index.js b/src/theme/Navbar/Content/index.js new file mode 100644 index 0000000..792b51d --- /dev/null +++ b/src/theme/Navbar/Content/index.js @@ -0,0 +1,144 @@ +import React, { useEffect, useState } from 'react'; +import { useThemeConfig, ErrorCauseBoundary } from '@docusaurus/theme-common'; +import { + splitNavbarItems, + useNavbarMobileSidebar, +} from '@docusaurus/theme-common/internal'; +import NavbarItem from '@theme/NavbarItem'; +import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle'; +import SearchBar from '@theme/SearchBar'; +import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle'; +import NavbarLogo from '@theme/Navbar/Logo'; +import NavbarSearch from '@theme/Navbar/Search'; +import styles from './styles.module.css'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@site/src/components/ui/select"; +import { useBoardStore } from "@site/src/lib/stores/store"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faMicrochip } from "@fortawesome/free-solid-svg-icons"; +import { useNavigate, useLocation } from 'react-router-dom'; // Verwende useLocation + +function useNavbarItems() { + return useThemeConfig().navbar.items; +} + +function NavbarItems({ items }) { + return ( + <> + {items.map((item, i) => ( + + new Error( + `A theme navbar item failed to render. +Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config: +${JSON.stringify(item, null, 2)}`, + { cause: error }, + ) + } + > + + + ))} + + ); +} + +function NavbarContentLayout({ left, right }) { + return ( +
+
{left}
+
{right}
+
+ ); +} + +const BoardDropdown = () => { + const board = useBoardStore((state) => state.board); + const location = useLocation(); + + const handleBoardChange = (selectedBoard) => { + // Verwende die setBoard-Funktion direkt, um das Board im Store zu aktualisieren + console.log(selectedBoard) + useBoardStore.setState({ board: selectedBoard }); + // Hier kannst du weitere Aktionen ausführen, wenn sich das Board ändert + }; + + useEffect(() => { + const searchParams = new URLSearchParams(location.search); + const currentBoard = searchParams.get('board'); + const validBoards = ['home', 'edu', 'edu S2', 'bike', 'CO2 Ampel']; + if (currentBoard && validBoards.includes(currentBoard)) { + // Wenn der aktuelle `board`-Parameter gültig ist, setze ihn als ausgewählten Wert + useBoardStore.setState({ board: ":"+currentBoard }); + } else { + console.log('Ungültiger Board-Parameter:', currentBoard); + } + }, [location.search]); // Überwache Änderungen an den Query-Parametern + + return ( + + ); +}; + +export default function NavbarContent() { + const mobileSidebar = useNavbarMobileSidebar(); + const items = useNavbarItems(); + const [leftItems, rightItems] = splitNavbarItems(items); + const searchBarItem = items.find((item) => item.type === 'search'); + + return ( + + {!mobileSidebar.disabled && } + + + + } + right={ + <> + + + + {!searchBarItem && ( + + + + )} + + } + /> + ); +} diff --git a/src/theme/Navbar/Content/styles.module.css b/src/theme/Navbar/Content/styles.module.css new file mode 100644 index 0000000..4c9471e --- /dev/null +++ b/src/theme/Navbar/Content/styles.module.css @@ -0,0 +1,8 @@ +/* +Hide color mode toggle in small viewports + */ +@media (max-width: 996px) { + .colorModeToggle { + display: none; + } +} diff --git a/src/theme/Navbar/Layout/index.js b/src/theme/Navbar/Layout/index.js new file mode 100644 index 0000000..492a929 --- /dev/null +++ b/src/theme/Navbar/Layout/index.js @@ -0,0 +1,52 @@ +import React from 'react'; +import clsx from 'clsx'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import { + useHideableNavbar, + useNavbarMobileSidebar, +} from '@docusaurus/theme-common/internal'; +import {translate} from '@docusaurus/Translate'; +import NavbarMobileSidebar from '@theme/Navbar/MobileSidebar'; +import styles from './styles.module.css'; +function NavbarBackdrop(props) { + return ( +
+ ); +} +export default function NavbarLayout({children}) { + const { + navbar: {hideOnScroll, style}, + } = useThemeConfig(); + const mobileSidebar = useNavbarMobileSidebar(); + const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll); + return ( + + ); +} diff --git a/src/theme/Navbar/Layout/styles.module.css b/src/theme/Navbar/Layout/styles.module.css new file mode 100644 index 0000000..e72891a --- /dev/null +++ b/src/theme/Navbar/Layout/styles.module.css @@ -0,0 +1,7 @@ +.navbarHideable { + transition: transform var(--ifm-transition-fast) ease; +} + +.navbarHidden { + transform: translate3d(0, calc(-100% - 2px), 0); +} diff --git a/src/theme/Navbar/Logo/index.js b/src/theme/Navbar/Logo/index.js new file mode 100644 index 0000000..f0fa51f --- /dev/null +++ b/src/theme/Navbar/Logo/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import Logo from '@theme/Logo'; +export default function NavbarLogo() { + return ( + + ); +} diff --git a/src/theme/Navbar/MobileSidebar/Header/index.js b/src/theme/Navbar/MobileSidebar/Header/index.js new file mode 100644 index 0000000..67e9e44 --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/Header/index.js @@ -0,0 +1,31 @@ +import React from 'react'; +import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal'; +import {translate} from '@docusaurus/Translate'; +import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle'; +import IconClose from '@theme/Icon/Close'; +import NavbarLogo from '@theme/Navbar/Logo'; +function CloseButton() { + const mobileSidebar = useNavbarMobileSidebar(); + return ( + + ); +} +export default function NavbarMobileSidebarHeader() { + return ( +
+ + + +
+ ); +} diff --git a/src/theme/Navbar/MobileSidebar/Layout/index.js b/src/theme/Navbar/MobileSidebar/Layout/index.js new file mode 100644 index 0000000..b19eb2f --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/Layout/index.js @@ -0,0 +1,22 @@ +import React from 'react'; +import clsx from 'clsx'; +import {useNavbarSecondaryMenu} from '@docusaurus/theme-common/internal'; +export default function NavbarMobileSidebarLayout({ + header, + primaryMenu, + secondaryMenu, +}) { + const {shown: secondaryMenuShown} = useNavbarSecondaryMenu(); + return ( +
+ {header} +
+
{primaryMenu}
+
{secondaryMenu}
+
+
+ ); +} diff --git a/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js new file mode 100644 index 0000000..9c5d0ec --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/PrimaryMenu/index.js @@ -0,0 +1,27 @@ +import React from 'react'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal'; +import NavbarItem from '@theme/NavbarItem'; +function useNavbarItems() { + // TODO temporary casting until ThemeConfig type is improved + return useThemeConfig().navbar.items; +} +// The primary menu displays the navbar items +export default function NavbarMobilePrimaryMenu() { + const mobileSidebar = useNavbarMobileSidebar(); + // TODO how can the order be defined for mobile? + // Should we allow providing a different list of items? + const items = useNavbarItems(); + return ( +
    + {items.map((item, i) => ( + mobileSidebar.toggle()} + key={i} + /> + ))} +
+ ); +} diff --git a/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js b/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js new file mode 100644 index 0000000..dd71af8 --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/SecondaryMenu/index.js @@ -0,0 +1,30 @@ +import React from 'react'; +import {useThemeConfig} from '@docusaurus/theme-common'; +import {useNavbarSecondaryMenu} from '@docusaurus/theme-common/internal'; +import Translate from '@docusaurus/Translate'; +function SecondaryMenuBackButton(props) { + return ( + + ); +} +// The secondary menu slides from the right and shows contextual information +// such as the docs sidebar +export default function NavbarMobileSidebarSecondaryMenu() { + const isPrimaryMenuEmpty = useThemeConfig().navbar.items.length === 0; + const secondaryMenu = useNavbarSecondaryMenu(); + return ( + <> + {/* edge-case: prevent returning to the primaryMenu when it's empty */} + {!isPrimaryMenuEmpty && ( + secondaryMenu.hide()} /> + )} + {secondaryMenu.content} + + ); +} diff --git a/src/theme/Navbar/MobileSidebar/Toggle/index.js b/src/theme/Navbar/MobileSidebar/Toggle/index.js new file mode 100644 index 0000000..bfe2988 --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/Toggle/index.js @@ -0,0 +1,22 @@ +import React from 'react'; +import {useNavbarMobileSidebar} from '@docusaurus/theme-common/internal'; +import {translate} from '@docusaurus/Translate'; +import IconMenu from '@theme/Icon/Menu'; +export default function MobileSidebarToggle() { + const {toggle, shown} = useNavbarMobileSidebar(); + return ( + + ); +} diff --git a/src/theme/Navbar/MobileSidebar/index.js b/src/theme/Navbar/MobileSidebar/index.js new file mode 100644 index 0000000..5db3cc7 --- /dev/null +++ b/src/theme/Navbar/MobileSidebar/index.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { + useLockBodyScroll, + useNavbarMobileSidebar, +} from '@docusaurus/theme-common/internal'; +import NavbarMobileSidebarLayout from '@theme/Navbar/MobileSidebar/Layout'; +import NavbarMobileSidebarHeader from '@theme/Navbar/MobileSidebar/Header'; +import NavbarMobileSidebarPrimaryMenu from '@theme/Navbar/MobileSidebar/PrimaryMenu'; +import NavbarMobileSidebarSecondaryMenu from '@theme/Navbar/MobileSidebar/SecondaryMenu'; +export default function NavbarMobileSidebar() { + const mobileSidebar = useNavbarMobileSidebar(); + useLockBodyScroll(mobileSidebar.shown); + if (!mobileSidebar.shouldRender) { + return null; + } + return ( + } + primaryMenu={} + secondaryMenu={} + /> + ); +} diff --git a/src/theme/Navbar/Search/index.js b/src/theme/Navbar/Search/index.js new file mode 100644 index 0000000..686f73b --- /dev/null +++ b/src/theme/Navbar/Search/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import clsx from 'clsx'; +import styles from './styles.module.css'; +export default function NavbarSearch({children, className}) { + return ( +
+ {children} +
+ ); +} diff --git a/src/theme/Navbar/Search/styles.module.css b/src/theme/Navbar/Search/styles.module.css new file mode 100644 index 0000000..f86db5e --- /dev/null +++ b/src/theme/Navbar/Search/styles.module.css @@ -0,0 +1,28 @@ +/* +Workaround to avoid rendering empty search container +See https://github.com/facebook/docusaurus/pull/9385 +*/ +/* +TODO temporary @supports check, remove before 2025 +only needed for Firefox < 121 +see https://github.com/facebook/docusaurus/issues/9527#issuecomment-1805272379 + */ +@supports selector(:has(*)) { + .navbarSearchContainer:not(:has(> *)) { + display: none; + } +} + +@media (max-width: 996px) { + .navbarSearchContainer { + position: absolute; + right: var(--ifm-navbar-padding-horizontal); + } +} + +@media (min-width: 997px) { + .navbarSearchContainer { + padding: var(--ifm-navbar-item-padding-vertical) + var(--ifm-navbar-item-padding-horizontal); + } +} diff --git a/src/theme/Navbar/index.js b/src/theme/Navbar/index.js new file mode 100644 index 0000000..d18a258 --- /dev/null +++ b/src/theme/Navbar/index.js @@ -0,0 +1,10 @@ +import React from 'react'; +import NavbarLayout from '@theme/Navbar/Layout'; +import NavbarContent from '@theme/Navbar/Content'; +export default function Navbar() { + return ( + + + + ); +}