{
+export const DialogDescription = ({ children, className, ...props }: DialogDescriptionProps) => {
return (
{children}
@@ -158,10 +148,7 @@ export interface DialogFooterProps extends React.HTMLAttributes
export const DialogFooter = ({ children, className, ...props }: DialogFooterProps) => {
return (
-
+
{children}
);
@@ -190,4 +177,3 @@ export const DialogClose = ({ onClose, className }: DialogCloseProps) => {
);
};
-
diff --git a/bugulma/frontend/components/ui/DropdownMenu.tsx b/bugulma/frontend/components/ui/DropdownMenu.tsx
index d0f0c15..846b9d0 100644
--- a/bugulma/frontend/components/ui/DropdownMenu.tsx
+++ b/bugulma/frontend/components/ui/DropdownMenu.tsx
@@ -1,6 +1,6 @@
-import React, { useEffect, useRef, useState } from 'react';
import { clsx } from 'clsx';
import { ChevronDown } from 'lucide-react';
+import React, { useEffect, useRef, useState } from 'react';
export interface DropdownMenuItem {
label: string;
@@ -11,6 +11,99 @@ export interface DropdownMenuItem {
onClick?: () => void;
}
+/**
+ * Composable Dropdown Menu Components
+ * These are alternative exports for a more flexible API
+ */
+
+export const DropdownMenuTrigger = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes
& { children: React.ReactNode }
+>(({ children, className, ...props }, ref) => {
+ return (
+
+ {children}
+
+ );
+});
+DropdownMenuTrigger.displayName = 'DropdownMenuTrigger';
+
+export const DropdownMenuContent = React.forwardRef<
+ HTMLDivElement,
+ React.HTMLAttributes & {
+ children: React.ReactNode;
+ align?: 'left' | 'right' | 'center' | 'start' | 'end';
+ className?: string;
+ }
+>(({ children, align = 'left', className, ...props }, ref) => {
+ const alignClasses = {
+ left: 'left-0',
+ right: 'right-0',
+ center: 'left-1/2 -translate-x-1/2',
+ start: 'left-0',
+ end: 'right-0',
+ };
+
+ return (
+
+ {children}
+
+ );
+});
+DropdownMenuContent.displayName = 'DropdownMenuContent';
+
+export const DropdownMenuItemComponent = React.forwardRef<
+ HTMLButtonElement,
+ React.ButtonHTMLAttributes & {
+ children: React.ReactNode;
+ disabled?: boolean;
+ className?: string;
+ }
+>(({ children, disabled, className, ...props }, ref) => {
+ return (
+
+ );
+});
+DropdownMenuItemComponent.displayName = 'DropdownMenuItem';
+
export interface DropdownMenuProps {
trigger: React.ReactNode;
items: DropdownMenuItem[];
@@ -99,11 +192,7 @@ export const DropdownMenu = ({
{isOpen && (
<>
- setIsOpen(false)}
- aria-hidden="true"
- />
+
setIsOpen(false)} aria-hidden="true" />
{
if (item.divider) {
return (
-
+
);
}
@@ -145,7 +230,7 @@ export const DropdownMenu = ({
)}
role="menuitem"
>
- {item.icon &&
{item.icon}}
+ {item.icon &&
{item.icon}}
{item.label}
);
@@ -198,7 +283,7 @@ export const SelectDropdown = ({
{selectedOption?.label || placeholder}
-
+
}
items={options.map((opt) => ({
@@ -213,3 +298,5 @@ export const SelectDropdown = ({
);
};
+// Export DropdownMenuItem as a named export for consistency
+export { DropdownMenuItemComponent as DropdownMenuItem };
diff --git a/bugulma/frontend/components/ui/EmptyState.tsx b/bugulma/frontend/components/ui/EmptyState.tsx
index 28355e6..778dfa1 100644
--- a/bugulma/frontend/components/ui/EmptyState.tsx
+++ b/bugulma/frontend/components/ui/EmptyState.tsx
@@ -64,9 +64,7 @@ export const EmptyState = ({
{displayIcon}
{displayTitle}
{displayDescription && (
-
- {displayDescription}
-
+
{displayDescription}
)}
{action && (
);
};
-
diff --git a/bugulma/frontend/components/ui/ErrorBoundary.tsx b/bugulma/frontend/components/ui/ErrorBoundary.tsx
index 378fedc..ebbfea5 100644
--- a/bugulma/frontend/components/ui/ErrorBoundary.tsx
+++ b/bugulma/frontend/components/ui/ErrorBoundary.tsx
@@ -40,7 +40,9 @@ class ErrorBoundary extends Component
{
Something went wrong
- We're sorry for the inconvenience. Please try refreshing the page.
+
+ We're sorry for the inconvenience. Please try refreshing the page.
+
{this.state.error?.message || 'An unknown error occurred'}
diff --git a/bugulma/frontend/components/ui/FormField.tsx b/bugulma/frontend/components/ui/FormField.tsx
index 26373d7..551b9c5 100644
--- a/bugulma/frontend/components/ui/FormField.tsx
+++ b/bugulma/frontend/components/ui/FormField.tsx
@@ -43,9 +43,7 @@ export const FormField = ({
{label}
)}
- {description && (
- {description}
- )}
+ {description && {description}
}
{React.isValidElement(children)
? React.cloneElement(children as React.ReactElement, {
@@ -67,4 +65,3 @@ export const FormField = ({
);
};
-
diff --git a/bugulma/frontend/components/ui/ImageGallery.tsx b/bugulma/frontend/components/ui/ImageGallery.tsx
index 0c61a1b..1fdc710 100644
--- a/bugulma/frontend/components/ui/ImageGallery.tsx
+++ b/bugulma/frontend/components/ui/ImageGallery.tsx
@@ -19,7 +19,7 @@ const ImageGallery: React.FC = ({
maxImages = 10,
className = '',
editable = false,
- title
+ title,
}) => {
const { t } = useTranslation();
const [selectedImageIndex, setSelectedImageIndex] = useState(null);
@@ -30,7 +30,7 @@ const ImageGallery: React.FC = ({
const newImages: string[] = [];
- Array.from(files).forEach(file => {
+ Array.from(files).forEach((file) => {
if (images.length + newImages.length >= maxImages) return;
const reader = new FileReader();
@@ -73,9 +73,7 @@ const ImageGallery: React.FC = ({
return (
- {title && (
-
{title}
- )}
+ {title &&
{title}
}
{images.map((image, index) => (
@@ -127,9 +125,7 @@ const ImageGallery: React.FC
= ({
);
};
-
diff --git a/bugulma/frontend/components/ui/PRIMITIVES_REVIEW.md b/bugulma/frontend/components/ui/PRIMITIVES_REVIEW.md
deleted file mode 100644
index f10c8e0..0000000
--- a/bugulma/frontend/components/ui/PRIMITIVES_REVIEW.md
+++ /dev/null
@@ -1,238 +0,0 @@
-# UI Primitives Review & Improvements
-
-## Summary
-
-Comprehensive review and enhancement of all UI primitive components for the admin panel and general use.
-
-## New Components Added
-
-### 1. **Accordion** (`Accordion.tsx`)
-- Expandable/collapsible sections
-- Support for multiple open items or single open
-- Default open state
-- Disabled state
-- **Use cases**: FAQ sections, settings panels, expandable content
-
-### 2. **Alert** (`Alert.tsx`)
-- Inline alert banners (different from Toast)
-- Variants: default, success, warning, error, info
-- Dismissible option
-- Icon support
-- **Use cases**: Form errors, inline notifications, status messages
-
-### 3. **Sheet/Drawer** (`Sheet.tsx`)
-- Side panel component
-- Positions: left, right, top, bottom
-- Sizes: sm, md, lg, xl, full
-- Full dialog functionality (focus trap, escape key)
-- **Use cases**: Settings panels, sidebars, mobile navigation
-
-### 4. **Popover** (`Popover.tsx`)
-- Contextual popup (different from Tooltip)
-- Controlled/uncontrolled modes
-- Positioning: top, bottom, left, right
-- Alignment: start, center, end
-- Modal option
-- **Use cases**: Context menus, additional info, action menus
-
-### 5. **CheckboxGroup** (`CheckboxGroup.tsx`)
-- Group of checkboxes
-- Horizontal/vertical orientation
-- Label and description support
-- Error state
-- **Use cases**: Multi-select filters, permissions, feature toggles
-
-### 6. **Combobox** (`Combobox.tsx`)
-- Autocomplete input
-- Search/filter functionality
-- Custom filter function support
-- Clear button option
-- **Use cases**: Searchable selects, autocomplete fields
-
-### 7. **Slider** (`Slider.tsx`)
-- Range input component
-- Value display option
-- Min/max labels
-- Custom styling
-- **Use cases**: Numeric ranges, volume controls, filters
-
-### 8. **Label** (`Label.tsx`)
-- Standalone label component
-- Required indicator
-- Error state
-- **Use cases**: Form labels, standalone labels
-
-### 9. **Kbd** (`Kbd.tsx`)
-- Keyboard shortcut display
-- Styled keyboard key representation
-- **Use cases**: Help text, keyboard shortcuts display
-
-## Improved Components
-
-### 1. **Dialog** - Enhanced
-- ✅ Added size variants: `sm`, `md`, `lg`, `xl`, `full`
-- Better responsive handling
-- More flexible sizing
-
-### 2. **Checkbox** - Enhanced
-- ✅ Added label and description support (like Switch)
-- Better accessibility
-- Consistent with other form components
-
-### 3. **Table** - Enhanced
-- ✅ Added loading state with skeleton
-- ✅ `isLoading` and `loadingRows` props
-- Better UX during data fetching
-
-## Component Status
-
-### ✅ Complete & Production Ready
-- Table (with loading states)
-- Dialog (with size variants)
-- Pagination
-- Breadcrumbs
-- Toast/Notifications
-- Switch
-- Progress
-- EmptyState
-- ConfirmDialog
-- SearchBar
-- StatusIndicator
-- Avatar
-- DropdownMenu
-- Tooltip
-- RadioGroup
-- FormField
-- Accordion ✨ NEW
-- Alert ✨ NEW
-- Sheet ✨ NEW
-- Popover ✨ NEW
-- CheckboxGroup ✨ NEW
-- Combobox ✨ NEW
-- Slider ✨ NEW
-- Label ✨ NEW
-- Kbd ✨ NEW
-- Checkbox (enhanced) ✨
-
-### Existing Components (Already Good)
-- Button
-- Input
-- Textarea
-- Select
-- Badge
-- Card
-- Tabs
-- Spinner
-- Skeleton
-- Separator
-- MultiSelect (exists, could be enhanced later)
-
-## Features Across All Components
-
-### ✅ Accessibility
-- ARIA labels and roles
-- Keyboard navigation
-- Focus management
-- Screen reader support
-
-### ✅ Responsiveness
-- Mobile-first design
-- Responsive breakpoints
-- Touch-friendly targets
-
-### ✅ Type Safety
-- Full TypeScript support
-- Proper prop types
-- Generic types where needed
-
-### ✅ Consistency
-- Unified design system
-- Consistent spacing
-- Theme-aware colors
-- Consistent animations
-
-### ✅ Performance
-- Memoization where needed
-- Efficient re-renders
-- Optimized event handlers
-
-## Usage Examples
-
-### Accordion
-```tsx
-Content },
- { id: '2', title: 'Section 2', content: More content
},
- ]}
- allowMultiple={false}
-/>
-```
-
-### Alert
-```tsx
- {}}
-/>
-```
-
-### Sheet
-```tsx
-
-
- Settings
-
- Content here
-
-```
-
-### Combobox
-```tsx
-
-```
-
-## Next Steps (Future Enhancements)
-
-1. **DatePicker** - Calendar component for date selection
-2. **TimePicker** - Time selection component
-3. **RichTextEditor** - WYSIWYG editor wrapper
-4. **FileUpload** - Enhanced file upload with drag & drop
-5. **FilterBar** - Advanced filtering component
-6. **CommandPalette** - Command menu (Cmd+K style)
-7. **DataTable** - Enhanced table with built-in pagination, sorting, filtering
-8. **TreeView** - Hierarchical data display
-9. **Stepper** - Multi-step wizard indicator
-10. **Timeline** - Timeline component (exists but could be enhanced)
-
-## Testing Checklist
-
-- [ ] All components render correctly
-- [ ] Accessibility tested with screen readers
-- [ ] Keyboard navigation works
-- [ ] Mobile responsiveness verified
-- [ ] Dark mode compatibility
-- [ ] TypeScript types are correct
-- [ ] No console errors
-- [ ] Performance is acceptable
-
-## Notes
-
-- All components follow the existing design patterns
-- Consistent with current codebase style
-- Production-ready with proper error handling
-- No technical debt introduced
-- Follows single responsibility principle
-- Clean, maintainable code
-
diff --git a/bugulma/frontend/components/ui/Pagination.tsx b/bugulma/frontend/components/ui/Pagination.tsx
index adb5501..3ccf297 100644
--- a/bugulma/frontend/components/ui/Pagination.tsx
+++ b/bugulma/frontend/components/ui/Pagination.tsx
@@ -156,4 +156,3 @@ export const Pagination = ({
);
};
-
diff --git a/bugulma/frontend/components/ui/Popover.tsx b/bugulma/frontend/components/ui/Popover.tsx
index f2911fc..4932629 100644
--- a/bugulma/frontend/components/ui/Popover.tsx
+++ b/bugulma/frontend/components/ui/Popover.tsx
@@ -99,11 +99,7 @@ export const Popover = ({
{open && (
<>
{modal && (
-
setOpen(false)}
- aria-hidden="true"
- />
+
setOpen(false)} aria-hidden="true" />
)}
);
};
-
diff --git a/bugulma/frontend/components/ui/PriceDisplay.tsx b/bugulma/frontend/components/ui/PriceDisplay.tsx
index 3e5e3e9..8dc0d93 100644
--- a/bugulma/frontend/components/ui/PriceDisplay.tsx
+++ b/bugulma/frontend/components/ui/PriceDisplay.tsx
@@ -90,4 +90,3 @@ export const PriceDisplay: React.FC
= ({
);
};
-
diff --git a/bugulma/frontend/components/ui/Progress.tsx b/bugulma/frontend/components/ui/Progress.tsx
index 300573d..3f72971 100644
--- a/bugulma/frontend/components/ui/Progress.tsx
+++ b/bugulma/frontend/components/ui/Progress.tsx
@@ -55,17 +55,10 @@ export const Progress = React.forwardRef(
{showLabel && (
Progress
-
- {Math.round(percentage)}%
-
+ {Math.round(percentage)}%
)}
-
+
(
}
);
Progress.displayName = 'Progress';
-
diff --git a/bugulma/frontend/components/ui/RadioGroup.tsx b/bugulma/frontend/components/ui/RadioGroup.tsx
index 2805d76..61bcc40 100644
--- a/bugulma/frontend/components/ui/RadioGroup.tsx
+++ b/bugulma/frontend/components/ui/RadioGroup.tsx
@@ -43,13 +43,9 @@ export const RadioGroup = ({
{options.map((option) => (