Skip to content

Commit e293313

Browse files
committed
Enhance fullscreen plugin functionality and styles
- Added CSS to align buttons in figcaption and improve button visibility on hover. - Updated logic to append fullscreen button based on frame title and terminal status. - Implemented auto-expansion for collapsed code blocks in fullscreen mode for better compatibility.
1 parent c457e8f commit e293313

1 file changed

Lines changed: 39 additions & 13 deletions

File tree

  • packages/expressive-code-fullscreen/src

packages/expressive-code-fullscreen/src/index.ts

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -318,18 +318,27 @@ export function pluginFullscreen(options: FullscreenPluginOptions = {}) {
318318
z-index: 100;
319319
}
320320
321+
/* Push all buttons in figcaption to the right as a group */
322+
figcaption button:first-of-type {
323+
margin-inline-start: auto !important;
324+
}
325+
321326
/* When inside figcaption header, use flex-compatible relative positioning and always visible */
322327
figcaption .cb-fullscreen__button,
323328
.header .cb-fullscreen__button {
324329
position: relative !important;
325330
top: auto !important;
326331
right: auto !important;
327-
margin-inline-start: auto;
328332
margin-inline-end: 0.5rem;
329333
opacity: 1 !important;
330334
transform: none !important;
331335
}
332336
337+
/* Push button down slightly for titled non-terminal blocks */
338+
.expressive-code.has-title:not(.is-terminal) figcaption .cb-fullscreen__button {
339+
margin-top: 0.25rem;
340+
}
341+
333342
/* Override hover effects for header buttons - keep them stable */
334343
figcaption .cb-fullscreen__button:hover,
335344
.header .cb-fullscreen__button:hover {
@@ -339,22 +348,22 @@ export function pluginFullscreen(options: FullscreenPluginOptions = {}) {
339348
340349
/* Hover-only visibility for untitled, non-terminal blocks (only buttons outside figcaption) */
341350
${config.showOnHoverOnly ? `
342-
.expressive-code:not(.has-title) .frame:not(.is-terminal) > .cb-fullscreen__button {
351+
.expressive-code:not(.has-title):not(.is-terminal) > .cb-fullscreen__button {
343352
opacity: 0;
344353
transition: opacity 0.2s ease, background-color 0.2s, border-color 0.2s, transform 0.2s ease;
345354
}
346355
347-
.expressive-code:not(.has-title):hover .frame:not(.is-terminal) > .cb-fullscreen__button,
348-
.expressive-code:not(.has-title) .frame:not(.is-terminal) > .cb-fullscreen__button:focus,
349-
.expressive-code:not(.has-title) .frame:not(.is-terminal) > .cb-fullscreen__button:focus-visible {
356+
.expressive-code:not(.has-title):not(.is-terminal):hover > .cb-fullscreen__button,
357+
.expressive-code:not(.has-title):not(.is-terminal) > .cb-fullscreen__button:focus,
358+
.expressive-code:not(.has-title):not(.is-terminal) > .cb-fullscreen__button:focus-visible {
350359
opacity: 0.7;
351360
border: 2px solid #888888 !important;
352361
border-radius: 0.25rem !important;
353362
}
354363
355364
/* Mobile/touch device fallback - show button on touch devices */
356365
@media (hover: none) and (pointer: coarse) {
357-
.expressive-code:not(.has-title) .frame:not(.is-terminal) > .cb-fullscreen__button {
366+
.expressive-code:not(.has-title):not(.is-terminal) > .cb-fullscreen__button {
358367
opacity: 0.7;
359368
}
360369
}
@@ -528,14 +537,21 @@ export function pluginFullscreen(options: FullscreenPluginOptions = {}) {
528537
return;
529538
}
530539

531-
const figcaption = frameElement.children?.find(
532-
(child: any) => child.type === 'element' && child.tagName === 'figcaption'
533-
);
534-
535-
if (figcaption && figcaption.type === 'element') {
536-
figcaption.children = figcaption.children || [];
537-
figcaption.children.push(fullscreenButton);
540+
// Only append to figcaption if the frame has a visible header (title or terminal)
541+
if (hasTitle || isTerminal) {
542+
const figcaption = frameElement.children?.find(
543+
(child: any) => child.type === 'element' && child.tagName === 'figcaption'
544+
);
545+
546+
if (figcaption && figcaption.type === 'element') {
547+
figcaption.children = figcaption.children || [];
548+
figcaption.children.push(fullscreenButton);
549+
} else {
550+
frameElement.children = frameElement.children || [];
551+
frameElement.children.push(fullscreenButton);
552+
}
538553
} else {
554+
// For untitled, non-terminal blocks, append to frame for absolute positioning
539555
frameElement.children = frameElement.children || [];
540556
frameElement.children.push(fullscreenButton);
541557
}
@@ -777,6 +793,16 @@ export function pluginFullscreen(options: FullscreenPluginOptions = {}) {
777793
clonedBlock.classList.add('expressive-code');
778794
}
779795
796+
// Auto-expand collapsed code blocks in fullscreen (for expressive-code-collapsible compatibility)
797+
const collapseWrapper = clonedBlock.querySelector('.ec-collapse--collapsed');
798+
if (collapseWrapper) {
799+
collapseWrapper.classList.remove('ec-collapse--collapsed');
800+
collapseWrapper.classList.add('ec-collapse--expanded');
801+
802+
// Update aria-expanded on collapse toggle buttons
803+
const collapseButtons = collapseWrapper.querySelectorAll('.ec-collapse__toggle, .ec-collapse__header-toggle');
804+
collapseButtons.forEach(btn => btn.setAttribute('aria-expanded', 'true'));
805+
}
780806
781807
// Force full width with inline styles.
782808
// Styles handled in baseStyles (.expressive-code.cb-fullscreen__active).

0 commit comments

Comments
 (0)