@gmoonc/ui
v0.0.2
Published
UI do Goalmoon Ctrl (gmoonc): shell e menu plugáveis para dashboards (React puro, SSR-safe).
Readme
@gmoonc/ui
Pluggable UI components for Goalmoon Ctrl (gmoonc): shell and menu for dashboards (pure React, SSR-safe).
Installation
npm install @gmoonc/uiCSS Import
Import the required CSS file:
import "@gmoonc/ui/styles.css";Basic Usage
import { defineConfig } from '@gmoonc/core';
import { GmooncShell } from '@gmoonc/ui';
import '@gmoonc/ui/styles.css';
const config = defineConfig({
appName: 'My Dashboard',
menu: [
{ id: 'home', label: 'Home', path: '/app' },
{
id: 'admin',
label: 'Admin',
path: '/app/admin',
roles: ['admin'],
submenu: [
{ id: 'admin-permissions', label: 'Permissions', path: '/app/admin/permissions' }
]
}
]
});
function App() {
return (
<GmooncShell
config={config}
roles={['admin']}
activePath="/app/admin/permissions"
onNavigate={(path) => {
// Your navigation logic here
console.log('Navigate to:', path);
}}
>
<div>Dashboard content</div>
</GmooncShell>
);
}Navigation Integration
@gmoonc/ui is framework-agnostic and doesn't depend on any specific routing system. You can integrate it with any framework using the onNavigate and/or renderLink props.
Using onNavigate
<GmooncShell
config={config}
onNavigate={(path) => {
// React Router
navigate(path);
// Next.js
router.push(path);
// Other system
window.location.href = path;
}}
/>Using renderLink
For full control over how links are rendered (e.g., React Router Link, Next.js Link):
import { Link } from 'react-router-dom';
<GmooncShell
config={config}
activePath={location.pathname}
renderLink={({ path, label, isActive, onClick }) => (
<Link
to={path}
onClick={onClick}
className={isActive ? 'active' : ''}
>
{label}
</Link>
)}
/>Menu Items with Icons
Menu items support optional icons (ReactNode). No default unicode icons are used:
import { Home, Settings } from 'lucide-react';
const config = defineConfig({
appName: 'My App',
menu: [
{
id: 'home',
label: 'Home',
path: '/app',
icon: <Home size={16} />
},
{
id: 'settings',
label: 'Settings',
path: '/app/settings',
icon: <Settings size={16} />,
submenu: [
{
id: 'settings-profile',
label: 'Profile',
path: '/app/settings/profile',
icon: <User size={16} />
}
]
}
]
});Active State
The menu automatically highlights active items based on activePath:
- Exact match:
activePath === item.path - Child route:
activePathstarts withitem.path + "/"
This ensures parent menu items are highlighted when viewing child pages.
Components
GmooncShell
Main component that combines header, sidebar, and menu.
Props:
config: GmooncConfig- App configuration (from@gmoonc/core)roles?: string[]- Current user roles for filtering menuactivePath?: string- Active path for highlighting menu itemonNavigate?: (path: string) => void- Callback when user clicks menu itemrenderLink?: (args) => React.ReactNode- Function to render custom linkschildren?: React.ReactNode- Main contentheaderRight?: React.ReactNode- Content for right side of headerlogoUrl?: string- Logo image URLlogoAlt?: string- Logo alt texttitleMobile?: string- Title for mobile view
GmooncMenu
Standalone menu component.
Props:
items: GmooncMenuItem[]- Array of menu itemsroles?: string[]- User roles for filteringactivePath?: string- Active path for highlightingonNavigate?: (path: string) => void- Navigation callbackrenderLink?: (args) => React.ReactNode- Custom link rendererisOpen?: boolean- Whether menu is open (mobile/tablet)onToggle?: () => void- Toggle menu callbackonLogoClick?: () => void- Logo click callbacklogoUrl?: string- Logo image URLlogoAlt?: string- Logo alt text
GmooncMenuItem Type
interface GmooncMenuItem {
id: string;
label: string;
path?: string;
icon?: React.ReactNode; // Optional icon (no default unicode icons)
roles?: string[]; // Roles required to see this item
submenu?: GmooncMenuItem[]; // Nested submenu
expandIcon?: React.ReactNode; // Optional icon for submenu expansion
collapseIcon?: React.ReactNode; // Optional icon for submenu collapse
}GmooncHeader
Standalone header component.
GmooncSidebar
Standalone sidebar component.
Role-Based Filtering
Menu items are automatically filtered based on user roles:
- Items without
rolesare visible to everyone - Items with
rolesare visible only if user has at least one matching role - Filtering is applied recursively to submenus
- Parent items without paths but with visible children appear as collapsible
SSR Safety
All components are SSR-safe and don't access browser APIs at the top level. Any access to window or document is done inside useEffect with appropriate checks.
Framework Agnostic
This package doesn't depend on:
- Next.js
- React Router
- Expo
- Any other specific framework
It's pure React and works in any React environment (including SSR).
License
MIT
