Skip to content

Commit

Permalink
feat(blog): add toc (#9707)
Browse files Browse the repository at this point in the history
* feat(blog): add toc

Only for large screens for now.
This also refactors the useStickyHeaderHeight hook.

* no placment on sponsored posts

* feedback

* use min height for top header

* Update client/src/blog/post.scss

Co-authored-by: Leo McArdle <lmcardle@mozilla.com>

* reanming and moving to resize observer

* fix scroll-margin-top without actions

* fix(blog): move main-page-content class to article

Avoids sidebar being inside the main-page-content,
to be consistent with document pages.

---------

Co-authored-by: Claas Augner <495429+caugner@users.noreply.github.com>
Co-authored-by: Leo McArdle <lmcardle@mozilla.com>
Co-authored-by: Claas Augner <caugner@mozilla.com>
  • Loading branch information
4 people authored Oct 2, 2023
1 parent e96e6f2 commit e31ba94
Show file tree
Hide file tree
Showing 13 changed files with 207 additions and 179 deletions.
18 changes: 15 additions & 3 deletions client/src/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,10 @@
--top-nav-height: 4rem;
--article-actions-container-height: 2rem;
--icon-size: 1rem;
--sticky-header-height: calc(
var(--top-nav-height) + var(--article-actions-container-height) + 2px
--sticky-header-without-actions-height: calc(var(--top-nav-height) + 1px);
--sticky-header-with-actions-height: calc(
var(--sticky-header-without-actions-height) +
var(--article-actions-container-height) + 1px
);
}

Expand All @@ -121,7 +123,11 @@
}

:target {
scroll-margin-top: var(--sticky-header-height);
scroll-margin-top: var(--sticky-header-with-actions-height);
}

.sticky-header-container.without-actions ~ * :target {
scroll-margin-top: var(--sticky-header-without-actions-height);
}

body {
Expand Down Expand Up @@ -340,3 +346,9 @@ sup.new {
background: var(--new-background-beta, var(--new-background));
}
}

.sticky-header-container {
position: sticky;
top: 0;
z-index: var(--z-index-main-header);
}
4 changes: 3 additions & 1 deletion client/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,9 @@ function Layout({ pageType, children }) {
>
<TopPlacement />
{pageType !== "document-page" && (
<TopNavigation extraClasses="main-document-header-container" />
<div className="sticky-header-container without-actions">
<TopNavigation />
</div>
)}
{children}
</div>
Expand Down
52 changes: 52 additions & 0 deletions client/src/blog/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
}

.blog-container {
--author-gap: 1rem;
--avatar-size: 3rem;
margin: 0 auto;
max-width: min(calc(80vw + 4rem), var(--max-width));
padding: 2rem 1rem;
Expand All @@ -30,6 +32,56 @@
}
}

.date-author,
.author {
align-content: flex-start;
align-items: center;
display: flex;
flex-wrap: wrap;
}

.date-author {
column-gap: 1.5rem;
padding-left: calc(var(--avatar-size) + var(--author-gap));
}

.author {
font-weight: var(--font-body-strong-weight);
gap: var(--author-gap);
margin-left: calc((var(--avatar-size) + var(--author-gap)) * -1);

&::after {
margin-left: calc(4px - var(--author-gap));
}

img {
border: none !important;
border-radius: 3rem;
height: var(--avatar-size);
margin: 0;
object-fit: cover;
width: var(--avatar-size);
}
}

figure.blog-image {
margin: 0 auto 2rem;
width: fit-content;

img {
background: transparent;
border: none !important;
margin: 0 0 0.125rem;
width: 100%;
}

figcaption {
font-size: smaller;
margin-left: auto;
width: fit-content;
}
}

h1 {
margin-top: 1rem;
}
Expand Down
1 change: 0 additions & 1 deletion client/src/blog/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { BlogPost, AuthorDateReadTime } from "./post";
import { BlogImage, BlogPostMetadata } from "../../../libs/types/blog.js";

import "./index.scss";
import "./post.scss";
import { Button } from "../ui/atoms/button";
import { SignUpSection as NewsletterSignUp } from "../newsletter";

Expand Down
194 changes: 93 additions & 101 deletions client/src/blog/post.scss
Original file line number Diff line number Diff line change
@@ -1,135 +1,127 @@
@use "../ui/vars" as *;

.blog-container.post {
max-width: calc(48rem + 4rem);

+ .section-newsletter h2 {
font: var(--type-heading-h3);
margin: 0;
}
}

.blog-container {
--author-gap: 1rem;
--avatar-size: 3rem;

.date-author,
.author {
align-content: flex-start;
align-items: center;
display: flex;
flex-wrap: wrap;
.blog-post-container {
display: grid;
gap: 3rem;
grid-template-areas:
"post"
"newsletter";
width: 100%;

@media screen and (min-width: $screen-lg) {
grid-template-areas:
"post toc"
"newsletter toc";
grid-template-columns: minmax(auto, 100%) minmax(0, 12rem);
}

.date-author {
column-gap: 1.5rem;
padding-left: calc(var(--avatar-size) + var(--author-gap));
@media screen and (min-width: $screen-xl) {
grid-template-areas:
"nothing post toc"
"nothing newsletter toc";
grid-template-columns: minmax(auto, 1fr) minmax(0, 52rem) minmax(15rem, 1fr);
}

.author {
font-weight: var(--font-body-strong-weight);
gap: var(--author-gap);
margin-left: calc((var(--avatar-size) + var(--author-gap)) * -1);
> .sidebar-container {
--offset: var(--top-nav-height);
display: none;

&::after {
margin-left: calc(4px - var(--author-gap));
.toc-container {
position: unset;
top: auto;
}

img {
border: none !important;
border-radius: 3rem;
height: var(--avatar-size);
margin: 0;
object-fit: cover;
width: var(--avatar-size);
}
}

figure.blog-image {
margin: 0 auto 2rem;
width: fit-content;
@media screen and (min-width: $screen-lg) {
display: flex;
grid-area: toc;

img {
background: transparent;
border: none !important;
margin: 0 0 0.125rem;
width: 100%;
.toc > nav {
margin-top: 2rem;
}
}
}

figcaption {
font-size: smaller;
margin-left: auto;
width: fit-content;
}
> .section-newsletter {
grid-area: newsletter;
}

.previous-next {
display: flex;
gap: 1rem;
> .blog-post {
grid-area: post;
max-width: 52rem;

@media screen and (max-width: $screen-md) {
flex-direction: column-reverse;
+ .section-newsletter h2 {
font: var(--type-heading-h3);
margin: 0;
}

a {
color: var(--text-primary);
.previous-next {
display: flex;
gap: 1rem;
text-decoration: none;
width: 100%;

&:hover h2 {
text-decoration: underline;
@media screen and (max-width: $screen-md) {
flex-direction: column-reverse;
}

&:active {
background: none;
}
a {
color: var(--text-primary);
display: flex;
gap: 1rem;
text-decoration: none;
width: 100%;

@media screen and (min-width: $screen-md) {
&.previous,
&.next {
&::before,
&::after {
align-self: center;
background-color: var(--text-primary);
flex-shrink: 0;
height: 1rem;
mask-position: center;
mask-repeat: no-repeat;
vertical-align: middle;
width: 1rem;
}
&:hover h2 {
text-decoration: underline;
}

&.previous::before {
content: "";
mask-image: url("../assets/icons/previous.svg");
&:active {
background: none;
}

&.next::after {
content: "";
mask-image: url("../assets/icons/next.svg");
@media screen and (min-width: $screen-md) {
&.previous,
&.next {
&::before,
&::after {
align-self: center;
background-color: var(--text-primary);
flex-shrink: 0;
height: 1rem;
mask-position: center;
mask-repeat: no-repeat;
vertical-align: middle;
width: 1rem;
}
}

&.previous::before {
content: "";
mask-image: url("../assets/icons/previous.svg");
}

&.next::after {
content: "";
mask-image: url("../assets/icons/next.svg");
}
}
}
}

article {
margin: 0 auto;
}

h2:first-of-type {
color: var(--text-link);
font-size: 1rem;
margin: 0;
text-align: center;
article {
margin: 0 auto;
}

strong {
color: var(--text-primary);
display: block;
font-size: 0.8em;
font-weight: normal;
line-height: 1.2rem;
h2:first-of-type {
color: var(--text-link);
font-size: 1rem;
margin: 0;
text-align: center;

strong {
color: var(--text-primary);
display: block;
font-size: 0.8em;
font-weight: normal;
line-height: 1.2rem;
}
}
}
}
Expand Down
20 changes: 16 additions & 4 deletions client/src/blog/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import useSWR from "swr";

import { HydrationData } from "../../../libs/types/hydration";
import { HTTPError, RenderDocumentBody } from "../document";
import { WRITER_MODE } from "../env";
import { PLACEMENT_ENABLED, WRITER_MODE } from "../env";

import "./index.scss";
import "./post.scss";
Expand All @@ -20,6 +20,8 @@ import {
} from "../document/hooks";
import { DEFAULT_LOCALE } from "../../../libs/constants";
import { SignUpSection as NewsletterSignUp } from "../newsletter";
import { TOC } from "../document/organisms/toc";
import { SidePlacement } from "../ui/organisms/placement";

function MaybeLink({ className = "", link, children }) {
return link ? (
Expand Down Expand Up @@ -191,9 +193,19 @@ export function BlogPost(props: HydrationData) {
return (
<>
{doc && blogMeta && (
<>
<main className="blog-post-container container">
<div className="sidebar-container">
<div className="toc-container">
<aside className="toc">
<nav>
{doc.toc && !!doc.toc.length && <TOC toc={doc.toc} />}
</nav>
</aside>
{PLACEMENT_ENABLED && !blogMeta?.sponsored && <SidePlacement />}
</div>
</div>
<article
className="blog-container post container main-page-content"
className="blog-post blog-container main-page-content"
lang={doc?.locale}
>
<BlogImageFigure image={blogMeta?.image} width={800} height={420} />
Expand All @@ -206,7 +218,7 @@ export function BlogPost(props: HydrationData) {
{blogMeta.links && <PreviousNext links={blogMeta.links} />}
</article>
<NewsletterSignUp />
</>
</main>
)}
</>
);
Expand Down
Loading

0 comments on commit e31ba94

Please sign in to comment.