diff --git a/components/Book/Sidenote.tsx b/components/Book/Sidenote.tsx
index 12c810b..301a16f 100644
--- a/components/Book/Sidenote.tsx
+++ b/components/Book/Sidenote.tsx
@@ -1,5 +1,6 @@
"use client";
+import "./expanding-side-img.scss"
import React, { ReactNode, createContext, useRef, useCallback, useMemo } from "react";
import Image from "@/components/Image";
@@ -134,23 +135,23 @@ export const ExpandingSideImg = ({src, alt, retina, caption, children}: {
className={retina ? " retina" : ""}
/>
- {caption &&
{caption}
}
+ {caption &&
}
{children &&
{children}
}
-
- {(caption || children) &&
-
- {caption &&
{caption}
}
- {children &&
{children}
}
-
- }
+
+ {(caption || children) &&
+
+ {caption &&
{caption}
}
+ {children &&
{children}
}
+
+ }
diff --git a/components/Book/expanding-side-img.scss b/components/Book/expanding-side-img.scss
new file mode 100644
index 0000000..de3032b
--- /dev/null
+++ b/components/Book/expanding-side-img.scss
@@ -0,0 +1,240 @@
+@use "../../styles/variables" as *;
+
+@keyframes show-icon {
+ 0% { opacity: 0; }
+ 25% { opacity: 1; }
+ 50% { opacity: 0; }
+ 75% { opacity: 1; }
+ 100% { opacity: 0.7; }
+}
+
+div.expanding-side-img-container {
+ div.expanding-side-img {
+ margin: 0;
+ position: absolute;
+ width: $aside-width;
+ transform: translateX(calc(-100% - $gap));
+
+ .caption {
+ padding-top: 0px;
+ }
+
+ .caption p {
+ font-weight: 400;
+ }
+ }
+
+ img {
+ margin: 0;
+ border-radius: 8px;
+ }
+
+ div.overlay {
+ visibility: hidden;
+
+ position: fixed;
+ top: 50%;
+ left: 50%;
+ width: 10vw;
+ height: 10vh;
+ transition: width 0.2s, height 0.2s;
+ transform: translate(-50%, -50%);
+
+ text-align: center;
+ z-index: 100;
+
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ .figure {
+ display: inline-block;
+ width: auto;
+ position: relative;
+ margin: auto;
+ margin-top: 0;
+ margin-bottom: 0;
+ overflow: hidden;
+
+ &:has(.children) img {
+ max-height: 98vh;
+ }
+
+ img {
+ width: auto;
+ height: auto;
+ max-width: 98vw;
+ max-height: 85vh;
+ }
+
+ &:hover .caption-overlay:has(.children)::after {
+ animation: show-icon 2s ease both;
+ }
+
+ .caption-overlay {
+ .children {
+ padding: 0 16px;
+ width: 100%;
+ text-align: left;
+ }
+
+ .caption p {
+ padding: 0 16px 0 16px;
+ font-weight: 800;
+ }
+
+ &:has(.children) {
+ position: absolute;
+ bottom: 0;
+ max-height: 32px;
+ overflow: hidden;
+
+ background-color: #fff9;
+ text-overflow: unset;
+ transition: background-color 0.5s ease, max-height 0.5s ease;
+
+ &::after {
+ content: "";
+ position: absolute;
+ top: auto;
+ bottom: 0;
+ left: 0;
+ width: 32px;
+ height: 32px;
+ opacity: 0;
+
+ background-color: rgb(80 80 80 / 70%);
+ background-image: url("/icons/eye.svg");
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 18px;
+
+ border-radius: 4px;
+ }
+
+ &:hover {
+ background-color: #fffd;
+ padding: 16px 16px 0 16px;
+ max-height: 100vh;
+
+ &::after {
+ opacity: 0 !important;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+@media ( min-width: 681px ) {
+ div.expanding-side-img-container {
+ &:has(:hover) .overlay {
+ width: 100vw;
+ height: 100vh;
+ background-color: #dddd;
+ visibility: visible;
+ pointer-events: none;
+
+ .caption-overlay:not(:has(.children)) {
+ visibility: visible;
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100vw;
+ padding: 12px;
+ background-color: #333a;
+ color: white;
+ display: flex;
+ align-content: center;
+ justify-content: center;
+ }
+ }
+
+ &:has(:hover) .figure {
+ opacity: 1;
+ pointer-events: auto;
+ }
+ }
+ .expanding-side-img img, .overlay .figure img {
+ border: 1px solid #bbb;
+ }
+
+ div.expanding-side-img {
+ transform-origin: top left;
+ max-width: $aside-width;
+ padding: 0;
+ object-fit: contain;
+
+ img {
+ border-radius: 5px;
+ }
+
+ &::after {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: 32px;
+ height: 32px;
+
+ background-color: rgb(80 80 80 / 70%);
+ background-image: url("/icons/magnifying-glass.svg");
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 18px;
+
+ border-radius: 4px;
+ }
+
+ .caption-cont {
+ .caption {
+ padding-top: 12px;
+
+ }
+
+ .children {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+ }
+}
+
+
+@media print, ( max-width: 680px ) {
+ div.expanding-side-img-container {
+ max-width: 100vw;
+ height: auto;
+ overflow: clip;
+
+ .overlay {
+ display: none !important;
+ }
+
+ .expanding-side-img {
+ img {
+ width: 100%
+ }
+ &:has(.caption) {
+ text-align: center;
+
+ &::after {
+ display: none;
+ }
+
+ img {
+ margin-bottom: 0;
+ }
+
+ .caption, .children {
+ font-weight: 400 !important;
+ padding: 8px 0 16px 0;
+ }
+ }
+ }
+ }
+}
diff --git a/components/MdxContent.tsx b/components/MdxContent.tsx
index c5b94c0..508c766 100644
--- a/components/MdxContent.tsx
+++ b/components/MdxContent.tsx
@@ -33,6 +33,23 @@ export const MdxContent = ({content, chapterId, bookId, t, env, allAnswers}: {
env?: Record;
allAnswers?: AnswersInBook;
}) => {
+ React.useEffect(() => {
+ const resize = (img: HTMLImageElement) => {
+ // Set only maxHeight to avoid overriding maxWidth set to images in side columns
+ img.style.maxHeight = `${img.naturalHeight / 2}px`;
+ };
+
+ const images = document.querySelectorAll("img.retina");
+ images.forEach(img => {
+ if (img.complete) {
+ resize(img);
+ }
+ else {
+ img.addEventListener("load", () => resize(img), {once: true});
+ }
+ });
+ }, []);
+
if (!content) {
return;
}
diff --git a/styles/globals.scss b/styles/globals.scss
index b379e40..0b0fbbd 100644
--- a/styles/globals.scss
+++ b/styles/globals.scss
@@ -1,4 +1,5 @@
@use "./colors" as *;
+@use "./variables" as *;
@use "quiz/quiz" as quiz;
/*@use "admin/admin" as admin; */
@use "content-index/content-index" as *;
@@ -80,7 +81,7 @@ $gap: var(--gap);
}
@media ( min-width: 681px ) {
- [data-float-aside] + p, [data-float-aside] + div, div.float-aside, div.expanding-side-img {
+ [data-float-aside] + p, [data-float-aside] + div, div.float-aside {
margin: 0 !important;
position: absolute;
width: $aside-width;
@@ -109,187 +110,15 @@ $gap: var(--gap);
) !important;
margin-right: auto;
}
-
- div.expanding-side-img {
- transform-origin: top left;
- max-width: $aside-width;
- padding: 0;
- object-fit: contain;
-
- img {
- border-radius: 5px;
- }
-
- img.retina {
- zoom: 0.5;
- }
-
- &::after {
- content: "";
- position: absolute;
- top: 8px;
- right: 0;
- width: 32px;
- height: 32px;
-
- background-color: rgb(80 80 80 / 70%);
- background-image: url("/icons/magnifying-glass.svg");
- background-repeat: no-repeat;
- background-position: center;
- background-size: 18px;
-
- border-radius: 4px;
- }
-
- .caption-cont .children {
- display: -webkit-box;
- -webkit-line-clamp: 2; // number of lines
- -webkit-box-orient: vertical;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
-}
-
-div.expanding-side-img-container div.overlay {
- visibility: hidden;
-
- position: fixed;
- top: 50% !important;
- left: 50% !important;
- width: 10vw;
- height: 10vh;
- transition: width 0.2s, height 0.2s;
- transform: translate(-50%, -50%);
-
- text-align: center;
- z-index: 100;
-
- inset: 0;
- display: flex;
- justify-content: center;
- align-items: center;
-
- .figure {
- display: inline-block;
- width: auto;
- position: relative;
- margin: auto;
- margin-top: 0 !important;
- margin-bottom: 0 !important;
- overflow: hidden;
- }
-
- img {
- width: auto;
- height: auto;
- display: block;
- margin: 0 !important;
- border: 1px solid gray;
- }
-
- .caption-cont:has(.no-children) {
- visibility: hidden;
- }
-
- .children {
- padding: 0 16px;
- width: 100%;
- }
-
- .caption.with-children {
- padding: 0px 16px 0 16px;
- font-weight: 800 !important;
- }
-
- .figure .caption-cont::after {
- content: "";
- position: absolute;
- top: auto;
- bottom: 0px;
- left: 0;
- width: 32px;
- height: 32px;
-
- background-color: rgb(80 80 80 / 70%);
- background-image: url("/icons/eye.svg");
- background-repeat: no-repeat;
- background-position: center;
- background-size: 18px;
-
- border-radius: 4px;
- }
-
- .figure .caption-cont:has(:hover)::after {
- opacity: 0
- }
-
- .caption-cont:has(.children) {
- background-color: #fff4;
- }
-
- .caption-cont {
- position: absolute;
- bottom: 0;
- background-color: white;
- overflow: visible;
- text-overflow: unset;
- height: 32px;
- }
-
- .caption-cont:hover {
- transition: opacity 0.2s linear;
- background-color: #fffd;
- padding: 16px 16px 0 16px;
- height: auto;
- }
-
- .children {
- text-align: left;
- }
-}
-
-div.expanding-side-img-container:has(:hover) .overlay, div.expanding-side-img-container.overlay:has(.figure:hover) {
- width: 100vw;
- height: 100vh;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background-color: #dddd;
- visibility: visible;
- pointer-events: none;
-
- .figure img {
- max-width: 90vw;
- max-height: 90vh;
- }
-}
-
-div.expanding-side-img-container:has(:hover) .figure, div.expanding-side-img-container.overlay .figure:hover {
- opacity: 1;
- pointer-events: visible;
}
@media print, ( max-width: 680px ) {
- img, div.expanding-side-img {
+ img {
max-width: $prose-width;
height: auto;
overflow: clip;
}
- img:has(+ .caption) {
- margin-bottom: 12px;
- }
-
- .expanding-side-img:has(.caption) {
- margin-bottom: 42px;
- }
-
- .caption.no-children, .caption.with-children, .children {
- font-weight: 400 !important;
- font-style: italic;
- }
-
.expressive-code {
max-width: $prose-width !important;
width: $prose-width !important;
@@ -324,7 +153,7 @@ div.expanding-side-img-container:has(:hover) .figure, div.expanding-side-img-con
margin-top: 0! important;
}
- .expanding-side-img img, .float-aside img {
+ .float-aside img {
width: 100% !important;
}
@@ -372,7 +201,7 @@ div.expanding-side-img-container:has(:hover) .figure, div.expanding-side-img-con
:where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::before,
:where(code):not(:where([class~="not-prose"],[class~="not-prose"] *))::after
{
- content: "";
+ content: "";
}
strong {
diff --git a/styles/variables.scss b/styles/variables.scss
new file mode 100644
index 0000000..43e4191
--- /dev/null
+++ b/styles/variables.scss
@@ -0,0 +1,19 @@
+
+$img-margin: 8px;
+$max-size: 140;
+
+:root {
+ --aside-width: 260px;
+ --prose-width: 940px;
+ --gap: 32px;
+
+ @media (max-width: 680px) {
+ --aside-width: 0;
+ --prose-width: 100vw; // Using 100% allows some elements to expand
+ --gap: 0;
+ }
+}
+
+$aside-width: var(--aside-width);
+$prose-width: var(--prose-width);
+$gap: var(--gap);