([])
-
- useEffect(() => {
- loadDynamicDropdowns()
- }, [])
-
- const loadDynamicDropdowns = async () => {
- const dropdowns = await Database.getDropdownConfigs()
- setDynamicDropdowns(dropdowns)
- }
-
- if (!component) {
- return (
-
-
Select a component to edit its properties
-
- )
- }
-
- const componentDef = componentCatalog.find(c => c.type === component.type)
-
- const handlePropChange = (propName: string, value: JsonValue) => {
- onUpdate(component.id, {
- ...component.props,
- [propName]: value,
- })
- }
-
- const openCssBuilder = (propName: string) => {
- setCssBuilderPropName(propName)
- setCssBuilderOpen(true)
- }
-
- const handleCssClassSave = (classes: string) => {
- handlePropChange(cssBuilderPropName, classes)
- setCssBuilderOpen(false)
- }
-
- return (
-
-
-
{component.type}
-
Component Properties
-
-
-
-
-
-
-
-
-
-
-
setCssBuilderOpen(false)}
- initialValue={
- typeof component.props[cssBuilderPropName] === 'string'
- ? component.props[cssBuilderPropName]
- : ''
- }
- onSave={handleCssClassSave}
- />
-
- )
-}
diff --git a/frontends/nextjs/src/components/rendering/RenderComponent.tsx b/frontends/nextjs/src/components/rendering/RenderComponent.tsx
deleted file mode 100644
index 13fa9f15e..000000000
--- a/frontends/nextjs/src/components/rendering/RenderComponent.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-import type React from 'react'
-
-import type { User } from '@/lib/level-types'
-import type { ComponentInstance } from '@/lib/types/builder-types'
-
-import { RenderNode } from './components/RenderNode'
-
-interface RenderComponentProps {
- component: ComponentInstance
- isSelected: boolean
- onSelect: (id: string) => void
- user?: User
-}
-
-export function RenderComponent({ component, isSelected, onSelect, user }: RenderComponentProps) {
- const handleClick = (e: React.MouseEvent) => {
- e.stopPropagation()
- onSelect(component.id)
- }
-
- const renderChildren = () => {
- if (component.children.length === 0) return null
- return component.children.map(child => (
-
- ))
- }
-
- const wrapperClass = `relative ${isSelected ? 'ring-2 ring-accent ring-offset-2' : 'hover:ring-1 hover:ring-accent/50'} transition-all cursor-pointer`
-
- return (
-
-
-
- )
-}
diff --git a/frontends/nextjs/src/components/rendering/components/FieldTypes.tsx b/frontends/nextjs/src/components/rendering/components/FieldTypes.tsx
deleted file mode 100644
index 5ddee243d..000000000
--- a/frontends/nextjs/src/components/rendering/components/FieldTypes.tsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import {
- Button,
- Input,
- Label,
- Select,
- SelectContent,
- SelectItem,
- SelectTrigger,
- SelectValue,
-} from '@/components/ui'
-import { Palette } from '@/fakemui/icons'
-import type { DropdownConfig } from '@/lib/database'
-import type { PropDefinition } from '@/lib/types/builder-types'
-import type { JsonValue } from '@/types/utility-types'
-
-interface FieldTypesProps {
- propDef: PropDefinition
- value: JsonValue
- onChange: (value: JsonValue) => void
- dynamicDropdown?: DropdownConfig | null
- onOpenCssBuilder?: () => void
-}
-
-export function FieldTypes({
- propDef,
- value,
- onChange,
- dynamicDropdown,
- onOpenCssBuilder,
-}: FieldTypesProps) {
- const renderInputByType = () => {
- if (propDef.name === 'className') {
- return (
-
-
onChange(e.target.value)}
- className="flex-1 font-mono text-xs"
- />
- {onOpenCssBuilder && (
-
- )}
-
- )
- }
-
- switch (propDef.type) {
- case 'string':
- return onChange(e.target.value)} />
- case 'number':
- return (
- onChange(Number(e.target.value))}
- />
- )
- case 'boolean':
- return (
-
- )
- case 'select': {
- const selectValue =
- typeof value === 'string'
- ? value
- : typeof propDef.defaultValue === 'string'
- ? propDef.defaultValue
- : ''
- return (
-
- )
- }
- case 'dynamic-select':
- return (
-
- )
- default:
- return null
- }
- }
-
- return (
-
-
- {renderInputByType()}
- {propDef.description && (
-
{propDef.description}
- )}
-
- )
-}
diff --git a/frontends/nextjs/src/components/rendering/components/PropertyPanels.tsx b/frontends/nextjs/src/components/rendering/components/PropertyPanels.tsx
deleted file mode 100644
index 05f7f3c7d..000000000
--- a/frontends/nextjs/src/components/rendering/components/PropertyPanels.tsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import { Button, ScrollArea, Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui'
-import { Code, PaintBrush } from '@/fakemui/icons'
-import type { DropdownConfig } from '@/lib/database'
-import type { ComponentDefinition, ComponentInstance } from '@/lib/types/builder-types'
-import type { JsonValue } from '@/types/utility-types'
-
-import { FieldTypes } from './FieldTypes'
-
-interface PropertyPanelsProps {
- component: ComponentInstance
- componentDef?: ComponentDefinition
- dynamicDropdowns: DropdownConfig[]
- onPropChange: (propName: string, value: JsonValue) => void
- onCodeEdit: () => void
- onOpenCssBuilder: (propName: string) => void
-}
-
-export function PropertyPanels({
- component,
- componentDef,
- dynamicDropdowns,
- onPropChange,
- onCodeEdit,
- onOpenCssBuilder,
-}: PropertyPanelsProps) {
- return (
-
-
-
-
- Props
-
-
-
- Code
-
-
-
-
-
-
- {componentDef?.propSchema?.length ? (
- componentDef.propSchema.map(propDef => {
- const dynamicDropdown =
- propDef.type === 'dynamic-select'
- ? dynamicDropdowns.find(d => d.name === propDef.dynamicSource)
- : null
-
- return (
-
onPropChange(propDef.name, value)}
- dynamicDropdown={dynamicDropdown}
- onOpenCssBuilder={() => onOpenCssBuilder(propDef.name)}
- />
- )
- })
- ) : (
-
- This component has no configurable properties.
-
- )}
-
-
-
-
-
-
-
-
-
- Add custom JavaScript code for this component
-
-
-
-
-
-
- )
-}
diff --git a/frontends/nextjs/src/components/rendering/components/RenderNode.tsx b/frontends/nextjs/src/components/rendering/components/RenderNode.tsx
deleted file mode 100644
index 03cf103ef..000000000
--- a/frontends/nextjs/src/components/rendering/components/RenderNode.tsx
+++ /dev/null
@@ -1,163 +0,0 @@
-import type React from 'react'
-
-import {
- Alert,
- Avatar,
- AvatarFallback,
- Badge,
- Button,
- Card,
- Checkbox,
- Input,
- Label,
- Progress,
- Separator,
- Slider,
- Switch,
- Table,
- TableBody,
- TableCell,
- TableHead,
- TableHeader,
- TableRow,
- Textarea,
-} from '@/components/ui'
-import { getDeclarativeRenderer } from '@/lib/declarative-component-renderer'
-import type { User } from '@/lib/level-types'
-import type { ComponentInstance } from '@/lib/types/builder-types'
-
-interface RenderNodeProps {
- component: ComponentInstance
- renderChildren: () => React.ReactNode
- user?: User
-}
-
-export function RenderNode({ component, renderChildren, user }: RenderNodeProps) {
- const { type, props } = component
- const renderer = getDeclarativeRenderer()
-
- if (renderer.hasComponentConfig(type)) {
- return (
-
- Lua Package Component: {type}
-
- This component is rendered from a Lua package
-
-
- )
- }
-
- switch (type) {
- case 'Container':
- return {renderChildren()}
-
- case 'Flex':
- return {renderChildren()}
-
- case 'Grid':
- return {renderChildren()}
-
- case 'Stack':
- return {renderChildren()}
-
- case 'Card':
- return {renderChildren()}
-
- case 'NotificationSummary':
- // Now handled via Lua package notification_center
- return (
-
- Lua Package Component: NotificationSummary
-
- Migrated to packages/notification_center
-
-
- )
-
- case 'Button':
- return (
-
- )
-
- case 'Input':
- return
-
- case 'Textarea':
- return
-
- case 'Label':
- return
-
- case 'Heading': {
- const level = props.level || '1'
- const className = props.className
- const text = props.children || 'Heading'
-
- if (level === '1') return {text}
- if (level === '2') return {text}
- if (level === '3') return {text}
- if (level === '4') return {text}
- return {text}
- }
-
- case 'Text':
- return {props.children || 'Text'}
-
- case 'Badge':
- return {props.children || 'Badge'}
-
- case 'Switch':
- return
-
- case 'Checkbox':
- return
-
- case 'Separator':
- return
-
- case 'Alert':
- return {renderChildren()}
-
- case 'Progress':
- return
-
- case 'Slider':
- return (
-
- )
-
- case 'Avatar':
- return (
-
- U
-
- )
-
- case 'Table':
- return (
-
-
-
- Column 1
- Column 2
-
-
-
-
- Data 1
- Data 2
-
-
-
- )
-
- default:
- return Unknown Component: {type}
- }
-}
diff --git a/frontends/nextjs/src/components/ui/README.md b/frontends/nextjs/src/components/ui/README.md
deleted file mode 100644
index 1cfdbe9d1..000000000
--- a/frontends/nextjs/src/components/ui/README.md
+++ /dev/null
@@ -1,99 +0,0 @@
-# UI Components Directory
-
-## โ ๏ธ IMPORTANT: This project uses fakemui, NOT Material-UI or Radix UI
-
-This directory uses **fakemui** (our custom UI library), organized with **Atomic Design** principles.
-
-## Directory Structure
-
-```
-ui/
-โโโ atoms/ # Basic building blocks
-โ โโโ Button.tsx
-โ โโโ Input.tsx
-โ โโโ Checkbox.tsx
-โ โโโ ...
-โโโ molecules/ # Simple component groups
-โ โโโ Card.tsx
-โ โโโ Dialog.tsx
-โ โโโ Select.tsx
-โ โโโ ...
-โโโ organisms/ # Complex UI sections
-โ โโโ Table.tsx
-โ โโโ Form.tsx
-โ โโโ Sidebar.tsx
-โ โโโ ...
-โโโ index.ts # Main export file
-```
-
-## Usage
-
-```tsx
-// Prefer the main barrel import
-import { Button, Card, Table, Dialog } from '@/components/ui'
-
-// Category imports are available when you want stricter layering
-import { Button, Input } from '@/components/ui/atoms'
-import { Card, Select } from '@/components/ui/molecules'
-import { Table, Form } from '@/components/ui/organisms'
-
-// Use fakemui for layout components
-import { Box, Typography, Grid } from '@/fakemui'
-
-// Use fakemui for icons
-import { Plus, Trash, Settings } from '@/fakemui/icons'
-```
-
-## Atomic Design Pattern
-
-### Atoms
-Basic UI elements that can't be broken down further:
-- Button, Input, Textarea, Label
-- Checkbox, Switch, Toggle
-- Badge, Avatar, Separator
-- Skeleton, Progress, Slider
-
-### Molecules
-Simple groups of atoms working together:
-- Card, Dialog, Select, Tabs
-- Alert, Accordion, Tooltip
-- DropdownMenu, RadioGroup, Popover
-- ToggleGroup, Breadcrumb
-
-### Tabs
-`Tabs` manages selection state. Provide `defaultValue` for uncontrolled usage or `value`/`onValueChange` for controlled usage. `TabsContent` hides inactive panels while keeping them mounted.
-
-### Organisms
-Complex, distinct UI sections:
-- Table, Form, Sheet
-- Sidebar, Navigation, Command
-- Pagination, AlertDialog
-
-## Styling
-
-Use fakemui's `sx` prop or SASS modules:
-
-```tsx
-// fakemui sx prop (recommended)
-
-
-// SASS module
-import styles from './MyComponent.module.scss'
-
-```
-
-## Legacy Files
-
-โ ๏ธ **Root wrapper files (like `button.tsx`, `dialog.tsx`, etc.) are legacy** and exist for
-backward compatibility. Avoid `@/components/ui/
` imports and use:
-- `atoms/`
-- `molecules/`
-- `organisms/`
-- Or direct fakemui imports from `@/fakemui`
-
-## Documentation
-
-- [UI Standards](../../../../UI_STANDARDS.md) - Project UI policy
-- [UI Migration Guide](../../../../docs/UI_MIGRATION.md) - Complete migration reference
-- [FakeMUI Theme](../../theme/fakemui-theme.ts) - Theme configuration
-- [FakeMUI README](../../../../fakemui/README.md) - Component library documentation
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Button.module.scss b/frontends/nextjs/src/components/ui/atoms/controls/Button.module.scss
deleted file mode 100644
index c31b80c40..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Button.module.scss
+++ /dev/null
@@ -1,22 +0,0 @@
-.button {
- // Base button styling handled by fakemui
- // Add custom overrides here
-}
-
-.link {
- text-decoration: underline;
-
- &:hover {
- text-decoration: underline;
- }
-}
-
-.icon {
- min-width: 40px;
- width: 40px;
- height: 40px;
- padding: 0;
- display: inline-flex;
- align-items: center;
- justify-content: center;
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Button.tsx b/frontends/nextjs/src/components/ui/atoms/controls/Button.tsx
deleted file mode 100644
index 9b232906f..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Button.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-'use client'
-
-import { type AnchorHTMLAttributes, CSSProperties,forwardRef } from 'react'
-
-import { Button as FakemuiButton, ButtonProps as FakemuiButtonProps, ButtonSize as FakemuiButtonSize,ButtonVariant as FakemuiButtonVariant } from '@/fakemui/fakemui/inputs'
-
-import styles from './Button.module.scss'
-
-/** Button visual style variants */
-export type ButtonVariant = 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link'
-
-/** Button size options */
-export type ButtonSize = 'default' | 'sm' | 'lg' | 'icon'
-
-/**
- * Props for the Button component
- * @extends {FakemuiButtonProps} Inherits fakemui Button props
- */
-export interface ButtonProps extends Omit {
- /** Visual style variant of the button */
- variant?: ButtonVariant
- /** Size of the button */
- size?: ButtonSize
- /** Compatibility prop - ignored */
- asChild?: boolean
- /** Target attribute for link buttons */
- target?: AnchorHTMLAttributes['target']
- /** Rel attribute for link buttons */
- rel?: AnchorHTMLAttributes['rel']
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const variantMap: Record = {
- default: 'primary',
- destructive: 'danger',
- outline: 'outline',
- secondary: 'secondary',
- ghost: 'ghost',
- link: 'text',
-}
-
-const sizeMap: Record = {
- default: 'md',
- sm: 'sm',
- lg: 'lg',
- icon: 'md',
-}
-
-const Button = forwardRef(
- ({ variant = 'default', size = 'default', children, className, style, ...props }, ref) => {
- const fakemuiVariant = variantMap[variant]
- const fakemuiSize = sizeMap[size]
- const isIcon = size === 'icon'
- const isLink = variant === 'link'
-
- return (
-
- {children}
-
- )
- }
-)
-
-Button.displayName = 'Button'
-
-export { Button }
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.module.scss b/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.module.scss
deleted file mode 100644
index 8e206660c..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.module.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-.checkbox {
- // Compact checkbox styling
- :global(.checkbox-box) {
- width: 18px;
- height: 18px;
- }
-
- :global(.checkbox-input) {
- width: 18px;
- height: 18px;
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.tsx b/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.tsx
deleted file mode 100644
index 267b6da9d..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Checkbox.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-'use client'
-
-import { forwardRef } from 'react'
-
-import { Checkbox as FakemuiCheckbox, CheckboxProps as FakemuiCheckboxProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Checkbox.module.scss'
-
-/**
- * Props for the Checkbox component
- * @extends {FakemuiCheckboxProps} Inherits fakemui Checkbox props
- */
-export interface CheckboxProps extends Omit {
- /** Callback when checked state changes (alternative to onChange) */
- onCheckedChange?: (checked: boolean) => void
- /** Standard onChange handler */
- onChange?: React.ChangeEventHandler
-}
-
-const Checkbox = forwardRef(
- ({ onCheckedChange, onChange, className, ...props }, ref) => {
- const handleChange: React.ChangeEventHandler = (event) => {
- onChange?.(event)
- onCheckedChange?.(event.target.checked)
- }
-
- return (
-
- )
- }
-)
-
-Checkbox.displayName = 'Checkbox'
-
-export { Checkbox }
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Slider.module.scss b/frontends/nextjs/src/components/ui/atoms/controls/Slider.module.scss
deleted file mode 100644
index c924b29c9..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Slider.module.scss
+++ /dev/null
@@ -1,18 +0,0 @@
-.slider {
- // Slider thumb styling
- :global(.fakemui-slider-thumb),
- &::-webkit-slider-thumb {
- width: 16px;
- height: 16px;
- }
-
- // Track styling
- :global(.fakemui-slider-track) {
- height: 4px;
- }
-
- // Rail styling
- :global(.fakemui-slider-rail) {
- height: 4px;
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Slider.tsx b/frontends/nextjs/src/components/ui/atoms/controls/Slider.tsx
deleted file mode 100644
index 1ae4b8abe..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Slider.tsx
+++ /dev/null
@@ -1,31 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { Slider as FakemuiSlider, SliderProps as FakemuiSliderProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Slider.module.scss'
-
-/**
- * Props for the Slider component
- * @extends {FakemuiSliderProps} Inherits fakemui Slider props
- */
-export interface SliderProps extends FakemuiSliderProps {
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const Slider = forwardRef(({ className, style, ...props }, ref) => {
- return (
-
- )
-})
-
-Slider.displayName = 'Slider'
-
-export { Slider }
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Switch.module.scss b/frontends/nextjs/src/components/ui/atoms/controls/Switch.module.scss
deleted file mode 100644
index 86b0c4408..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Switch.module.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.switch {
- // Switch styling - fakemui uses default styling
- // Add any custom overrides here if needed
- display: inline-flex;
- align-items: center;
-
- :global(.switch-track) {
- width: 34px;
- height: 14px;
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Switch.tsx b/frontends/nextjs/src/components/ui/atoms/controls/Switch.tsx
deleted file mode 100644
index a68c8740a..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Switch.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-'use client'
-
-import { forwardRef } from 'react'
-
-import { Switch as FakemuiSwitch, SwitchProps as FakemuiSwitchProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Switch.module.scss'
-
-/**
- * Props for the Switch component
- * @extends {FakemuiSwitchProps} Inherits fakemui Switch props
- */
-export interface SwitchProps extends Omit {
- /** Callback when checked state changes (alternative to onChange) */
- onCheckedChange?: (checked: boolean) => void
- /** Standard onChange handler */
- onChange?: React.ChangeEventHandler
-}
-
-const Switch = forwardRef(
- ({ onCheckedChange, onChange, className, ...props }, ref) => {
- const handleChange: React.ChangeEventHandler = (event) => {
- onChange?.(event)
- onCheckedChange?.(event.target.checked)
- }
-
- return (
-
- )
- }
-)
-
-Switch.displayName = 'Switch'
-
-export { Switch }
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Toggle.module.scss b/frontends/nextjs/src/components/ui/atoms/controls/Toggle.module.scss
deleted file mode 100644
index 6556dba81..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Toggle.module.scss
+++ /dev/null
@@ -1,49 +0,0 @@
-.toggle {
- border: none;
- background-color: transparent;
- transition: background-color 0.2s;
-
- &:hover {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
- }
-
- &.pressed {
- background-color: var(--action-selected, rgba(0, 0, 0, 0.08));
- }
-}
-
-.outline {
- border: 1px solid var(--divider, #e0e0e0);
-}
-
-.sm {
- height: 32px;
- min-width: 32px;
-}
-
-.default {
- height: 40px;
- min-width: 40px;
-}
-
-.lg {
- height: 48px;
- min-width: 48px;
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .toggle {
- &:hover {
- background-color: var(--action-hover-dark, rgba(255, 255, 255, 0.08));
- }
-
- &.pressed {
- background-color: var(--action-selected-dark, rgba(255, 255, 255, 0.16));
- }
- }
-
- .outline {
- border-color: var(--divider-dark, #424242);
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/controls/Toggle.tsx b/frontends/nextjs/src/components/ui/atoms/controls/Toggle.tsx
deleted file mode 100644
index e629bafc9..000000000
--- a/frontends/nextjs/src/components/ui/atoms/controls/Toggle.tsx
+++ /dev/null
@@ -1,62 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { ToggleButton, ToggleButtonProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Toggle.module.scss'
-
-/** Toggle button visual style variants */
-export type ToggleVariant = 'default' | 'outline'
-
-/** Toggle button size options */
-export type ToggleSize = 'default' | 'sm' | 'lg'
-
-/**
- * Props for the Toggle component
- * @extends {ToggleButtonProps} Inherits fakemui ToggleButton props
- */
-export interface ToggleProps extends Omit {
- /** Visual style variant of the toggle button */
- variant?: ToggleVariant
- /** Size of the toggle button */
- size?: ToggleSize
- /** Controlled pressed state */
- pressed?: boolean
- /** Callback when pressed state changes */
- onPressedChange?: (pressed: boolean) => void
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const sizeMap: Record = {
- sm: 'small',
- default: 'medium',
- lg: 'large',
-}
-
-const Toggle = forwardRef(
- (
- { variant = 'default', size = 'default', pressed, onPressedChange, className, style, value, ...props },
- ref
- ) => {
- const sizeClass = styles[size] || styles.default
-
- return (
- onPressedChange?.(!pressed)}
- size={sizeMap[size]}
- className={`${styles.toggle} ${sizeClass} ${variant === 'outline' ? styles.outline : ''} ${pressed ? styles.pressed : ''} ${className || ''}`}
- style={style}
- {...props}
- />
- )
- }
-)
-
-Toggle.displayName = 'Toggle'
-
-export { Toggle }
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Avatar.module.scss b/frontends/nextjs/src/components/ui/atoms/display/Avatar.module.scss
deleted file mode 100644
index 45766cb50..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Avatar.module.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-.avatar {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- overflow: hidden;
- display: flex;
- align-items: center;
- justify-content: center;
- background-color: var(--action-hover, #f5f5f5);
- color: var(--text-primary, #333);
- font-weight: 500;
-
- img {
- width: 100%;
- height: 100%;
- object-fit: cover;
- }
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .avatar {
- background-color: var(--action-hover-dark, #2c2c2c);
- color: var(--text-primary-dark, #fff);
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Avatar.tsx b/frontends/nextjs/src/components/ui/atoms/display/Avatar.tsx
deleted file mode 100644
index 427c5df85..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Avatar.tsx
+++ /dev/null
@@ -1,51 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { Avatar as FakemuiAvatar, AvatarProps as FakemuiAvatarProps } from '@/fakemui/fakemui/data-display'
-
-import styles from './Avatar.module.scss'
-
-/**
- * Props for the Avatar component
- * @extends {FakemuiAvatarProps} Inherits fakemui Avatar props
- */
-export interface AvatarProps extends FakemuiAvatarProps {
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const Avatar = forwardRef(({ className, style, ...props }, ref) => {
- return (
-
- )
-})
-
-Avatar.displayName = 'Avatar'
-
-// For compatibility with shadcn pattern
-const AvatarImage = forwardRef>(
- (props, ref) => {
- return (
-
- )
- }
-)
-AvatarImage.displayName = 'AvatarImage'
-
-interface AvatarFallbackProps {
- children?: React.ReactNode
- className?: string
-}
-
-const AvatarFallback = ({ children }: AvatarFallbackProps) => {
- return <>{children}>
-}
-
-export { Avatar, AvatarFallback, AvatarImage }
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Badge.module.scss b/frontends/nextjs/src/components/ui/atoms/display/Badge.module.scss
deleted file mode 100644
index 31fd5fdaf..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Badge.module.scss
+++ /dev/null
@@ -1,39 +0,0 @@
-.badge {
- height: auto;
- padding: 2px 6px;
- font-size: 0.75rem;
- font-weight: 500;
- border-radius: 9999px;
- display: inline-flex;
- align-items: center;
- justify-content: center;
-}
-
-.default {
- background-color: var(--primary-main, #1976d2);
- color: var(--primary-contrast-text, #fff);
-}
-
-.secondary {
- background-color: var(--secondary-main, #9c27b0);
- color: var(--secondary-contrast-text, #fff);
-}
-
-.destructive {
- background-color: var(--error-main, #d32f2f);
- color: var(--error-contrast-text, #fff);
-}
-
-.outline {
- background-color: transparent;
- border: 1px solid var(--border-color, #e0e0e0);
- color: var(--text-primary, #333);
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .outline {
- border-color: var(--border-color-dark, #424242);
- color: var(--text-primary-dark, #fff);
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Badge.tsx b/frontends/nextjs/src/components/ui/atoms/display/Badge.tsx
deleted file mode 100644
index 75fcadab9..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Badge.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef, ReactNode } from 'react'
-
-import { Chip } from '@/fakemui/fakemui/data-display'
-
-import styles from './Badge.module.scss'
-
-/** Badge visual style variants */
-export type BadgeVariant = 'default' | 'secondary' | 'destructive' | 'outline'
-
-/**
- * Props for the Badge component
- */
-export interface BadgeProps {
- /** Visual style variant of the badge */
- variant?: BadgeVariant
- /** Content to display inside the badge */
- children?: ReactNode
- /** CSS class name for custom styling */
- className?: string
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const Badge = forwardRef(
- ({ variant = 'default', children, className, style, ...props }, ref) => {
- const variantClass = {
- default: styles.default,
- secondary: styles.secondary,
- destructive: styles.destructive,
- outline: styles.outline,
- }[variant]
-
- return (
-
- {children}
-
- )
- }
-)
-
-Badge.displayName = 'Badge'
-
-export { Badge }
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Label.module.scss b/frontends/nextjs/src/components/ui/atoms/display/Label.module.scss
deleted file mode 100644
index 70b679581..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Label.module.scss
+++ /dev/null
@@ -1,20 +0,0 @@
-.label {
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--text-primary, #333);
-
- &.disabled {
- opacity: 0.5;
- cursor: not-allowed;
- }
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .label {
- color: var(--text-primary-dark, #fff);
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/display/Label.tsx b/frontends/nextjs/src/components/ui/atoms/display/Label.tsx
deleted file mode 100644
index 943c0d2e5..000000000
--- a/frontends/nextjs/src/components/ui/atoms/display/Label.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { FormLabel, FormLabelProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Label.module.scss'
-
-/**
- * Props for the Label component
- * @extends {FormLabelProps} Inherits fakemui FormLabel props
- */
-export interface LabelProps extends FormLabelProps {
- /** ID of the form element this label is associated with */
- htmlFor?: string
- /** Content to display inside the label */
- children?: ReactNode
- /** Whether the label is disabled */
- disabled?: boolean
-}
-
-const Label = forwardRef(({ children, disabled, className, ...props }, ref) => {
- return (
-
- {children}
-
- )
-})
-
-Label.displayName = 'Label'
-
-export { Label }
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Progress.module.scss b/frontends/nextjs/src/components/ui/atoms/feedback/Progress.module.scss
deleted file mode 100644
index 876f293ea..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Progress.module.scss
+++ /dev/null
@@ -1,19 +0,0 @@
-.progress {
- height: 8px;
- border-radius: 4px;
- background-color: var(--action-hover, rgba(0, 0, 0, 0.08));
- overflow: hidden;
-
- // Override fakemui progress bar styling
- :global(.fakemui-progress-bar),
- :global([class*="bar"]) {
- border-radius: 4px;
- }
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .progress {
- background-color: var(--action-hover-dark, rgba(255, 255, 255, 0.08));
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Progress.tsx b/frontends/nextjs/src/components/ui/atoms/feedback/Progress.tsx
deleted file mode 100644
index 0b8ef1b3c..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Progress.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { LinearProgress, LinearProgressProps } from '@/fakemui/fakemui/feedback'
-
-import styles from './Progress.module.scss'
-
-/**
- * Props for the Progress component
- * @extends {LinearProgressProps} Inherits fakemui LinearProgress props
- */
-export interface ProgressProps extends LinearProgressProps {
- /** Progress value (0-100) for determinate mode */
- value?: number
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const Progress = forwardRef(({ value, className, style, ...props }, ref) => {
- return (
-
- )
-})
-
-Progress.displayName = 'Progress'
-
-export { Progress }
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.module.scss b/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.module.scss
deleted file mode 100644
index a0eb2313e..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.module.scss
+++ /dev/null
@@ -1,39 +0,0 @@
-.scrollArea {
- overflow: auto;
-
- // Custom scrollbar styling
- &::-webkit-scrollbar {
- width: 8px;
- height: 8px;
- }
-
- &::-webkit-scrollbar-track {
- background-color: transparent;
- }
-
- &::-webkit-scrollbar-thumb {
- background-color: rgba(0, 0, 0, 0.2);
- border-radius: 4px;
-
- &:hover {
- background-color: rgba(0, 0, 0, 0.3);
- }
- }
-}
-
-.scrollBarHidden {
- display: none;
-}
-
-// Dark mode scrollbar
-[data-theme='dark'] {
- .scrollArea {
- &::-webkit-scrollbar-thumb {
- background-color: rgba(255, 255, 255, 0.2);
-
- &:hover {
- background-color: rgba(255, 255, 255, 0.3);
- }
- }
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.tsx b/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.tsx
deleted file mode 100644
index b04bb0296..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/ScrollArea.tsx
+++ /dev/null
@@ -1,48 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { Box, BoxProps } from '@/fakemui/fakemui/layout'
-
-import styles from './ScrollArea.module.scss'
-
-export interface ScrollAreaProps extends Omit {
- /** Custom inline styles */
- style?: CSSProperties
- /** CSS class name */
- className?: string
- /** Children to render inside scroll area */
- children?: React.ReactNode
-}
-
-/**
- * ScrollArea - Fakemui-based scrollable container
- * Provides a styled scrollable area with custom scrollbar styling
- */
-export const ScrollArea = forwardRef(
- ({ children, className, style, ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-
-ScrollArea.displayName = 'ScrollArea'
-
-/**
- * ScrollBar - Placeholder for Radix ScrollBar API compatibility
- * Not needed with fakemui implementation but exported for compatibility
- */
-export const ScrollBar = forwardRef(({ ...props }, ref) => {
- // fakemui handles scrollbars natively via CSS
- return
-})
-
-ScrollBar.displayName = 'ScrollBar'
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Separator.module.scss b/frontends/nextjs/src/components/ui/atoms/feedback/Separator.module.scss
deleted file mode 100644
index 7b2eebc64..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Separator.module.scss
+++ /dev/null
@@ -1,23 +0,0 @@
-.separator {
- border: none;
- background-color: var(--divider, #e0e0e0);
-}
-
-.horizontal {
- width: 100%;
- height: 1px;
- margin: 16px 0;
-}
-
-.vertical {
- width: 1px;
- height: 100%;
- margin: 0 16px;
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .separator {
- background-color: var(--divider-dark, #424242);
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Separator.tsx b/frontends/nextjs/src/components/ui/atoms/feedback/Separator.tsx
deleted file mode 100644
index 003f1dbc3..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Separator.tsx
+++ /dev/null
@@ -1,35 +0,0 @@
-'use client'
-
-import { forwardRef } from 'react'
-
-import { Divider, DividerProps } from '@/fakemui/fakemui/data-display'
-
-import styles from './Separator.module.scss'
-
-/**
- * Props for the Separator component
- * @extends {DividerProps} Inherits fakemui Divider props
- */
-export interface SeparatorProps extends DividerProps {
- /** Direction of the separator */
- orientation?: 'horizontal' | 'vertical'
- /** Whether the separator is decorative (for accessibility) */
- decorative?: boolean
-}
-
-const Separator = forwardRef(
- ({ orientation = 'horizontal', className, ...props }, ref) => {
- return (
-
- )
- }
-)
-
-Separator.displayName = 'Separator'
-
-export { Separator }
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.module.scss b/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.module.scss
deleted file mode 100644
index 264426bf5..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.module.scss
+++ /dev/null
@@ -1,11 +0,0 @@
-.skeleton {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.08));
- border-radius: 4px;
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .skeleton {
- background-color: var(--action-hover-dark, rgba(255, 255, 255, 0.08));
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.tsx b/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.tsx
deleted file mode 100644
index e99402b98..000000000
--- a/frontends/nextjs/src/components/ui/atoms/feedback/Skeleton.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-'use client'
-
-import { CSSProperties,forwardRef } from 'react'
-
-import { Skeleton as FakemuiSkeleton, SkeletonProps as FakemuiSkeletonProps } from '@/fakemui/fakemui/feedback'
-
-import styles from './Skeleton.module.scss'
-
-/**
- * Props for the Skeleton component
- * @extends {FakemuiSkeletonProps} Inherits fakemui Skeleton props
- */
-export interface SkeletonProps extends FakemuiSkeletonProps {
- /** Custom inline styles */
- style?: CSSProperties
-}
-
-const Skeleton = forwardRef(({ className, style, ...props }, ref) => {
- return (
-
- )
-})
-
-Skeleton.displayName = 'Skeleton'
-
-export { Skeleton }
diff --git a/frontends/nextjs/src/components/ui/atoms/index.ts b/frontends/nextjs/src/components/ui/atoms/index.ts
deleted file mode 100644
index 4496b1145..000000000
--- a/frontends/nextjs/src/components/ui/atoms/index.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-// Atoms - Basic building blocks of the UI
-// These are the smallest, most fundamental components
-
-export { Button, type ButtonProps, type ButtonSize, type ButtonVariant } from './controls/Button'
-export { Checkbox, type CheckboxProps } from './controls/Checkbox'
-export { Slider, type SliderProps } from './controls/Slider'
-export { Switch, type SwitchProps } from './controls/Switch'
-export { Toggle, type ToggleProps, type ToggleSize, type ToggleVariant } from './controls/Toggle'
-export { Avatar, AvatarFallback, AvatarImage, type AvatarProps } from './display/Avatar'
-export { Badge, type BadgeProps, type BadgeVariant } from './display/Badge'
-export { Label, type LabelProps } from './display/Label'
-export { Progress, type ProgressProps } from './feedback/Progress'
-export { ScrollArea, type ScrollAreaProps, ScrollBar } from './feedback/ScrollArea'
-export { Separator, type SeparatorProps } from './feedback/Separator'
-export { Skeleton, type SkeletonProps } from './feedback/Skeleton'
-export { Input, type InputProps } from './inputs/Input'
-export { Textarea, type TextareaProps } from './inputs/Textarea'
-
-// New atoms from @/components/atoms (available in God Tier panel)
-export { Radio, type RadioProps } from '../../atoms/controls/Radio'
-export { Icon, type IconName, type IconProps, type IconSize } from '../../atoms/display/Icon'
-export { Link, type LinkProps } from '../../atoms/display/Link'
-export {
- Text,
- type TextAlign,
- type TextProps,
- type TextVariant,
- type TextWeight,
-} from '../../atoms/display/Text'
-export {
- Select as AtomSelect,
- type SelectOption,
- type SelectProps,
-} from '../../atoms/inputs/Select'
-export { TextArea, type TextAreaProps } from '../../atoms/inputs/TextArea'
diff --git a/frontends/nextjs/src/components/ui/atoms/inputs/Input.module.scss b/frontends/nextjs/src/components/ui/atoms/inputs/Input.module.scss
deleted file mode 100644
index 8cc3b808b..000000000
--- a/frontends/nextjs/src/components/ui/atoms/inputs/Input.module.scss
+++ /dev/null
@@ -1,69 +0,0 @@
-.input {
- width: 100%;
-
- :global(.fakemui-input-base) {
- padding: 8px 12px;
- font-size: 0.875rem;
- border: 1px solid var(--border-color, #e0e0e0);
- border-radius: 4px;
- background-color: var(--background-paper, #fff);
- transition: border-color 0.2s, box-shadow 0.2s;
- }
-
- :global(.fakemui-input-base:hover) {
- border-color: var(--text-primary, #333);
- }
-
- :global(.fakemui-input-base-input:focus) {
- outline: none;
- }
-
- :global(.fakemui-input-base:focus-within) {
- border-color: var(--primary-main, #1976d2);
- box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.15);
- }
-
- :global(.fakemui-input-base-disabled) {
- opacity: 0.5;
- cursor: not-allowed;
- }
-
- :global(.fakemui-input-base-input) {
- padding: 0;
- border: none;
- background: transparent;
- font-family: inherit;
- font-size: inherit;
- width: 100%;
- }
-
- &.error {
- :global(.fakemui-input-base) {
- border-color: var(--error-main, #d32f2f);
- }
-
- :global(.fakemui-input-base:hover) {
- border-color: var(--error-main, #d32f2f);
- }
-
- :global(.fakemui-input-base:focus-within) {
- border-color: var(--error-main, #d32f2f);
- box-shadow: 0 0 0 2px rgba(211, 47, 47, 0.15);
- }
- }
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .input {
- :global(.fakemui-input-base) {
- background-color: var(--background-paper-dark, #1e1e1e);
- border-color: var(--border-color-dark, #424242);
- color: var(--text-primary-dark, #fff);
- }
-
- :global(.fakemui-input-base:hover) {
- border-color: var(--text-primary-dark, #fff);
- }
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/inputs/Input.tsx b/frontends/nextjs/src/components/ui/atoms/inputs/Input.tsx
deleted file mode 100644
index 3d7f4e552..000000000
--- a/frontends/nextjs/src/components/ui/atoms/inputs/Input.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-'use client'
-
-import { forwardRef, InputHTMLAttributes } from 'react'
-
-import { InputBase, InputBaseProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Input.module.scss'
-
-/**
- * Props for the Input component
- * @extends {InputHTMLAttributes} Inherits HTML input element attributes
- */
-export interface InputProps extends Omit, 'size'> {
- /** Whether the input is in an error state */
- error?: boolean
-}
-
-const Input = forwardRef(
- ({ type, error, className, style, ...props }, ref) => {
- // Filter out HTML-specific props that conflict with InputBase
- const { color, ...restProps } = props as InputProps & { color?: string }
- return (
-
- )
- }
-)
-
-Input.displayName = 'Input'
-
-export { Input }
diff --git a/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.module.scss b/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.module.scss
deleted file mode 100644
index 8c04e363f..000000000
--- a/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.module.scss
+++ /dev/null
@@ -1,52 +0,0 @@
-.textarea {
- width: 100%;
- padding: 8px 12px;
- font-size: 0.875rem;
- border: 1px solid var(--border-color, #e0e0e0);
- border-radius: 4px;
- background-color: var(--background-paper, #fff);
- font-family: inherit;
- resize: vertical;
- transition: border-color 0.2s, box-shadow 0.2s;
-
- &:hover {
- border-color: var(--text-primary, #333);
- }
-
- &:focus {
- outline: none;
- border-color: var(--primary-main, #1976d2);
- box-shadow: 0 0 0 2px rgba(25, 118, 210, 0.15);
- }
-
- &:disabled {
- opacity: 0.5;
- cursor: not-allowed;
- }
-
- &.error {
- border-color: var(--error-main, #d32f2f);
-
- &:hover {
- border-color: var(--error-main, #d32f2f);
- }
-
- &:focus {
- border-color: var(--error-main, #d32f2f);
- box-shadow: 0 0 0 2px rgba(211, 47, 47, 0.15);
- }
- }
-}
-
-// Dark mode support
-[data-theme='dark'] {
- .textarea {
- background-color: var(--background-paper-dark, #1e1e1e);
- border-color: var(--border-color-dark, #424242);
- color: var(--text-primary-dark, #fff);
-
- &:hover {
- border-color: var(--text-primary-dark, #fff);
- }
- }
-}
diff --git a/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.tsx b/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.tsx
deleted file mode 100644
index dc598d102..000000000
--- a/frontends/nextjs/src/components/ui/atoms/inputs/Textarea.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-'use client'
-
-import { forwardRef } from 'react'
-
-import { Textarea as FakemuiTextarea, TextareaProps as FakemuiTextareaProps } from '@/fakemui/fakemui/inputs'
-
-import styles from './Textarea.module.scss'
-
-/**
- * Props for the Textarea component
- */
-export interface TextareaProps extends Omit {
- /** Whether the textarea is in an error state */
- error?: boolean
- /** Whether the textarea is disabled */
- disabled?: boolean
- /** Placeholder text to display when empty */
- placeholder?: string
- /** Controlled value */
- value?: string
- /** Default value for uncontrolled mode */
- defaultValue?: string
- /** Callback when value changes */
- onChange?: (event: React.ChangeEvent) => void
- /** Callback when textarea loses focus */
- onBlur?: (event: React.FocusEvent) => void
- /** Callback when textarea receives focus */
- onFocus?: (event: React.FocusEvent) => void
- /** Form field name */
- name?: string
- /** Element ID */
- id?: string
- /** Number of visible rows */
- rows?: number
- /** Minimum number of rows (for auto-resize) */
- minRows?: number
- /** Maximum number of rows (for auto-resize) */
- maxRows?: number
- /** CSS class name for custom styling */
- className?: string
- /** Whether the field is required */
- required?: boolean
- /** Whether the textarea is read-only */
- readOnly?: boolean
- /** Whether to auto-focus on mount */
- autoFocus?: boolean
-}
-
-const Textarea = forwardRef(
- ({ error, minRows = 3, className, ...props }, ref) => {
- return (
-
- )
- }
-)
-
-Textarea.displayName = 'Textarea'
-
-export { Textarea }
diff --git a/frontends/nextjs/src/components/ui/core.ts b/frontends/nextjs/src/components/ui/core.ts
deleted file mode 100644
index bee6384e0..000000000
--- a/frontends/nextjs/src/components/ui/core.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-// Core UI exports: foundational atoms and common building blocks
-export * from './atoms'
-
-// Common molecules
-export {
- Accordion,
- AccordionContent,
- AccordionItem,
- AccordionTrigger,
- Alert,
- AlertDescription,
- type AlertProps,
- AlertTitle,
- type AlertVariant,
- Breadcrumb,
- BreadcrumbEllipsis,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbList,
- BreadcrumbPage,
- BreadcrumbSeparator,
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
- NavGroup,
- type NavGroupProps,
- NavItem,
- type NavItemProps,
- NavLink,
- type NavLinkProps,
- RadioGroup,
- RadioGroupItem,
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectScrollDownButton,
- SelectScrollUpButton,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
- Tabs,
- TabsContent,
- TabsList,
- TabsTrigger,
- ToggleGroup,
- ToggleGroupItem,
-} from './molecules'
-
-// Navigation and command organisms
-export type { SidebarItem, SidebarProps } from './organisms'
-export {
- Command,
- CommandEmpty,
- CommandGroup,
- CommandInput,
- CommandItem,
- CommandList,
- CommandSeparator,
- CommandShortcut,
- Navigation,
- NavigationBrand,
- NavigationContent,
- NavigationItem,
- NavigationLink,
- NavigationList,
- NavigationMenu,
- NavigationMobileToggle,
- NavigationSeparator,
- NavigationSpacer,
- NavigationTrigger,
- Sidebar,
- SidebarContent,
- SidebarFooter,
- SidebarHeader,
- SidebarNav,
- SidebarSection,
- SidebarSeparator,
- SidebarToggle,
- useCommandShortcut,
- useNavigationDropdown,
-} from './organisms'
diff --git a/frontends/nextjs/src/components/ui/data.ts b/frontends/nextjs/src/components/ui/data.ts
deleted file mode 100644
index c9c21a66e..000000000
--- a/frontends/nextjs/src/components/ui/data.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-// Data-centric UI exports
-export {
- Form,
- FormControl,
- FormDescription,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
- Pagination,
- PaginationContent,
- PaginationEllipsis,
- PaginationItem,
- PaginationLink,
- PaginationNext,
- PaginationPrevious,
- SimplePagination,
- Table,
- TableBody,
- TableCaption,
- TableCell,
- TableFooter,
- TableHead,
- TableHeader,
- TablePagination,
- TableRow,
- useFormField,
-} from './organisms'
diff --git a/frontends/nextjs/src/components/ui/display/avatar.ts b/frontends/nextjs/src/components/ui/display/avatar.ts
deleted file mode 100644
index 8b36236a5..000000000
--- a/frontends/nextjs/src/components/ui/display/avatar.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Avatar, AvatarFallback, AvatarImage, type AvatarProps } from './atoms/Avatar'
diff --git a/frontends/nextjs/src/components/ui/display/badge.ts b/frontends/nextjs/src/components/ui/display/badge.ts
deleted file mode 100644
index 1fa13dc76..000000000
--- a/frontends/nextjs/src/components/ui/display/badge.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Badge, type BadgeProps, type BadgeVariant } from './atoms/Badge'
diff --git a/frontends/nextjs/src/components/ui/display/label.ts b/frontends/nextjs/src/components/ui/display/label.ts
deleted file mode 100644
index 2b4dbfd19..000000000
--- a/frontends/nextjs/src/components/ui/display/label.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Label, type LabelProps } from './atoms/Label'
diff --git a/frontends/nextjs/src/components/ui/display/table.ts b/frontends/nextjs/src/components/ui/display/table.ts
deleted file mode 100644
index 4ef29253d..000000000
--- a/frontends/nextjs/src/components/ui/display/table.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// Re-export for backward compatibility
-export {
- Table,
- TableBody,
- TableCaption,
- TableCell,
- TableFooter,
- TableHead,
- TableHeader,
- TableRow,
-} from './organisms/Table'
diff --git a/frontends/nextjs/src/components/ui/feedback/alert-dialog.ts b/frontends/nextjs/src/components/ui/feedback/alert-dialog.ts
deleted file mode 100644
index ef1e39a5f..000000000
--- a/frontends/nextjs/src/components/ui/feedback/alert-dialog.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-// Re-export for backward compatibility
-export {
- AlertDialog,
- AlertDialogAction,
- AlertDialogCancel,
- AlertDialogContent,
- AlertDialogDescription,
- AlertDialogFooter,
- AlertDialogHeader,
- AlertDialogTitle,
- AlertDialogTrigger,
-} from './organisms/AlertDialog'
diff --git a/frontends/nextjs/src/components/ui/feedback/alert.ts b/frontends/nextjs/src/components/ui/feedback/alert.ts
deleted file mode 100644
index 2988d4d8a..000000000
--- a/frontends/nextjs/src/components/ui/feedback/alert.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-// Re-export for backward compatibility
-export {
- Alert,
- AlertDescription,
- type AlertProps,
- AlertTitle,
- type AlertVariant,
-} from './molecules/Alert'
diff --git a/frontends/nextjs/src/components/ui/feedback/dialog.ts b/frontends/nextjs/src/components/ui/feedback/dialog.ts
deleted file mode 100644
index 1ff6f9c9c..000000000
--- a/frontends/nextjs/src/components/ui/feedback/dialog.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Re-export for backward compatibility
-export {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-} from './molecules/Dialog'
diff --git a/frontends/nextjs/src/components/ui/feedback/progress.ts b/frontends/nextjs/src/components/ui/feedback/progress.ts
deleted file mode 100644
index c16961c85..000000000
--- a/frontends/nextjs/src/components/ui/feedback/progress.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Progress, type ProgressProps } from './atoms/Progress'
diff --git a/frontends/nextjs/src/components/ui/feedback/skeleton.ts b/frontends/nextjs/src/components/ui/feedback/skeleton.ts
deleted file mode 100644
index f38eba5f7..000000000
--- a/frontends/nextjs/src/components/ui/feedback/skeleton.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Skeleton, type SkeletonProps } from './atoms/Skeleton'
diff --git a/frontends/nextjs/src/components/ui/forms/controls/checkbox.ts b/frontends/nextjs/src/components/ui/forms/controls/checkbox.ts
deleted file mode 100644
index 77857c5a6..000000000
--- a/frontends/nextjs/src/components/ui/forms/controls/checkbox.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Checkbox, type CheckboxProps } from './atoms/Checkbox'
diff --git a/frontends/nextjs/src/components/ui/forms/controls/radio-group.ts b/frontends/nextjs/src/components/ui/forms/controls/radio-group.ts
deleted file mode 100644
index cbc991767..000000000
--- a/frontends/nextjs/src/components/ui/forms/controls/radio-group.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { RadioGroup, RadioGroupItem } from './molecules/RadioGroup'
diff --git a/frontends/nextjs/src/components/ui/forms/controls/select.ts b/frontends/nextjs/src/components/ui/forms/controls/select.ts
deleted file mode 100644
index 51d5a5034..000000000
--- a/frontends/nextjs/src/components/ui/forms/controls/select.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-// Re-export for backward compatibility
-export {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectScrollDownButton,
- SelectScrollUpButton,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-} from './molecules/Select'
diff --git a/frontends/nextjs/src/components/ui/forms/controls/slider.ts b/frontends/nextjs/src/components/ui/forms/controls/slider.ts
deleted file mode 100644
index ee91f7bf8..000000000
--- a/frontends/nextjs/src/components/ui/forms/controls/slider.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Slider, type SliderProps } from './atoms/Slider'
diff --git a/frontends/nextjs/src/components/ui/forms/controls/switch.ts b/frontends/nextjs/src/components/ui/forms/controls/switch.ts
deleted file mode 100644
index 39373ed11..000000000
--- a/frontends/nextjs/src/components/ui/forms/controls/switch.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Switch, type SwitchProps } from './atoms/Switch'
diff --git a/frontends/nextjs/src/components/ui/forms/inputs/input.ts b/frontends/nextjs/src/components/ui/forms/inputs/input.ts
deleted file mode 100644
index 7f7a0b872..000000000
--- a/frontends/nextjs/src/components/ui/forms/inputs/input.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Input, type InputProps } from './atoms/Input'
diff --git a/frontends/nextjs/src/components/ui/forms/inputs/textarea.ts b/frontends/nextjs/src/components/ui/forms/inputs/textarea.ts
deleted file mode 100644
index 80214eb01..000000000
--- a/frontends/nextjs/src/components/ui/forms/inputs/textarea.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Textarea, type TextareaProps } from './atoms/Textarea'
diff --git a/frontends/nextjs/src/components/ui/index.test.ts b/frontends/nextjs/src/components/ui/index.test.ts
deleted file mode 100644
index 36100da0e..000000000
--- a/frontends/nextjs/src/components/ui/index.test.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { describe, expect, it } from 'vitest'
-
-import { Button, Card, Dialog, Select, Table, Tabs } from '@/components/ui'
-
-describe('ui barrel exports', () => {
- it('exposes common UI components', () => {
- expect(Button).toBeDefined()
- expect(Card).toBeDefined()
- expect(Dialog).toBeDefined()
- expect(Select).toBeDefined()
- expect(Table).toBeDefined()
- expect(Tabs).toBeDefined()
- })
-})
diff --git a/frontends/nextjs/src/components/ui/index.ts b/frontends/nextjs/src/components/ui/index.ts
deleted file mode 100644
index 4f0dac7be..000000000
--- a/frontends/nextjs/src/components/ui/index.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// Central UI barrel exports
-export * from './core'
-export * from './data'
-export * from './overlay'
-
-// Preserve category-level entrypoints
-export * from './atoms'
-export * from './molecules'
-export * from './organisms'
diff --git a/frontends/nextjs/src/components/ui/layout/containers/accordion.ts b/frontends/nextjs/src/components/ui/layout/containers/accordion.ts
deleted file mode 100644
index ffcab0f32..000000000
--- a/frontends/nextjs/src/components/ui/layout/containers/accordion.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './molecules/Accordion'
diff --git a/frontends/nextjs/src/components/ui/layout/containers/card.ts b/frontends/nextjs/src/components/ui/layout/containers/card.ts
deleted file mode 100644
index ac9d23eeb..000000000
--- a/frontends/nextjs/src/components/ui/layout/containers/card.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-// Re-export for backward compatibility
-export {
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
-} from './molecules/Card'
diff --git a/frontends/nextjs/src/components/ui/layout/containers/sheet.ts b/frontends/nextjs/src/components/ui/layout/containers/sheet.ts
deleted file mode 100644
index 85f549350..000000000
--- a/frontends/nextjs/src/components/ui/layout/containers/sheet.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// Re-export for backward compatibility
-export {
- Sheet,
- SheetClose,
- SheetContent,
- SheetDescription,
- SheetFooter,
- SheetHeader,
- SheetTitle,
- SheetTrigger,
-} from './organisms/Sheet'
diff --git a/frontends/nextjs/src/components/ui/layout/scroll-area.ts b/frontends/nextjs/src/components/ui/layout/scroll-area.ts
deleted file mode 100644
index e56b9605d..000000000
--- a/frontends/nextjs/src/components/ui/layout/scroll-area.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { ScrollArea, type ScrollAreaProps, ScrollBar } from './atoms/ScrollArea'
diff --git a/frontends/nextjs/src/components/ui/layout/separator.ts b/frontends/nextjs/src/components/ui/layout/separator.ts
deleted file mode 100644
index d90361a2e..000000000
--- a/frontends/nextjs/src/components/ui/layout/separator.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Separator, type SeparatorProps } from './atoms/Separator'
diff --git a/frontends/nextjs/src/components/ui/layout/tabs.ts b/frontends/nextjs/src/components/ui/layout/tabs.ts
deleted file mode 100644
index 8713e089e..000000000
--- a/frontends/nextjs/src/components/ui/layout/tabs.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-// Re-export for backward compatibility
-export { Tabs, TabsContent, TabsList, TabsTrigger } from './molecules/Tabs'
diff --git a/frontends/nextjs/src/components/ui/molecules/display/Accordion.tsx b/frontends/nextjs/src/components/ui/molecules/display/Accordion.tsx
deleted file mode 100644
index 4956b50c1..000000000
--- a/frontends/nextjs/src/components/ui/molecules/display/Accordion.tsx
+++ /dev/null
@@ -1,99 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode, useState } from 'react'
-
-import {
- Accordion as FakeMuiAccordion,
- AccordionDetails,
- AccordionSummary,
- Typography,
-} from '@/fakemui'
-import { ExpandMore } from '@/fakemui/icons'
-
-interface AccordionProps {
- children: ReactNode
- type?: 'single' | 'multiple'
- collapsible?: boolean
- defaultValue?: string | string[]
- value?: string | string[]
- onValueChange?: (value: string | string[]) => void
- className?: string
-}
-
-const Accordion = forwardRef(
- ({ children, type = 'single', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-Accordion.displayName = 'Accordion'
-
-interface AccordionItemProps {
- children: ReactNode
- value: string
- disabled?: boolean
- className?: string
-}
-
-const AccordionItem = forwardRef(
- ({ children, value, disabled, className, ...props }, ref) => {
- const [expanded, setExpanded] = useState(false)
-
- return (
-
- !disabled && setExpanded(!expanded)}>{children}
-
- )
- }
-)
-AccordionItem.displayName = 'AccordionItem'
-
-interface AccordionTriggerProps {
- children: ReactNode
- className?: string
-}
-
-const AccordionTrigger = forwardRef(
- ({ children, className, ...props }, ref) => {
- return (
- }
- className={className}
- {...props}
- >
-
- {children}
-
-
- )
- }
-)
-AccordionTrigger.displayName = 'AccordionTrigger'
-
-interface AccordionContentProps {
- children: ReactNode
- className?: string
-}
-
-const AccordionContent = forwardRef(
- ({ children, className, ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-AccordionContent.displayName = 'AccordionContent'
-
-export { Accordion, AccordionContent, AccordionItem, AccordionTrigger }
diff --git a/frontends/nextjs/src/components/ui/molecules/display/Alert.tsx b/frontends/nextjs/src/components/ui/molecules/display/Alert.tsx
deleted file mode 100644
index 9e480cc5d..000000000
--- a/frontends/nextjs/src/components/ui/molecules/display/Alert.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Alert as FakeMuiAlert, AlertTitle as FakeMuiAlertTitle } from '@/fakemui'
-
-export type AlertVariant = 'default' | 'destructive'
-
-export interface AlertProps {
- variant?: AlertVariant
- children?: ReactNode
- className?: string
-}
-
-const Alert = forwardRef(
- ({ variant = 'default', children, className, ...props }, ref) => {
- const severity = variant === 'destructive' ? 'error' : 'info'
-
- return (
-
- {children}
-
- )
- }
-)
-
-Alert.displayName = 'Alert'
-
-interface AlertTitleProps {
- children: ReactNode
- className?: string
-}
-
-const AlertTitle = forwardRef(({ children, ...props }, ref) => {
- return (
-
- {children}
-
- )
-})
-AlertTitle.displayName = 'AlertTitle'
-
-interface AlertDescriptionProps {
- children: ReactNode
- className?: string
-}
-
-const AlertDescription = forwardRef(
- ({ children, ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-AlertDescription.displayName = 'AlertDescription'
-
-export { Alert, AlertDescription, AlertTitle }
diff --git a/frontends/nextjs/src/components/ui/molecules/display/Card.module.scss b/frontends/nextjs/src/components/ui/molecules/display/Card.module.scss
deleted file mode 100644
index e6590c6ed..000000000
--- a/frontends/nextjs/src/components/ui/molecules/display/Card.module.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-// Card styles - migrated from MUI sx prop
-
-.card {
- border-radius: 8px;
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
-}
-
-.cardHeader {
- padding: 24px;
- padding-bottom: 0;
-}
-
-.cardTitle {
- font-size: 1.25rem;
- font-weight: 600;
- line-height: 1.6;
-}
-
-.cardDescription {
- font-size: 0.875rem;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.cardContent {
- padding: 24px;
-}
-
-.cardFooter {
- padding: 24px;
- padding-top: 0;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/display/Card.tsx b/frontends/nextjs/src/components/ui/molecules/display/Card.tsx
deleted file mode 100644
index ef79d0f27..000000000
--- a/frontends/nextjs/src/components/ui/molecules/display/Card.tsx
+++ /dev/null
@@ -1,127 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Box } from '@/fakemui/fakemui/layout'
-import {
- Card as FakeMuiCard,
- CardActions,
- CardContent as FakeMuiCardContent,
- CardDescription as FakeMuiCardDescription,
- CardFooter as FakeMuiCardFooter,
- CardTitle as FakeMuiCardTitle,
-} from '@/fakemui/fakemui/surfaces'
-
-import styles from './Card.module.scss'
-
-export interface CardProps extends React.HTMLAttributes {
- children?: ReactNode
- raised?: boolean
- clickable?: boolean
-}
-
-const Card = forwardRef(
- ({ children, className = '', raised, clickable, ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-Card.displayName = 'Card'
-
-interface CardHeaderProps {
- children?: ReactNode
- className?: string
-}
-
-const CardHeaderComponent = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-CardHeaderComponent.displayName = 'CardHeader'
-
-interface CardTitleProps {
- children?: ReactNode
- className?: string
-}
-
-const CardTitle = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-CardTitle.displayName = 'CardTitle'
-
-interface CardDescriptionProps {
- children?: ReactNode
- className?: string
-}
-
-const CardDescription = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-CardDescription.displayName = 'CardDescription'
-
-interface CardContentProps {
- children?: ReactNode
- className?: string
-}
-
-const CardContentComponent = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-CardContentComponent.displayName = 'CardContent'
-
-interface CardFooterProps {
- children?: ReactNode
- className?: string
-}
-
-const CardFooter = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-CardFooter.displayName = 'CardFooter'
-
-export {
- Card,
- CardContentComponent as CardContent,
- CardDescription,
- CardFooter,
- CardHeaderComponent as CardHeader,
- CardTitle,
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/index.ts b/frontends/nextjs/src/components/ui/molecules/index.ts
deleted file mode 100644
index 3d5309097..000000000
--- a/frontends/nextjs/src/components/ui/molecules/index.ts
+++ /dev/null
@@ -1,86 +0,0 @@
-// Molecules - Combinations of atoms that form functional UI groups
-// These are relatively simple groups of UI elements functioning together as a unit
-
-export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from './display/Accordion'
-export {
- Alert,
- AlertDescription,
- type AlertProps,
- AlertTitle,
- type AlertVariant,
-} from './display/Alert'
-export {
- Card,
- CardContent,
- CardDescription,
- CardFooter,
- CardHeader,
- CardTitle,
-} from './display/Card'
-export {
- Breadcrumb,
- BreadcrumbEllipsis,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbList,
- BreadcrumbPage,
- BreadcrumbSeparator,
-} from './navigation/Breadcrumb'
-export { NavGroup, type NavGroupProps } from './navigation/NavGroup'
-export { NavItem, type NavItemProps } from './navigation/NavItem'
-export { NavLink, type NavLinkProps } from './navigation/NavLink'
-export { Tabs, TabsContent, TabsList, TabsTrigger } from './navigation/Tabs'
-export {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-} from './overlay/Dialog'
-export { DialogSection, DialogSections } from './overlay/Dialog/Sections'
-export {
- DropdownMenu,
- DropdownMenuCheckboxItem,
- DropdownMenuContent,
- DropdownMenuGroup,
- DropdownMenuItem,
- DropdownMenuLabel,
- DropdownMenuPortal,
- DropdownMenuRadioGroup,
- DropdownMenuRadioItem,
- DropdownMenuSeparator,
- DropdownMenuShortcut,
- DropdownMenuSub,
- DropdownMenuSubContent,
- DropdownMenuSubTrigger,
- DropdownMenuTrigger,
-} from './overlay/DropdownMenu'
-export { MenuItem, type MenuItemProps } from './overlay/DropdownMenu/MenuItem'
-export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger } from './overlay/Popover'
-export {
- SimpleTooltip,
- Tooltip,
- TooltipContent,
- TooltipProvider,
- TooltipTrigger,
-} from './overlay/Tooltip'
-export { useDropdownState } from './overlay/useDropdownState'
-export { RadioGroup, RadioGroupItem } from './selection/RadioGroup'
-export {
- Select,
- SelectContent,
- SelectGroup,
- SelectItem,
- SelectLabel,
- SelectScrollDownButton,
- SelectScrollUpButton,
- SelectSeparator,
- SelectTrigger,
- SelectValue,
-} from './selection/Select'
-export { ToggleGroup, ToggleGroupItem } from './selection/ToggleGroup'
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.module.scss b/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.module.scss
deleted file mode 100644
index 1e52634ac..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.module.scss
+++ /dev/null
@@ -1,73 +0,0 @@
-// Breadcrumb styles - converted from MUI sx props
-
-.breadcrumbs {
- display: flex;
- align-items: center;
-}
-
-.breadcrumbsList {
- display: flex;
- align-items: center;
- flex-wrap: wrap;
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-.breadcrumbsItem {
- display: flex;
- align-items: center;
-}
-
-.breadcrumbsSeparator {
- display: flex;
- align-items: center;
- margin: 0 8px;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.breadcrumbItem {
- display: inline-flex;
- align-items: center;
-}
-
-.breadcrumbLink {
- display: flex;
- align-items: center;
- font-size: 0.875rem;
- color: inherit;
- text-decoration: none;
- transition: text-decoration 0.2s;
-
- &:hover {
- text-decoration: underline;
- }
-}
-
-.breadcrumbPage {
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--text-primary, rgba(0, 0, 0, 0.87));
-}
-
-.breadcrumbSeparator {
- display: inline-flex;
- align-items: center;
- margin: 0 8px;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.breadcrumbEllipsis {
- display: flex;
- align-items: center;
- position: relative;
-}
-
-.srOnly {
- position: absolute;
- width: 1px;
- height: 1px;
- overflow: hidden;
- clip: rect(0, 0, 0, 0);
- white-space: nowrap;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.tsx
deleted file mode 100644
index bc2f5802e..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/Breadcrumb.tsx
+++ /dev/null
@@ -1,141 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Box, Breadcrumbs, Link, Typography } from '@/fakemui'
-import { MoreHoriz, NavigateNext } from '@/fakemui/icons'
-
-import styles from './Breadcrumb.module.scss'
-
-interface BreadcrumbProps {
- children: ReactNode
- className?: string
-}
-
-const Breadcrumb = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
- }
- className={`${styles.breadcrumbs} ${className}`}
- aria-label="breadcrumb"
- {...props}
- >
- {children}
-
- )
- }
-)
-Breadcrumb.displayName = 'Breadcrumb'
-
-interface BreadcrumbListProps {
- children: ReactNode
- className?: string
-}
-
-const BreadcrumbList = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return <>{children}>
- }
-)
-BreadcrumbList.displayName = 'BreadcrumbList'
-
-interface BreadcrumbItemProps {
- children: ReactNode
- className?: string
-}
-
-const BreadcrumbItem = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-BreadcrumbItem.displayName = 'BreadcrumbItem'
-
-interface BreadcrumbLinkProps {
- children: ReactNode
- href?: string
- asChild?: boolean
- className?: string
-}
-
-const BreadcrumbLink = forwardRef(
- ({ children, href, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-BreadcrumbLink.displayName = 'BreadcrumbLink'
-
-interface BreadcrumbPageProps {
- children: ReactNode
- className?: string
-}
-
-const BreadcrumbPage = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-BreadcrumbPage.displayName = 'BreadcrumbPage'
-
-interface BreadcrumbSeparatorProps {
- children?: ReactNode
- className?: string
-}
-
-const BreadcrumbSeparator = ({ children, className = '', ...props }: BreadcrumbSeparatorProps) => {
- return (
-
- {children || }
-
- )
-}
-BreadcrumbSeparator.displayName = 'BreadcrumbSeparator'
-
-interface BreadcrumbEllipsisProps {
- className?: string
-}
-
-const BreadcrumbEllipsis = ({ className = '', ...props }: BreadcrumbEllipsisProps) => {
- return (
-
-
- More
-
- )
-}
-BreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis'
-
-export {
- Breadcrumb,
- BreadcrumbEllipsis,
- BreadcrumbItem,
- BreadcrumbLink,
- BreadcrumbList,
- BreadcrumbPage,
- BreadcrumbSeparator,
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.module.scss b/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.module.scss
deleted file mode 100644
index ff75e20cb..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.module.scss
+++ /dev/null
@@ -1,89 +0,0 @@
-// NavGroup styles - converted from MUI sx props
-
-.navGroup {
- width: 100%;
-}
-
-.divider {
- margin: 8px 0;
- border: none;
- border-top: 1px solid var(--divider, rgba(0, 0, 0, 0.12));
-}
-
-.groupItem {
- list-style: none;
- padding: 0;
-}
-
-.groupButton {
- display: flex;
- align-items: center;
- width: 100%;
- padding: 8px 12px;
- margin: 2px 4px;
- border: none;
- border-radius: 4px;
- background: transparent;
- cursor: pointer;
- text-align: left;
- transition: background-color 0.2s;
-
- &:hover {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
- }
-
- &:focus-visible {
- outline: 2px solid var(--primary-main, #1976d2);
- outline-offset: -2px;
- }
-}
-
-.groupButtonDisabled {
- cursor: not-allowed;
- opacity: 0.5;
- pointer-events: none;
-}
-
-.icon {
- display: flex;
- align-items: center;
- min-width: 40px;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.labelText {
- flex: 1;
- font-size: 0.875rem;
- font-weight: 600;
- color: var(--text-primary, rgba(0, 0, 0, 0.87));
-}
-
-.expandIcon {
- display: flex;
- align-items: center;
- color: rgba(0, 0, 0, 0.54);
-}
-
-.collapse {
- overflow: hidden;
- height: 0;
- transition: height 0.2s ease-out;
-}
-
-.collapseOpen {
- height: auto;
-}
-
-.childList {
- list-style: none;
- padding: 0;
- margin: 0;
-}
-
-.childListWithIcon {
- padding-left: 24px;
-}
-
-.childListNoIcon {
- padding-left: 8px;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.test.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.test.tsx
deleted file mode 100644
index 1248ae639..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.test.tsx
+++ /dev/null
@@ -1,109 +0,0 @@
-import { fireEvent, render, screen } from '@testing-library/react'
-import { describe, expect, it, vi } from 'vitest'
-
-import { Folder as FolderIcon } from '@/fakemui/icons'
-
-import { NavGroup } from './NavGroup'
-import { NavItem } from './NavItem'
-
-describe('NavGroup', () => {
- it.each([
- { label: 'Navigation', defaultOpen: false },
- { label: 'Settings', defaultOpen: true },
- { label: 'Admin', defaultOpen: false },
- ])('renders with label "$label" and defaultOpen=$defaultOpen', ({ label, defaultOpen }) => {
- render(
-
-
-
- )
-
- expect(screen.getByText(label)).toBeTruthy()
-
- const childItem = screen.queryByText('Child Item')
- if (defaultOpen) {
- expect(childItem).toBeTruthy()
- }
- })
-
- it('toggles collapse when clicked', () => {
- render(
-
-
-
- )
-
- const button = screen.getByRole('button', { name: /Menu/i })
- const childItem = screen.queryByText('Child Item')
-
- // Children are always in DOM (CSS-based collapse)
- expect(childItem).toBeTruthy()
-
- // Click to expand
- fireEvent.click(button)
- expect(screen.queryByText('Child Item')).toBeTruthy()
-
- // Click to collapse
- fireEvent.click(button)
- // Children remain in DOM but are hidden via CSS
- expect(screen.queryByText('Child Item')).toBeTruthy()
- })
-
- it('renders with icon', () => {
- const { container } = render(
- }>
-
-
- )
-
- expect(screen.getByTestId('folder-icon')).toBeTruthy()
- })
-
- it.each([{ disabled: true }, { disabled: false }])(
- 'handles disabled=$disabled state',
- ({ disabled }) => {
- render(
-
-
-
- )
-
- const button = screen.getByRole('button', { name: /Menu/i })
-
- if (disabled) {
- expect(button.hasAttribute('disabled')).toBe(true)
- fireEvent.click(button)
- // Children remain in DOM (CSS-based collapse), click doesn't toggle state
- expect(screen.queryByText('Child')).toBeTruthy()
- } else {
- expect(button.hasAttribute('disabled')).toBe(false)
- }
- }
- )
-
- it('renders divider when divider=true', () => {
- const { container } = render(
-
-
-
- )
-
- // Check for fakemui Divider component (renders as hr)
- const divider = container.querySelector('hr')
- expect(divider).toBeTruthy()
- })
-
- it('renders multiple children', () => {
- render(
-
-
-
-
-
- )
-
- expect(screen.getByText('Child 1')).toBeTruthy()
- expect(screen.getByText('Child 2')).toBeTruthy()
- expect(screen.getByText('Child 3')).toBeTruthy()
- })
-})
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.tsx
deleted file mode 100644
index b939dab1b..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavGroup.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode, useState } from 'react'
-
-import { Box, Collapse, Divider, List, ListItem, ListItemIcon, ListItemText } from '@/fakemui'
-import { ExpandLess, ExpandMore } from '@/fakemui/icons'
-
-import styles from './NavGroup.module.scss'
-
-export interface NavGroupProps {
- label: string
- icon?: ReactNode
- children: ReactNode
- defaultOpen?: boolean
- disabled?: boolean
- divider?: boolean
- className?: string
-}
-
-const NavGroup = forwardRef(
- (
- { label, icon, children, defaultOpen = false, disabled = false, divider = false, className = '', ...props },
- ref
- ) => {
- const [open, setOpen] = useState(defaultOpen)
-
- const handleToggle = () => {
- if (!disabled) {
- setOpen(prev => !prev)
- }
- }
-
- const buttonClasses = [styles.groupButton, disabled && styles.groupButtonDisabled]
- .filter(Boolean)
- .join(' ')
-
- const collapseClasses = [styles.collapse, open && styles.collapseOpen].filter(Boolean).join(' ')
-
- const childListClasses = [
- styles.childList,
- icon ? styles.childListWithIcon : styles.childListNoIcon,
- ]
- .filter(Boolean)
- .join(' ')
-
- return (
-
- {divider && }
-
-
-
-
- {children}
-
-
- )
- }
-)
-
-NavGroup.displayName = 'NavGroup'
-
-export { NavGroup }
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.module.scss b/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.module.scss
deleted file mode 100644
index faa9432ae..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.module.scss
+++ /dev/null
@@ -1,131 +0,0 @@
-// NavItem styles - converted from MUI sx props
-
-.navItem {
- list-style: none;
- padding: 0;
-}
-
-.navItemButton {
- display: flex;
- align-items: center;
- width: 100%;
- padding: 8px 12px;
- margin: 2px 4px;
- border: none;
- border-radius: 4px;
- background: transparent;
- cursor: pointer;
- text-align: left;
- transition: background-color 0.2s;
-
- &:hover {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
- }
-
- &:focus-visible {
- outline: 2px solid var(--primary-main, #1976d2);
- outline-offset: -2px;
- }
-}
-
-.navItemButtonSelected {
- background-color: var(--action-selected, rgba(0, 0, 0, 0.08));
-
- &:hover {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
- }
-}
-
-.navItemButtonDisabled {
- cursor: not-allowed;
- opacity: 0.5;
- pointer-events: none;
-}
-
-.navItemButtonDense {
- padding: 4px 12px;
-}
-
-.icon {
- display: flex;
- align-items: center;
- min-width: 40px;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.iconActive {
- color: var(--primary-main, #1976d2);
-}
-
-.text {
- flex: 1;
- min-width: 0;
-}
-
-.textPrimary {
- display: block;
- font-size: 0.875rem;
- font-weight: 400;
- color: var(--text-primary, rgba(0, 0, 0, 0.87));
-}
-
-.textPrimaryActive {
- font-weight: 600;
- color: var(--primary-main, #1976d2);
-}
-
-.textSecondary {
- display: block;
- font-size: 0.75rem;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.badgeWrapper {
- margin-left: 8px;
-}
-
-.badge {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- font-size: 0.625rem;
- min-width: 16px;
- height: 16px;
- padding: 0 4px;
- border-radius: 8px;
- background-color: var(--primary-main, #1976d2);
- color: #fff;
-}
-
-.badgeDefault {
- background-color: var(--grey-500, #9e9e9e);
-}
-
-.badgePrimary {
- background-color: var(--primary-main, #1976d2);
-}
-
-.badgeSecondary {
- background-color: var(--secondary-main, #9c27b0);
-}
-
-.badgeError {
- background-color: var(--error-main, #d32f2f);
-}
-
-.badgeWarning {
- background-color: var(--warning-main, #ed6c02);
-}
-
-.badgeInfo {
- background-color: var(--info-main, #0288d1);
-}
-
-.badgeSuccess {
- background-color: var(--success-main, #2e7d32);
-}
-
-.badgeStatic {
- position: static;
- transform: none;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.test.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.test.tsx
deleted file mode 100644
index f088093dd..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.test.tsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import { fireEvent, render, screen } from '@testing-library/react'
-import { describe, expect, it, vi } from 'vitest'
-
-import { Home as HomeIcon } from '@/fakemui/icons'
-
-import { NavItem } from './NavItem'
-
-describe('NavItem', () => {
- it.each([
- { label: 'Home', icon: , active: false },
- { label: 'Dashboard', icon: , active: true },
- { label: 'Settings', icon: undefined, active: false },
- ])('renders with label "$label", icon presence, active=$active', ({ label, icon, active }) => {
- render()
-
- expect(screen.getByText(label)).toBeTruthy()
-
- const button = screen.getByRole('button')
- // Check for CSS module active class pattern
- if (active) {
- expect(button.className).toMatch(/navItemButtonSelected/)
- }
- })
-
- it.each([
- { badge: 5, badgeColor: 'primary' as const },
- { badge: '99+', badgeColor: 'error' as const },
- { badge: undefined, badgeColor: 'default' as const },
- ])('displays badge=$badge with badgeColor=$badgeColor', ({ badge, badgeColor }) => {
- render(} badge={badge} badgeColor={badgeColor} />)
-
- if (badge !== undefined) {
- expect(screen.getByText(badge.toString())).toBeTruthy()
- }
- })
-
- it('calls onClick when clicked', () => {
- const handleClick = vi.fn()
- render()
-
- const button = screen.getByRole('button')
- fireEvent.click(button)
-
- expect(handleClick).toHaveBeenCalled()
- })
-
- it.each([
- { disabled: true, shouldBeDisabled: true },
- { disabled: false, shouldBeDisabled: false },
- ])('handles disabled=$disabled state', ({ disabled, shouldBeDisabled }) => {
- render()
-
- const button = screen.getByRole('button')
- expect(button.hasAttribute('disabled')).toBe(shouldBeDisabled)
- })
-
- it('renders with secondary label', () => {
- render()
-
- expect(screen.getByText('Home')).toBeTruthy()
- expect(screen.getByText('Main page')).toBeTruthy()
- })
-
- it('renders with href for navigation', () => {
- render()
-
- // When href is provided, fakemui renders it as a link, not a button
- const link = screen.getByRole('link')
- expect(link.getAttribute('href')).toBe('/home')
- })
-})
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.tsx
deleted file mode 100644
index de1951ca9..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavItem.tsx
+++ /dev/null
@@ -1,108 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { ListItem, ListItemIcon, ListItemText } from '@/fakemui'
-
-import styles from './NavItem.module.scss'
-
-export interface NavItemProps extends React.LiHTMLAttributes {
- icon?: ReactNode
- label: string
- onClick?: () => void
- active?: boolean
- disabled?: boolean
- badge?: number | string
- badgeColor?: 'default' | 'primary' | 'secondary' | 'error' | 'warning' | 'info' | 'success'
- href?: string
- secondaryLabel?: string
- dense?: boolean
- className?: string
-}
-
-const badgeColorMap: Record = {
- default: styles.badgeDefault,
- primary: styles.badgePrimary,
- secondary: styles.badgeSecondary,
- error: styles.badgeError,
- warning: styles.badgeWarning,
- info: styles.badgeInfo,
- success: styles.badgeSuccess,
-}
-
-const NavItem = forwardRef(
- (
- {
- icon,
- label,
- onClick,
- active = false,
- disabled = false,
- badge,
- badgeColor = 'primary',
- href,
- secondaryLabel,
- dense = false,
- className = '',
- ...props
- },
- ref
- ) => {
- const buttonClasses = [
- styles.navItemButton,
- active && styles.navItemButtonSelected,
- disabled && styles.navItemButtonDisabled,
- dense && styles.navItemButtonDense,
- ]
- .filter(Boolean)
- .join(' ')
-
- const iconClasses = [styles.icon, active && styles.iconActive].filter(Boolean).join(' ')
-
- const primaryTextClasses = [styles.textPrimary, active && styles.textPrimaryActive]
- .filter(Boolean)
- .join(' ')
-
- const badgeClasses = [styles.badge, badgeColorMap[badgeColor]].filter(Boolean).join(' ')
-
- const ButtonComponent = href ? 'a' : 'button'
-
- return (
-
-
- {icon && (
-
- {badge !== undefined ? (
-
- {icon}
- {badge}
-
- ) : (
- icon
- )}
-
- )}
- {label}}
- secondary={secondaryLabel && {secondaryLabel}}
- />
- {badge !== undefined && !icon && (
-
- {badge}
-
- )}
-
-
- )
- }
-)
-
-NavItem.displayName = 'NavItem'
-
-export { NavItem }
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.module.scss b/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.module.scss
deleted file mode 100644
index b27c1e5e3..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.module.scss
+++ /dev/null
@@ -1,57 +0,0 @@
-// NavLink styles - converted from MUI sx props
-
-.navLink {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 8px 16px;
- border-radius: 4px;
- font-size: 0.875rem;
- font-weight: 500;
- color: var(--text-primary, rgba(0, 0, 0, 0.87));
- background-color: transparent;
- cursor: pointer;
- text-decoration: none;
- transition: background-color 0.2s, color 0.2s;
-
- &:hover {
- background-color: var(--action-hover, rgba(0, 0, 0, 0.04));
- color: var(--text-primary, rgba(0, 0, 0, 0.87));
- }
-
- &:focus-visible {
- outline: 2px solid var(--primary-main, #1976d2);
- outline-offset: 2px;
- }
-}
-
-.navLinkActive {
- font-weight: 600;
- color: var(--primary-main, #1976d2);
- background-color: var(--action-selected, rgba(0, 0, 0, 0.08));
-
- &:hover {
- background-color: var(--action-selected, rgba(0, 0, 0, 0.08));
- color: var(--primary-main, #1976d2);
- }
-}
-
-.navLinkDisabled {
- cursor: not-allowed;
- opacity: 0.5;
-
- &:hover {
- background-color: transparent;
- }
-}
-
-.icon {
- display: flex;
- align-items: center;
- font-size: 1.25rem;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.iconActive {
- color: var(--primary-main, #1976d2);
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.test.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.test.tsx
deleted file mode 100644
index be587429f..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.test.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import { fireEvent, render, screen } from '@testing-library/react'
-import { describe, expect, it, vi } from 'vitest'
-
-import { Home as HomeIcon } from '@/fakemui/icons'
-
-import { NavLink } from './NavLink'
-
-describe('NavLink', () => {
- it.each([
- { href: '/home', children: 'Home', active: false },
- { href: '/dashboard', children: 'Dashboard', active: true },
- { href: '/settings', children: 'Settings', active: false },
- ])(
- 'renders with href="$href", children="$children", active=$active',
- ({ href, children, active }) => {
- render(
-
- {children}
-
- )
-
- const link = screen.getByText(children)
- expect(link).toBeTruthy()
-
- const linkElement = link.closest('a')
- expect(linkElement?.getAttribute('href')).toBe(href)
- }
- )
-
- it('renders with icon', () => {
- const { container } = render(
- }>
- Home
-
- )
-
- expect(screen.getByTestId('home-icon')).toBeTruthy()
- })
-
- it.each([
- { disabled: true, href: '/home' },
- { disabled: false, href: '/dashboard' },
- ])('handles disabled=$disabled state', ({ disabled, href }) => {
- render(
-
- Link
-
- )
-
- const link = screen.getByText('Link').closest('a')
-
- if (disabled) {
- expect(link?.hasAttribute('href')).toBe(false)
- } else {
- expect(link?.getAttribute('href')).toBe(href)
- }
- })
-
- it('applies active styling when active=true', () => {
- render(
-
- Home
-
- )
-
- const link = screen.getByText('Home').closest('a')
- // Check for active styling - fakemui applies CSS module classes
- expect(link).toBeTruthy()
- expect(link?.className).toMatch(/navLinkActive/)
- })
-
- it('does not have underline by default', () => {
- render(Home)
-
- const link = screen.getByText('Home').closest('a')
- // fakemui Link with underline="none" doesn't add text-decoration
- expect(link).toBeTruthy()
- })
-})
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.tsx
deleted file mode 100644
index b35e57e7c..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/NavLink.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Box, Link } from '@/fakemui'
-
-import styles from './NavLink.module.scss'
-
-export interface NavLinkProps extends React.AnchorHTMLAttributes {
- href: string
- active?: boolean
- disabled?: boolean
- children: ReactNode
- icon?: ReactNode
- className?: string
-}
-
-const NavLink = forwardRef(
- ({ href, active = false, disabled = false, children, icon, className = '', ...props }, ref) => {
- const linkClasses = [
- styles.navLink,
- active && styles.navLinkActive,
- disabled && styles.navLinkDisabled,
- className,
- ]
- .filter(Boolean)
- .join(' ')
-
- const iconClasses = [styles.icon, active && styles.iconActive].filter(Boolean).join(' ')
-
- return (
-
- {icon && (
-
- {icon}
-
- )}
- {children}
-
- )
- }
-)
-
-NavLink.displayName = 'NavLink'
-
-export { NavLink }
diff --git a/frontends/nextjs/src/components/ui/molecules/navigation/Tabs.tsx b/frontends/nextjs/src/components/ui/molecules/navigation/Tabs.tsx
deleted file mode 100644
index 338fb3899..000000000
--- a/frontends/nextjs/src/components/ui/molecules/navigation/Tabs.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-export type { TabsContentProps } from '../tabs/components/TabsContent'
-export { TabsContent } from '../tabs/components/TabsContent'
-export type { TabsListProps } from '../tabs/components/TabsList'
-export { TabsList } from '../tabs/components/TabsList'
-export type { TabsTriggerProps } from '../tabs/components/TabsTrigger'
-export { TabsTrigger } from '../tabs/components/TabsTrigger'
-export type { TabsProps } from '../tabs/core/Tabs'
-export { Tabs } from '../tabs/core/Tabs'
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.module.scss
deleted file mode 100644
index 46f7abb73..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.module.scss
+++ /dev/null
@@ -1,16 +0,0 @@
-// Dialog molecule component styles
-
-.trigger {
- display: inline-flex;
-}
-
-.closeButton {
- position: absolute;
- right: 8px;
- top: 8px;
- color: var(--color-text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.description {
- color: var(--color-text-secondary, rgba(0, 0, 0, 0.6));
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.tsx b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.tsx
deleted file mode 100644
index 1aabfbf37..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog.tsx
+++ /dev/null
@@ -1,149 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Typography } from '@/fakemui/fakemui/data-display'
-import { IconButton } from '@/fakemui/fakemui/inputs'
-import { Box } from '@/fakemui/fakemui/layout'
-import {
- Dialog as FakeMuiDialog,
- DialogTitle as FakeMuiDialogTitle,
-} from '@/fakemui/fakemui/utils'
-import { Close } from '@/fakemui/icons'
-
-import styles from './Dialog.module.scss'
-import { DialogContent, type DialogContentProps } from './dialog/Body'
-import { DialogFooter, type DialogFooterProps } from './dialog/Footer'
-import { DialogHeader, type DialogHeaderProps } from './dialog/Header'
-
-export interface DialogProps {
- open?: boolean
- onOpenChange?: (open: boolean) => void
- onClose?: () => void
- children?: ReactNode
- className?: string
-}
-
-const Dialog = forwardRef(
- ({ open, onOpenChange, onClose, children, className, ...props }, ref) => {
- const handleClose = () => {
- onClose?.()
- onOpenChange?.(false)
- }
-
- return (
-
- {children}
-
- )
- }
-)
-Dialog.displayName = 'Dialog'
-
-interface DialogTriggerProps {
- children: ReactNode
- asChild?: boolean
- onClick?: () => void
-}
-
-const DialogTrigger = forwardRef(
- ({ children, onClick, ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-DialogTrigger.displayName = 'DialogTrigger'
-
-const DialogPortal = ({ children }: { children: ReactNode }) => <>{children}>
-DialogPortal.displayName = 'DialogPortal'
-
-const DialogOverlay = forwardRef((props, ref) => )
-DialogOverlay.displayName = 'DialogOverlay'
-
-interface DialogCloseProps {
- children?: ReactNode
- onClick?: () => void
- asChild?: boolean
-}
-
-const DialogClose = forwardRef(
- ({ children, onClick, ...props }, ref) => {
- if (children) {
- return (
- }
- onClick={onClick}
- className={styles.trigger}
- {...props}
- >
- {children}
-
- )
- }
- return (
-
-
-
- )
- }
-)
-DialogClose.displayName = 'DialogClose'
-
-interface DialogTitleProps {
- children: ReactNode
- className?: string
-}
-
-const DialogTitle = forwardRef((props, ref) => {
- const { children, ...rest } = props
- return (
-
- {children}
-
- )
-})
-DialogTitle.displayName = 'DialogTitle'
-
-interface DialogDescriptionProps {
- children: ReactNode
- className?: string
-}
-
-const DialogDescription = forwardRef((props, ref) => {
- const { children, className, ...rest } = props
- return (
-
- {children}
-
- )
-})
-DialogDescription.displayName = 'DialogDescription'
-
-export {
- Dialog,
- DialogClose,
- DialogContent,
- DialogDescription,
- DialogFooter,
- DialogHeader,
- DialogOverlay,
- DialogPortal,
- DialogTitle,
- DialogTrigger,
-}
-
-export type { DialogContentProps, DialogFooterProps, DialogHeaderProps }
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Body.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Body.module.scss
deleted file mode 100644
index 40e5f0211..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Body.module.scss
+++ /dev/null
@@ -1,17 +0,0 @@
-// DialogBody molecule component styles
-
-.body {
- position: relative;
- padding: 16px 24px;
-
- &.hasCloseButton {
- padding-top: 48px;
- }
-}
-
-.closeButton {
- position: absolute;
- right: 8px;
- top: 8px;
- color: var(--color-text-secondary, rgba(0, 0, 0, 0.6));
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Footer.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Footer.module.scss
deleted file mode 100644
index 10fabe11b..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Footer.module.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-// DialogFooter molecule component styles
-
-.footer {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- padding: 16px 24px;
- gap: 8px;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Header.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Header.module.scss
deleted file mode 100644
index 72aa22288..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Header.module.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-// DialogHeader molecule component styles
-
-.header {
- display: flex;
- flex-direction: column;
- gap: 8px;
- padding-bottom: 16px;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.module.scss
deleted file mode 100644
index de713f974..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.module.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-// DialogSections molecule component styles
-
-.sections {
- display: flex;
- flex-direction: column;
-}
-
-.section {
- display: flex;
- flex-direction: column;
- gap: 16px;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.tsx b/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.tsx
deleted file mode 100644
index d90d59fb6..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/Dialog/Sections.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-'use client'
-
-import { ReactNode } from 'react'
-
-import { Divider } from '@/fakemui/fakemui/data-display'
-import { Stack } from '@/fakemui/fakemui/layout'
-
-import styles from './Sections.module.scss'
-
-interface DialogSectionsProps {
- children: ReactNode
- spacing?: number
- divided?: boolean
-}
-
-const DialogSections = ({ children, spacing = 3, divided = false }: DialogSectionsProps) => {
- return (
- : undefined}
- >
- {children}
-
- )
-}
-DialogSections.displayName = 'DialogSections'
-
-interface DialogSectionProps {
- children: ReactNode
-}
-
-const DialogSection = ({ children }: DialogSectionProps) => {
- return {children}
-}
-DialogSection.displayName = 'DialogSection'
-
-export { DialogSection, DialogSections }
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.module.scss
deleted file mode 100644
index 5099f5dcf..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.module.scss
+++ /dev/null
@@ -1,40 +0,0 @@
-// DropdownMenu styles - migrated from MUI sx prop
-
-.dropdownMenuTrigger {
- display: inline-flex;
-}
-
-.dropdownMenuContent {
- min-width: 180px;
-}
-
-.dropdownMenuItem {
- font-size: 0.875rem;
- padding: 8px 16px;
- min-height: auto;
-
- &.inset {
- padding-left: 32px;
- }
-}
-
-.dropdownMenuLabel {
- padding: 8px 16px;
- font-size: 0.875rem;
- font-weight: 600;
-
- &.inset {
- padding-left: 32px;
- }
-}
-
-.dropdownMenuSeparator {
- margin: 4px 0;
-}
-
-.dropdownMenuShortcut {
- margin-left: auto;
- font-size: 0.75rem;
- letter-spacing: 0.1em;
- color: var(--text-secondary, rgba(0, 0, 0, 0.6));
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.tsx b/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.tsx
deleted file mode 100644
index 3add080fc..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu.tsx
+++ /dev/null
@@ -1,210 +0,0 @@
-'use client'
-
-import { forwardRef, ReactNode } from 'react'
-
-import { Divider } from '@/fakemui/fakemui/data-display'
-import { Box } from '@/fakemui/fakemui/layout'
-import { MenuItem } from '@/fakemui/fakemui/navigation'
-
-import styles from './DropdownMenu.module.scss'
-
-interface DropdownMenuProps {
- children: ReactNode
- open?: boolean
- onOpenChange?: (open: boolean) => void
-}
-
-const DropdownMenu = ({ children }: DropdownMenuProps) => <>{children}>
-DropdownMenu.displayName = 'DropdownMenu'
-
-interface DropdownMenuTriggerProps {
- children: ReactNode
- asChild?: boolean
- className?: string
-}
-
-const DropdownMenuTrigger = forwardRef(
- ({ children, asChild, className = '', ...props }, ref) => {
- return (
- }
- className={`${styles.dropdownMenuTrigger} ${className}`}
- {...props}
- >
- {children}
-
- )
- }
-)
-DropdownMenuTrigger.displayName = 'DropdownMenuTrigger'
-
-interface DropdownMenuContentProps {
- children: ReactNode
- align?: 'start' | 'center' | 'end'
- sideOffset?: number
- className?: string
-}
-
-const DropdownMenuContent = forwardRef(
- ({ children, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-DropdownMenuContent.displayName = 'DropdownMenuContent'
-
-interface DropdownMenuItemProps {
- children: ReactNode
- disabled?: boolean
- onSelect?: () => void
- onClick?: () => void
- className?: string
- inset?: boolean
-}
-
-const DropdownMenuItem = forwardRef(
- ({ children, disabled, onSelect, onClick, inset, className = '', ...props }, ref) => {
- return (
-
- )
- }
-)
-DropdownMenuItem.displayName = 'DropdownMenuItem'
-
-interface DropdownMenuLabelProps {
- children: ReactNode
- className?: string
- inset?: boolean
-}
-
-const DropdownMenuLabel = forwardRef(
- ({ children, inset, className = '', ...props }, ref) => {
- return (
-
- {children}
-
- )
- }
-)
-DropdownMenuLabel.displayName = 'DropdownMenuLabel'
-
-interface DropdownMenuSeparatorProps {
- className?: string
-}
-
-const DropdownMenuSeparator = forwardRef(
- ({ className = '', ...props }, ref) => {
- return
- }
-)
-DropdownMenuSeparator.displayName = 'DropdownMenuSeparator'
-
-interface DropdownMenuShortcutProps {
- children: ReactNode
- className?: string
-}
-
-const DropdownMenuShortcut = ({ children, className = '', ...props }: DropdownMenuShortcutProps) => {
- return (
-
- {children}
-
- )
-}
-DropdownMenuShortcut.displayName = 'DropdownMenuShortcut'
-
-const DropdownMenuGroup = ({ children }: { children: ReactNode }) => <>{children}>
-DropdownMenuGroup.displayName = 'DropdownMenuGroup'
-
-const DropdownMenuPortal = ({ children }: { children: ReactNode }) => <>{children}>
-DropdownMenuPortal.displayName = 'DropdownMenuPortal'
-
-const DropdownMenuSub = ({ children }: { children: ReactNode }) => <>{children}>
-DropdownMenuSub.displayName = 'DropdownMenuSub'
-
-const DropdownMenuSubContent = forwardRef(
- ({ children, className = '', ...props }, ref) => (
-
- {children}
-
- )
-)
-DropdownMenuSubContent.displayName = 'DropdownMenuSubContent'
-
-const DropdownMenuSubTrigger = forwardRef(
- ({ children, className = '', ...props }, ref) => (
-
- )
-)
-DropdownMenuSubTrigger.displayName = 'DropdownMenuSubTrigger'
-
-interface DropdownMenuCheckboxItemProps extends DropdownMenuItemProps {
- checked?: boolean
- onCheckedChange?: (checked: boolean) => void
-}
-
-const DropdownMenuCheckboxItem = forwardRef(
- ({ children, checked, onCheckedChange, className = '', ...props }, ref) => (
-
- )
-)
-DropdownMenuCheckboxItem.displayName = 'DropdownMenuCheckboxItem'
-
-interface DropdownMenuRadioGroupProps {
- children: ReactNode
- value?: string
- onValueChange?: (value: string) => void
-}
-
-const DropdownMenuRadioGroup = ({ children }: DropdownMenuRadioGroupProps) => <>{children}>
-DropdownMenuRadioGroup.displayName = 'DropdownMenuRadioGroup'
-
-interface DropdownMenuRadioItemProps extends DropdownMenuItemProps {
- value: string
-}
-
-const DropdownMenuRadioItem = forwardRef(
- ({ children, value, className = '', ...props }, ref) => (
-
- )
-)
-DropdownMenuRadioItem.displayName = 'DropdownMenuRadioItem'
-
-export {
- DropdownMenu,
- DropdownMenuCheckboxItem,
- DropdownMenuContent,
- DropdownMenuGroup,
- DropdownMenuItem,
- DropdownMenuLabel,
- DropdownMenuPortal,
- DropdownMenuRadioGroup,
- DropdownMenuRadioItem,
- DropdownMenuSeparator,
- DropdownMenuShortcut,
- DropdownMenuSub,
- DropdownMenuSubContent,
- DropdownMenuSubTrigger,
- DropdownMenuTrigger,
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.module.scss b/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.module.scss
deleted file mode 100644
index 8c667be3a..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.module.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-// MenuItem molecule component styles
-
-.container {
- display: flex;
- align-items: center;
- gap: 16px;
- width: 100%;
-
- &.hasDescription {
- align-items: flex-start;
- }
-}
-
-.content {
- flex: 1;
-}
-
-.label {
- font-size: 0.875rem;
- line-height: 1.43;
-}
-
-.description {
- margin-top: 4px;
- color: var(--color-text-secondary, rgba(0, 0, 0, 0.6));
-}
-
-.detail {
- color: var(--color-text-secondary, rgba(0, 0, 0, 0.6));
- font-size: 0.875rem;
-}
diff --git a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.tsx b/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.tsx
deleted file mode 100644
index e13ce6cab..000000000
--- a/frontends/nextjs/src/components/ui/molecules/overlay/DropdownMenu/MenuItem.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-'use client'
-
-import { ComponentPropsWithoutRef, forwardRef, ReactNode } from 'react'
-
-import { Typography } from '@/fakemui/fakemui/data-display'
-
-import { DropdownMenuItem } from '../DropdownMenu'
-import styles from './MenuItem.module.scss'
-
-type DropdownMenuItemComponentProps = ComponentPropsWithoutRef
-
-interface MenuItemProps extends DropdownMenuItemComponentProps {
- description?: ReactNode
- detail?: ReactNode
-}
-
-const MenuItem = forwardRef(
- ({ children, description, detail, ...props }, ref) => {
- return (
-
-