Skip to content

Instantly share code, notes, and snippets.

@shricodev
Last active January 18, 2026 15:40
Show Gist options
  • Select an option

  • Save shricodev/5403f82ea5cf5991c14bc43ce3f47476 to your computer and use it in GitHub Desktop.

Select an option

Save shricodev/5403f82ea5cf5991c14bc43ce3f47476 to your computer and use it in GitHub Desktop.
Test 1: Add a global Action Palette (Ctrl + K) - claude-opus-4.5
diff --git a/opus-4.5.patch b/opus-4.5.patch
new file mode 100644
index 0000000..9dfd197
--- /dev/null
+++ b/opus-4.5.patch
@@ -0,0 +1,72 @@
+diff --git a/src/components/App.tsx b/src/components/App.tsx
+index a578cc8..958747d 100644
+--- a/src/components/App.tsx
++++ b/src/components/App.tsx
+@@ -1,7 +1,7 @@
+ import { BrowserRouter, useRoutes } from 'react-router-dom';
+ import routesConfig from '../config/routesConfig';
+ import Navbar from './Navbar';
+-import { Suspense, useState, useEffect } from 'react';
++import { Suspense, useState, useEffect, useCallback } from 'react';
+ import Loading from './Loading';
+ import { CssBaseline, Theme, ThemeProvider } from '@mui/material';
+ import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
+@@ -13,6 +13,7 @@ import ScrollToTopButton from './ScrollToTopButton';
+ import { I18nextProvider } from 'react-i18next';
+ import i18n from '../i18n';
+ import { UserTypeFilterProvider } from 'providers/UserTypeFilterProvider';
++import ActionPalette from './ActionPalette';
+
+ export type Mode = 'dark' | 'light' | 'system';
+
+@@ -29,8 +30,28 @@ function App() {
+ () => (localStorage.getItem('theme') || 'system') as Mode
+ );
+ const [theme, setTheme] = useState<Theme>(() => getTheme(mode));
++ const [actionPaletteOpen, setActionPaletteOpen] = useState(false);
++
+ useEffect(() => setTheme(getTheme(mode)), [mode]);
+
++ // Global keyboard shortcut handler for Ctrl/Cmd + K
++ useEffect(() => {
++ const handleKeyDown = (e: KeyboardEvent) => {
++ if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
++ e.preventDefault();
++ setActionPaletteOpen(true);
++ }
++ };
++
++ window.addEventListener('keydown', handleKeyDown);
++ return () => window.removeEventListener('keydown', handleKeyDown);
++ }, []);
++
++ const handleChangeMode = useCallback(() => {
++ setMode((prev) => nextMode(prev));
++ localStorage.setItem('theme', nextMode(mode));
++ }, [mode]);
++
+ // Make sure to update the theme when the mode changes
+ useEffect(() => {
+ const systemDarkModeQuery = window.matchMedia(
+@@ -62,14 +83,17 @@ function App() {
+ <BrowserRouter>
+ <Navbar
+ mode={mode}
+- onChangeMode={() => {
+- setMode((prev) => nextMode(prev));
+- localStorage.setItem('theme', nextMode(mode));
+- }}
++ onChangeMode={handleChangeMode}
+ />
+ <Suspense fallback={<Loading />}>
+ <AppRoutes />
+ </Suspense>
++ <ActionPalette
++ open={actionPaletteOpen}
++ onClose={() => setActionPaletteOpen(false)}
++ mode={mode}
++ onChangeMode={handleChangeMode}
++ />
+ </BrowserRouter>
+ </UserTypeFilterProvider>
+ </CustomSnackBarProvider>
diff --git a/src/components/ActionPalette/ActionPalette.tsx b/src/components/ActionPalette/ActionPalette.tsx
new file mode 100644
index 0000000..eacdc72
--- /dev/null
+++ b/src/components/ActionPalette/ActionPalette.tsx
@@ -0,0 +1,528 @@
+import React, { useState, useEffect, useMemo, useCallback } from 'react';
+import {
+ Dialog,
+ DialogContent,
+ TextField,
+ List,
+ ListItem,
+ ListItemButton,
+ ListItemText,
+ ListItemIcon,
+ Typography,
+ Box,
+ Stack,
+ useTheme,
+ Chip,
+ Paper,
+ InputAdornment
+} from '@mui/material';
+import { Icon } from '@iconify/react';
+import { useNavigate } from 'react-router-dom';
+import { useTranslation } from 'react-i18next';
+import { tools } from '@tools/index';
+import { DefinedTool } from '@tools/defineTool';
+import { useUserTypeFilter } from 'providers/UserTypeFilterProvider';
+import { filterTools } from '@tools/index';
+import {
+ getBookmarkedToolPaths,
+ toggleBookmarked as toggleBookmark
+} from '@utils/bookmark';
+import { validNamespaces } from '../../i18n';
+
+type ActionType = 'tool' | 'action';
+
+interface Action {
+ id: string;
+ type: ActionType;
+ label: string;
+ description?: string;
+ icon: string;
+ category?: string;
+ keywords?: string[];
+ action?: () => void;
+ tool?: DefinedTool;
+}
+
+interface ActionPaletteProps {
+ open: boolean;
+ onClose: () => void;
+ mode: 'dark' | 'light' | 'system';
+ onChangeMode: () => void;
+}
+
+const ActionPalette: React.FC<ActionPaletteProps> = ({
+ open,
+ onClose,
+ mode,
+ onChangeMode
+}) => {
+ const { t, i18n } = useTranslation(validNamespaces);
+ const navigate = useNavigate();
+ const theme = useTheme();
+ const { selectedUserTypes, setSelectedUserTypes } = useUserTypeFilter();
+ const [searchQuery, setSearchQuery] = useState('');
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const [bookmarkedPaths, setBookmarkedPaths] = useState<string[]>([]);
+
+ // Load bookmarked paths
+ useEffect(() => {
+ if (open) {
+ setBookmarkedPaths(getBookmarkedToolPaths());
+ }
+ }, [open]);
+
+ // Reset state when opening
+ useEffect(() => {
+ if (open) {
+ setSearchQuery('');
+ setSelectedIndex(0);
+ }
+ }, [open]);
+
+ const getModeIcon = () => {
+ switch (mode) {
+ case 'dark':
+ return 'mdi:weather-night';
+ case 'light':
+ return 'mdi:weather-sunny';
+ default:
+ return 'mdi:laptop';
+ }
+ };
+
+ const getModeLabel = () => {
+ switch (mode) {
+ case 'dark':
+ return 'Dark Mode';
+ case 'light':
+ return 'Light Mode';
+ default:
+ return 'System Mode';
+ }
+ };
+
+ // Build all available actions
+ const allActions = useMemo(() => {
+ const actions: Action[] = [];
+
+ // Add tool navigation actions
+ const filteredTools = filterTools(tools, '', selectedUserTypes, t);
+ filteredTools.forEach((tool) => {
+ actions.push({
+ id: `tool-${tool.path}`,
+ type: 'tool',
+ label: t(tool.name),
+ description: t(tool.shortDescription),
+ icon: typeof tool.icon === 'string' ? tool.icon : 'mdi:tools',
+ category: 'Tools',
+ keywords: tool.keywords,
+ tool
+ });
+ });
+
+ // Add system actions
+ actions.push({
+ id: 'toggle-theme',
+ type: 'action',
+ label: `Toggle Theme (Current: ${getModeLabel()})`,
+ description: 'Switch between light, dark, and system theme',
+ icon: getModeIcon(),
+ category: 'Settings',
+ keywords: ['theme', 'dark', 'light', 'mode', 'appearance'],
+ action: onChangeMode
+ });
+
+ // Add language switch actions
+ const languages = [
+ { code: 'en', label: 'English' },
+ { code: 'de', label: 'Deutsch' },
+ { code: 'es', label: 'Español' },
+ { code: 'fr', label: 'Français' },
+ { code: 'pt', label: 'Português' },
+ { code: 'ja', label: '日本語' },
+ { code: 'hi', label: 'हिंदी' },
+ { code: 'nl', label: 'Nederlands' },
+ { code: 'ru', label: 'Русский' },
+ { code: 'zh', label: '中文' }
+ ];
+
+ languages.forEach((lang) => {
+ actions.push({
+ id: `lang-${lang.code}`,
+ type: 'action',
+ label: `Switch to ${lang.label}`,
+ description:
+ i18n.language === lang.code ? 'Currently active' : undefined,
+ icon: 'mdi:translate',
+ category: 'Language',
+ keywords: [
+ 'language',
+ 'translate',
+ lang.label.toLowerCase(),
+ lang.code
+ ],
+ action: () => {
+ i18n.changeLanguage(lang.code);
+ localStorage.setItem('lang', lang.code);
+ }
+ });
+ });
+
+ // User type filter actions
+ actions.push({
+ id: 'toggle-general-user',
+ type: 'action',
+ label: `${
+ selectedUserTypes.includes('generalUsers') ? 'Hide' : 'Show'
+ } General User Tools`,
+ description: 'Toggle visibility of general user tools',
+ icon: 'mdi:account',
+ category: 'Filters',
+ keywords: ['filter', 'user', 'general', 'toggle'],
+ action: () => {
+ if (selectedUserTypes.includes('generalUsers')) {
+ setSelectedUserTypes(
+ selectedUserTypes.filter((t) => t !== 'generalUsers')
+ );
+ } else {
+ setSelectedUserTypes([...selectedUserTypes, 'generalUsers']);
+ }
+ }
+ });
+
+ actions.push({
+ id: 'toggle-developer',
+ type: 'action',
+ label: `${
+ selectedUserTypes.includes('developers') ? 'Hide' : 'Show'
+ } Developer Tools`,
+ description: 'Toggle visibility of developer tools',
+ icon: 'mdi:code-braces',
+ category: 'Filters',
+ keywords: ['filter', 'developer', 'dev', 'toggle'],
+ action: () => {
+ if (selectedUserTypes.includes('developers')) {
+ setSelectedUserTypes(
+ selectedUserTypes.filter((t) => t !== 'developers')
+ );
+ } else {
+ setSelectedUserTypes([...selectedUserTypes, 'developers']);
+ }
+ }
+ });
+
+ // Navigation actions
+ actions.push({
+ id: 'go-home',
+ type: 'action',
+ label: 'Go to Home',
+ description: 'Navigate to the home page',
+ icon: 'mdi:home',
+ category: 'Navigation',
+ keywords: ['home', 'main', 'start', 'navigate'],
+ action: () => {
+ navigate('/');
+ onClose();
+ }
+ });
+
+ // Bookmarks action
+ if (bookmarkedPaths.length > 0) {
+ actions.push({
+ id: 'view-bookmarks',
+ type: 'action',
+ label: 'View Bookmarked Tools',
+ description: `You have ${bookmarkedPaths.length} bookmarked tool${
+ bookmarkedPaths.length > 1 ? 's' : ''
+ }`,
+ icon: 'mdi:bookmark',
+ category: 'Navigation',
+ keywords: ['bookmark', 'favorites', 'saved'],
+ action: () => {
+ navigate('/');
+ onClose();
+ }
+ });
+
+ actions.push({
+ id: 'clear-bookmarks',
+ type: 'action',
+ label: 'Clear All Bookmarks',
+ description: 'Remove all bookmarked tools',
+ icon: 'mdi:bookmark-remove',
+ category: 'Navigation',
+ keywords: ['bookmark', 'clear', 'remove', 'delete'],
+ action: () => {
+ localStorage.removeItem('bookmarkedTools');
+ setBookmarkedPaths([]);
+ }
+ });
+ }
+
+ return actions;
+ }, [
+ selectedUserTypes,
+ t,
+ i18n,
+ mode,
+ navigate,
+ onChangeMode,
+ setSelectedUserTypes,
+ bookmarkedPaths,
+ onClose
+ ]);
+
+ // Filter actions based on search query
+ const filteredActions = useMemo(() => {
+ if (!searchQuery.trim()) {
+ return allActions;
+ }
+
+ const query = searchQuery.toLowerCase();
+ return allActions.filter((action) => {
+ // Check label
+ if (action.label.toLowerCase().includes(query)) return true;
+ // Check description
+ if (action.description?.toLowerCase().includes(query)) return true;
+ // Check category
+ if (action.category?.toLowerCase().includes(query)) return true;
+ // Check keywords
+ if (action.keywords?.some((k) => k.toLowerCase().includes(query)))
+ return true;
+ return false;
+ });
+ }, [allActions, searchQuery]);
+
+ // Group actions by category
+ const groupedActions = useMemo(() => {
+ const groups: Record<string, Action[]> = {};
+ filteredActions.forEach((action) => {
+ const category = action.category || 'Other';
+ if (!groups[category]) {
+ groups[category] = [];
+ }
+ groups[category].push(action);
+ });
+ return groups;
+ }, [filteredActions]);
+
+ // Flatten actions for keyboard navigation
+ const flatActions = useMemo(() => {
+ return Object.values(groupedActions).flat();
+ }, [groupedActions]);
+
+ // Keyboard navigation
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if (!open) return;
+
+ switch (e.key) {
+ case 'ArrowDown':
+ e.preventDefault();
+ setSelectedIndex((prev) =>
+ prev < flatActions.length - 1 ? prev + 1 : 0
+ );
+ break;
+ case 'ArrowUp':
+ e.preventDefault();
+ setSelectedIndex((prev) =>
+ prev > 0 ? prev - 1 : flatActions.length - 1
+ );
+ break;
+ case 'Enter':
+ e.preventDefault();
+ if (flatActions[selectedIndex]) {
+ executeAction(flatActions[selectedIndex]);
+ }
+ break;
+ case 'Escape':
+ e.preventDefault();
+ onClose();
+ break;
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
+ }, [open, selectedIndex, flatActions, onClose]);
+
+ const executeAction = useCallback(
+ (action: Action) => {
+ if (action.type === 'tool' && action.tool) {
+ navigate('/' + action.tool.path);
+ onClose();
+ } else if (action.type === 'action' && action.action) {
+ action.action();
+ // Only close for navigation actions
+ if (action.id.startsWith('go-') || action.id === 'view-bookmarks') {
+ onClose();
+ }
+ }
+ },
+ [navigate, onClose]
+ );
+
+ // Reset selected index when search changes
+ useEffect(() => {
+ setSelectedIndex(0);
+ }, [searchQuery]);
+
+ // Scroll selected item into view
+ useEffect(() => {
+ if (open) {
+ const element = document.getElementById(`action-item-${selectedIndex}`);
+ element?.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
+ }
+ }, [selectedIndex, open]);
+
+ return (
+ <Dialog
+ open={open}
+ onClose={onClose}
+ maxWidth="md"
+ fullWidth
+ PaperProps={{
+ sx: {
+ position: 'fixed',
+ top: '20%',
+ transform: 'translateY(-20%)',
+ maxHeight: '60vh',
+ borderRadius: 2
+ }
+ }}
+ >
+ <DialogContent sx={{ p: 0, display: 'flex', flexDirection: 'column' }}>
+ <Box sx={{ p: 2, borderBottom: 1, borderColor: 'divider' }}>
+ <TextField
+ fullWidth
+ autoFocus
+ placeholder="Search for tools and actions..."
+ value={searchQuery}
+ onChange={(e) => setSearchQuery(e.target.value)}
+ InputProps={{
+ startAdornment: (
+ <InputAdornment position="start">
+ <Icon icon="mdi:magnify" />
+ </InputAdornment>
+ ),
+ endAdornment: (
+ <InputAdornment position="end">
+ <Stack direction="row" spacing={0.5}>
+ <Chip
+ size="small"
+ label="↑↓"
+ variant="outlined"
+ sx={{ fontSize: '0.7rem' }}
+ />
+ <Chip
+ size="small"
+ label="Enter"
+ variant="outlined"
+ sx={{ fontSize: '0.7rem' }}
+ />
+ <Chip
+ size="small"
+ label="Esc"
+ variant="outlined"
+ sx={{ fontSize: '0.7rem' }}
+ />
+ </Stack>
+ </InputAdornment>
+ ),
+ sx: {
+ '& .MuiOutlinedInput-notchedOutline': { border: 'none' }
+ }
+ }}
+ />
+ </Box>
+
+ <Box sx={{ flexGrow: 1, overflowY: 'auto' }}>
+ {Object.entries(groupedActions).length === 0 ? (
+ <Box sx={{ p: 3, textAlign: 'center' }}>
+ <Typography variant="body2" color="text.secondary">
+ No results found for "{searchQuery}"
+ </Typography>
+ </Box>
+ ) : (
+ <List sx={{ py: 0 }}>
+ {Object.entries(groupedActions).map(
+ ([category, actions], categoryIndex) => (
+ <React.Fragment key={category}>
+ <Box
+ sx={{
+ px: 2,
+ py: 0.5,
+ backgroundColor: 'action.hover',
+ position: 'sticky',
+ top: 0,
+ zIndex: 1
+ }}
+ >
+ <Typography
+ variant="caption"
+ color="text.secondary"
+ fontWeight="bold"
+ >
+ {category.toUpperCase()}
+ </Typography>
+ </Box>
+ {actions.map((action, actionIndex) => {
+ const globalIndex =
+ Object.values(groupedActions)
+ .slice(0, categoryIndex)
+ .reduce((acc, arr) => acc + arr.length, 0) +
+ actionIndex;
+
+ return (
+ <ListItem
+ key={action.id}
+ id={`action-item-${globalIndex}`}
+ disablePadding
+ sx={{
+ backgroundColor:
+ selectedIndex === globalIndex
+ ? 'action.selected'
+ : 'transparent'
+ }}
+ >
+ <ListItemButton
+ onClick={() => executeAction(action)}
+ onMouseEnter={() => setSelectedIndex(globalIndex)}
+ >
+ <ListItemIcon sx={{ minWidth: 36 }}>
+ <Icon icon={action.icon} fontSize={20} />
+ </ListItemIcon>
+ <ListItemText
+ primary={action.label}
+ secondary={action.description}
+ primaryTypographyProps={{
+ fontSize: '0.9rem'
+ }}
+ secondaryTypographyProps={{
+ fontSize: '0.75rem'
+ }}
+ />
+ {action.type === 'tool' && (
+ <Chip
+ size="small"
+ label="Tool"
+ variant="outlined"
+ sx={{ ml: 1 }}
+ />
+ )}
+ </ListItemButton>
+ </ListItem>
+ );
+ })}
+ </React.Fragment>
+ )
+ )}
+ </List>
+ )}
+ </Box>
+ </DialogContent>
+ </Dialog>
+ );
+};
+
+export default ActionPalette;
diff --git a/src/components/ActionPalette/index.ts b/src/components/ActionPalette/index.ts
new file mode 100644
index 0000000..ca94a8a
--- /dev/null
+++ b/src/components/ActionPalette/index.ts
@@ -0,0 +1 @@
+export { default } from './ActionPalette';
diff --git a/src/components/App.tsx b/src/components/App.tsx
index a578cc8..889442d 100644
--- a/src/components/App.tsx
+++ b/src/components/App.tsx
@@ -1,7 +1,7 @@
import { BrowserRouter, useRoutes } from 'react-router-dom';
import routesConfig from '../config/routesConfig';
import Navbar from './Navbar';
-import { Suspense, useState, useEffect } from 'react';
+import { Suspense, useState, useEffect, useCallback } from 'react';
import Loading from './Loading';
import { CssBaseline, Theme, ThemeProvider } from '@mui/material';
import { CustomSnackBarProvider } from '../contexts/CustomSnackBarContext';
@@ -13,6 +13,7 @@ import ScrollToTopButton from './ScrollToTopButton';
import { I18nextProvider } from 'react-i18next';
import i18n from '../i18n';
import { UserTypeFilterProvider } from 'providers/UserTypeFilterProvider';
+import ActionPalette from './ActionPalette';
export type Mode = 'dark' | 'light' | 'system';
@@ -29,8 +30,28 @@ function App() {
() => (localStorage.getItem('theme') || 'system') as Mode
);
const [theme, setTheme] = useState<Theme>(() => getTheme(mode));
+ const [actionPaletteOpen, setActionPaletteOpen] = useState(false);
+
useEffect(() => setTheme(getTheme(mode)), [mode]);
+ // Global keyboard shortcut handler for Ctrl/Cmd + K
+ useEffect(() => {
+ const handleKeyDown = (e: KeyboardEvent) => {
+ if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
+ e.preventDefault();
+ setActionPaletteOpen(true);
+ }
+ };
+
+ window.addEventListener('keydown', handleKeyDown);
+ return () => window.removeEventListener('keydown', handleKeyDown);
+ }, []);
+
+ const handleChangeMode = useCallback(() => {
+ setMode((prev) => nextMode(prev));
+ localStorage.setItem('theme', nextMode(mode));
+ }, [mode]);
+
// Make sure to update the theme when the mode changes
useEffect(() => {
const systemDarkModeQuery = window.matchMedia(
@@ -60,16 +81,16 @@ function App() {
<CustomSnackBarProvider>
<UserTypeFilterProvider>
<BrowserRouter>
- <Navbar
- mode={mode}
- onChangeMode={() => {
- setMode((prev) => nextMode(prev));
- localStorage.setItem('theme', nextMode(mode));
- }}
- />
+ <Navbar mode={mode} onChangeMode={handleChangeMode} />
<Suspense fallback={<Loading />}>
<AppRoutes />
</Suspense>
+ <ActionPalette
+ open={actionPaletteOpen}
+ onClose={() => setActionPaletteOpen(false)}
+ mode={mode}
+ onChangeMode={handleChangeMode}
+ />
</BrowserRouter>
</UserTypeFilterProvider>
</CustomSnackBarProvider>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment