diff --git a/resources/ts/image-block-helper.ts b/resources/ts/image-block-helper.ts
new file mode 100644
index 00000000..397f2306
--- /dev/null
+++ b/resources/ts/image-block-helper.ts
@@ -0,0 +1,98 @@
+import { Modal } from './modal.js';
+
+declare global {
+ interface Window {
+ imageBlockHelper: (element: HTMLElement) => void;
+ }
+}
+
+const BASE_BUTTON_CLASS_NAME: string[] = [
+ 'absolute',
+ 'size-8',
+ 'flex',
+ 'justify-center',
+ 'items-center',
+ 'text-gray-50',
+ 'bg-emerald-500',
+ 'dark:bg-lividus-500',
+ 'rounded-md',
+ 'text-lg',
+ 'hover:bg-emerald-600',
+ 'dark:hover:bg-lividus-400',
+ 'active:bg-emerald-500',
+ 'dark:active:bg-lividus-500',
+ 'opacity-0',
+ 'group-hover:opacity-100',
+ 'transition-all',
+ 'duration-200',
+];
+
+const ARROWS_ANGLE_EXPAND_ICON_SVG: string = `
+
+`;
+
+function createExpandImageButton(preOuterHtml: string): HTMLButtonElement {
+ const expandImageButton: HTMLButtonElement =
+ document.createElement('button');
+ expandImageButton.classList.add(
+ 'top-2',
+ 'right-2',
+ ...BASE_BUTTON_CLASS_NAME,
+ );
+ expandImageButton.innerHTML = ARROWS_ANGLE_EXPAND_ICON_SVG;
+
+ const modal = new Modal({
+ innerHtml: preOuterHtml,
+ customClassName: ['font-jetbrains-mono', 'text-xl'],
+ });
+
+ expandImageButton.addEventListener(
+ 'click',
+ function (this: HTMLButtonElement) {
+ modal.open();
+ },
+ );
+
+ return expandImageButton;
+}
+
+window.imageBlockHelper = function (element: HTMLElement): void {
+ const figureTags: HTMLCollectionOf =
+ element.getElementsByTagName('figure');
+
+ for (const figureTag of figureTags) {
+ if (figureTag.classList.contains('image-block-helper-added')) {
+ return;
+ }
+
+ figureTag.classList.add(
+ 'image-block-helper-added',
+ 'group',
+ 'relative',
+ );
+
+ const image = figureTag.getElementsByTagName('img')[0];
+
+ image.removeAttribute('height');
+ image.removeAttribute('width');
+
+ const expandImageButton = createExpandImageButton(image.outerHTML);
+
+ figureTag.appendChild(expandImageButton);
+
+ document.addEventListener(
+ 'livewire:navigating',
+ () => {
+ expandImageButton.remove();
+ figureTag.classList.remove(
+ 'image-block-helper-added',
+ 'group',
+ 'relative',
+ );
+ },
+ { once: true },
+ );
+ }
+};
diff --git a/resources/views/livewire/pages/posts/show-post-page.blade.php b/resources/views/livewire/pages/posts/show-post-page.blade.php
index 6b6d61e9..37115cbc 100644
--- a/resources/views/livewire/pages/posts/show-post-page.blade.php
+++ b/resources/views/livewire/pages/posts/show-post-page.blade.php
@@ -17,6 +17,7 @@
@vite('resources/ts/highlight.ts')
{{-- code block copy button --}}
@vite('resources/ts/code-block-helper.ts')
+ @vite('resources/ts/image-block-helper.ts')
{{-- post read pregress bar --}}
@vite('resources/ts/progress-bar.ts')
{{-- scroll --}}
@@ -38,6 +39,7 @@
window.setupPostOutline(this.$refs.postOutline, this.$refs.postBody);
window.hljs.highlightAll();
window.codeBlockHelper(this.$refs.postBody);
+ window.imageBlockHelper(this.$refs.postBody);
window.processYoutubeOembeds();
window.processTwitterOembeds(this.$refs.postBody);
window.setupProgressBar(this.$refs.postCard, this.$refs.progressBar);
diff --git a/vite.config.js b/vite.config.js
index a5226d01..a9f4d3fe 100644
--- a/vite.config.js
+++ b/vite.config.js
@@ -17,6 +17,7 @@ export default defineConfig({
'resources/ts/progress-bar.ts',
'resources/ts/scroll-to-anchor.ts',
'resources/ts/post-outline.ts',
+ 'resources/ts/image-block-helper.ts',
// css
'resources/css/app.css',
'node_modules/@yaireo/tagify/dist/tagify.css',