feat(story-blocks): add full-bleed and image-caption shortcodes
Two new shortcodes for immersive storytelling: - [full-bleed image="" caption="" credit=""] — viewport-wide image, max 80vh - [image-caption image="" caption="" credit="" width="column|full|bleed"] — photo at configurable width with caption Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPJztrVGbwic2xTG7G9fjM
This commit is contained in:
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Plugin\Shortcodes;
|
||||||
|
|
||||||
|
use Thunder\Shortcode\Shortcode\ShortcodeInterface;
|
||||||
|
|
||||||
|
class FullBleedShortcode extends Shortcode
|
||||||
|
{
|
||||||
|
public function init(): void
|
||||||
|
{
|
||||||
|
$this->shortcode->getHandlers()->add('full-bleed', function (ShortcodeInterface $sc) {
|
||||||
|
$plugin = $this->grav['plugins']->getPlugin('story-blocks');
|
||||||
|
$page = $plugin ? $plugin->getCurrentPage() : null;
|
||||||
|
|
||||||
|
$imageName = htmlspecialchars($sc->getParameter('image', ''), ENT_QUOTES);
|
||||||
|
$alt = htmlspecialchars($sc->getParameter('alt', ''), ENT_QUOTES);
|
||||||
|
$caption = htmlspecialchars($sc->getParameter('caption', ''), ENT_QUOTES);
|
||||||
|
$credit = htmlspecialchars($sc->getParameter('credit', ''), ENT_QUOTES);
|
||||||
|
$imageUrl = ($page && $imageName) ? $page->url() . '/' . $imageName : $imageName;
|
||||||
|
|
||||||
|
$captionHtml = '';
|
||||||
|
if ($caption || $credit) {
|
||||||
|
$creditHtml = $credit ? '<span class="full-bleed__credit"> · ' . $credit . '</span>' : '';
|
||||||
|
$captionHtml = '<figcaption class="full-bleed__caption">' . $caption . $creditHtml . '</figcaption>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return <<<HTML
|
||||||
|
<figure class="full-bleed">
|
||||||
|
<img src="{$imageUrl}" alt="{$alt}" class="full-bleed__img" loading="lazy">
|
||||||
|
{$captionHtml}
|
||||||
|
</figure>
|
||||||
|
HTML;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
namespace Grav\Plugin\Shortcodes;
|
||||||
|
|
||||||
|
use Thunder\Shortcode\Shortcode\ShortcodeInterface;
|
||||||
|
|
||||||
|
class ImageCaptionShortcode extends Shortcode
|
||||||
|
{
|
||||||
|
public function init(): void
|
||||||
|
{
|
||||||
|
$this->shortcode->getHandlers()->add('image-caption', function (ShortcodeInterface $sc) {
|
||||||
|
$plugin = $this->grav['plugins']->getPlugin('story-blocks');
|
||||||
|
$page = $plugin ? $plugin->getCurrentPage() : null;
|
||||||
|
|
||||||
|
$imageName = htmlspecialchars($sc->getParameter('image', ''), ENT_QUOTES);
|
||||||
|
$alt = htmlspecialchars($sc->getParameter('alt', ''), ENT_QUOTES);
|
||||||
|
$caption = htmlspecialchars($sc->getParameter('caption', ''), ENT_QUOTES);
|
||||||
|
$credit = htmlspecialchars($sc->getParameter('credit', ''), ENT_QUOTES);
|
||||||
|
$width = $sc->getParameter('width', 'column');
|
||||||
|
if (!in_array($width, ['column', 'full', 'bleed'])) $width = 'column';
|
||||||
|
$imageUrl = ($page && $imageName) ? $page->url() . '/' . $imageName : $imageName;
|
||||||
|
|
||||||
|
$widthClass = $width !== 'column' ? ' img-caption--' . $width : '';
|
||||||
|
$captionHtml = '';
|
||||||
|
if ($caption || $credit) {
|
||||||
|
$creditHtml = $credit ? '<span class="img-caption__credit"> · ' . $credit . '</span>' : '';
|
||||||
|
$captionHtml = '<figcaption class="img-caption__text">' . $caption . $creditHtml . '</figcaption>';
|
||||||
|
}
|
||||||
|
|
||||||
|
return <<<HTML
|
||||||
|
<figure class="img-caption{$widthClass}">
|
||||||
|
<img src="{$imageUrl}" alt="{$alt}" class="img-caption__img" loading="lazy">
|
||||||
|
{$captionHtml}
|
||||||
|
</figure>
|
||||||
|
HTML;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1647,6 +1647,65 @@ body::after {
|
|||||||
}
|
}
|
||||||
.pgallery__dot.is-active { background: var(--color-accent); }
|
.pgallery__dot.is-active { background: var(--color-accent); }
|
||||||
|
|
||||||
|
/* ── FullBleed shortcode ──────────────────────────────────── */
|
||||||
|
.full-bleed {
|
||||||
|
width: 100vw;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -50vw;
|
||||||
|
position: relative;
|
||||||
|
margin-top: var(--space-16);
|
||||||
|
margin-bottom: var(--space-16);
|
||||||
|
}
|
||||||
|
.full-bleed__img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
max-height: 80vh;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
.full-bleed__caption {
|
||||||
|
text-align: center;
|
||||||
|
font-family: var(--font-ui);
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
color: var(--color-ink-muted);
|
||||||
|
margin-top: var(--space-3);
|
||||||
|
padding: 0 var(--space-8);
|
||||||
|
}
|
||||||
|
.full-bleed__credit { font-style: italic; }
|
||||||
|
|
||||||
|
/* ── ImageCaption shortcode ───────────────────────────────── */
|
||||||
|
.img-caption {
|
||||||
|
margin-top: var(--space-12);
|
||||||
|
margin-bottom: var(--space-12);
|
||||||
|
}
|
||||||
|
.img-caption__img {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
border-radius: var(--radius-sm);
|
||||||
|
}
|
||||||
|
.img-caption__text {
|
||||||
|
font-family: var(--font-ui);
|
||||||
|
font-size: var(--text-sm);
|
||||||
|
color: var(--color-ink-muted);
|
||||||
|
margin-top: var(--space-3);
|
||||||
|
}
|
||||||
|
.img-caption__credit { font-style: italic; }
|
||||||
|
.img-caption--full {
|
||||||
|
width: calc(100% + var(--space-16));
|
||||||
|
margin-left: calc(var(--space-8) * -1);
|
||||||
|
}
|
||||||
|
.img-caption--full .img-caption__img { border-radius: 0; }
|
||||||
|
.img-caption--bleed {
|
||||||
|
width: 100vw;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -50vw;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.img-caption--bleed .img-caption__img {
|
||||||
|
border-radius: 0;
|
||||||
|
max-height: 80vh;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Stories listing ──────────────────────────────────────── */
|
/* ── Stories listing ──────────────────────────────────────── */
|
||||||
.stories-listing { padding: var(--space-10) 0; }
|
.stories-listing { padding: var(--space-10) 0; }
|
||||||
.stories-listing__heading {
|
.stories-listing__heading {
|
||||||
|
|||||||
Reference in New Issue
Block a user