Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions app/explorer/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';

import { HyperwebExplorer } from '@hyperweb/explorer';
import { useTheme } from '@/hooks';

export default function ExplorerPage() {
const theme = useTheme();

return <HyperwebExplorer theme={theme} className='mt-4' />;
}
36 changes: 17 additions & 19 deletions app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'
import { Providers } from './providers'
import { DashboardLayout } from '@/components/dashboard-layout'
import type { Metadata } from 'next';
import { Inter } from 'next/font/google';
import './globals.css';
import { Providers } from './providers';
import { DashboardLayout } from '@/components/dashboard-layout';
import '@hyperweb/explorer/styles';
import '@hyperweb/playground/styles';
import '@hyperweb/playground/wallet-styles';
import { cn } from '@/lib/utils';

const inter = Inter({ subsets: ['latin'] })
const inter = Inter({ subsets: ['latin'] });

export const metadata: Metadata = {
title: 'Kubernetes Dashboard',
description: 'A modern dashboard for managing Kubernetes resources',
}
};

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body className={inter.className}>
<html lang='en'>
<body className={cn('overflow-hidden', inter.className)}>
<Providers>
<DashboardLayout>
{children}
</DashboardLayout>
<DashboardLayout>{children}</DashboardLayout>
</Providers>
</body>
</html>
)
}
);
}
10 changes: 10 additions & 0 deletions app/playground/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use client';

import { HyperwebPlayground } from '@hyperweb/playground';
import { useTheme } from '@/hooks';

export default function PlaygroundPage() {
const theme = useTheme();

return <HyperwebPlayground theme={theme} />;
}
306 changes: 205 additions & 101 deletions components/dashboard-layout.tsx

Large diffs are not rendered by default.

58 changes: 26 additions & 32 deletions components/ui/theme-toggle.tsx
Original file line number Diff line number Diff line change
@@ -1,53 +1,47 @@
'use client'
'use client';

import { useEffect, useState } from 'react'
import { Moon, Sun } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { useEffect, useState } from 'react';
import { Moon, Sun } from 'lucide-react';
import { Button } from '@/components/ui/button';

export function ThemeToggle() {
const [theme, setTheme] = useState<'light' | 'dark'>('light')
const [theme, setTheme] = useState<'light' | 'dark'>('light');

useEffect(() => {
// Check for saved theme preference or default to light
const savedTheme = localStorage.getItem('theme') || 'light'
setTheme(savedTheme as 'light' | 'dark')
const savedTheme = localStorage.getItem('theme') || 'light';
setTheme(savedTheme as 'light' | 'dark');

// Apply theme to document
if (savedTheme === 'dark') {
document.documentElement.classList.add('dark')
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark')
document.documentElement.classList.remove('dark');
}
}, [])
}, []);

const toggleTheme = () => {
const newTheme = theme === 'light' ? 'dark' : 'light'
setTheme(newTheme)
const newTheme = theme === 'light' ? 'dark' : 'light';
setTheme(newTheme);

// Save to localStorage
localStorage.setItem('theme', newTheme)
localStorage.setItem('theme', newTheme);

// Apply to document
if (newTheme === 'dark') {
document.documentElement.classList.add('dark')
document.documentElement.classList.add('dark');
} else {
document.documentElement.classList.remove('dark')
document.documentElement.classList.remove('dark');
}
}

// Dispatch custom event for same-tab listeners
window.dispatchEvent(new CustomEvent('theme-change'));
};

return (
<Button
variant="ghost"
size="icon"
onClick={toggleTheme}
className="w-9 h-9"
>
{theme === 'light' ? (
<Moon className="h-4 w-4" />
) : (
<Sun className="h-4 w-4" />
)}
<span className="sr-only">Toggle theme</span>
<Button variant='ghost' size='icon' onClick={toggleTheme} className='w-9 h-9'>
{theme === 'light' ? <Moon className='h-4 w-4' /> : <Sun className='h-4 w-4' />}
<span className='sr-only'>Toggle theme</span>
</Button>
)
);
}
19 changes: 10 additions & 9 deletions hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
// Export all hooks from a single entry point
export * from './useNamespaces'
export * from './useDeployments'
export * from './useServices'
export * from './useSecrets'
export * from './useConfigMaps'
export * from './usePods'
export * from './useDaemonSets'
export * from './useReplicaSets'
export * from './useConfirm'
export * from './useNamespaces';
export * from './useDeployments';
export * from './useServices';
export * from './useSecrets';
export * from './useConfigMaps';
export * from './usePods';
export * from './useDaemonSets';
export * from './useReplicaSets';
export * from './useConfirm';
export * from './useTheme';
36 changes: 36 additions & 0 deletions hooks/useTheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
'use client';

import { useEffect, useState } from 'react';

export type Theme = 'light' | 'dark';

export function useTheme() {
const [theme, setTheme] = useState<Theme>('light');

useEffect(() => {
// Check for saved theme preference or default to light
const savedTheme = (localStorage.getItem('theme') || 'light') as Theme;
setTheme(savedTheme);
}, []);

useEffect(() => {
// Listen for theme changes (from storage events or direct localStorage changes)
const handleThemeChange = () => {
const newTheme = (localStorage.getItem('theme') || 'light') as Theme;
setTheme(newTheme);
};

// Listen for storage events (changes from other tabs/windows)
window.addEventListener('storage', handleThemeChange);

// Listen for custom theme change events (changes from same tab)
window.addEventListener('theme-change', handleThemeChange);

return () => {
window.removeEventListener('storage', handleThemeChange);
window.removeEventListener('theme-change', handleThemeChange);
};
}, []);

return theme;
}
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"codegen": "ts-node ./scripts/codegen.ts"
},
"dependencies": {
"@hyperweb/explorer": "^0.0.1",
"@hyperweb/playground": "^0.0.2",
"@kubernetesjs/react": "^0.6.1",
"@monaco-editor/react": "^4.7.0",
"@radix-ui/react-dialog": "^1.0.5",
Expand All @@ -23,8 +25,8 @@
"clsx": "^2.1.0",
"js-yaml": "^4.1.0",
"kubernetesjs": "^0.6.1",
"lucide-react": "^0.314.0",
"next": "14.1.0",
"lucide-react": "^0.525.0",
"next": "15.2.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.22.3",
Expand Down
Loading