this.gui 1.3.22 → 1.3.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/this-gui.es.js +0 -1
- package/dist/this-gui.umd.js +65 -65
- package/index.ts +3 -2
- package/init/index.html +4 -5
- package/init/package-lock.json +2 -2
- package/init/package.json +1 -1
- package/init/src/App.tsx +24 -0
- package/init/src/index.css +16 -0
- package/init/src/main.tsx +14 -0
- package/init/src/router/DerivableRouter.tsx +36 -0
- package/package.json +1 -1
- package/src/GUI.tsx +15 -0
- package/src/components/generics/Cards/Gridme.jsx +52 -0
- package/src/components/generics/Cards/LilBox.jsx +65 -0
- package/src/components/generics/Cards/ModuleCard.jsx +106 -0
- package/src/components/generics/Chats/FullChatBot.jsx +223 -0
- package/src/components/generics/Code/CodeBlock.jsx +33 -0
- package/src/components/generics/Feedback/Callout.jsx +92 -0
- package/src/components/generics/Layout/GridX.jsx +29 -0
- package/src/components/generics/Layout/Hero2.jsx +132 -0
- package/src/components/generics/Layout/PageContainer.jsx +29 -0
- package/src/components/generics/Layout/PageDivider.jsx +20 -0
- package/src/components/generics/Layout/Section.jsx +43 -0
- package/src/components/generics/Layout/SectionHeader.jsx +21 -0
- package/src/components/generics/Media/Img.jsx +58 -0
- package/src/components/generics/Media/VideoEmbed.jsx +51 -0
- package/src/components/generics/Organization/TableOfContents.jsx +51 -0
- package/src/components/generics/Organization/Tabs.jsx +45 -0
- package/src/components/generics/Text/TextList.jsx +41 -0
- package/src/components/generics/Text/TextParagraph.jsx +28 -0
- package/src/components/generics/Text/TextQuote.jsx +23 -0
- package/src/components/generics/Text/TextTitle.jsx +44 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.resolver.tsx +0 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.stories.tsx +88 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.tsx +53 -0
- package/src/gui/Layouts/ResponsiveUI/Content/Content.types.tsx +40 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.resolver.tsx +45 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.stories.tsx +209 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.tsx +337 -0
- package/src/gui/Layouts/ResponsiveUI/Footer/Footer.types.ts +40 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.resolver.tsx +37 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.stories.tsx +290 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.tsx +112 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/Layout.types.ts +56 -0
- package/src/gui/Layouts/ResponsiveUI/Layout/useLayoutBreakpoints.ts +9 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.resolver.tsx +87 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.stories.tsx +199 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.tsx +311 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/LeftSidebar.types.ts +41 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/SidebarToggleButton.tsx +53 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.resolver.tsx +19 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarAction/LeftSidebarAction.tsx +107 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.resolver.tsx +0 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.tsx +122 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarLink/LeftSidebarLink.types.ts +13 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarMenu/LeftSidebarMenu.tsx +142 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/LeftSidebar/components/LeftSidebarToggleButton/LeftSidebarToggleButton.tsx +23 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.resolver.tsx +35 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.stories.tsx +240 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.tsx +319 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/RightSidebar.types.ts +17 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarAction/RightSidebarAction.tsx +102 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarLink/RightSidebarLink.tsx +132 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarMenu/RightSidebarMenu.tsx +140 -0
- package/src/gui/Layouts/ResponsiveUI/Sidebars/RightSidebar/components/RightSidebarToggleButton/RightSidebarToggleButton.tsx +22 -0
- package/src/gui/Layouts/ResponsiveUI/StickyOptions/StickyOptionsTop.stories.tsx +469 -0
- package/src/gui/Layouts/ResponsiveUI/StickyOptions/StickyOptionsTop.tsx +489 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.resolver.tsx +86 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.stories.tsx +350 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.tsx +281 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/TopBar.types.ts +39 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.stories.tsx +83 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.tsx +18 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarAction/TopBarAction.types.ts +4 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.stories.tsx +189 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.tsx +30 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarLink/TopBarLink.types.ts +9 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.resolver.tsx +14 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.stories.tsx +56 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.tsx +123 -0
- package/src/gui/Layouts/ResponsiveUI/TopBar/components/TopBarMenu/TopBarMenu.types.ts +44 -0
- package/src/gui/Theme/GuiProvider.tsx +125 -0
- package/src/gui/Theme/Icon/Icon.resolver.tsx +29 -0
- package/src/gui/Theme/Icon/Icon.tsx +43 -0
- package/src/gui/Theme/catalog/CherryByte/CherryByte.png +0 -0
- package/src/gui/Theme/catalog/CherryByte/dark.tokens.ts +47 -0
- package/src/gui/Theme/catalog/CherryByte/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/CherryByte/manifest.ts +24 -0
- package/src/gui/Theme/catalog/GhostShell/dark.tokens.ts +43 -0
- package/src/gui/Theme/catalog/GhostShell/ghost.png +0 -0
- package/src/gui/Theme/catalog/GhostShell/light.tokens.ts +39 -0
- package/src/gui/Theme/catalog/GhostShell/manifest.ts +24 -0
- package/src/gui/Theme/catalog/LunaHex/LunaHex.png +0 -0
- package/src/gui/Theme/catalog/LunaHex/dark.tokens.ts +34 -0
- package/src/gui/Theme/catalog/LunaHex/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/LunaHex/manifest.ts +24 -0
- package/src/gui/Theme/catalog/MUI/MUI.png +0 -0
- package/src/gui/Theme/catalog/MUI/dark.tokens.ts +58 -0
- package/src/gui/Theme/catalog/MUI/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/MUI/manifest.ts +24 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/dark.tokens.ts +48 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/manifest.ts +24 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/prince.png +0 -0
- package/src/gui/Theme/catalog/PrinceOfDarkness/princeOfDarkness.png +0 -0
- package/src/gui/Theme/catalog/Seafoam/dark.tokens.ts +49 -0
- package/src/gui/Theme/catalog/Seafoam/light.tokens.ts +47 -0
- package/src/gui/Theme/catalog/Seafoam/manifest.ts +24 -0
- package/src/gui/Theme/catalog/Seafoam/seaFoam.png +0 -0
- package/src/gui/Theme/catalog/neurons/dark.tokens.ts +58 -0
- package/src/gui/Theme/catalog/neurons/light.tokens.ts +74 -0
- package/src/gui/Theme/catalog/neurons/manifest.ts +24 -0
- package/src/gui/Theme/catalog/neurons/neurons.me.png +0 -0
- package/src/gui/Theme/fromTokens.ts +273 -0
- package/src/gui/Theme/gui.css +31 -0
- package/src/gui/Theme/index.ts +17 -0
- package/src/gui/Theme/styles/buildShadows.ts +83 -0
- package/src/gui/Theme/styles/theme.tokens.ts +108 -0
- package/src/gui/Theme/utils/catalog.ts +61 -0
- package/src/gui/Theme/utils/persistence.ts +66 -0
- package/src/gui/Theme/utils/themeUtils.ts +34 -0
- package/src/gui/apis/codegen.api.ts +38 -0
- package/src/gui/components/atoms/AppBar/AppBar.resolver.tsx +41 -0
- package/src/gui/components/atoms/AppBar/AppBar.stories.tsx +225 -0
- package/src/gui/components/atoms/AppBar/AppBar.tsx +8 -0
- package/src/gui/components/atoms/AppBar/AppBar.types.ts +28 -0
- package/src/gui/components/atoms/Avatar/Avatar.resolver.tsx +61 -0
- package/src/gui/components/atoms/Avatar/Avatar.stories.tsx +36 -0
- package/src/gui/components/atoms/Avatar/Avatar.tsx +14 -0
- package/src/gui/components/atoms/Box/Box.resolver.tsx +171 -0
- package/src/gui/components/atoms/Box/Box.stories.tsx +263 -0
- package/src/gui/components/atoms/Box/Box.tsx +15 -0
- package/src/gui/components/atoms/Button/Button.resolver.tsx +103 -0
- package/src/gui/components/atoms/Button/Button.stories.tsx +219 -0
- package/src/gui/components/atoms/Button/Button.tsx +40 -0
- package/src/gui/components/atoms/Card/Card.resolver.tsx +63 -0
- package/src/gui/components/atoms/Card/Card.stories.tsx +54 -0
- package/src/gui/components/atoms/Card/Card.tsx +13 -0
- package/src/gui/components/atoms/CardActions/CardActions.resolver.tsx +59 -0
- package/src/gui/components/atoms/CardActions/CardActions.stories.tsx +32 -0
- package/src/gui/components/atoms/CardActions/CardActions.tsx +14 -0
- package/src/gui/components/atoms/CardContent/CardContent.resolver.tsx +60 -0
- package/src/gui/components/atoms/CardContent/CardContent.stories.tsx +34 -0
- package/src/gui/components/atoms/CardContent/CardContent.tsx +13 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.resolver.tsx +68 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.stories.tsx +40 -0
- package/src/gui/components/atoms/CardHeader/CardHeader.tsx +12 -0
- package/src/gui/components/atoms/Collapse/Collapse.resolver.tsx +85 -0
- package/src/gui/components/atoms/Collapse/Collapse.stories.tsx +130 -0
- package/src/gui/components/atoms/Collapse/Collapse.tsx +17 -0
- package/src/gui/components/atoms/Divider/Divider.resolver.tsx +95 -0
- package/src/gui/components/atoms/Divider/Divider.stories.tsx +108 -0
- package/src/gui/components/atoms/Divider/Divider.tsx +14 -0
- package/src/gui/components/atoms/Drawer/Drawer.resolver.tsx +116 -0
- package/src/gui/components/atoms/Drawer/Drawer.stories.tsx +223 -0
- package/src/gui/components/atoms/Drawer/Drawer.tsx +25 -0
- package/src/gui/components/atoms/Grid/Grid.resolver.tsx +33 -0
- package/src/gui/components/atoms/Grid/Grid.stories.tsx +136 -0
- package/src/gui/components/atoms/Grid/Grid.tsx +15 -0
- package/src/gui/components/atoms/Grid/Grid.types.ts +9 -0
- package/src/gui/components/atoms/IconButton/IconButton.resolver.tsx +137 -0
- package/src/gui/components/atoms/IconButton/IconButton.stories.tsx +134 -0
- package/src/gui/components/atoms/IconButton/IconButton.tsx +22 -0
- package/src/gui/components/atoms/Link/Link.resolver.tsx +74 -0
- package/src/gui/components/atoms/Link/Link.stories.tsx +157 -0
- package/src/gui/components/atoms/Link/Link.tsx +36 -0
- package/src/gui/components/atoms/List/List.resolver.tsx +94 -0
- package/src/gui/components/atoms/List/List.stories.tsx +137 -0
- package/src/gui/components/atoms/List/List.tsx +20 -0
- package/src/gui/components/atoms/ListItem/ListItem.resolver.tsx +88 -0
- package/src/gui/components/atoms/ListItem/ListItem.stories.tsx +151 -0
- package/src/gui/components/atoms/ListItem/ListItem.tsx +19 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.resolver.tsx +214 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.stories.tsx +155 -0
- package/src/gui/components/atoms/ListItemButton/ListItemButton.tsx +15 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.resolver.tsx +102 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.stories.tsx +132 -0
- package/src/gui/components/atoms/ListItemIcon/ListItemIcon.tsx +11 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.resolver.tsx +112 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.stories.tsx +156 -0
- package/src/gui/components/atoms/ListItemText/ListItemText.tsx +15 -0
- package/src/gui/components/atoms/Menu/Menu.resolver.tsx +112 -0
- package/src/gui/components/atoms/Menu/Menu.stories.tsx +162 -0
- package/src/gui/components/atoms/Menu/Menu.tsx +17 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.resolver.tsx +183 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.stories.tsx +134 -0
- package/src/gui/components/atoms/MenuItem/MenuItem.tsx +14 -0
- package/src/gui/components/atoms/Paper/Paper.resolver.tsx +98 -0
- package/src/gui/components/atoms/Paper/Paper.stories.tsx +184 -0
- package/src/gui/components/atoms/Paper/Paper.tsx +15 -0
- package/src/gui/components/atoms/Section/Section.resolver.tsx +10 -0
- package/src/gui/components/atoms/Section/Section.stories.tsx +189 -0
- package/src/gui/components/atoms/Section/Section.tsx +76 -0
- package/src/gui/components/atoms/Section/Section.types.tsx +24 -0
- package/src/gui/components/atoms/Stack/Stack.resolver.tsx +94 -0
- package/src/gui/components/atoms/Stack/Stack.stories.tsx +160 -0
- package/src/gui/components/atoms/Stack/Stack.tsx +15 -0
- package/src/gui/components/atoms/Surface/Surface.resolver.tsx +37 -0
- package/src/gui/components/atoms/Surface/Surface.tsx +49 -0
- package/src/gui/components/atoms/Surface/Surface.types.ts +20 -0
- package/src/gui/components/atoms/Switch/Switch.resolver.tsx +53 -0
- package/src/gui/components/atoms/Switch/Switch.stories.tsx +236 -0
- package/src/gui/components/atoms/Switch/Switch.tsx +22 -0
- package/src/gui/components/atoms/TextField/TextField.stories.tsx +28 -0
- package/src/gui/components/atoms/TextField/TextField.tsx +15 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.resolver.tsx +60 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.stories.tsx +155 -0
- package/src/gui/components/atoms/Toolbar/Toolbar.tsx +16 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.resolver.tsx +142 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.stories.tsx +117 -0
- package/src/gui/components/atoms/Tooltip/Tooltip.tsx +70 -0
- package/src/gui/components/atoms/Typography/Typography.resolver.tsx +158 -0
- package/src/gui/components/atoms/Typography/Typography.stories.tsx +222 -0
- package/src/gui/components/atoms/Typography/Typography.tsx +27 -0
- package/src/gui/components/atoms.tsx +138 -0
- package/src/gui/components/molecules/Dialog/Dialog.stories.tsx +18 -0
- package/src/gui/components/molecules/Dialog/Dialog.tsx +5 -0
- package/src/gui/components/molecules/HeroSection/HeroSection.stories.tsx +141 -0
- package/src/gui/components/molecules/HeroSection/HeroSection.tsx +152 -0
- package/src/gui/components/molecules/HeroSection/HeroSection.types.tsx +18 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.resolver.tsx +38 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.stories.tsx +82 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.tsx +106 -0
- package/src/gui/components/molecules/ModalBox/ModalBox.types.ts +29 -0
- package/src/gui/components/molecules/Page/Page.stories.tsx +135 -0
- package/src/gui/components/molecules/Page/Page.tsx +94 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.resolver.tsx +58 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.stories.tsx +133 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.tsx +101 -0
- package/src/gui/components/molecules/Theme/ThemeModeToggle/ThemeModeToggle.types.ts +29 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.resolver.tsx +15 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.stories.tsx +88 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.tsx +167 -0
- package/src/gui/components/molecules/Theme/ThemesCatalog/ThemesCatalog.types.ts +34 -0
- package/src/gui/components/organism/ChatGPTInterface/ChatGPTInterface.stories.tsx +17 -0
- package/src/gui/components/organism/ChatGPTInterface/ChatGPTInterface.tsx +71 -0
- package/src/gui/components/organism/RootDomain/RootDomain.stories.tsx +31 -0
- package/src/gui/components/organism/RootDomain/RootDomain.tsx +100 -0
- package/src/gui/components/organism/RootDomain/staticServices.ts +66 -0
- package/src/gui/components/window/Nodes/node.ts +0 -0
- package/src/gui/components/window/code/block/node.tsx +0 -0
- package/src/gui/components/window/code/hugging.face.api.ts +11 -0
- package/src/gui/components/window/connectors/index.ts +19 -0
- package/src/gui/components/window/window.stories.tsx +20 -0
- package/src/gui/components/window/window.tsx +633 -0
- package/src/gui/contexts/InsetsContext.tsx +38 -0
- package/src/gui/contexts/LeftSidebarContext.tsx +20 -0
- package/src/gui/contexts/RightSidebarContext.tsx +25 -0
- package/src/gui/contexts/ThemeContext.ts +34 -0
- package/src/gui/contexts/index.ts +4 -0
- package/src/gui/hooks/index.ts +11 -0
- package/src/gui/hooks/resolveColorToken.ts +39 -0
- package/src/gui/hooks/useCodeGen.ts +12 -0
- package/src/gui/hooks/useGuiMediaQuery.ts +18 -0
- package/src/gui/hooks/useGuiTheme.ts +18 -0
- package/src/gui/hooks/useInsets.ts +26 -0
- package/src/gui/hooks/useIsMobile.ts +13 -0
- package/src/gui/hooks/useIsTouchDevice.ts +25 -0
- package/src/gui/hooks/useLeftSidebar.ts +10 -0
- package/src/gui/hooks/useRightSidebar.ts +12 -0
- package/src/gui/hooks/useViewportKey.ts +19 -0
- package/src/gui/hooks/useViewportProp.ts +17 -0
- package/src/gui/me/Logic.tsx +31 -0
- package/src/gui/me/Me.stories.tsx +8 -0
- package/src/gui/me/Me.tsx +197 -0
- package/src/gui/me/fundamentals/verbs/verbs.tsx +94 -0
- package/src/gui/me/modificators/Adjectives.ts +0 -0
- package/src/gui/me/modificators/Adverbs.ts +0 -0
- package/src/gui/me/modificators/Complements.ts +27 -0
- package/src/gui/me/utils/Context.tsx +14 -0
- package/src/gui/me/utils/hooks/useMe.js +37 -0
- package/src/gui/utils/nodeID.ts +11 -0
- package/src/registry/GuiRegistry.ts +19 -0
- package/src/registry/factory.ts +12 -0
- package/src/registry/index.ts +3 -0
- package/src/registry/types.ts +6 -0
- package/src/stories/01.Home.mdx +22 -0
- package/src/stories/02.Understanding.This.GUI.mdx +149 -0
- package/src/stories/Theme/Palette.stories.tsx +86 -0
- package/src/stories/Theme/ThemeViewer.stories.tsx +91 -0
- package/src/stories/Theme/Typography.stories.jsx +211 -0
- package/src/types/gui.d.ts +67 -0
- package/src/types/theme.d.ts +191 -0
- package/src/types/viewport.ts +132 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import TopBarAction from './TopBarAction';
|
|
3
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
4
|
+
|
|
5
|
+
const meta: Meta<typeof TopBarAction> = {
|
|
6
|
+
title: 'Layouts/ResponsiveUI/TopBar/TopBarAction',
|
|
7
|
+
component: TopBarAction,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component: `
|
|
13
|
+
The **TopBarAction** component is a simple wrapper designed for placing interactive or visual elements (like icons, buttons, or toggles) inside the TopBar.
|
|
14
|
+
|
|
15
|
+
It standardizes alignment, spacing, and styling for small atomic actions in the top navigation area.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### 🧩 Features
|
|
20
|
+
- Wraps any ReactNode element inside a styled container.
|
|
21
|
+
- Accepts custom \`className\` and \`style\` props for styling flexibility.
|
|
22
|
+
- Commonly used to host action icons, buttons, or mini components in the TopBar.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
### ⚙️ Props
|
|
27
|
+
| Name | Type | Default | Description |
|
|
28
|
+
|------|------|----------|-------------|
|
|
29
|
+
| \`element\` | \`ReactNode\` | — | The element to render inside the TopBar action slot. |
|
|
30
|
+
| \`className?\` | \`string\` | — | Optional class name for extra styling. |
|
|
31
|
+
| \`style?\` | \`React.CSSProperties\` | — | Inline style overrides. |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
### 🧠 Behavior
|
|
36
|
+
TopBarAction is purely structural — it doesn’t manage state or events.
|
|
37
|
+
It ensures consistent alignment and padding so that icons or buttons within the TopBar remain visually balanced.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
### 🧩 Example Usage
|
|
42
|
+
|
|
43
|
+
#### React
|
|
44
|
+
~~~tsx
|
|
45
|
+
import TopBarAction from '@/gui/Layouts/TopBar/TopBarAction';
|
|
46
|
+
import Icon from '@/themes/Icon/Icon';
|
|
47
|
+
|
|
48
|
+
export const Example = () => (
|
|
49
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
50
|
+
<TopBarAction element={<Icon name="notifications" />} />
|
|
51
|
+
<TopBarAction element={<Icon name="settings" iconColor="#1976d2" />} />
|
|
52
|
+
<TopBarAction element={<button>Click me</button>} />
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
~~~
|
|
56
|
+
|
|
57
|
+
#### Declarative JSON
|
|
58
|
+
~~~json
|
|
59
|
+
{
|
|
60
|
+
"type": "TopBarAction",
|
|
61
|
+
"props": {
|
|
62
|
+
"element": {
|
|
63
|
+
"type": "Icon",
|
|
64
|
+
"props": { "name": "notifications" }
|
|
65
|
+
},
|
|
66
|
+
"style": { "marginRight": "8px" }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
~~~
|
|
70
|
+
`,
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export default meta;
|
|
77
|
+
type Story = StoryObj<typeof TopBarAction>;
|
|
78
|
+
|
|
79
|
+
export const Playground: Story = {
|
|
80
|
+
args: {
|
|
81
|
+
element: <Icon name="notifications" />,
|
|
82
|
+
},
|
|
83
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
|
|
4
|
+
export type TopBarActionProps = {
|
|
5
|
+
element: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: React.CSSProperties;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const TopBarAction: React.FC<TopBarActionProps> = ({ element, className, style }) => {
|
|
11
|
+
return (
|
|
12
|
+
<div className={clsx('TopBarAction', className)} style={style}>
|
|
13
|
+
{element}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default TopBarAction;
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ## TopBarLink Component
|
|
3
|
+
*
|
|
4
|
+
* `TopBarLink` represents an individual navigation link for the TopBar.
|
|
5
|
+
* It supports icons, color customization, and responsive label visibility.
|
|
6
|
+
*
|
|
7
|
+
* ---
|
|
8
|
+
*
|
|
9
|
+
* ### 🧩 Props
|
|
10
|
+
*
|
|
11
|
+
* | Prop | Type | Description |
|
|
12
|
+
* |---------------|-------------|-------------|
|
|
13
|
+
* | `label` | `string` | The text displayed next to the icon. |
|
|
14
|
+
* | `href` | `string` | The target URL or route. |
|
|
15
|
+
* | `icon` | `string?` | Optional icon name from the `Icon` component (Material Symbols). |
|
|
16
|
+
* | `iconColor` | `string?` | Optional custom color for the icon (defaults to `currentColor`). |
|
|
17
|
+
* | `external` | `boolean?` | If true, opens the link in a new tab (`target="_blank"`). |
|
|
18
|
+
* | `showLabel` | `boolean?` | Determines whether to show the label (used for responsive collapse). Defaults to `true`. |
|
|
19
|
+
*
|
|
20
|
+
* ---
|
|
21
|
+
*
|
|
22
|
+
* ### 💡 Responsive Behavior
|
|
23
|
+
*
|
|
24
|
+
* The `TopBarLink` component automatically adapts to screen size:
|
|
25
|
+
*
|
|
26
|
+
* | Viewport | Behavior |
|
|
27
|
+
* |-----------|-----------|
|
|
28
|
+
* | **Desktop (≥900px)** | Shows icon + label. |
|
|
29
|
+
* | **Tablet (600–899px)** | Shows only icons (`showLabel = false`). |
|
|
30
|
+
* | **Mobile (<600px)** | Collapsed within grouped menus (managed by `TopBar`). |
|
|
31
|
+
*
|
|
32
|
+
* In mobile view, individual `TopBarLink` components are typically grouped under a collapsed menu icon (such as `settings` or `more_horiz`), handled by the TopBar responsiveness system.
|
|
33
|
+
*
|
|
34
|
+
* ---
|
|
35
|
+
*
|
|
36
|
+
* ### 📘 Examples
|
|
37
|
+
* - `Basic` → Simple text link.
|
|
38
|
+
* - `WithIcon` → Link with an icon.
|
|
39
|
+
* - `IconOnly` → Icon-only mode (used for tablet responsiveness).
|
|
40
|
+
* - `ExternalLink` → Opens an external page in a new tab.
|
|
41
|
+
* - `ColoredIcon` → Example with custom icon color.
|
|
42
|
+
*/
|
|
43
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
44
|
+
import TopBarLink from './TopBarLink';
|
|
45
|
+
// ======================= Meta =======================
|
|
46
|
+
const meta: Meta<typeof TopBarLink> = {
|
|
47
|
+
title: 'Layouts/ResponsiveUI/TopBar/TopBarLink',
|
|
48
|
+
component: TopBarLink,
|
|
49
|
+
tags: ['autodocs'],
|
|
50
|
+
parameters: {
|
|
51
|
+
docs: {
|
|
52
|
+
description: {
|
|
53
|
+
component: `
|
|
54
|
+
The **TopBarLink** component represents an individual link or navigation item inside the TopBar.
|
|
55
|
+
It supports icons, color customization, and responsive label visibility.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Features
|
|
60
|
+
- Displays a **label**, **icon**, or both depending on viewport size.
|
|
61
|
+
- Automatically adapts to screen width through responsive breakpoints.
|
|
62
|
+
- External links open in a new tab when \`external = true\`.
|
|
63
|
+
- The label visibility can be controlled with the \`showLabel\` prop for tablet responsiveness.
|
|
64
|
+
- Works seamlessly with **TopBar** to handle desktop, tablet, and mobile layouts.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Responsiveness
|
|
69
|
+
The \`TopBarLink\` automatically adapts to viewport width using MUI's breakpoints:
|
|
70
|
+
|
|
71
|
+
| Viewport | Range | Behavior |
|
|
72
|
+
|-----------|--------|-----------|
|
|
73
|
+
| **Desktop** | ≥ 900px | Shows icon + label |
|
|
74
|
+
| **Tablet** | 600–899px | Shows icons only (label hidden) |
|
|
75
|
+
| **Mobile** | < 600px | Included in collapsed TopBar menu |
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Key Props
|
|
80
|
+
| Prop | Type | Description |
|
|
81
|
+
|------|------|-------------|
|
|
82
|
+
| \`label\` | \`string\` | The text shown beside the icon. |
|
|
83
|
+
| \`href\` | \`string\` | The URL or route the link navigates to. |
|
|
84
|
+
| \`icon\` | \`string\` | Material icon name. Optional. |
|
|
85
|
+
| \`iconColor\` | \`string\` | Custom icon color. Defaults to \`currentColor\`. |
|
|
86
|
+
| \`external\` | \`boolean\` | Opens the link in a new tab if true. |
|
|
87
|
+
| \`showLabel\` | \`boolean\` | Controls label visibility (used in responsive layouts). |
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### Basic usage (React)
|
|
92
|
+
~~~tsx
|
|
93
|
+
import TopBarLink from '@/gui/Layouts/TopBar/TopBarLink';
|
|
94
|
+
|
|
95
|
+
<TopBarLink label="Home" href="/" icon="home" />
|
|
96
|
+
~~~
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
### In a responsive TopBar
|
|
100
|
+
~~~tsx
|
|
101
|
+
<TopBar
|
|
102
|
+
title="neurons.me"
|
|
103
|
+
elementsRight={[
|
|
104
|
+
{ type: 'link', props: { label: 'Home', href: '/', icon: 'home' } },
|
|
105
|
+
{ type: 'link', props: { label: 'Settings', href: '/settings', icon: 'settings' } }
|
|
106
|
+
]}
|
|
107
|
+
/>
|
|
108
|
+
~~~
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Declarative JSON / Config usage
|
|
113
|
+
The **TopBarLink** can also be described declaratively within a resolver-driven UI definition.
|
|
114
|
+
|
|
115
|
+
### 🧩 Example usage
|
|
116
|
+
|
|
117
|
+
#### React
|
|
118
|
+
~~~tsx
|
|
119
|
+
import TopBarLink from '@/gui/Layouts/TopBar/TopBarLink';
|
|
120
|
+
|
|
121
|
+
export const Example = () => (
|
|
122
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
123
|
+
<TopBarLink label="Home" href="/" icon="home" />
|
|
124
|
+
<TopBarLink label="Profile" href="/profile" icon="person" />
|
|
125
|
+
<TopBarLink label="Settings" href="/settings" icon="settings" iconColor="#1976d2" />
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
~~~
|
|
129
|
+
|
|
130
|
+
#### Declarative JSON
|
|
131
|
+
~~~json
|
|
132
|
+
{
|
|
133
|
+
"type": "TopBar",
|
|
134
|
+
"props": {
|
|
135
|
+
"title": "neurons.me",
|
|
136
|
+
"elementsRight": [
|
|
137
|
+
{ "type": "TopBarLink", "props": { "label": "Home", "href": "/", "icon": "home" } },
|
|
138
|
+
{ "type": "TopBarLink", "props": { "label": "Profile", "href": "/profile", "icon": "person" } },
|
|
139
|
+
{ "type": "TopBarLink", "props": { "label": "Settings", "href": "/settings", "icon": "settings", "iconColor": "#1976d2" } }
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
~~~
|
|
144
|
+
`,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
argTypes: {
|
|
149
|
+
label: { control: 'text', description: 'Text label displayed next to the icon.' },
|
|
150
|
+
href: { control: 'text', description: 'URL or route target.' },
|
|
151
|
+
icon: { control: 'text', description: 'Material icon name (string).' },
|
|
152
|
+
iconColor: { control: 'color', description: 'Custom icon color.' },
|
|
153
|
+
external: { control: 'boolean', description: 'Open link in new tab if true.' },
|
|
154
|
+
showLabel: { control: 'boolean', description: 'Determines label visibility.' },
|
|
155
|
+
},
|
|
156
|
+
args: {
|
|
157
|
+
label: 'Home',
|
|
158
|
+
href: '/',
|
|
159
|
+
icon: 'home',
|
|
160
|
+
iconColor: 'currentColor',
|
|
161
|
+
external: false,
|
|
162
|
+
showLabel: true,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
export default meta;
|
|
167
|
+
|
|
168
|
+
type Story = StoryObj<typeof TopBarLink>;
|
|
169
|
+
|
|
170
|
+
// ======================= Stories =======================
|
|
171
|
+
export const Basic: Story = {
|
|
172
|
+
args: { label: 'Home', href: '/' },
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
export const WithIcon: Story = {
|
|
176
|
+
args: { label: 'Dashboard', href: '/dashboard', icon: 'dashboard' },
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const IconOnly: Story = {
|
|
180
|
+
args: { label: 'Profile', href: '/profile', icon: 'person', showLabel: false },
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
export const ExternalLink: Story = {
|
|
184
|
+
args: { label: 'GitHub', href: 'https://github.com', external: true, icon: 'code' },
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
export const ColoredIcon: Story = {
|
|
188
|
+
args: { label: 'Settings', href: '/settings', icon: 'settings', iconColor: '#1976d2' },
|
|
189
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Link from '@/gui/components/atoms/Link/Link'; // Adjust import path if necessary
|
|
3
|
+
import Icon from '@/gui/Theme/Icon/Icon'; // Import Icon component
|
|
4
|
+
import type { TopBarLinkProps } from './TopBarLink.types';
|
|
5
|
+
const TopBarLink: React.FC<TopBarLinkProps> = ({ label, href, icon, iconColor, external, showLabel = true }) => {
|
|
6
|
+
const content = (
|
|
7
|
+
<>
|
|
8
|
+
{icon && (
|
|
9
|
+
<Icon
|
|
10
|
+
name={icon}
|
|
11
|
+
iconColor={iconColor || 'currentColor'}
|
|
12
|
+
style={{ marginRight: 3, fontSize: 20, position: 'relative', top: -1 }}
|
|
13
|
+
/>
|
|
14
|
+
)}
|
|
15
|
+
{showLabel && <span>{label}</span>}
|
|
16
|
+
</>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Link
|
|
21
|
+
href={href ?? '#'}
|
|
22
|
+
target={external ? '_blank' : '_self'}
|
|
23
|
+
style={{ display: 'inline-flex', alignItems: 'center', color: 'inherit', textDecoration: 'none' }}
|
|
24
|
+
>
|
|
25
|
+
{content}
|
|
26
|
+
</Link>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default TopBarLink;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TopBarMenuResolverSpec } from './TopBarMenu.types';
|
|
2
|
+
|
|
3
|
+
const resolver: TopBarMenuResolverSpec = {
|
|
4
|
+
type: 'TopBarMenu',
|
|
5
|
+
props: {
|
|
6
|
+
label: 'Menu',
|
|
7
|
+
items: [
|
|
8
|
+
{ label: 'About', href: '/about' },
|
|
9
|
+
{ label: 'Contact', href: '/contact' },
|
|
10
|
+
],
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default resolver;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { Meta } from '@storybook/react';
|
|
2
|
+
import TopBarMenu from './TopBarMenu';
|
|
3
|
+
const meta: Meta<typeof TopBarMenu> = {
|
|
4
|
+
component: TopBarMenu,
|
|
5
|
+
title: 'Layouts/ResponsiveUI/TopBar/TopBarMenu',
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export default meta;
|
|
9
|
+
export const ReactUsage = () => (
|
|
10
|
+
<TopBarMenu
|
|
11
|
+
label="More"
|
|
12
|
+
items={[
|
|
13
|
+
{ label: 'About', href: '/about' },
|
|
14
|
+
{ label: 'Contact', href: '/contact' },
|
|
15
|
+
{ label: 'External', href: 'https://external.com', external: true },
|
|
16
|
+
]}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
export const DeclarativeUsage = {
|
|
21
|
+
type: 'menu',
|
|
22
|
+
props: {
|
|
23
|
+
label: 'More',
|
|
24
|
+
items: [
|
|
25
|
+
{ label: 'About', href: '/about' },
|
|
26
|
+
{ label: 'Contact', href: '/contact' },
|
|
27
|
+
{ label: 'External', href: 'https://external.com', external: true },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const NestedItemsExample = () => (
|
|
33
|
+
<TopBarMenu
|
|
34
|
+
label="Services"
|
|
35
|
+
items={[
|
|
36
|
+
{ label: 'Web Development', href: '/services/web' },
|
|
37
|
+
{
|
|
38
|
+
label: 'Design',
|
|
39
|
+
href: '/services/design',
|
|
40
|
+
items: [
|
|
41
|
+
{ label: 'UI Design', href: '/services/design/ui' },
|
|
42
|
+
{ label: 'UX Research', href: '/services/design/ux' },
|
|
43
|
+
{
|
|
44
|
+
label: 'Branding',
|
|
45
|
+
href: '/services/design/branding',
|
|
46
|
+
items: [
|
|
47
|
+
{ label: 'Logo Design', href: '/services/design/branding/logo' },
|
|
48
|
+
{ label: 'Identity Systems', href: '/services/design/branding/identity' },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{ label: 'Consulting', href: '/services/consulting' },
|
|
54
|
+
]}
|
|
55
|
+
/>
|
|
56
|
+
);
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import Icon from '@/gui/Theme/Icon/Icon';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import { Menu, MenuItem, Typography } from '@mui/material';
|
|
4
|
+
import Link from '@/gui/components/atoms/Link/Link';
|
|
5
|
+
import type { TopBarMenuProps, TopBarMenuItemProps } from './TopBarMenu.types';
|
|
6
|
+
|
|
7
|
+
const renderMenuItems = (
|
|
8
|
+
items: TopBarMenuItemProps[],
|
|
9
|
+
handleClose: () => void,
|
|
10
|
+
expandedItems: Set<string>,
|
|
11
|
+
toggleExpand: (label: string) => void
|
|
12
|
+
): React.ReactElement[] =>
|
|
13
|
+
items.map(({ label, href, icon, iconColor, external, items: subItems }) => {
|
|
14
|
+
const isExpanded = expandedItems.has(label);
|
|
15
|
+
|
|
16
|
+
const content = (
|
|
17
|
+
<Link
|
|
18
|
+
to={!external ? href : undefined}
|
|
19
|
+
href={external ? href : undefined}
|
|
20
|
+
target={external ? '_blank' : undefined}
|
|
21
|
+
style={{ display: 'inline-flex', alignItems: 'center', color: 'inherit', textDecoration: 'none', flexGrow: 1 }}
|
|
22
|
+
>
|
|
23
|
+
{icon && (
|
|
24
|
+
<Icon
|
|
25
|
+
name={typeof icon === 'string' ? icon : 'info'}
|
|
26
|
+
iconColor={iconColor || 'currentColor'}
|
|
27
|
+
style={{ marginRight: 2, fontSize: 20, position: 'relative', top: -1 }}
|
|
28
|
+
/>
|
|
29
|
+
)}
|
|
30
|
+
{label}
|
|
31
|
+
</Link>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
if (subItems && subItems.length > 0) {
|
|
35
|
+
return (
|
|
36
|
+
<React.Fragment key={label}>
|
|
37
|
+
<MenuItem
|
|
38
|
+
onClick={() => toggleExpand(label)}
|
|
39
|
+
sx={{ color: 'inherit', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}
|
|
40
|
+
>
|
|
41
|
+
{content}
|
|
42
|
+
<Icon
|
|
43
|
+
name={isExpanded ? 'expand_less' : 'expand_more'}
|
|
44
|
+
iconColor="currentColor"
|
|
45
|
+
style={{ fontSize: 20, position: 'relative', top: -1, marginLeft: 1 }}
|
|
46
|
+
/>
|
|
47
|
+
</MenuItem>
|
|
48
|
+
<div
|
|
49
|
+
style={{
|
|
50
|
+
maxHeight: isExpanded ? '500px' : '0px',
|
|
51
|
+
opacity: isExpanded ? 1 : 0,
|
|
52
|
+
overflow: 'hidden',
|
|
53
|
+
transition: 'max-height 0.2s ease-out, opacity 0.2s ease-out',
|
|
54
|
+
paddingLeft: 16,
|
|
55
|
+
}}
|
|
56
|
+
>
|
|
57
|
+
{renderMenuItems(subItems, handleClose, expandedItems, toggleExpand)}
|
|
58
|
+
</div>
|
|
59
|
+
</React.Fragment>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<MenuItem key={label} onClick={handleClose} sx={{ color: 'inherit' }}>
|
|
65
|
+
{content}
|
|
66
|
+
</MenuItem>
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const TopBarMenu: React.FC<TopBarMenuProps> = ({ label, icon, iconColor, items, showLabel = true }) => {
|
|
71
|
+
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
|
|
72
|
+
const [expandedItems, setExpandedItems] = useState<Set<string>>(new Set());
|
|
73
|
+
|
|
74
|
+
const handleOpen = (event: React.MouseEvent<HTMLElement>) => {
|
|
75
|
+
setAnchorEl(event.currentTarget);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const handleClose = () => {
|
|
79
|
+
setAnchorEl(null);
|
|
80
|
+
setExpandedItems(new Set());
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const toggleExpand = (label: string) => {
|
|
84
|
+
setExpandedItems(prev => {
|
|
85
|
+
const newSet = new Set(prev);
|
|
86
|
+
if (newSet.has(label)) {
|
|
87
|
+
newSet.delete(label);
|
|
88
|
+
} else {
|
|
89
|
+
newSet.add(label);
|
|
90
|
+
}
|
|
91
|
+
return newSet;
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<>
|
|
97
|
+
<Typography
|
|
98
|
+
onClick={handleOpen}
|
|
99
|
+
sx={{
|
|
100
|
+
cursor: 'pointer',
|
|
101
|
+
px: 1,
|
|
102
|
+
display: 'inline-flex',
|
|
103
|
+
alignItems: 'center',
|
|
104
|
+
color: 'inherit',
|
|
105
|
+
}}
|
|
106
|
+
>
|
|
107
|
+
{icon && (
|
|
108
|
+
<Icon
|
|
109
|
+
name={typeof icon === 'string' ? icon : 'info'}
|
|
110
|
+
iconColor={iconColor || 'currentColor'}
|
|
111
|
+
style={{ marginRight: showLabel ? 2 : 0, fontSize: 20, position: 'relative', top: -1 }}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
{showLabel && <span>{label}</span>}
|
|
115
|
+
</Typography>
|
|
116
|
+
<Menu anchorEl={anchorEl} open={Boolean(anchorEl)} onClose={handleClose} sx={{ color: 'inherit' }}>
|
|
117
|
+
{items && renderMenuItems(items, handleClose, expandedItems, toggleExpand)}
|
|
118
|
+
</Menu>
|
|
119
|
+
</>
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export default TopBarMenu;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export type TopBarMenuProps = {
|
|
4
|
+
label: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
iconColor?: string;
|
|
7
|
+
/** Whether to display the label next to the icon in the top-level menu trigger. Defaults to true. */
|
|
8
|
+
showLabel?: boolean;
|
|
9
|
+
items?: TopBarMenuItemProps[];
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type TopBarMenuItemProps = {
|
|
13
|
+
label: string;
|
|
14
|
+
href: string;
|
|
15
|
+
icon?: ReactNode;
|
|
16
|
+
iconColor?: string;
|
|
17
|
+
external?: boolean;
|
|
18
|
+
items?: TopBarMenuItemProps[];
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Note: The items property in TopBarMenuItemProps is added to support nested menu items if needed.
|
|
22
|
+
// This allows for multi-level dropdown menus in the TopBarMenu component.
|
|
23
|
+
// The iconColor property allows customization of each menu item’s icon color.
|
|
24
|
+
|
|
25
|
+
// Example usage:
|
|
26
|
+
// const menu: TopBarMenuProps = {
|
|
27
|
+
// label: 'Menu',
|
|
28
|
+
// icon: <MenuIcon />,
|
|
29
|
+
// items: [
|
|
30
|
+
// { label: 'Item 1', href: '/item1', icon: <Item1Icon /> },
|
|
31
|
+
// { label: 'Item 2', href: '/item2', icon: <Item2Icon />, items: [ // Nested items
|
|
32
|
+
// { label: 'Subitem 1', href: '/item2/subitem1' },
|
|
33
|
+
// { label: 'Subitem 2', href: '/item2/subitem2' },
|
|
34
|
+
// ] },
|
|
35
|
+
// ],
|
|
36
|
+
// };
|
|
37
|
+
// The above example shows how to define a menu with nested items using the updated types.
|
|
38
|
+
// The items property in TopBarMenuProps is optional, allowing for menus without dropdowns.
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
export type TopBarMenuItemResolverSpec = {
|
|
42
|
+
type: 'TopBarMenuItem';
|
|
43
|
+
props?: TopBarMenuItemProps;
|
|
44
|
+
};
|