Skip to content

Commit 7856092

Browse files
committed
Merge podcast branch: preserve architectural improvements + bug fixes
Resolved merge conflicts by accepting podcast's architectural refactoring while porting main's bug fixes to the new structure. Architecture changes from podcast (accepted): - Extract presentation CSS to central presentation-system.css file - Add PresentationAwareProps interface for visual components - Implement compact mode across all visual components - Add PresentationSlideContent component - Add visual components documentation Bug fixes from main (ported to new structure): - Caption sizing improvements: 0.75rem→0.8rem, 1vw→1.5vw, 0.85em→0.95em - Caption padding reduction: 1.5em→0.5em for better spacing - Add .presentationList base class for DRY principle - Update .bulletList and .takeawayList to compose base class - Add align-self: stretch to .centeredContent Conflict resolution strategy: - RevealSlideshow.module.css: Accept podcast extraction, port main fixes - manifest.json: Accept podcast regeneration - lesson-3 & lesson-2 JSONs: Accept podcast content structure - Build verified: All changes compile successfully
2 parents 4ee6052 + 75f0619 commit 7856092

24 files changed

+1704
-578
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/**
2+
* Presentation slide content wrapper styles
3+
*
4+
* Provides reusable layout primitive for all presentation slide content.
5+
* Replaces scattered centering and container patterns in RevealSlideshow.
6+
*/
7+
8+
/* Base container - flexbox with configurable alignment */
9+
.container {
10+
display: flex;
11+
flex-direction: column;
12+
width: 100%;
13+
height: 100%;
14+
margin: 0 auto;
15+
overflow: hidden; /* Constrain to slide boundaries by default */
16+
}
17+
18+
/* Content wrapper - handles scaling and centering */
19+
.content {
20+
display: flex;
21+
flex-direction: column;
22+
align-items: center;
23+
justify-content: center;
24+
width: 100%;
25+
height: 100%;
26+
}
27+
28+
/* Allow content to overflow slide boundaries (for scrollable content) */
29+
.allowOverflow {
30+
overflow: visible;
31+
}
32+
33+
.allowOverflow .content {
34+
overflow: visible;
35+
}
36+
37+
/* GPU optimization for smooth slide transitions */
38+
.gpuOptimized {
39+
will-change: transform;
40+
contain: layout paint;
41+
transform: translateZ(0);
42+
}
43+
44+
/* Responsive adjustments for edge cases */
45+
@media (max-width: 768px) {
46+
.container {
47+
max-width: 95%;
48+
}
49+
}
50+
51+
/* Accessibility - disable transforms for reduced motion */
52+
@media (prefers-reduced-motion: reduce) {
53+
.gpuOptimized {
54+
will-change: auto;
55+
transform: none;
56+
}
57+
58+
.content {
59+
transform: none !important;
60+
}
61+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import type { PresentationLayoutConfig } from './types';
3+
import styles from './PresentationSlideContent.module.css';
4+
5+
/**
6+
* Props for PresentationSlideContent wrapper component
7+
*/
8+
export interface PresentationSlideContentProps {
9+
/** Child content to render within the slide layout */
10+
children: React.ReactNode;
11+
12+
/** Layout configuration (alignment, overflow, scaling, sizing) */
13+
config?: PresentationLayoutConfig;
14+
15+
/** CSS class name to apply to the container */
16+
className?: string;
17+
18+
/** Enable GPU optimization for smooth animations */
19+
gpuOptimized?: boolean;
20+
}
21+
22+
/**
23+
* Wrapper component for presentation slide content
24+
*
25+
* Provides consistent layout, spacing, and positioning for all slide types.
26+
* Eliminates the need for ad-hoc centering classes and visual containers.
27+
*
28+
* Features:
29+
* - Vertical alignment control (flex-start, center, space-between, etc.)
30+
* - Overflow handling (scrollable vs constrained)
31+
* - Content scaling for visual prominence
32+
* - Max width/height constraints
33+
* - GPU optimization for smooth transitions
34+
*
35+
* Usage:
36+
* ```tsx
37+
* <PresentationSlideContent
38+
* config={{
39+
* verticalAlign: 'center',
40+
* scaleContent: 1.5,
41+
* maxWidthPercent: 90
42+
* }}
43+
* >
44+
* <MyVisualComponent compact />
45+
* </PresentationSlideContent>
46+
* ```
47+
*/
48+
export const PresentationSlideContent: React.FC<
49+
PresentationSlideContentProps
50+
> = ({ children, config = {}, className = '', gpuOptimized = false }) => {
51+
const {
52+
verticalAlign = 'flex-start',
53+
allowOverflow = false,
54+
scaleContent = 1.0,
55+
maxWidthPercent = 90,
56+
maxHeightPercent = 85,
57+
} = config;
58+
59+
// Build CSS classes
60+
const containerClasses = [
61+
styles.container,
62+
gpuOptimized && styles.gpuOptimized,
63+
allowOverflow && styles.allowOverflow,
64+
className,
65+
]
66+
.filter(Boolean)
67+
.join(' ');
68+
69+
// Build inline styles for dynamic configuration
70+
const containerStyle: React.CSSProperties = {
71+
justifyContent: verticalAlign,
72+
maxWidth: `${maxWidthPercent}%`,
73+
maxHeight: `${maxHeightPercent}%`,
74+
};
75+
76+
const contentStyle: React.CSSProperties =
77+
scaleContent !== 1.0
78+
? {
79+
transform: `scale(${scaleContent})`,
80+
transformOrigin: 'center center',
81+
}
82+
: {};
83+
84+
return (
85+
<div className={containerClasses} style={containerStyle}>
86+
<div className={styles.content} style={contentStyle}>
87+
{children}
88+
</div>
89+
</div>
90+
);
91+
};

website/src/components/PresentationMode/RevealSlideshow.module.css

Lines changed: 19 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -54,25 +54,22 @@
5454
.objectives {
5555
margin-top: 1.5em;
5656
text-align: left;
57-
max-width: 100%;
57+
max-width: 90%;
5858
margin-left: auto;
5959
margin-right: auto;
60+
display: flex;
61+
flex-direction: column;
62+
justify-content: center;
6063
}
6164

6265
.objectives h3 {
6366
font-size: clamp(1rem, 2vw, 1.2em);
6467
margin-bottom: 0.5em;
65-
margin-left: 0;
66-
margin-right: 0;
6768
}
6869

69-
:global(.reveal) .objectives ul {
70+
.objectives ul {
7071
list-style: none;
7172
padding: 0;
72-
display: block;
73-
max-width: 100%;
74-
margin-left: 0;
75-
margin-right: 0;
7673
}
7774

7875
.objectives li {
@@ -129,14 +126,11 @@
129126
overflow-y: auto;
130127
overflow-x: auto;
131128
height: 100%;
132-
white-space: pre-wrap;
129+
white-space: pre;
133130
}
134131

135-
:global(.reveal) .codeBlock code {
132+
.codeBlock code {
136133
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
137-
word-break: break-word;
138-
white-space: pre-wrap;
139-
overflow-wrap: break-word;
140134
}
141135

142136
.codeBlockSmall {
@@ -151,14 +145,11 @@
151145
overflow-y: auto;
152146
overflow-x: auto;
153147
max-height: 400px;
154-
white-space: pre-wrap;
148+
white-space: pre;
155149
}
156150

157-
:global(.reveal) .codeBlockSmall code {
151+
.codeBlockSmall code {
158152
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
159-
word-break: break-word;
160-
white-space: pre-wrap;
161-
overflow-wrap: break-word;
162153
}
163154

164155
.caption {
@@ -311,11 +302,15 @@
311302
align-items: center;
312303
overflow: visible;
313304
width: 100%;
305+
height: 100%;
306+
max-height: 100%;
314307
transform-origin: center center;
315308
}
316309

317310
.visualContainer > * {
318311
object-fit: contain;
312+
max-width: 100%;
313+
max-height: 100%;
319314
}
320315

321316
.takeawayList {
@@ -481,131 +476,9 @@
481476
padding: 2em;
482477
}
483478

484-
/* Override Reveal.js theme colors to match course design */
485-
:global(.reveal) {
486-
font-family: var(--ifm-font-family-base);
487-
}
488-
489-
:global(.reveal h1),
490-
:global(.reveal h2),
491-
:global(.reveal h3),
492-
:global(.reveal h4) {
493-
font-family: var(--ifm-font-family-base);
494-
font-weight: 700;
495-
}
496-
497-
:global(.reveal h1) {
498-
font-size: clamp(2.5rem, 4.5vw, 3em);
499-
color: var(--ifm-color-primary);
500-
max-width: 90%;
501-
margin-left: auto;
502-
margin-right: auto;
503-
word-wrap: break-word;
504-
}
505-
506-
:global(.reveal h2) {
507-
font-size: clamp(1.2rem, 2.5vw, 1.5em);
508-
color: var(--ifm-color-primary);
509-
max-width: 90%;
510-
margin-left: auto;
511-
margin-right: auto;
512-
word-wrap: break-word;
513-
}
514-
515-
:global(.reveal h3) {
516-
font-size: clamp(1rem, 2vw, 1.3em);
517-
max-width: 90%;
518-
margin-left: auto;
519-
margin-right: auto;
520-
word-wrap: break-word;
521-
}
522-
523-
:global(.reveal .controls) {
524-
color: var(--ifm-color-primary);
525-
}
526-
527-
:global(.reveal .progress) {
528-
background: rgba(0, 0, 0, 0.2);
529-
}
530-
531-
:global(.reveal .progress span) {
532-
background: var(--ifm-color-primary);
533-
}
534-
535-
/* Enable dark mode CSS variables for all components in presentation mode */
536-
:global(.reveal) {
537-
--ifm-font-color-base: #c9d1d9;
538-
--ifm-heading-color: #e6edf3;
539-
--ifm-color-emphasis-700: #8b949e;
540-
--ifm-color-emphasis-600: #6e7681;
541-
--ifm-color-emphasis-300: #3d444d;
542-
--ifm-color-emphasis-200: #30363d;
543-
--ifm-background-color: #0d1117;
544-
--ifm-background-surface-color: #161b22;
545-
546-
/* Visual element colors - adjusted for dark mode */
547-
--visual-workflow: #a78bfa;
548-
--visual-capability: #22d3ee;
549-
--visual-limitation: #fb923c;
550-
--visual-decision: #c4b5fd;
551-
--visual-error: #fb7185;
552-
--visual-neutral: #94a3b8;
553-
554-
/* Visual element backgrounds */
555-
--visual-bg-workflow: rgba(167, 139, 250, 0.15);
556-
--visual-bg-capability: rgba(34, 211, 238, 0.15);
557-
--visual-bg-limitation: rgba(251, 146, 60, 0.15);
558-
--visual-bg-decision: rgba(196, 181, 253, 0.15);
559-
}
560-
561-
/* Fixed layout structure for consistent positioning across slides */
562-
:global(.reveal .slides section) {
563-
max-width: 95%;
564-
margin-left: auto;
565-
margin-right: auto;
566-
height: 100%;
567-
display: flex !important;
568-
flex-direction: column;
569-
justify-content: flex-start;
570-
padding: 1em 0 2.5em 0;
571-
box-sizing: border-box;
572-
}
573-
574-
/* Title area - fixed height and position */
575-
:global(.reveal .slides section > h2) {
576-
margin-top: 0;
577-
margin-bottom: 0.5em;
578-
flex-shrink: 0;
579-
}
580-
581-
/* Title slides have h1 instead */
582-
:global(.reveal .slides section > h1) {
583-
margin-top: 2em;
584-
margin-bottom: 0;
585-
flex-shrink: 0;
586-
}
587-
588-
/* Content area - fills remaining space with natural flow (safe by default) */
589-
:global(.reveal .slides section)
590-
> *:not(h1):not(h2):not(.slideCaption):not(.subtitle) {
591-
flex-grow: 1;
592-
min-height: 0;
593-
margin-top: 0.5em;
594-
}
595-
596-
/* Caption area - fixed at bottom when present */
597-
:global(.reveal) .slideCaption {
598-
margin-top: auto;
599-
margin-bottom: 2em;
600-
flex-shrink: 0;
601-
padding-top: 0.5em;
602-
padding-bottom: 0;
603-
}
604-
605-
:global(.reveal p:not(.slideCaption)),
606-
:global(.reveal ul),
607-
:global(.reveal ol) {
608-
max-width: 90%;
609-
margin-left: auto;
610-
margin-right: auto;
611-
}
479+
/**
480+
* NOTE: Core Reveal.js overrides (typography, layout, dark mode CSS variables)
481+
* have been moved to /website/src/styles/presentation-system.css
482+
*
483+
* This file now contains only component-specific styles for RevealSlideshow.
484+
*/

0 commit comments

Comments
 (0)