diff --git a/RESTYLE.md b/RESTYLE.md new file mode 100644 index 0000000..8581d53 --- /dev/null +++ b/RESTYLE.md @@ -0,0 +1,247 @@ +# Semantic Styling Framework Refactoring Checklist + +This document tracks the refactoring of our CSS and TSX files to use the semantic styling framework, eliminating duplicate CSS and creating consistent component patterns. + +## Framework Overview + +Our semantic styling framework consists of: +- **`colors.css`** - CSS variables and color system +- **`semantic-components.css`** - Semantic component classes (cards, badges, actions, drag-and-drop, etc.) +- **`application.css`** - Utility classes and base component styles +- **`aspectRatios.css`** - Dedicated aspect ratio styling for slides (preserved) + +## Refactoring Principles + +1. **Use semantic classes** instead of component-specific CSS +2. **Leverage CSS variables** for colors, spacing, and typography +3. **Eliminate duplicate styles** by consolidating common patterns +4. **Preserve presentation/theme CSS** - slides should NOT use semantic framework +5. **Only keep minimal component-specific CSS** when absolutely necessary + +--- + +## ✅ COMPLETED REFACTORING + +### Core Framework Files +- **`src/styles/colors.css`** ✅ - Comprehensive CSS variable system +- **`src/styles/semantic-components.css`** ✅ - Semantic component classes +- **`src/styles/application.css`** ✅ - Utility classes and base styles +- **`src/styles/aspectRatios.css`** ✅ - Preserved dedicated slide aspect ratios + +### Presentation Components +- **`src/components/presentations/PresentationEditor.tsx`** ✅ - Uses semantic classes +- **`src/components/presentations/PresentationEditor.css`** ✅ - Reduced by ~85%, only layout-specific CSS +- **`src/components/presentations/SlidesSidebar.tsx`** ✅ - Uses semantic classes +- **`src/components/presentations/SlidesSidebar.css`** ✅ - Minimal component-specific CSS +- **`src/components/presentations/shared/SlideThumbnail.tsx`** ✅ - Uses semantic classes +- **`src/components/presentations/shared/SlideThumbnail.css`** ✅ - Minimal component overrides +- **`src/components/presentations/PresentationMode.tsx`** ✅ - Uses semantic classes for UI +- **`src/components/presentations/PresentationMode.css`** ✅ - Isolated slide content from semantic framework +- **`src/components/presentations/shared/LoadingState.tsx`** ✅ - Uses semantic classes +- **`src/components/presentations/shared/LoadingState.css`** ✅ - Minimal overrides +- **`src/components/presentations/shared/ErrorState.tsx`** ✅ - Uses semantic classes (slide-editor version) +- **`src/components/presentations/shared/ErrorState.css`** ✅ - Minimal overrides + +### Slide Operations +- **`src/hooks/useSlideOperations.ts`** ✅ - Added drag-and-drop reordering functionality + +--- + +## 🚧 NEEDS REFACTORING + +### High Priority - Presentation Components + +#### **`src/components/presentations/NewPresentationPage.tsx`** +- **Status**: Partially refactored (documented in CSS) +- **Needs**: Full TSX refactoring to use semantic classes +- **Current Issues**: Uses custom classes that could be semantic utilities + +#### **`src/components/presentations/NewPresentationPage.css`** +- **Status**: Has some semantic references but needs full refactoring +- **Needs**: Remove duplicate styles, use semantic framework +- **Current Issues**: Custom `.creation-form`, `.aspect-ratio-card` styles + +#### **`src/components/presentations/ThemeSelector.tsx`** +- **Status**: Not refactored +- **Needs**: Use semantic classes for cards, grids, badges +- **Current Issues**: Likely uses hardcoded CSS classes + +#### **`src/components/presentations/ThemeSelector.css`** +- **Status**: Partially refactored (hardcoded colors removed) +- **Needs**: Complete semantic class integration +- **Current Issues**: Custom `.theme-card`, `.themes-grid` could use semantic classes + +#### **`src/components/presentations/PresentationsList.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Full refactoring assessment +- **Likely Issues**: Custom card layouts, button styles + +#### **`src/components/presentations/PresentationsList.css`** +- **Status**: Not examined/refactored +- **Needs**: Full refactoring assessment +- **Likely Issues**: Duplicate card, button, grid styles + +### Medium Priority - Form Components + +#### **`src/components/presentations/PresentationDetailsForm.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic form classes +- **Likely Issues**: Custom form styling + +#### **`src/components/presentations/PresentationDetailsForm.css`** +- **Status**: Not examined/refactored +- **Needs**: Use `.form-group`, `.form-input`, `.form-label` semantic classes +- **Likely Issues**: Duplicate form styles + +#### **`src/components/presentations/AspectRatioSelector.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic card and selection classes +- **Likely Issues**: Custom card selection UI + +#### **`src/components/presentations/AspectRatioSelector.css`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic `.card-interactive` and selection states +- **Likely Issues**: Custom card hover/selection styles + +### Lower Priority - Supporting Components + +#### **`src/components/presentations/CreationActions.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic button classes +- **Likely Issues**: Custom button layouts + +#### **`src/components/presentations/CreationActions.css`** +- **Status**: Not examined/refactored +- **Needs**: Use `.btn`, `.btn-primary`, `.btn-secondary` classes +- **Likely Issues**: Duplicate button styles + +#### **`src/components/presentations/ThemeSelectionSection.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic layout and card classes +- **Likely Issues**: Custom section layouts + +#### **`src/components/presentations/ThemeSelectionSection.css`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic grid and card classes +- **Likely Issues**: Custom grid layouts + +#### **`src/components/presentations/EmptyPresentationState.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Use semantic empty state classes +- **Likely Issues**: Custom empty state styling + +#### **`src/components/presentations/EmptyPresentationState.css`** +- **Status**: Not examined/refactored +- **Needs**: Use `.empty-content` semantic class +- **Likely Issues**: Duplicate empty state styles + +### Slide Editor Components (Lower Priority) + +#### **`src/components/slide-editor/SlideEditor.tsx`** +- **Status**: Not examined/refactored +- **Needs**: Assessment for semantic class usage +- **Note**: May have complex layout requirements + +#### **`src/components/slide-editor/SlideEditor.css`** +- **Status**: Not examined/refactored +- **Needs**: Assessment for consolidation opportunities +- **Note**: May need to preserve slide-specific styling + +### Theme Components + +#### **`src/components/themes/` (Multiple files)** +- **Status**: Not examined for this refactoring +- **Priority**: Low (theme browsing is separate from presentations) +- **Needs**: Future assessment + +### UI Components + +#### **`src/components/ui/` (Multiple files)** +- **Status**: Not examined for this refactoring +- **Priority**: Medium (shared components should use semantic framework) +- **Needs**: Future assessment for modal, dialog, form components + +--- + +## 🎯 NEXT STEPS + +### Immediate Priority (Sprint 1) +1. **NewPresentationPage.tsx** - Full semantic refactoring +2. **ThemeSelector.tsx** - Use semantic card and grid classes +3. **PresentationsList.tsx** - Assessment and refactoring + +### Short Term (Sprint 2) +1. **Form Components** - PresentationDetailsForm, AspectRatioSelector +2. **Supporting Components** - CreationActions, ThemeSelectionSection +3. **Empty States** - EmptyPresentationState + +### Long Term (Sprint 3) +1. **Slide Editor Components** - Assessment and selective refactoring +2. **UI Components** - Modal, dialog, form utilities +3. **Theme Components** - If needed for consistency + +--- + +## 📋 REFACTORING CHECKLIST + +For each component refactoring, ensure: + +### TSX File Updates +- [ ] Replace custom CSS classes with semantic classes +- [ ] Use utility classes for layout (`flex`, `gap-4`, `items-center`, etc.) +- [ ] Use semantic typography classes (`text-lg`, `font-semibold`, etc.) +- [ ] Use semantic color classes (`text-primary`, `bg-secondary`, etc.) +- [ ] Use semantic component classes (`.card-interactive`, `.btn`, `.badge-secondary`, etc.) +- [ ] Remove imports of CSS files that become empty + +### CSS File Updates +- [ ] Remove duplicate styles covered by semantic framework +- [ ] Replace hardcoded colors with CSS variables +- [ ] Keep only truly component-specific styling +- [ ] Use semantic classes as base, add minimal overrides only +- [ ] Document what semantic classes replace in comments +- [ ] Delete CSS file if it becomes empty/unnecessary + +### Testing Requirements +- [ ] Visual consistency with existing design +- [ ] Interactive states work correctly (hover, focus, disabled) +- [ ] Responsive behavior maintained +- [ ] No regression in functionality +- [ ] Accessibility maintained (focus states, etc.) + +--- + +## 🚨 SPECIAL CONSIDERATIONS + +### Presentation/Slide Content Isolation +- **Theme CSS** (`public/themes/default/style.css`) must remain completely isolated +- **Slide content** should NEVER use semantic framework classes +- **PresentationMode** must prevent semantic class interference with slide rendering +- **AspectRatios.css** preserved for slide-specific aspect ratio handling + +### Performance Considerations +- **Bundle size reduction** achieved through elimination of duplicate CSS +- **CSS loading order** maintained (colors → semantic-components → application) +- **Critical CSS** identified and preserved for above-the-fold content + +### Drag-and-Drop Functionality +- **Semantic drag classes** implemented and working (`.draggable`, `.dragged`, `.drag-over`, `.drag-handle`) +- **Slide reordering** functionality preserved and enhanced +- **Visual feedback** consistent across all drag operations + +--- + +## 📊 PROGRESS SUMMARY + +- **✅ Completed**: 14 files (Core framework + key presentation components) +- **🚧 Needs Refactoring**: ~15-20 files (High and medium priority) +- **📈 CSS Reduction**: ~85% reduction achieved in refactored files +- **🎨 Consistency**: Semantic framework provides consistent design patterns +- **⚡ Performance**: Reduced CSS bundle size and eliminated duplicates + +**Estimated Completion**: 2-3 sprints for high/medium priority items + +--- + +*Last Updated: September 28, 2025* +*Framework Version: 1.0* diff --git a/src/components/presentations/PresentationEditor.css b/src/components/presentations/PresentationEditor.css index 8a50526..0f361ab 100644 --- a/src/components/presentations/PresentationEditor.css +++ b/src/components/presentations/PresentationEditor.css @@ -1,3 +1,5 @@ +/* Presentation Editor - Minimal component-specific styles only */ + .presentation-editor { min-height: 100vh; background: var(--bg-primary); @@ -5,161 +7,28 @@ flex-direction: column; } -/* Header */ -.editor-header { - background: var(--bg-secondary); - border-bottom: 1px solid var(--border-primary); - padding: 1rem 2rem; +/* Component-specific layout overrides only */ +.editor-layout { display: flex; - justify-content: space-between; - align-items: center; - gap: 2rem; - flex-wrap: wrap; -} - -.presentation-info { - display: flex; - align-items: center; - gap: 1.5rem; flex: 1; - min-width: 0; + min-height: 0; } -.back-link { - color: var(--text-secondary); - text-decoration: none; - font-weight: 500; - font-size: 0.875rem; - padding: 0.5rem 0.75rem; - border-radius: 0.375rem; - transition: all 0.2s ease; - flex-shrink: 0; -} - -.back-link:hover { - background: var(--bg-hover); - color: var(--text-primary); -} - -.presentation-title span { - color: var(--text-secondary); - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} -.presentation-meta { - display: flex; - gap: 1rem; - align-items: center; - flex-shrink: 0; - flex-wrap: wrap; -} - -.theme-badge { - background: var(--color-blue-100); - color: var(--color-blue-800); - padding: 0.25rem 0.75rem; - border-radius: 0.375rem; - font-size: 0.75rem; - font-weight: 500; -} - -.slide-counter { - color: var(--text-tertiary); - font-size: 0.875rem; - font-weight: 500; -} - -.saving-indicator { - color: var(--text-warning); - font-size: 0.875rem; - font-weight: 500; -} - -.editor-actions { - display: flex; - gap: 0.75rem; - flex-shrink: 0; -} - -.action-button { - padding: 0.5rem 1rem; - border-radius: 0.375rem; - font-weight: 500; - font-size: 0.875rem; - border: none; - cursor: pointer; - transition: all 0.2s ease; - text-decoration: none; - display: inline-flex; - align-items: center; - justify-content: center; -} - -.action-button.primary { - background: var(--btn-primary-bg); - color: var(--btn-primary-text); -} - -.action-button.primary:hover:not(:disabled) { - background: var(--btn-primary-bg-hover); -} - -.action-button.secondary { - background: var(--btn-secondary-bg); - color: var(--btn-secondary-text); - border: 1px solid var(--btn-secondary-border); -} - -.action-button.secondary:hover:not(:disabled) { - background: var(--btn-secondary-bg-hover); - color: var(--btn-secondary-text-hover); -} - -.action-button.large { - padding: 0.75rem 1.5rem; - font-size: 1rem; -} - -.action-button:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -/* Main Content */ -.editor-content { +.slide-editor-area { flex: 1; display: flex; flex-direction: column; + min-width: 0; } -/* Empty State */ -.empty-presentation { +.slide-editor { flex: 1; display: flex; - align-items: center; - justify-content: center; - padding: 2rem; + flex-direction: column; + padding: 1rem; } -.empty-content { - text-align: center; - max-width: 800px; -} - -.empty-content h2 { - margin: 0 0 0.5rem 0; - color: var(--text-secondary); - font-size: 1.5rem; -} - -.empty-content p { - margin: 0 0 2rem 0; - color: var(--text-tertiary); - font-size: 1rem; -} - -/* Theme Preview in Empty State */ +/* Theme preview in empty state - component specific */ .theme-preview { background: var(--bg-primary); border: 1px solid var(--border-primary); @@ -173,19 +42,6 @@ flex-direction: column; } -.theme-preview h3 { - margin: 0 0 0.5rem 0; - color: var(--text-primary); - font-size: 1.25rem; - font-weight: 600; -} - -.theme-description { - margin: 0 0 1.5rem 0; - color: var(--text-secondary); - font-size: 0.875rem; -} - .available-layouts { flex: 1; min-height: 0; @@ -193,14 +49,6 @@ flex-direction: column; } -.available-layouts h4 { - margin: 0 0 1rem 0; - color: var(--text-secondary); - font-size: 1rem; - font-weight: 600; - flex-shrink: 0; -} - .layouts-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); @@ -229,361 +77,12 @@ background: var(--color-slate-400); } -.layout-preview-card { - background: var(--bg-secondary); - border: 1px solid var(--border-primary); - border-radius: 0.5rem; - padding: 1rem; - transition: all 0.2s ease; -} - -.layout-preview-card:hover { - border-color: var(--border-hover); - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); -} - -.layout-name { - font-weight: 600; - color: var(--text-primary); - font-size: 0.875rem; - margin-bottom: 0.25rem; -} - -.layout-description { - color: var(--text-secondary); - font-size: 0.75rem; - margin-bottom: 0.5rem; - line-height: 1.4; -} - -.slot-count { - color: var(--color-emerald-600); - font-size: 0.75rem; - font-weight: 500; -} - -.more-layouts { - display: flex; - align-items: center; - justify-content: center; - background: var(--bg-tertiary); - border: 1px dashed var(--border-hover); - border-radius: 0.5rem; - padding: 1rem; - color: var(--text-secondary); - font-size: 0.875rem; - font-weight: 500; -} - -/* Editor Layout */ -.editor-layout { - display: flex; - flex: 1; - min-height: 0; -} - -/* Slide Sidebar */ -.slide-sidebar { - width: 280px; - background: var(--bg-secondary); - border-right: 1px solid var(--border-primary); - display: flex; - flex-direction: column; -} - -.sidebar-header { - padding: 1rem; - border-bottom: 1px solid var(--border-primary); - display: flex; - justify-content: space-between; - align-items: center; -} - -.sidebar-header h3 { - margin: 0; - font-size: 1rem; - font-weight: 600; - color: var(--text-primary); -} - -.add-slide-button { - width: 32px; - height: 32px; - border: 1px solid var(--border-primary); - background: var(--bg-secondary); - border-radius: 0.375rem; - cursor: pointer; - font-size: 1.25rem; - color: var(--text-accent); - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s ease; -} - -.add-slide-button:hover:not(:disabled) { - background: var(--bg-hover); - border-color: var(--border-accent); -} - -.add-slide-button:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.slides-list { - flex: 1; - overflow-y: auto; - padding: 0.5rem; -} - -/* Slide thumbnails specific to editor layout - positioning only */ +/* Slide thumbnail positioning in editor context */ .slide-thumbnail { margin-bottom: 0.5rem; } -/* Layout-related thumbnail styles moved to SlideThumbnail.css */ - - -/* Slide Editor Area */ -.slide-editor-area { - flex: 1; - display: flex; - flex-direction: column; - min-width: 0; -} - -.slide-editor { - flex: 1; - display: flex; - flex-direction: column; - padding: 1rem; -} - -.slide-header { - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 1rem; - gap: 1rem; - flex-wrap: wrap; -} - -.slide-header h3 { - margin: 0; - font-size: 1.125rem; - font-weight: 600; - color: var(--text-primary); -} - -.slide-controls { - display: flex; - gap: 0.5rem; -} - -.control-button { - padding: 0.375rem 0.75rem; - border: 1px solid var(--border-primary); - background: var(--bg-secondary); - color: var(--text-secondary); - border-radius: 0.375rem; - cursor: pointer; - font-weight: 500; - font-size: 0.875rem; - transition: all 0.2s ease; -} - -.control-button:hover:not(:disabled) { - background: var(--bg-hover); - border-color: var(--border-hover); -} - -.control-button:disabled { - opacity: 0.5; - cursor: not-allowed; -} - -.control-button.edit-slide-button { - background: var(--btn-primary-bg); - color: var(--btn-primary-text); - border-color: var(--btn-primary-border); - font-weight: 600; -} - -.control-button.edit-slide-button:hover:not(:disabled) { - background: var(--btn-primary-bg-hover); - border-color: var(--btn-primary-border-hover); -} - -.slide-content-editor { - flex: 1; - display: flex; - flex-direction: column; - gap: 1rem; -} - -.content-preview { - flex: 1; - background: var(--bg-secondary); - border: 1px solid var(--border-primary); - border-radius: 0.75rem; - padding: 2rem; - min-height: 400px; -} - -.editor-placeholder { - text-align: center; - color: var(--text-tertiary); -} - -.editor-placeholder h4 { - margin: 0 0 1rem 0; - color: var(--text-secondary); -} - -.editor-placeholder p { - margin: 0.5rem 0; -} - -.content-slots { - margin: 1.5rem 0; - text-align: left; -} - -.content-slot { - margin-bottom: 1rem; - padding: 0.75rem; - background: var(--bg-primary); - border-radius: 0.375rem; -} - -.content-slot label { - display: block; - font-weight: 500; - color: var(--text-secondary); - margin-bottom: 0.25rem; - font-size: 0.875rem; -} - -.slot-content { - color: var(--text-tertiary); - font-size: 0.875rem; -} - -.placeholder-note { - font-style: italic; - color: var(--text-muted); - margin-top: 1.5rem; -} - -.slide-notes-editor { - background: var(--bg-secondary); - border: 1px solid var(--border-primary); - border-radius: 0.75rem; - padding: 1rem; -} - -.slide-notes-editor h4 { - margin: 0 0 0.75rem 0; - font-size: 0.875rem; - font-weight: 600; - color: var(--text-secondary); -} - -.notes-textarea { - width: 100%; - min-height: 80px; - padding: 0.75rem; - border: 1px solid var(--border-secondary); - border-radius: 0.5rem; - font-size: 0.875rem; - color: var(--text-secondary); - background: var(--bg-secondary); - box-sizing: border-box; - resize: vertical; - font-family: inherit; -} - -.notes-textarea:focus { - outline: none; - border-color: var(--border-focus); - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); -} - -.slide-error { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 2rem; - text-align: center; - color: var(--text-error); -} - -/* Loading and Error States */ -.loading-content, -.error-content, -.not-found-content { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: 50vh; - text-align: center; - gap: 1rem; -} - -.loading-spinner { - color: var(--text-secondary); - font-size: 1.125rem; -} - -.error-content h2, -.not-found-content h2 { - color: var(--text-error); - margin: 0; -} - -.error-content p, -.not-found-content p { - color: var(--text-secondary); - margin: 0.5rem 0 1.5rem 0; -} - -/* Responsive Design */ -@media (max-width: 1024px) { - .slide-sidebar { - width: 240px; - } - - .editor-header { - padding: 1rem; - flex-direction: column; - align-items: stretch; - gap: 1rem; - } - - .presentation-info { - flex-direction: column; - align-items: flex-start; - gap: 1rem; - } - - .presentation-meta { - flex-direction: column; - align-items: flex-start; - gap: 0.5rem; - } - - .editor-actions { - justify-content: stretch; - } - - .action-button { - flex: 1; - } -} - +/* Responsive design */ @media (max-width: 768px) { .editor-layout { flex-direction: column; @@ -592,32 +91,5 @@ .slide-sidebar { width: 100%; max-height: 200px; - border-right: none; - border-bottom: 1px solid var(--border-primary); - } - - .slides-list { - display: flex; - gap: 0.5rem; - overflow-x: auto; - padding: 0.5rem; - } - - .slide-thumbnail { - min-width: 120px; - margin-bottom: 0; - } - - .slide-header { - flex-direction: column; - align-items: stretch; - } - - .slide-controls { - justify-content: stretch; - } - - .control-button { - flex: 1; } } \ No newline at end of file diff --git a/src/components/presentations/PresentationEditor.tsx b/src/components/presentations/PresentationEditor.tsx index 5fc75b4..cf9f55e 100644 --- a/src/components/presentations/PresentationEditor.tsx +++ b/src/components/presentations/PresentationEditor.tsx @@ -140,25 +140,23 @@ export const PresentationEditor: React.FC = () => { return (
-
-
- ← Back to Presentations -
- {presentation.metadata.name} - {presentation.metadata.description && ( - {presentation.metadata.description} - )} -
-
- - {totalSlides === 0 ? 'No slides' : `Slide ${currentSlideIndex + 1} of ${totalSlides}`} - - {saving && Saving...} -
+
+ ← Back to Presentations +
+

{presentation.metadata.name}

+ {presentation.metadata.description && ( +

{presentation.metadata.description}

+ )} +
+
+ + {totalSlides === 0 ? 'No slides' : `Slide ${currentSlideIndex + 1} of ${totalSlides}`} + + {saving && Saving...}
-
+
{totalSlides === 0 ? ( {
{currentSlide ? (
-
-

Slide {currentSlideIndex + 1}

+
+

Slide {currentSlideIndex + 1}

-
-
+
+
{/* TODO: Render actual slide content with editing capabilities */} -
-
+
+
{Object.entries(currentSlide.content).map(([slotId, content]) => ( -
- -
{content || '(empty)'}
+
+ +
{content || '(empty)'}
))}
-

+

Interactive slide editor will be implemented next

{currentSlide.notes && ( -
-

Speaker Notes

-