From 47c236388b3f016a9210d865aa9efdde56929ae5 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 25 Jan 2024 09:59:39 +0100 Subject: [PATCH 001/102] wip --- .github/workflows/stage-build.yml | 10 + build/build-curriculum.ts | 4 + build/curriculum.ts | 276 +++++++++++++++++++ build/utils.ts | 33 ++- client/src/app.tsx | 9 + client/src/assets/icons/cur-ext-resource.svg | 12 + client/src/assets/icons/cur-mdn-resource.svg | 8 + client/src/assets/icons/cur-resources.svg | 12 + client/src/curriculum/module.scss | 219 +++++++++++++++ client/src/curriculum/module.tsx | 88 ++++++ client/src/document/organisms/toc/index.tsx | 4 +- client/src/placement-context.tsx | 2 +- client/src/ui/molecules/main-menu/index.tsx | 1 + cloud-function/src/app.ts | 2 +- deployer/src/deployer/search/__init__.py | 5 + libs/env/index.d.ts | 1 + libs/env/index.js | 2 + libs/types/curriculum.ts | 28 ++ libs/types/document.ts | 2 + libs/types/hydration.ts | 2 + package.json | 1 + server/index.ts | 25 ++ 22 files changed, 737 insertions(+), 9 deletions(-) create mode 100644 build/build-curriculum.ts create mode 100644 build/curriculum.ts create mode 100644 client/src/assets/icons/cur-ext-resource.svg create mode 100644 client/src/assets/icons/cur-mdn-resource.svg create mode 100644 client/src/assets/icons/cur-resources.svg create mode 100644 client/src/curriculum/module.scss create mode 100644 client/src/curriculum/module.tsx create mode 100644 libs/types/curriculum.ts diff --git a/.github/workflows/stage-build.yml b/.github/workflows/stage-build.yml index c74e6035d6c0..c3ca523e35b8 100644 --- a/.github/workflows/stage-build.yml +++ b/.github/workflows/stage-build.yml @@ -89,6 +89,12 @@ jobs: lfs: true token: ${{ secrets.MDN_STUDIO_PAT }} + - uses: actions/checkout@v4 + if: ${{ ! vars.SKIP_BUILD }} + with: + repository: mdn/curriculum + path: mdn/curriculum + # Our usecase is a bit complicated. When the cron schedule runs this workflow, # we rely on the env vars defined at the top of the file. But if it's a manual # trigger we rely on the inputs and only the inputs. That way, the user can @@ -169,6 +175,7 @@ jobs: CONTENT_TRANSLATED_ROOT: ${{ github.workspace }}/mdn/translated-content/files CONTRIBUTOR_SPOTLIGHT_ROOT: ${{ github.workspace }}/mdn/mdn-contributor-spotlight/contributors BLOG_ROOT: ${{ github.workspace }}/mdn/mdn-studio/content/posts + CURRICULUM_ROOT: ${{ github.workspace }}/mdn/curriculum BASE_URL: "https://developer.allizom.org" # The default for this environment variable is geared for writers @@ -271,6 +278,9 @@ jobs: # Build the blog yarn build:blog + # Build the curriculum + yarn build:curriculum + # Generate whatsdeployed files. yarn tool whatsdeployed --output client/build/_whatsdeployed/code.json yarn tool whatsdeployed $CONTENT_ROOT --output client/build/_whatsdeployed/content.json diff --git a/build/build-curriculum.ts b/build/build-curriculum.ts new file mode 100644 index 000000000000..af8f1303f1e2 --- /dev/null +++ b/build/build-curriculum.ts @@ -0,0 +1,4 @@ +#!/usr/bin/env node +import { buildCurriculum } from "./curriculum.js"; + +buildCurriculum({ verbose: true }); diff --git a/build/curriculum.ts b/build/curriculum.ts new file mode 100644 index 000000000000..a7a98f39f74f --- /dev/null +++ b/build/curriculum.ts @@ -0,0 +1,276 @@ +import { fdir } from "fdir"; +import { BUILD_OUT_ROOT, CURRICULUM_ROOT } from "../libs/env/index.js"; +import { Doc } from "../libs/types/document.js"; +import { DEFAULT_LOCALE } from "../libs/constants/index.js"; +import * as kumascript from "../kumascript/index.js"; +import LANGUAGES_RAW from "../libs/languages/index.js"; +import { syntaxHighlight } from "./syntax-highlight.js"; +import { + injectLoadingLazyAttributes, + injectNoTranslate, + makeTOC, + postLocalFileLinks, + postProcessCurriculumLinks, + postProcessExternalLinks, + postProcessSmallerHeadingIDs, +} from "./utils.js"; +import { wrapTables } from "./wrap-tables.js"; +import { extractSections } from "./extract-sections.js"; +import path from "node:path"; +import fs from "node:fs/promises"; +import { + CurriculumFrontmatter, + ModuleData, + ModuleMetaData, + SidebarEntry, +} from "../libs/types/curriculum.js"; +import frontmatter from "front-matter"; +import { HydrationData } from "../libs/types/hydration.js"; +import { memoize, slugToFolder } from "../content/utils.js"; +import { renderHTML } from "../ssr/dist/main.js"; + +async function allFiles(): Promise { + const api = new fdir() + .withFullPaths() + .withErrors() + .filter((filePath) => filePath.endsWith(".md")) + .crawl(path.join(CURRICULUM_ROOT, "curriculum")); + return await api.withPromise(); +} + +export const buildIndex = memoize(async () => { + const files = await allFiles(); + const modules = await Promise.all( + files.map( + async (file) => + (await readModule(file, { previousNext: false, sidebar: false })).meta + ) + ); + return modules; +}); + +export async function buildSidebar(): Promise { + const index = await buildIndex(); + + const s = index.reduce((sidebar, { url, title, slug }) => { + const currentLvl = slug.split("/").length; + const last = sidebar.length ? sidebar[sidebar.length - 1] : null; + const entry = { + url, + title, + slug, + }; + if (currentLvl > 2) { + if (last) { + last.children.push(entry); + return sidebar; + } + } + + sidebar.push({ children: [], ...entry }); + return sidebar; + }, []); + + return s; +} + +async function readModule( + file: string, + options?: { + previousNext?: boolean; + sidebar?: boolean; + } +): Promise<{ meta: ModuleMetaData; body: string; sidebar: any }> { + const raw = await fs.readFile(file, "utf-8"); + const { attributes, body: rawBody } = frontmatter(raw); + const filename = file.replace(CURRICULUM_ROOT, "").replace(/^\/?/, ""); + const title = rawBody.match(/^[\w\n]*#+(.*\n)/)[1]?.trim(); + const body = rawBody.replace(/^[\w\n]*#+(.*\n)/, ""); + + const slug = filename.replace(/\.md$/, "").replace("/0-README", ""); + const url = `/${DEFAULT_LOCALE}/${slug}/`; + + const sidebar = options?.sidebar && (await buildSidebar()); + + return { + meta: { filename, slug, url, title, ...attributes }, + sidebar, + body, + }; +} + +export async function findModuleBySlug( + slug: string +): Promise { + let slugPath = `${slug}.md`.split("/"); + let file = path.join(CURRICULUM_ROOT, "curriculum", ...slugPath); + let module; + try { + module = await readModule(file, { sidebar: true }); + } catch { + slugPath = `${slug}/0-README.md`.split("/"); + file = path.join(CURRICULUM_ROOT, "curriculum", ...slugPath); + try { + module = await readModule(file, { sidebar: true }); + } catch { + console.error(`No file found for ${slug}`); + } + } + const { body, meta, sidebar } = module; + + const d = { + url: meta.url, + rawBody: body, + metadata: { locale: DEFAULT_LOCALE, ...meta }, + isMarkdown: true, + fileInfo: { + path: file, + }, + sidebar, + }; + + const doc = await buildModule(d); + return { doc, curriculumMeta: meta }; +} + +export async function buildModule(document: any): Promise { + const { metadata, sidebar } = document; + + const doc = { locale: DEFAULT_LOCALE } as Partial; + let $ = null; + + [$] = await kumascript.render(document.url, {}, document as any); + + $("[data-token]").removeAttr("data-token"); + $("[data-flaw-src]").removeAttr("data-flaw-src"); + + doc.title = metadata.title || ""; + doc.mdn_url = document.url; + doc.locale = metadata.locale as string; + doc.native = LANGUAGES_RAW[DEFAULT_LOCALE]?.native; + + if ($("math").length > 0) { + doc.hasMathML = true; + } + $("div.hidden").remove(); + syntaxHighlight($, doc); + injectNoTranslate($); + injectLoadingLazyAttributes($); + postProcessCurriculumLinks($, document.url); + postProcessExternalLinks($); + postLocalFileLinks($, doc); + postProcessSmallerHeadingIDs($); + wrapTables($); + setCurriculumTypes($); + try { + const [sections] = await extractSections($); + doc.body = sections; + } catch (error) { + console.error( + `Extracting sections failed in ${doc.mdn_url} (${document.fileInfo.path})` + ); + throw error; + } + + doc.pageTitle = `${doc.title} | MDN Blog`; + + doc.noIndexing = false; + doc.toc = makeTOC(doc, true); + doc.sidebar = sidebar; + + return doc as Doc; +} + +export async function buildCurriculum(options: { + verbose?: boolean; + noIndexing?: boolean; +}) { + const locale = DEFAULT_LOCALE; + + for (const file of await allFiles()) { + console.log(`building: ${file}`); + + const { meta, body, sidebar } = await readModule(file, { sidebar: true }); + + const url = meta.url; + const renderUrl = url.replace(/\/$/, ""); + const renderDoc = { + url: renderUrl, + rawBody: body, + metadata: { locale, ...meta }, + isMarkdown: true, + fileInfo: { + path: file, + }, + }; + const builtDoc = await buildModule(renderDoc); + const { doc } = { + doc: { ...builtDoc, summary: meta.summary, mdn_url: url, sidebar }, + }; + + const context: HydrationData = { + doc, + pageTitle: meta.title, + locale, + noIndexing: options.noIndexing, + }; + + const outPath = path.join( + BUILD_OUT_ROOT, + locale.toLowerCase(), + slugToFolder(meta.slug) + ); + + await fs.mkdir(outPath, { recursive: true }); + + const html = renderHTML(`/${locale}/${meta.slug}/`, context); + + const filePath = path.join(outPath, "index.html"); + const jsonFilePath = path.join(outPath, "index.json"); + + await fs.mkdir(outPath, { recursive: true }); + await fs.writeFile(filePath, html); + await fs.writeFile(jsonFilePath, JSON.stringify(context)); + + if (options.verbose) { + console.log("Wrote", filePath); + } + } +} + +function setCurriculumTypes($) { + $("p").each((_, child) => { + const p = $(child); + const text = p.text(); + switch (text) { + case "Learning outcomes:": + p.addClass("curriculum-outcomes"); + break; + case "General resources:": + case "Resources:": + p.addClass("curriculum-resources"); + break; + } + }); + + $("p.curriculum-resources + ul > li").each((_, child) => { + const li = $(child); + + if (li.find("a.external").length) { + li.addClass("external"); + } + }); + + $("blockquote").each((_, child) => { + const bq = $(child); + + const [p] = bq.find("p"); + + if (p) { + const notes = $(p); + if (notes.text() === "Notes:") { + bq.addClass("curriculum-notes"); + } + } + }); +} diff --git a/build/utils.ts b/build/utils.ts index 86750a18e201..b5fc50fd7d8f 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -239,6 +239,28 @@ export function postProcessExternalLinks($) { }); } +/** + * For every `` remove the ".md" + * + * @param {Cheerio document instance} $ + * @param {current url} url + */ +export function postProcessCurriculumLinks($, url) { + $("a[href^=./]").each((_, element) => { + // Expand relative links (TODO: fix) + const $a = $(element); + $a.attr("href", $a.attr("href").replace(/^\.\//, `${url}`)); + }); + $("a[href^=/en-US/curriculum]").each((_, element) => { + const $a = $(element); + $a.attr("href", $a.attr("href").replace(/(.*)\.md(#.*|$)/, "$1/$2")); + }); + $("a[href^=/curriculum]").each((_, element) => { + const $a = $(element); + $a.attr("href", $a.attr("href").replace(/(.*)\.md(#.*|$)/, "/en-US$1/$2")); + }); +} + /** * For every ``, where 'THING' is not a http or / link, make it * `` @@ -294,16 +316,17 @@ export function postProcessSmallerHeadingIDs($) { * * @param {Document} doc */ -export function makeTOC(doc) { +export function makeTOC(doc, withH3 = false) { return doc.body .map((section) => { if ( - (section.type === "prose" || + ((section.type === "prose" || section.type === "browser_compatibility" || section.type === "specifications") && - section.value.id && - section.value.title && - !section.value.isH3 + section.value.id && + section.value.title && + !section.value.isH3) || + withH3 ) { return { text: section.value.title, id: section.value.id }; } diff --git a/client/src/app.tsx b/client/src/app.tsx index 243208bed85e..0ac9c10bdd19 100644 --- a/client/src/app.tsx +++ b/client/src/app.tsx @@ -28,6 +28,7 @@ import { HydrationData } from "../../libs/types/hydration"; import { TopPlacement } from "./ui/organisms/placement"; import { Blog } from "./blog"; import { Newsletter } from "./newsletter"; +import { CurriculumModule } from "./curriculum/module"; const AllFlaws = React.lazy(() => import("./flaws")); const Translations = React.lazy(() => import("./translations")); @@ -164,6 +165,14 @@ export function App(appProps: HydrationData) { time it hits any React code. */} + + + + } + /> + + + + + + + + + diff --git a/client/src/assets/icons/cur-mdn-resource.svg b/client/src/assets/icons/cur-mdn-resource.svg new file mode 100644 index 000000000000..d327580cfb25 --- /dev/null +++ b/client/src/assets/icons/cur-mdn-resource.svg @@ -0,0 +1,8 @@ + + + + diff --git a/client/src/assets/icons/cur-resources.svg b/client/src/assets/icons/cur-resources.svg new file mode 100644 index 000000000000..67042f7e1189 --- /dev/null +++ b/client/src/assets/icons/cur-resources.svg @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss new file mode 100644 index 000000000000..160b17740fc6 --- /dev/null +++ b/client/src/curriculum/module.scss @@ -0,0 +1,219 @@ +@use "../ui/vars" as *; + +.curriculum-content-container { + h1, + h2, + h3, + h4, + h5, + h6 { + a:link, + a:visited { + color: var(--text-primary); + text-decoration: none; + } + + a:hover, + a:focus { + text-decoration: underline; + } + + a:active { + background-color: transparent; + } + + a[href^="#"] { + &::before { + color: var(--text-inactive); + content: "#"; + display: inline-block; + font-size: 0.7em; + line-height: 1; + margin-left: -0.8em; + text-decoration: none; + visibility: hidden; + width: 0.8em; + } + + &:hover { + &::before { + visibility: visible; + } + } + } + } + + .sidebar, + .toc, + .curriculum-content { + padding-bottom: 3rem; + padding-top: 3rem; + } + + .sidebar { + align-self: start; + grid-area: sidebar; + + li { + margin-left: 1rem; + } + } + + .curriculum-content { + grid-area: main; + + blockquote.curriculum-notes { + border: 0px; + border-radius: var(--elem-radius); + background-color: #fcefe299; + padding: 1rem 2rem; + margin: 1rem; + } + + p.curriculum-outcomes { + display: flex; + font-weight: var(--font-body-strong-weight); + margin-bottom: 0.5rem; + &::before { + content: url("../assets/icons/cur-resources.svg"); + margin-right: 1rem; + width: 24px; + height: 24px; + display: block; + } + } + + li { + list-style-type: disc; + list-style-position: inside; + margin-left: 1rem; + } + + p.curriculum-resources { + margin-bottom: 0.5rem; + + ul > li { + list-style-type: none; + + &:not(.external)::before { + content: url("../assets/icons/cur-mdn-resource.svg"); + margin-right: 0.5rem; + display: inline-block; + width: 1em; + height: 1em; + } + &.external { + &::before { + content: url("../assets/icons/cur-ext-resource.svg"); + margin-right: 0.5rem; + display: inline-block; + width: 1em; + height: 1em; + } + } + } + } + } + + @media screen and (min-width: $screen-md) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + padding-left: 1.5rem; + padding-right: 3rem; + } + + @media screen and (min-width: $screen-xl) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main toc"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); + padding-left: 1rem; + padding-right: 1rem; + + .toc { + --offset: var(--sticky-header-with-actions-height); + + display: block; + grid-area: toc; + height: fit-content; + padding-bottom: 0; + } + + .in-nav-toc { + display: none; + } + } + + .sidebar-container { + --offset: var(--sticky-header-with-actions-height); + --max-height: calc(100vh - var(--offset)); + + @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { + display: flex; + flex-direction: column; + } + + max-height: var(--max-height); + position: sticky; + top: var(--offset); + z-index: var(--z-index-sidebar-mobile); + + @media screen and (min-width: $screen-md) { + z-index: auto; + + .sidebar { + mask-image: linear-gradient( + to bottom, + rgb(0, 0, 0) 0% calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + } + + @media screen and not (min-height: $screen-height-place-limit) { + overflow: auto; + } + } + + &.toc-container, + .toc-container { + grid-area: toc; + .place { + grid-area: toc; + margin: 0; + } + @media screen and (min-width: $screen-xl) { + display: flex; + flex-direction: column; + gap: 0; + height: calc(100vh - var(--offset)); + mask-image: linear-gradient( + to bottom, + rgba(0, 0, 0, 0) 0%, + rgb(0, 0, 0) 3rem calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + overflow: auto; + position: sticky; + top: var(--offset); + + .place { + margin: 1rem 0; + padding-bottom: 3rem; + } + } + @media screen and (max-width: #{$screen-md - 1}) { + .place { + display: none; + } + } + } + @media screen and (min-width: $screen-xl) { + display: contents; + + .sidebar { + mask-image: none; + } + } + } +} diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx new file mode 100644 index 000000000000..3a0d8d1449ce --- /dev/null +++ b/client/src/curriculum/module.tsx @@ -0,0 +1,88 @@ +import useSWR from "swr"; +import { HydrationData } from "../../../libs/types/hydration"; +import { ModuleData, SidebarEntry } from "../../../libs/types/curriculum"; +import { HTTPError, RenderDocumentBody } from "../document"; +import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; +import { TOC } from "../document/organisms/toc"; +import { SidePlacement } from "../ui/organisms/placement"; + +import "./module.scss"; + +export function CurriculumModule(props: HydrationData) { + const dataURL = `./index.json`; + const { data } = useSWR( + dataURL, + async (url) => { + const response = await fetch(url); + + if (!response.ok) { + switch (response.status) { + case 404: + throw new HTTPError(response.status, url, "Page not found"); + } + + const text = await response.text(); + throw new HTTPError(response.status, url, text); + } + + return await response.json(); + }, + { + fallbackData: props as ModuleData, + revalidateOnFocus: WRITER_MODE, + revalidateOnMount: !props.blogMeta, + } + ); + const { doc, curriculumMeta } = data || props || {}; + return ( + <> + {doc && ( +
+
+
+ + {PLACEMENT_ENABLED && } +
+ +
+
+
+

{doc?.title}

+ {curriculumMeta?.topic &&

{curriculumMeta.topic}

} +
+ +
+
+ )} + + ); +} + +function Sidebar({ sidebar = [] }: { sidebar: SidebarEntry[] }) { + return ( +
+ ); +} diff --git a/client/src/document/organisms/toc/index.tsx b/client/src/document/organisms/toc/index.tsx index 31a6693473fe..26f3ca38eb5f 100644 --- a/client/src/document/organisms/toc/index.tsx +++ b/client/src/document/organisms/toc/index.tsx @@ -72,13 +72,13 @@ function TOCItem({ currentViewedTocItem, }: Toc & { currentViewedTocItem: string }) { const gleanClick = useGleanClick(); - const href = `#${id.toLowerCase()}`; + const href = id && `#${id.toLowerCase()}`; return (
  • gleanClick(`${TOC_CLICK}: ${href}`)} diff --git a/client/src/placement-context.tsx b/client/src/placement-context.tsx index e4eafb266973..0f562db8532e 100644 --- a/client/src/placement-context.tsx +++ b/client/src/placement-context.tsx @@ -21,7 +21,7 @@ export interface PlacementContextData } const PLACEMENT_MAP: Record = { - side: /\/[^/]+\/(play|docs\/|blog\/|search$)/i, + side: /\/[^/]+\/(play|docs\/|blog\/|curriculum\/|search$)/i, top: /\/[^/]+\/(?!$|_homepage$).*/i, hpMain: /\/[^/]+\/($|_homepage$)/i, hpFooter: /\/[^/]+\/($|_homepage$)/i, diff --git a/client/src/ui/molecules/main-menu/index.tsx b/client/src/ui/molecules/main-menu/index.tsx index 7a8b10e52e32..8cfcef56142b 100644 --- a/client/src/ui/molecules/main-menu/index.tsx +++ b/client/src/ui/molecules/main-menu/index.tsx @@ -82,6 +82,7 @@ export default function MainMenu({ isOpenOnMobile }) { toggleMenu={toggleMenu} /> )} + Curriculum Blog Play diff --git a/cloud-function/src/app.ts b/cloud-function/src/app.ts index 04ed76e07541..66019a394427 100644 --- a/cloud-function/src/app.ts +++ b/cloud-function/src/app.ts @@ -74,7 +74,7 @@ router.get( proxyContent ); router.get( - "/[^/]+/blog($|/*)", + ["/[^/]+/blog($|/*)", "/[^/]+/curriculum($|/*)"], requireOrigin(Origin.main), redirectLocale, redirectEnforceTrailingSlash, diff --git a/deployer/src/deployer/search/__init__.py b/deployer/src/deployer/search/__init__.py index 710f7870e88a..06da5e8ebd79 100644 --- a/deployer/src/deployer/search/__init__.py +++ b/deployer/src/deployer/search/__init__.py @@ -216,6 +216,11 @@ def to_search(file, _index=None): # other SPAs like the home page. Skip these. return doc = data["doc"] + + if doc["mdn_url"].startswith("/en-US/curriculum/"): + # Skip curriculum content for now. + return + locale, slug = doc["mdn_url"].split("/docs/", 1) if slug.endswith("/Index"): # We have a lot of pages that uses the `{{Index(...)}}` kumascript macro diff --git a/libs/env/index.d.ts b/libs/env/index.d.ts index d8c5b3b57e4e..a619ba438f61 100644 --- a/libs/env/index.d.ts +++ b/libs/env/index.d.ts @@ -15,6 +15,7 @@ export const CONTENT_ROOT: string; export const CONTENT_TRANSLATED_ROOT: string; export const CONTRIBUTOR_SPOTLIGHT_ROOT: string; export const BLOG_ROOT: string; +export const CURRICULUM_ROOT: string; export const REPOSITORY_URLS: { [path: string]: string; }; diff --git a/libs/env/index.js b/libs/env/index.js index 9593cd7327a5..22e6282195b2 100644 --- a/libs/env/index.js +++ b/libs/env/index.js @@ -82,6 +82,8 @@ export const CONTRIBUTOR_SPOTLIGHT_ROOT = correctContentPathFromEnv( export const BLOG_ROOT = correctContentPathFromEnv("BLOG_ROOT"); +export const CURRICULUM_ROOT = process.env.CURRICULUM_ROOT; + // This makes it possible to know, give a root folder, what is the name of // the repository on GitHub. // E.g. `'https://github.com/' + REPOSITORY_URLS[document.fileInfo.root]` diff --git a/libs/types/curriculum.ts b/libs/types/curriculum.ts new file mode 100644 index 000000000000..0e7dc5a1084d --- /dev/null +++ b/libs/types/curriculum.ts @@ -0,0 +1,28 @@ +import { Doc } from "./document.js"; + +export enum Topic {} + +export interface SidebarEntry { + url: string; + title: string; + slug: string; + children?: SidebarEntry[]; +} + +export interface CurriculumFrontmatter { + summary?: string; + icon?: string; + topic?: Topic; +} + +export interface ModuleMetaData extends CurriculumFrontmatter { + url: string; + filename: string; + slug: string; + title: string; +} + +export interface ModuleData { + doc: Doc; + curriculumMeta: ModuleMetaData; +} diff --git a/libs/types/document.ts b/libs/types/document.ts index 4aca45f50064..512ddfdf74fb 100644 --- a/libs/types/document.ts +++ b/libs/types/document.ts @@ -1,3 +1,4 @@ +import { SidebarEntry } from "./curriculum.js"; import type { SupportStatus } from "./web-features.js"; export interface Source { @@ -155,6 +156,7 @@ export interface DocMetadata { export interface Doc extends DocMetadata { sidebarHTML: string; sidebarMacro?: string; + sidebar: SidebarEntry[]; toc: Toc[]; body: Section[]; } diff --git a/libs/types/hydration.ts b/libs/types/hydration.ts index 56b8aec0399c..f502ceb7d3b1 100644 --- a/libs/types/hydration.ts +++ b/libs/types/hydration.ts @@ -1,9 +1,11 @@ import { BlogPostMetadata } from "./blog.js"; +import { ModuleMetaData } from "./curriculum.js"; interface HydrationData { hyData?: T; doc?: any; blogMeta?: BlogPostMetadata | null; + curriculumMeta?: ModuleMetaData | null; pageNotFound?: boolean; pageTitle?: any; possibleLocales?: any; diff --git a/package.json b/package.json index a9928caacab8..711a7e339aad 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "build": "cross-env NODE_ENV=production NODE_OPTIONS='--no-warnings=ExperimentalWarning --loader ts-node/esm' node build/cli.ts", "build:blog": "cross-env NODE_ENV=production ts-node build/build-blog.ts", "build:client": "cd client && cross-env NODE_ENV=production BABEL_ENV=production INLINE_RUNTIME_CHUNK=false node scripts/build.js", + "build:curriculum": "cross-env NODE_ENV=production ts-node build/build-curriculum.ts", "build:dist": "tsc -p tsconfig.dist.json", "build:glean": "cd client && cross-env VIRTUAL_ENV=venv glean translate src/telemetry/metrics.yaml src/telemetry/pings.yaml -f typescript -o src/telemetry/generated", "build:prepare": "yarn build:client && yarn build:ssr && yarn tool optimize-client-build && yarn tool google-analytics-code && yarn tool popularities && yarn tool spas && yarn tool gather-git-history && yarn tool build-robots-txt", diff --git a/server/index.ts b/server/index.ts index 21539484f193..3f0bb28819cb 100644 --- a/server/index.ts +++ b/server/index.ts @@ -53,6 +53,7 @@ import { findPostBySlug, findPostPathBySlug, } from "../build/blog.js"; +import { buildIndex, findModuleBySlug } from "../build/curriculum.js"; async function buildDocumentFromURL(url: string) { const document = Document.findByURL(url); @@ -236,6 +237,30 @@ app.get("/*/contributors.txt", async (req, res) => { ); }); +//app.get("/:locale/curriculum/index.json", async (req, res) => { +// const data = await buildIndex(); +// if (!data) { +// return res.status(404).send("Nothing here 🤷‍♂️"); +// } +// return res.json(data); +//}); + +app.get( + [ + "/:locale/curriculum/:slug([\\S\\/]+)/index.json", + "/:locale/curriculum/index.json", + ], + async (req, res) => { + const { slug = "" } = req.params; + console.log(slug); + const data = await findModuleBySlug(slug); + if (!data) { + return res.status(404).send("Nothing here 🤷‍♂️"); + } + return res.json(data); + } +); + app.get("/:locale/blog/index.json", async (_, res) => { const posts = await allPostFrontmatter( { includeUnpublished: true }, From 597ef298ca7c39929a5f3f1374405a27faf10714 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Tue, 30 Jan 2024 23:25:02 +0100 Subject: [PATCH 002/102] wip --- build/curriculum.ts | 117 ++++++++++++++++++++--------- build/utils.ts | 4 + client/src/app.tsx | 6 +- client/src/curriculum/index.scss | 9 +++ client/src/curriculum/index.tsx | 86 +++++++++++++++++++++ client/src/curriculum/module.tsx | 30 +------- client/src/curriculum/modules.tsx | 33 ++++++++ client/src/curriculum/overview.tsx | 67 +++++++++++++++++ client/src/curriculum/sidebar.tsx | 27 +++++++ libs/types/curriculum.ts | 15 +++- libs/types/document.ts | 5 +- 11 files changed, 330 insertions(+), 69 deletions(-) create mode 100644 client/src/curriculum/index.scss create mode 100644 client/src/curriculum/index.tsx create mode 100644 client/src/curriculum/modules.tsx create mode 100644 client/src/curriculum/overview.tsx create mode 100644 client/src/curriculum/sidebar.tsx diff --git a/build/curriculum.ts b/build/curriculum.ts index a7a98f39f74f..37a13a0d8ee6 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -22,44 +22,65 @@ import { CurriculumFrontmatter, ModuleData, ModuleMetaData, - SidebarEntry, + ModuleIndexEntry, } from "../libs/types/curriculum.js"; import frontmatter from "front-matter"; import { HydrationData } from "../libs/types/hydration.js"; import { memoize, slugToFolder } from "../content/utils.js"; import { renderHTML } from "../ssr/dist/main.js"; -async function allFiles(): Promise { +export const allFiles = memoize(async () => { const api = new fdir() .withFullPaths() .withErrors() .filter((filePath) => filePath.endsWith(".md")) .crawl(path.join(CURRICULUM_ROOT, "curriculum")); - return await api.withPromise(); -} + return (await api.withPromise()).sort(); +}); export const buildIndex = memoize(async () => { const files = await allFiles(); const modules = await Promise.all( files.map( async (file) => - (await readModule(file, { previousNext: false, sidebar: false })).meta + (await readModule(file, { previousNext: false, withIndex: false })).meta ) ); return modules; }); -export async function buildSidebar(): Promise { +export function fileToSlug(file) { + return file + .replace(`${CURRICULUM_ROOT}/`, "") + .replace(/(\d+-|\.md$|\/0?-?README)/g, ""); +} + +export async function slugToFile(slug) { + const all = await allFiles(); + const re = new RegExp( + path.join( + CURRICULUM_ROOT, + "curriculum", + `${slug + .split("/") + .map((x) => String.raw`(\d+-)?${x}`) + .join("/")}.md` + ) + ); + return all.find((x) => { + return re.test(x); + }); +} + +export async function buildModuleIndex( + mapper: (x: ModuleMetaData) => Partial = (x) => x +): Promise { const index = await buildIndex(); - const s = index.reduce((sidebar, { url, title, slug }) => { - const currentLvl = slug.split("/").length; + const s = index.reduce((sidebar, meta) => { + const currentLvl = meta.slug.split("/").length; const last = sidebar.length ? sidebar[sidebar.length - 1] : null; - const entry = { - url, - title, - slug, - }; + const entry = mapper(meta); if (currentLvl > 2) { if (last) { last.children.push(entry); @@ -74,27 +95,52 @@ export async function buildSidebar(): Promise { return s; } +export async function buildSidebar(): Promise { + const index = await buildModuleIndex(({ url, slug, title }) => { + return { url, slug, title }; + }); + + return index; +} + async function readModule( file: string, options?: { previousNext?: boolean; - sidebar?: boolean; + withIndex?: boolean; } -): Promise<{ meta: ModuleMetaData; body: string; sidebar: any }> { +): Promise<{ + meta: ModuleMetaData; + body: string; + sidebar?: ModuleIndexEntry[]; + modules?: ModuleIndexEntry[]; +}> { const raw = await fs.readFile(file, "utf-8"); const { attributes, body: rawBody } = frontmatter(raw); const filename = file.replace(CURRICULUM_ROOT, "").replace(/^\/?/, ""); const title = rawBody.match(/^[\w\n]*#+(.*\n)/)[1]?.trim(); const body = rawBody.replace(/^[\w\n]*#+(.*\n)/, ""); - const slug = filename.replace(/\.md$/, "").replace("/0-README", ""); + const slug = fileToSlug(file); const url = `/${DEFAULT_LOCALE}/${slug}/`; - const sidebar = options?.sidebar && (await buildSidebar()); + const sidebar = options?.withIndex && (await buildSidebar()); + + // For module overview and landing page set modules. + let modules: ModuleIndexEntry[] | undefined; + if (options?.withIndex) { + const index = await buildModuleIndex(); + if (slug === "curriculum") { + modules = index?.filter((x) => x.children?.length); + } else { + modules = index?.find((x) => x.slug === slug)?.children; + } + } return { meta: { filename, slug, url, title, ...attributes }, sidebar, + modules, body, }; } @@ -102,21 +148,18 @@ async function readModule( export async function findModuleBySlug( slug: string ): Promise { - let slugPath = `${slug}.md`.split("/"); - let file = path.join(CURRICULUM_ROOT, "curriculum", ...slugPath); + let file = await slugToFile(slug); + if (!file) { + file = await slugToFile(`${slug}${slug ? "/" : ""}README`); + } let module; try { - module = await readModule(file, { sidebar: true }); - } catch { - slugPath = `${slug}/0-README.md`.split("/"); - file = path.join(CURRICULUM_ROOT, "curriculum", ...slugPath); - try { - module = await readModule(file, { sidebar: true }); - } catch { - console.error(`No file found for ${slug}`); - } + module = await readModule(file, { withIndex: true }); + } catch (e) { + console.error(`No file found for ${slug}`, e); + return; } - const { body, meta, sidebar } = module; + const { body, meta, sidebar, modules } = module; const d = { url: meta.url, @@ -127,6 +170,7 @@ export async function findModuleBySlug( path: file, }, sidebar, + modules, }; const doc = await buildModule(d); @@ -134,7 +178,7 @@ export async function findModuleBySlug( } export async function buildModule(document: any): Promise { - const { metadata, sidebar } = document; + const { metadata, sidebar, modules } = document; const doc = { locale: DEFAULT_LOCALE } as Partial; let $ = null; @@ -172,11 +216,12 @@ export async function buildModule(document: any): Promise { throw error; } - doc.pageTitle = `${doc.title} | MDN Blog`; + doc.pageTitle = `${doc.title} | MDN Curriculum`; doc.noIndexing = false; doc.toc = makeTOC(doc, true); doc.sidebar = sidebar; + doc.modules = modules; return doc as Doc; } @@ -190,7 +235,9 @@ export async function buildCurriculum(options: { for (const file of await allFiles()) { console.log(`building: ${file}`); - const { meta, body, sidebar } = await readModule(file, { sidebar: true }); + const { meta, body, sidebar, modules } = await readModule(file, { + withIndex: true, + }); const url = meta.url; const renderUrl = url.replace(/\/$/, ""); @@ -202,10 +249,12 @@ export async function buildCurriculum(options: { fileInfo: { path: file, }, + sidebar, + modules, }; const builtDoc = await buildModule(renderDoc); const { doc } = { - doc: { ...builtDoc, summary: meta.summary, mdn_url: url, sidebar }, + doc: { ...builtDoc, summary: meta.summary, mdn_url: url }, }; const context: HydrationData = { @@ -268,7 +317,7 @@ function setCurriculumTypes($) { if (p) { const notes = $(p); - if (notes.text() === "Notes:") { + if (/Notes?:/.test(notes.text())) { bq.addClass("curriculum-notes"); } } diff --git a/build/utils.ts b/build/utils.ts index b5fc50fd7d8f..213827cbe290 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -259,6 +259,10 @@ export function postProcessCurriculumLinks($, url) { const $a = $(element); $a.attr("href", $a.attr("href").replace(/(.*)\.md(#.*|$)/, "/en-US$1/$2")); }); + $("a[href^=/en-US/curriculum]").each((_, element) => { + const $a = $(element); + $a.attr("href", $a.attr("href").replace(/\d+-/g, "")); + }); } /** diff --git a/client/src/app.tsx b/client/src/app.tsx index 0ac9c10bdd19..273d614e9e71 100644 --- a/client/src/app.tsx +++ b/client/src/app.tsx @@ -28,7 +28,7 @@ import { HydrationData } from "../../libs/types/hydration"; import { TopPlacement } from "./ui/organisms/placement"; import { Blog } from "./blog"; import { Newsletter } from "./newsletter"; -import { CurriculumModule } from "./curriculum/module"; +import { Curriculum } from "./curriculum"; const AllFlaws = React.lazy(() => import("./flaws")); const Translations = React.lazy(() => import("./translations")); @@ -168,8 +168,8 @@ export function App(appProps: HydrationData) { - + + } /> diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss new file mode 100644 index 000000000000..5e633ac21898 --- /dev/null +++ b/client/src/curriculum/index.scss @@ -0,0 +1,9 @@ +.curriculum-content-container { + .curriculum-content { + .modules { + input[type="radio"]:not(:checked) ~ ol { + display: none; + } + } + } +} diff --git a/client/src/curriculum/index.tsx b/client/src/curriculum/index.tsx new file mode 100644 index 000000000000..37a95e4d30f0 --- /dev/null +++ b/client/src/curriculum/index.tsx @@ -0,0 +1,86 @@ +import useSWR from "swr"; +import { Route, Routes } from "react-router-dom"; + +import { HydrationData } from "../../../libs/types/hydration"; +import { ModuleData } from "../../../libs/types/curriculum"; +import { HTTPError, RenderDocumentBody } from "../document"; +import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; +import { TOC } from "../document/organisms/toc"; +import { SidePlacement } from "../ui/organisms/placement"; +import { Sidebar } from "./sidebar"; +import { ModulesListList } from "./modules"; +import { CurriculumModuleOverview } from "./overview"; +import { CurriculumModule } from "./module"; + +import "./index.scss"; + +export function Curriculum(appProps: HydrationData) { + return ( + + } /> + } + /> + } /> + + ); +} + +export function CurriculumLanding(props: HydrationData) { + const dataURL = `./index.json`; + const { data } = useSWR( + dataURL, + async (url) => { + const response = await fetch(url); + + if (!response.ok) { + switch (response.status) { + case 404: + throw new HTTPError(response.status, url, "Page not found"); + } + + const text = await response.text(); + throw new HTTPError(response.status, url, text); + } + + return await response.json(); + }, + { + fallbackData: props as ModuleData, + revalidateOnFocus: WRITER_MODE, + revalidateOnMount: !props.blogMeta, + } + ); + const { doc, curriculumMeta } = data || props || {}; + return ( + <> + {doc && ( +
    +
    +
    + + {PLACEMENT_ENABLED && } +
    + +
    +
    +
    +

    {doc?.title}

    + {curriculumMeta?.topic &&

    {curriculumMeta.topic}

    } +
    + +
    +

    Modules:

    + +
    +
    +
    + )} + + ); +} diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 3a0d8d1449ce..6a795cdd9ade 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -1,12 +1,13 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; -import { ModuleData, SidebarEntry } from "../../../libs/types/curriculum"; +import { ModuleData } from "../../../libs/types/curriculum"; import { HTTPError, RenderDocumentBody } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { TOC } from "../document/organisms/toc"; import { SidePlacement } from "../ui/organisms/placement"; import "./module.scss"; +import { Sidebar } from "./sidebar"; export function CurriculumModule(props: HydrationData) { const dataURL = `./index.json`; @@ -30,7 +31,7 @@ export function CurriculumModule(props: HydrationData) { { fallbackData: props as ModuleData, revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.blogMeta, + revalidateOnMount: !props.curriculumMeta, } ); const { doc, curriculumMeta } = data || props || {}; @@ -61,28 +62,3 @@ export function CurriculumModule(props: HydrationData) { ); } - -function Sidebar({ sidebar = [] }: { sidebar: SidebarEntry[] }) { - return ( -
    - ); -} diff --git a/client/src/curriculum/modules.tsx b/client/src/curriculum/modules.tsx new file mode 100644 index 000000000000..9a5e43509d43 --- /dev/null +++ b/client/src/curriculum/modules.tsx @@ -0,0 +1,33 @@ +import { ModuleIndexEntry } from "../../../libs/types/curriculum"; + +export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { + return ( +
      + {modules.map((c, i) => { + return ( +
    1. + + + {c.children && } +
    2. + ); + })} +
    + ); +} + +export function ModulesList({ modules }: { modules: ModuleIndexEntry[] }) { + return ( +
      + {modules.map((c, j) => { + return ( +
    1. + {c.title} +

      {c.summary}

      +

      {c.topic}

      +
    2. + ); + })} +
    + ); +} diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx new file mode 100644 index 000000000000..e32aafbd416f --- /dev/null +++ b/client/src/curriculum/overview.tsx @@ -0,0 +1,67 @@ +import useSWR from "swr"; +import { HydrationData } from "../../../libs/types/hydration"; +import { ModuleData } from "../../../libs/types/curriculum"; +import { HTTPError, RenderDocumentBody } from "../document"; +import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; +import { TOC } from "../document/organisms/toc"; +import { SidePlacement } from "../ui/organisms/placement"; +import { Sidebar } from "./sidebar"; +import { ModulesList } from "./modules"; + +export function CurriculumModuleOverview(props: HydrationData) { + const dataURL = `./index.json`; + const { data } = useSWR( + dataURL, + async (url) => { + const response = await fetch(url); + + if (!response.ok) { + switch (response.status) { + case 404: + throw new HTTPError(response.status, url, "Page not found"); + } + + const text = await response.text(); + throw new HTTPError(response.status, url, text); + } + + return await response.json(); + }, + { + fallbackData: props as ModuleData, + revalidateOnFocus: WRITER_MODE, + revalidateOnMount: !props.blogMeta, + } + ); + const { doc, curriculumMeta } = data || props || {}; + return ( + <> + {doc && ( +
    +
    +
    + + {PLACEMENT_ENABLED && } +
    + +
    +
    +
    +

    {doc?.title}

    + {curriculumMeta?.topic &&

    {curriculumMeta.topic}

    } +
    + +
    +

    Module Contents:

    + +
    +
    +
    + )} + + ); +} diff --git a/client/src/curriculum/sidebar.tsx b/client/src/curriculum/sidebar.tsx new file mode 100644 index 000000000000..d64e06e58c26 --- /dev/null +++ b/client/src/curriculum/sidebar.tsx @@ -0,0 +1,27 @@ +import { ModuleIndexEntry } from "../../../libs/types/curriculum"; + +import "./module.scss"; +export function Sidebar({ sidebar = [] }: { sidebar: ModuleIndexEntry[] }) { + return ( + + ); +} diff --git a/libs/types/curriculum.ts b/libs/types/curriculum.ts index 0e7dc5a1084d..38bec027a543 100644 --- a/libs/types/curriculum.ts +++ b/libs/types/curriculum.ts @@ -1,12 +1,21 @@ import { Doc } from "./document.js"; -export enum Topic {} +export enum Topic { + WebStandards = "Web Standards & Semantics", + Styling = "Styling", + Scripting = "Scripting", + BestPractices = "Best Practices", + Tooling = "Tooling", + None = "", +} -export interface SidebarEntry { +export interface ModuleIndexEntry { url: string; title: string; slug: string; - children?: SidebarEntry[]; + summary?: string; + topic?: Topic; + children?: ModuleIndexEntry[]; } export interface CurriculumFrontmatter { diff --git a/libs/types/document.ts b/libs/types/document.ts index 512ddfdf74fb..b217de7bc17a 100644 --- a/libs/types/document.ts +++ b/libs/types/document.ts @@ -1,4 +1,4 @@ -import { SidebarEntry } from "./curriculum.js"; +import { ModuleIndexEntry } from "./curriculum.js"; import type { SupportStatus } from "./web-features.js"; export interface Source { @@ -156,7 +156,8 @@ export interface DocMetadata { export interface Doc extends DocMetadata { sidebarHTML: string; sidebarMacro?: string; - sidebar: SidebarEntry[]; + sidebar: ModuleIndexEntry[]; + modules: ModuleIndexEntry[]; toc: Toc[]; body: Section[]; } From 714682cd0825c6b389d6b84744bdce24dc98f36f Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 14:50:06 +0100 Subject: [PATCH 003/102] wip --- build/curriculum.ts | 118 +++++++++++++----- .../assets/curriculum/cur-topic-practices.svg | 6 + .../assets/curriculum/cur-topic-scripting.svg | 6 + .../assets/curriculum/cur-topic-standards.svg | 6 + .../assets/curriculum/cur-topic-styling.svg | 5 + .../assets/curriculum/cur-topic-tooling.svg | 6 + client/src/app.tsx | 6 +- client/src/curriculum/index.tsx | 62 +++++---- client/src/curriculum/module.scss | 29 +++-- client/src/curriculum/module.tsx | 67 ++++++---- .../{modules.tsx => modules-list.tsx} | 2 + client/src/curriculum/overview.tsx | 64 ++++++---- client/src/curriculum/topic-icon.tsx | 33 +++++ client/src/document/hooks.ts | 3 + libs/types/curriculum.ts | 45 ++++++- libs/types/document.ts | 3 - libs/types/hydration.ts | 4 +- 17 files changed, 335 insertions(+), 130 deletions(-) create mode 100644 client/public/assets/curriculum/cur-topic-practices.svg create mode 100644 client/public/assets/curriculum/cur-topic-scripting.svg create mode 100644 client/public/assets/curriculum/cur-topic-standards.svg create mode 100644 client/public/assets/curriculum/cur-topic-styling.svg create mode 100644 client/public/assets/curriculum/cur-topic-tooling.svg rename client/src/curriculum/{modules.tsx => modules-list.tsx} (89%) create mode 100644 client/src/curriculum/topic-icon.tsx diff --git a/build/curriculum.ts b/build/curriculum.ts index 37a13a0d8ee6..a0fa3301fae4 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -1,6 +1,6 @@ import { fdir } from "fdir"; import { BUILD_OUT_ROOT, CURRICULUM_ROOT } from "../libs/env/index.js"; -import { Doc } from "../libs/types/document.js"; +import { Doc, DocParent } from "../libs/types/document.js"; import { DEFAULT_LOCALE } from "../libs/constants/index.js"; import * as kumascript from "../kumascript/index.js"; import LANGUAGES_RAW from "../libs/languages/index.js"; @@ -23,6 +23,11 @@ import { ModuleData, ModuleMetaData, ModuleIndexEntry, + PrevNext, + Template, + CurriculumDoc, + ReadCurriculum, + BuildData, } from "../libs/types/curriculum.js"; import frontmatter from "front-matter"; import { HydrationData } from "../libs/types/hydration.js"; @@ -103,18 +108,53 @@ export async function buildSidebar(): Promise { return index; } +export async function buildPrevNext(slug: string): Promise { + const index = await buildIndex(); + const i = index.findIndex((x) => x.slug === slug); + return { + prev: i > 0 ? index[i - 1] : undefined, + next: i < index.length - 2 ? index[i + 1] : undefined, + }; +} + +function breadPath(url: string, cur: ModuleIndexEntry[]): DocParent[] | null { + for (const entry of cur) { + if (entry.url === url) { + return [{ uri: entry.url, title: entry.title }]; + } + if (entry.children?.length) { + const found = breadPath(url, entry.children); + if (found) { + return [{ uri: entry.url, title: entry.title }, ...found]; + } + } + } + return null; +} + +export async function buildParents(url: string): Promise { + const index = await buildModuleIndex(({ url, title }) => { + return { url, title }; + }); + const parents = breadPath(url, index); + if (parents) { + const { url, title } = index[0]; + if (parents[0]?.uri !== url) { + return [{ uri: url, title }, ...parents]; + } + return parents; + } + + return []; +} + async function readModule( file: string, options?: { previousNext?: boolean; withIndex?: boolean; } -): Promise<{ - meta: ModuleMetaData; - body: string; - sidebar?: ModuleIndexEntry[]; - modules?: ModuleIndexEntry[]; -}> { +): Promise { const raw = await fs.readFile(file, "utf-8"); const { attributes, body: rawBody } = frontmatter(raw); const filename = file.replace(CURRICULUM_ROOT, "").replace(/^\/?/, ""); @@ -124,23 +164,40 @@ async function readModule( const slug = fileToSlug(file); const url = `/${DEFAULT_LOCALE}/${slug}/`; - const sidebar = options?.withIndex && (await buildSidebar()); + let sidebar: ModuleIndexEntry[]; + let parents: DocParent[]; // For module overview and landing page set modules. - let modules: ModuleIndexEntry[] | undefined; + let modules: ModuleIndexEntry[]; + let prevNext: PrevNext; if (options?.withIndex) { - const index = await buildModuleIndex(); - if (slug === "curriculum") { - modules = index?.filter((x) => x.children?.length); - } else { - modules = index?.find((x) => x.slug === slug)?.children; + if (attributes.template === Template.landing) { + modules = (await buildModuleIndex())?.filter((x) => x.children?.length); + } else if (attributes.template === Template.overview) { + modules = (await buildModuleIndex())?.find( + (x) => x.slug === slug + )?.children; + } + if (attributes.template === Template.module) { + prevNext = await buildPrevNext(slug); } + + sidebar = await buildSidebar(); + parents = await buildParents(url); } return { - meta: { filename, slug, url, title, ...attributes }, - sidebar, - modules, + meta: { + filename, + slug, + url, + title, + sidebar, + modules, + parents, + prevNext, + ...attributes, + }, body, }; } @@ -159,9 +216,9 @@ export async function findModuleBySlug( console.error(`No file found for ${slug}`, e); return; } - const { body, meta, sidebar, modules } = module; + const { body, meta } = module; - const d = { + const d: BuildData = { url: meta.url, rawBody: body, metadata: { locale: DEFAULT_LOCALE, ...meta }, @@ -169,18 +226,16 @@ export async function findModuleBySlug( fileInfo: { path: file, }, - sidebar, - modules, }; const doc = await buildModule(d); - return { doc, curriculumMeta: meta }; + return { doc }; } -export async function buildModule(document: any): Promise { - const { metadata, sidebar, modules } = document; +export async function buildModule(document: BuildData): Promise { + const { metadata } = document; - const doc = { locale: DEFAULT_LOCALE } as Partial; + const doc = { locale: DEFAULT_LOCALE } as Partial; let $ = null; [$] = await kumascript.render(document.url, {}, document as any); @@ -220,8 +275,11 @@ export async function buildModule(document: any): Promise { doc.noIndexing = false; doc.toc = makeTOC(doc, true); - doc.sidebar = sidebar; - doc.modules = modules; + doc.sidebar = metadata.sidebar; + doc.modules = metadata.modules; + doc.prevNext = metadata.prevNext; + doc.parents = metadata.parents; + doc.topic = metadata.topic; return doc as Doc; } @@ -235,13 +293,13 @@ export async function buildCurriculum(options: { for (const file of await allFiles()) { console.log(`building: ${file}`); - const { meta, body, sidebar, modules } = await readModule(file, { + const { meta, body } = await readModule(file, { withIndex: true, }); const url = meta.url; const renderUrl = url.replace(/\/$/, ""); - const renderDoc = { + const renderDoc: BuildData = { url: renderUrl, rawBody: body, metadata: { locale, ...meta }, @@ -249,8 +307,6 @@ export async function buildCurriculum(options: { fileInfo: { path: file, }, - sidebar, - modules, }; const builtDoc = await buildModule(renderDoc); const { doc } = { diff --git a/client/public/assets/curriculum/cur-topic-practices.svg b/client/public/assets/curriculum/cur-topic-practices.svg new file mode 100644 index 000000000000..5e8e3f6e57c9 --- /dev/null +++ b/client/public/assets/curriculum/cur-topic-practices.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/public/assets/curriculum/cur-topic-scripting.svg b/client/public/assets/curriculum/cur-topic-scripting.svg new file mode 100644 index 000000000000..afc18e11a523 --- /dev/null +++ b/client/public/assets/curriculum/cur-topic-scripting.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/public/assets/curriculum/cur-topic-standards.svg b/client/public/assets/curriculum/cur-topic-standards.svg new file mode 100644 index 000000000000..3dd7e8e457ba --- /dev/null +++ b/client/public/assets/curriculum/cur-topic-standards.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/public/assets/curriculum/cur-topic-styling.svg b/client/public/assets/curriculum/cur-topic-styling.svg new file mode 100644 index 000000000000..cd69f02e1fe4 --- /dev/null +++ b/client/public/assets/curriculum/cur-topic-styling.svg @@ -0,0 +1,5 @@ + + + + diff --git a/client/public/assets/curriculum/cur-topic-tooling.svg b/client/public/assets/curriculum/cur-topic-tooling.svg new file mode 100644 index 000000000000..b9a306d2f273 --- /dev/null +++ b/client/public/assets/curriculum/cur-topic-tooling.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/src/app.tsx b/client/src/app.tsx index 273d614e9e71..4dc6121f0d9c 100644 --- a/client/src/app.tsx +++ b/client/src/app.tsx @@ -55,7 +55,7 @@ function Layout({ pageType, children }) { } ${pageType}`} > - {pageType !== "document-page" && ( + {pageType !== "document-page" && pageType !== "curriculum" && (
    @@ -168,9 +168,9 @@ export function App(appProps: HydrationData) { + - + } /> ) { const dataURL = `./index.json`; const { data } = useSWR( dataURL, @@ -52,34 +54,40 @@ export function CurriculumLanding(props: HydrationData) { revalidateOnMount: !props.blogMeta, } ); - const { doc, curriculumMeta } = data || props || {}; + const { doc }: { doc?: CurriculumDoc } = data || props || {}; return ( <> {doc && ( -
    -
    -
    - - {PLACEMENT_ENABLED && } -
    - + <> +
    + +
    -
    -
    -

    {doc?.title}

    - {curriculumMeta?.topic &&

    {curriculumMeta.topic}

    } -
    - -
    -

    Modules:

    - -
    -
    -
    +
    +
    +
    + + {PLACEMENT_ENABLED && } +
    + {doc.sidebar && } +
    +
    +
    +

    {doc?.title}

    + {doc?.topic &&

    {doc.topic}

    } +
    + +
    +

    Modules:

    + {doc.modules && } +
    +
    +
    + )} ); diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 160b17740fc6..264b4227e946 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -62,52 +62,60 @@ .curriculum-content { grid-area: main; + .topic-icon { + height: 4rem; + width: 4rem; + } + blockquote.curriculum-notes { - border: 0px; - border-radius: var(--elem-radius); background-color: #fcefe299; - padding: 1rem 2rem; + border: 0; + border-radius: var(--elem-radius); margin: 1rem; + padding: 1rem 2rem; } p.curriculum-outcomes { display: flex; font-weight: var(--font-body-strong-weight); margin-bottom: 0.5rem; + &::before { content: url("../assets/icons/cur-resources.svg"); + display: block; + height: 24px; margin-right: 1rem; width: 24px; - height: 24px; - display: block; } } li { - list-style-type: disc; list-style-position: inside; + list-style-type: disc; margin-left: 1rem; } p.curriculum-resources { margin-bottom: 0.5rem; + + ul > li { list-style-type: none; &:not(.external)::before { content: url("../assets/icons/cur-mdn-resource.svg"); - margin-right: 0.5rem; display: inline-block; - width: 1em; height: 1em; + margin-right: 0.5rem; + width: 1em; } + &.external { &::before { content: url("../assets/icons/cur-ext-resource.svg"); - margin-right: 0.5rem; display: inline-block; - width: 1em; height: 1em; + margin-right: 0.5rem; + width: 1em; } } } @@ -178,6 +186,7 @@ &.toc-container, .toc-container { grid-area: toc; + .place { grid-area: toc; margin: 0; diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 6a795cdd9ade..0efc51ba478a 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -1,15 +1,17 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; -import { ModuleData } from "../../../libs/types/curriculum"; +import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; import { HTTPError, RenderDocumentBody } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { TOC } from "../document/organisms/toc"; import { SidePlacement } from "../ui/organisms/placement"; - import "./module.scss"; import { Sidebar } from "./sidebar"; +import { TopNavigation } from "../ui/organisms/top-navigation"; +import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; +import { TopicIcon } from "./topic-icon"; -export function CurriculumModule(props: HydrationData) { +export function CurriculumModule(props: HydrationData) { const dataURL = `./index.json`; const { data } = useSWR( dataURL, @@ -34,30 +36,49 @@ export function CurriculumModule(props: HydrationData) { revalidateOnMount: !props.curriculumMeta, } ); - const { doc, curriculumMeta } = data || props || {}; + const { doc }: { doc?: CurriculumDoc } = data || props || {}; return ( <> {doc && ( -
    -
    -
    - - {PLACEMENT_ENABLED && } -
    - + <> +
    + +
    -
    -
    -

    {doc?.title}

    - {curriculumMeta?.topic &&

    {curriculumMeta.topic}

    } -
    - -
    -
    +
    +
    +
    + + {PLACEMENT_ENABLED && } +
    + {doc.sidebar && } +
    + +
    + )} ); diff --git a/client/src/curriculum/modules.tsx b/client/src/curriculum/modules-list.tsx similarity index 89% rename from client/src/curriculum/modules.tsx rename to client/src/curriculum/modules-list.tsx index 9a5e43509d43..8fbc256193b7 100644 --- a/client/src/curriculum/modules.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -1,4 +1,5 @@ import { ModuleIndexEntry } from "../../../libs/types/curriculum"; +import { TopicIcon } from "./topic-icon"; export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { return ( @@ -22,6 +23,7 @@ export function ModulesList({ modules }: { modules: ModuleIndexEntry[] }) { {modules.map((c, j) => { return (
  • + {c.topic && } {c.title}

    {c.summary}

    {c.topic}

    diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index e32aafbd416f..5e57f5ebcbf5 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -1,14 +1,18 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; -import { ModuleData } from "../../../libs/types/curriculum"; +import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; import { HTTPError, RenderDocumentBody } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { TOC } from "../document/organisms/toc"; import { SidePlacement } from "../ui/organisms/placement"; import { Sidebar } from "./sidebar"; -import { ModulesList } from "./modules"; +import { ModulesList } from "./modules-list"; +import { TopNavigation } from "../ui/organisms/top-navigation"; +import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -export function CurriculumModuleOverview(props: HydrationData) { +export function CurriculumModuleOverview( + props: HydrationData +) { const dataURL = `./index.json`; const { data } = useSWR( dataURL, @@ -33,34 +37,40 @@ export function CurriculumModuleOverview(props: HydrationData) { revalidateOnMount: !props.blogMeta, } ); - const { doc, curriculumMeta } = data || props || {}; + const { doc }: { doc?: CurriculumDoc } = data || props || {}; return ( <> {doc && ( -
    -
    -
    - - {PLACEMENT_ENABLED && } -
    - + <> +
    + +
    -
    -
    -

    {doc?.title}

    - {curriculumMeta?.topic &&

    {curriculumMeta.topic}

    } -
    - -
    -

    Module Contents:

    - -
    -
    -
    +
    +
    +
    + + {PLACEMENT_ENABLED && } +
    + {doc.sidebar && } +
    +
    +
    +

    {doc?.title}

    + {doc?.topic &&

    {doc.topic}

    } +
    + +
    +

    Module Contents:

    + {doc.modules && } +
    +
    +
    + )} ); diff --git a/client/src/curriculum/topic-icon.tsx b/client/src/curriculum/topic-icon.tsx new file mode 100644 index 000000000000..7732a17c788f --- /dev/null +++ b/client/src/curriculum/topic-icon.tsx @@ -0,0 +1,33 @@ +import { ReactComponent as ScriptingSVG } from "../../public/assets/curriculum/cur-topic-scripting.svg"; +import { ReactComponent as ToolingSVG } from "../../public/assets/curriculum/cur-topic-tooling.svg"; +import { ReactComponent as StandardsSVG } from "../../public/assets/curriculum/cur-topic-standards.svg"; +import { ReactComponent as StylingSVG } from "../../public/assets/curriculum/cur-topic-styling.svg"; +import { ReactComponent as PracticesSVG } from "../../public/assets/curriculum/cur-topic-practices.svg"; + +// Using this import fails the build... +//import { Topic } from "../../../libs/types/curriculum"; +enum Topic { + WebStandards = "Web Standards & Semantics", + Styling = "Styling", + Scripting = "Scripting", + BestPractices = "Best Practices", + Tooling = "Tooling", + None = "", +} + +export function TopicIcon({ topic }: { topic: Topic }) { + switch (topic) { + case Topic.WebStandards: + return ; + case Topic.Styling: + return ; + case Topic.Scripting: + return ; + case Topic.Tooling: + return ; + case Topic.BestPractices: + return ; + default: + return <>; + } +} diff --git a/client/src/document/hooks.ts b/client/src/document/hooks.ts index 1d6c9e432103..38c9114cea10 100644 --- a/client/src/document/hooks.ts +++ b/client/src/document/hooks.ts @@ -138,6 +138,9 @@ export function useStickyHeaderHeight() { const header = document.getElementsByClassName( "sticky-header-container" )?.[0]; + if (!header) { + return; + } const resizeObserver = new ResizeObserver((entries) => { for (const entry of entries) { const { height } = entry.contentRect; diff --git a/libs/types/curriculum.ts b/libs/types/curriculum.ts index 38bec027a543..09e1c36ae712 100644 --- a/libs/types/curriculum.ts +++ b/libs/types/curriculum.ts @@ -1,4 +1,4 @@ -import { Doc } from "./document.js"; +import { Doc, DocParent } from "./document.js"; export enum Topic { WebStandards = "Web Standards & Semantics", @@ -9,6 +9,13 @@ export enum Topic { None = "", } +export enum Template { + module = "module", + overview = "overview", + landing = "landing", + about = "about", +} + export interface ModuleIndexEntry { url: string; title: string; @@ -18,9 +25,14 @@ export interface ModuleIndexEntry { children?: ModuleIndexEntry[]; } +export interface PrevNext { + next?: ModuleIndexEntry; + prev?: ModuleIndexEntry; +} + export interface CurriculumFrontmatter { summary?: string; - icon?: string; + template?: Template; topic?: Topic; } @@ -29,9 +41,34 @@ export interface ModuleMetaData extends CurriculumFrontmatter { filename: string; slug: string; title: string; + sidebar: ModuleIndexEntry[]; + modules: ModuleIndexEntry[]; + parents: DocParent[]; + prevNext?: PrevNext; +} + +export interface CurriculumDoc extends Doc { + sidebar?: ModuleIndexEntry[]; + modules?: ModuleIndexEntry[]; + prevNext?: PrevNext; + topic?: Topic; } export interface ModuleData { - doc: Doc; - curriculumMeta: ModuleMetaData; + doc: CurriculumDoc; +} + +export interface ReadCurriculum { + meta: ModuleMetaData; + body: string; +} + +export interface BuildData { + url: string; + rawBody: string; + metadata: { locale: string } & ModuleMetaData; + isMarkdown: true; + fileInfo: { + path: string; + }; } diff --git a/libs/types/document.ts b/libs/types/document.ts index b217de7bc17a..4aca45f50064 100644 --- a/libs/types/document.ts +++ b/libs/types/document.ts @@ -1,4 +1,3 @@ -import { ModuleIndexEntry } from "./curriculum.js"; import type { SupportStatus } from "./web-features.js"; export interface Source { @@ -156,8 +155,6 @@ export interface DocMetadata { export interface Doc extends DocMetadata { sidebarHTML: string; sidebarMacro?: string; - sidebar: ModuleIndexEntry[]; - modules: ModuleIndexEntry[]; toc: Toc[]; body: Section[]; } diff --git a/libs/types/hydration.ts b/libs/types/hydration.ts index f502ceb7d3b1..0141600e2731 100644 --- a/libs/types/hydration.ts +++ b/libs/types/hydration.ts @@ -1,9 +1,9 @@ import { BlogPostMetadata } from "./blog.js"; import { ModuleMetaData } from "./curriculum.js"; -interface HydrationData { +interface HydrationData { hyData?: T; - doc?: any; + doc?: S; blogMeta?: BlogPostMetadata | null; curriculumMeta?: ModuleMetaData | null; pageNotFound?: boolean; From 8479d92e8c04bd5a7ffb688203a56122670d0499 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 15:09:28 +0100 Subject: [PATCH 004/102] add colors --- client/src/curriculum/index.scss | 23 +++++++++++++++++++++++ client/src/curriculum/modules-list.tsx | 14 +++++++++----- client/src/curriculum/topic-icon.tsx | 10 +++++----- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 5e633ac21898..50846e182a30 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -1,9 +1,32 @@ .curriculum-content-container { + --cur-color: #fcefe2; + --cur-color-topic-standards: #d5f4f5; + --cur-color-topic-styling: #fff8d6; + --cur-color-topic-scripting: #eff5d5; + --cur-color-topic-tooling: #d5e4f5; + --cur-color-topic-practices: #f5dfd5; + .curriculum-content { .modules { input[type="radio"]:not(:checked) ~ ol { display: none; } } + + .module-list-item { + display: flex; + flex-direction: column; + + > header { + display: flex; + flex-direction: column; + align-items: center; + + .topic-icon { + width: 6rem; + height: 6rem; + } + } + } } } diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 8fbc256193b7..9fd3225d138b 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -22,11 +22,15 @@ export function ModulesList({ modules }: { modules: ModuleIndexEntry[] }) {
      {modules.map((c, j) => { return ( -
    1. - {c.topic && } - {c.title} -

      {c.summary}

      -

      {c.topic}

      +
    2. +
      + {c.topic && } + {c.title} +
      +
      +

      {c.summary}

      +

      {c.topic}

      +
    3. ); })} diff --git a/client/src/curriculum/topic-icon.tsx b/client/src/curriculum/topic-icon.tsx index 7732a17c788f..fb331526e59f 100644 --- a/client/src/curriculum/topic-icon.tsx +++ b/client/src/curriculum/topic-icon.tsx @@ -18,15 +18,15 @@ enum Topic { export function TopicIcon({ topic }: { topic: Topic }) { switch (topic) { case Topic.WebStandards: - return ; + return ; case Topic.Styling: - return ; + return ; case Topic.Scripting: - return ; + return ; case Topic.Tooling: - return ; + return ; case Topic.BestPractices: - return ; + return ; default: return <>; } From 7b1b8454ca5eba5b6de0e551485f8e35d0f4a7d0 Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 15:18:25 +0100 Subject: [PATCH 005/102] fix(curriculum): correct CURRICULUM_ROOT --- libs/env/index.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/libs/env/index.js b/libs/env/index.js index 22e6282195b2..09870e4051ef 100644 --- a/libs/env/index.js +++ b/libs/env/index.js @@ -82,7 +82,7 @@ export const CONTRIBUTOR_SPOTLIGHT_ROOT = correctContentPathFromEnv( export const BLOG_ROOT = correctContentPathFromEnv("BLOG_ROOT"); -export const CURRICULUM_ROOT = process.env.CURRICULUM_ROOT; +export const CURRICULUM_ROOT = correctPathFromEnv("CURRICULUM_ROOT"); // This makes it possible to know, give a root folder, what is the name of // the repository on GitHub. @@ -100,12 +100,20 @@ if (CONTENT_TRANSLATED_ROOT) { REPOSITORY_URLS[CONTENT_TRANSLATED_ROOT] = "mdn/translated-content"; } -function correctContentPathFromEnv(envVarName) { +function correctPathFromEnv(envVarName) { let pathName = process.env[envVarName]; if (!pathName) { return; } pathName = fs.realpathSync(pathName); + return pathName; +} + +function correctContentPathFromEnv(envVarName) { + let pathName = correctPathFromEnv(envVarName); + if (!pathName) { + return; + } if ( path.basename(pathName) !== "files" && fs.existsSync(path.join(pathName, "files")) From aa81f67ab03c9c36f571c6dc03989af2db70ab38 Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 15:24:39 +0100 Subject: [PATCH 006/102] fix(curriculum): style lists like in content --- client/src/curriculum/module.scss | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 264b4227e946..7243dabecfb5 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -89,10 +89,15 @@ } } + ol, + ul { + margin: 1rem 0 2rem; + padding-left: 2rem; + } + li { - list-style-position: inside; list-style-type: disc; - margin-left: 1rem; + margin: 0.5rem 0; } p.curriculum-resources { From d89db886ffbb12c94b6f3edf961b77d28d3b1c9a Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 15:25:07 +0100 Subject: [PATCH 007/102] fix(curriculum): align learning outcomes with list items --- client/src/curriculum/module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 7243dabecfb5..9d1ec3a23ac9 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -84,7 +84,7 @@ content: url("../assets/icons/cur-resources.svg"); display: block; height: 24px; - margin-right: 1rem; + margin-right: 0.5rem; width: 24px; } } From 6be7dbc9ccbd48a7010682c6252404e1602cf2cd Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 16:04:23 +0100 Subject: [PATCH 008/102] chore(observatory): add color to toc --- client/src/curriculum/index.scss | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 50846e182a30..f2dbc3917f39 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -1,4 +1,6 @@ .curriculum-content-container { + --background-toc-active: #fcefe2; + --category-color: #e3642a; --cur-color: #fcefe2; --cur-color-topic-standards: #d5f4f5; --cur-color-topic-styling: #fff8d6; @@ -18,13 +20,13 @@ flex-direction: column; > header { + align-items: center; display: flex; flex-direction: column; - align-items: center; .topic-icon { - width: 6rem; height: 6rem; + width: 6rem; } } } From 7948401b136504d529fc9ba28bde4acec5b82774 Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 16:04:52 +0100 Subject: [PATCH 009/102] fix(curriculum): remove margin-bottom from last blockquote child --- client/src/curriculum/module.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 9d1ec3a23ac9..f3764bca9784 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -73,6 +73,10 @@ border-radius: var(--elem-radius); margin: 1rem; padding: 1rem 2rem; + + > :last-child { + margin-bottom: 0; + } } p.curriculum-outcomes { From ade8300c440754360e87239a284cd07d9ef0d181 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 16:21:59 +0100 Subject: [PATCH 010/102] move colors --- client/src/curriculum/landing.scss | 86 ++++++++++++++++++++++++++ client/src/curriculum/modules-list.tsx | 6 +- client/src/curriculum/overview.tsx | 2 +- client/src/ui/base/_themes.scss | 26 ++++++++ 4 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 client/src/curriculum/landing.scss diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss new file mode 100644 index 000000000000..1737348a3f67 --- /dev/null +++ b/client/src/curriculum/landing.scss @@ -0,0 +1,86 @@ +.curriculum-content-container { + .curriculum-content { + .modules { + input[type="radio"]:not(:checked) ~ ol { + display: none; + } + } + + .module-contents { + h2 { + width: 100%; + } + + ol { + display: flex; + flex-wrap: wrap; + + .module-list-item { + --cur-bg-color-topic: var(--cur-bg-color); + --cur-color-topic: var(--cur-color); + border: 0; + border-radius: var(--elem-radius); + box-shadow: var(--shadow-02); + display: flex; + flex-direction: column; + margin: 0.5rem; + max-width: 100%; + min-width: 10rem; + width: 30%; + + &.topic-standards { + --cur-bg-color-topic: var(--cur-bg-color-topic-standards); + --cur-color-topic: var(--cur-color-topic-standards); + } + + &.topic-styling { + --cur-bg-color-topic: var(--cur-bg-color-topic-styling); + --cur-color-topic: var(--cur-color-topic-styling); + } + + &.topic-scripting { + --cur-bg-color-topic: var(--cur-bg-color-topic-scripting); + --cur-color-topic: var(--cur-color-topic-scripting); + } + + &.topic-tooling { + --cur-bg-color-topic: var(--cur-bg-color-topic-tooling); + --cur-color-topic: var(--cur-color-topic-tooling); + } + + &.topic-practices { + --cur-bg-color-topic: var(--cur-bg-color-topic-practices); + --cur-color-topic: var(--cur-color-topic-practices); + } + + > header { + align-items: center; + background-color: var(--cur-bg-color-topic); + display: flex; + flex-direction: column; + padding: 2rem; + + .topic-icon { + height: 6rem; + width: 6rem; + } + } + + > section { + align-items: center; + display: flex; + flex-direction: column; + font-size: var(--type-smaller-font-size); + height: 100%; + justify-content: space-between; + padding: 0.5rem 2rem; + + p:last-child { + color: var(--cur-color-topic); + } + } + } + } + } + } +} diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 9fd3225d138b..73ca4bef752c 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -1,5 +1,6 @@ import { ModuleIndexEntry } from "../../../libs/types/curriculum"; import { TopicIcon } from "./topic-icon"; +import { topic2css } from "./utils"; export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { return ( @@ -22,7 +23,10 @@ export function ModulesList({ modules }: { modules: ModuleIndexEntry[] }) {
        {modules.map((c, j) => { return ( -
      1. +
      2. {c.topic && } {c.title} diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index 5e57f5ebcbf5..752fcfd05c95 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -64,7 +64,7 @@ export function CurriculumModuleOverview( {doc?.topic &&

        {doc.topic}

        }
        -
        +

        Module Contents:

        {doc.modules && }
        diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index 183861105850..3fbca813665f 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -207,6 +207,19 @@ --baseline-limited-check: #1e8e3e; --baseline-limited-cross: #ea8600; + --cur-bg-color: #fcefe2; + --cur-bg-color-topic-standards: #d5f4f5; + --cur-bg-color-topic-styling: #eff5d5; + --cur-bg-color-topic-scripting: #fff8d6; + --cur-bg-color-topic-tooling: #d5e4f5; + --cur-bg-color-topic-practices: #f5dfd5; + --cur-color: #fcefe2; + --cur-color-topic-standards: #187b7f; + --cur-color-topic-styling: #187f22; + --cur-color-topic-scripting: #7f6f16; + --cur-color-topic-tooling: #182f7f; + --cur-color-topic-practices: #a25e3f; + color-scheme: light; } @@ -414,6 +427,19 @@ --baseline-limited-check: #1e8e3e; --baseline-limited-cross: #ea8600; + --cur-color: #fcefe2; + --cur-color-topic-standards: #d5f4f5; + --cur-color-topic-styling: #eff5d5; + --cur-color-topic-scripting: #fff8d6; + --cur-color-topic-tooling: #d5e4f5; + --cur-color-topic-practices: #f5dfd5; + --cur-bg-color: #fcefe2; + --cur-bg-color-topic-standards: #187b7f; + --cur-bg-color-topic-styling: #187f22; + --cur-bg-color-topic-scripting: #7f6f16; + --cur-bg-color-topic-tooling: #182f7f; + --cur-bg-color-topic-practices: #a25e3f; + color-scheme: dark; } From 389caede59731960ecd08812fd8e796cb87486be Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 16:23:52 +0100 Subject: [PATCH 011/102] fix modules-list --- .../{landing.scss => modules-list.scss} | 0 client/src/curriculum/modules-list.tsx | 2 ++ client/src/curriculum/utils.ts | 26 +++++++++++++++++++ 3 files changed, 28 insertions(+) rename client/src/curriculum/{landing.scss => modules-list.scss} (100%) create mode 100644 client/src/curriculum/utils.ts diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/modules-list.scss similarity index 100% rename from client/src/curriculum/landing.scss rename to client/src/curriculum/modules-list.scss diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 73ca4bef752c..d456fa520c2b 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -2,6 +2,8 @@ import { ModuleIndexEntry } from "../../../libs/types/curriculum"; import { TopicIcon } from "./topic-icon"; import { topic2css } from "./utils"; +import "./modules-list.scss"; + export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { return (
          diff --git a/client/src/curriculum/utils.ts b/client/src/curriculum/utils.ts new file mode 100644 index 000000000000..d73e1dd26bf3 --- /dev/null +++ b/client/src/curriculum/utils.ts @@ -0,0 +1,26 @@ +// Using this import fails the build... +//import { Topic } from "../../../libs/types/curriculum"; +export enum Topic { + WebStandards = "Web Standards & Semantics", + Styling = "Styling", + Scripting = "Scripting", + BestPractices = "Best Practices", + Tooling = "Tooling", + None = "", +} +export function topic2css(topic?: Topic) { + switch (topic) { + case Topic.WebStandards: + return "standards"; + case Topic.Styling: + return "styling"; + case Topic.Scripting: + return "scripting"; + case Topic.Tooling: + return "tooling"; + case Topic.BestPractices: + return "practices"; + default: + return "none"; + } +} From 1dd9d60f1f9754a75ad05f272fe4e71c09fbfbe6 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 16:25:43 +0100 Subject: [PATCH 012/102] cleanup --- client/src/curriculum/index.scss | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index f2dbc3917f39..d00801faa69e 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -1,12 +1,6 @@ .curriculum-content-container { --background-toc-active: #fcefe2; --category-color: #e3642a; - --cur-color: #fcefe2; - --cur-color-topic-standards: #d5f4f5; - --cur-color-topic-styling: #fff8d6; - --cur-color-topic-scripting: #eff5d5; - --cur-color-topic-tooling: #d5e4f5; - --cur-color-topic-practices: #f5dfd5; .curriculum-content { .modules { @@ -14,21 +8,5 @@ display: none; } } - - .module-list-item { - display: flex; - flex-direction: column; - - > header { - align-items: center; - display: flex; - flex-direction: column; - - .topic-icon { - height: 6rem; - width: 6rem; - } - } - } } } From 1f937d2c01ad3b7c8e952da026dd1fc69542c878 Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 16:36:11 +0100 Subject: [PATCH 013/102] chore(curriculum): style header --- client/src/curriculum/module.scss | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index f3764bca9784..26fe2b26daeb 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -62,9 +62,32 @@ .curriculum-content { grid-area: main; - .topic-icon { - height: 4rem; - width: 4rem; + header { + align-items: center; + display: grid; + grid-template-areas: "icon heading" "nothing category"; + justify-content: flex-start; + justify-items: flex-start; + + .topic-icon { + background-color: #eee; + grid-area: icon; + height: 4rem; + width: 4rem; + } + h1 { + grid-area: heading; + margin-bottom: 0rem; + } + p { + font-weight: 400; + grid-area: category; + margin: 0; + + &::before { + content: "Category: "; + } + } } blockquote.curriculum-notes { From 6f92d66774c1c148ebba7d113f74b99c8ac456cf Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 16:40:24 +0100 Subject: [PATCH 014/102] fix(curriculum): align resources items with other items --- client/src/curriculum/module.scss | 33 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 26fe2b26daeb..368a7ba59315 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -130,24 +130,27 @@ p.curriculum-resources { margin-bottom: 0.5rem; - + ul > li { - list-style-type: none; - - &:not(.external)::before { - content: url("../assets/icons/cur-mdn-resource.svg"); - display: inline-block; - height: 1em; - margin-right: 0.5rem; - width: 1em; - } + + ul { + padding-left: 0.25rem; + > li { + list-style-type: none; - &.external { &::before { - content: url("../assets/icons/cur-ext-resource.svg"); display: inline-block; - height: 1em; - margin-right: 0.5rem; - width: 1em; + height: 1.5rem; + margin-right: 0.25rem; + width: 1.5rem; + vertical-align: bottom; + } + + &:not(.external)::before { + content: url("../assets/icons/cur-mdn-resource.svg"); + } + + &.external { + &::before { + content: url("../assets/icons/cur-ext-resource.svg"); + } } } } From 2fe98064ccfba74174bcf073890447992808b7cc Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 16:49:49 +0100 Subject: [PATCH 015/102] svg colors --- build/curriculum.ts | 14 ++++++++------ client/src/curriculum/modules-list.scss | 13 +++++++++++-- client/src/curriculum/topic-icon.scss | 9 +++++++++ client/src/curriculum/topic-icon.tsx | 2 ++ 4 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 client/src/curriculum/topic-icon.scss diff --git a/build/curriculum.ts b/build/curriculum.ts index a0fa3301fae4..7a13c96100ad 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -48,7 +48,7 @@ export const buildIndex = memoize(async () => { const modules = await Promise.all( files.map( async (file) => - (await readModule(file, { previousNext: false, withIndex: false })).meta + (await readModule(file, { previousNext: false, forIndex: true })).meta ) ); return modules; @@ -152,13 +152,13 @@ async function readModule( file: string, options?: { previousNext?: boolean; - withIndex?: boolean; + forIndex?: boolean; } ): Promise { const raw = await fs.readFile(file, "utf-8"); const { attributes, body: rawBody } = frontmatter(raw); const filename = file.replace(CURRICULUM_ROOT, "").replace(/^\/?/, ""); - const title = rawBody.match(/^[\w\n]*#+(.*\n)/)[1]?.trim(); + let title = rawBody.match(/^[\w\n]*#+(.*\n)/)[1]?.trim(); const body = rawBody.replace(/^[\w\n]*#+(.*\n)/, ""); const slug = fileToSlug(file); @@ -170,7 +170,7 @@ async function readModule( // For module overview and landing page set modules. let modules: ModuleIndexEntry[]; let prevNext: PrevNext; - if (options?.withIndex) { + if (!options?.forIndex) { if (attributes.template === Template.landing) { modules = (await buildModuleIndex())?.filter((x) => x.children?.length); } else if (attributes.template === Template.overview) { @@ -184,6 +184,8 @@ async function readModule( sidebar = await buildSidebar(); parents = await buildParents(url); + } else { + title = title.replace(/^\d+\s+/, ""); } return { @@ -211,7 +213,7 @@ export async function findModuleBySlug( } let module; try { - module = await readModule(file, { withIndex: true }); + module = await readModule(file, { forIndex: false }); } catch (e) { console.error(`No file found for ${slug}`, e); return; @@ -294,7 +296,7 @@ export async function buildCurriculum(options: { console.log(`building: ${file}`); const { meta, body } = await readModule(file, { - withIndex: true, + forIndex: false, }); const url = meta.url; diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 1737348a3f67..3dfe32244b4d 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -58,12 +58,20 @@ background-color: var(--cur-bg-color-topic); display: flex; flex-direction: column; - padding: 2rem; + height: 20rem; + padding: 1rem; .topic-icon { height: 6rem; width: 6rem; } + + > a { + color: var(--text-primary); + font-weight: var(--font-body-strong-weight); + margin-top: 1rem; + text-align: center; + } } > section { @@ -73,10 +81,11 @@ font-size: var(--type-smaller-font-size); height: 100%; justify-content: space-between; - padding: 0.5rem 2rem; + padding: 0.5rem 1rem; p:last-child { color: var(--cur-color-topic); + text-align: center; } } } diff --git a/client/src/curriculum/topic-icon.scss b/client/src/curriculum/topic-icon.scss new file mode 100644 index 000000000000..41ca11cfbb23 --- /dev/null +++ b/client/src/curriculum/topic-icon.scss @@ -0,0 +1,9 @@ +svg.topic-icon { + circle { + fill: var(--background-primary); + } + + path { + fill: var(--cur-color-topic); + } +} diff --git a/client/src/curriculum/topic-icon.tsx b/client/src/curriculum/topic-icon.tsx index fb331526e59f..fdd67d40561f 100644 --- a/client/src/curriculum/topic-icon.tsx +++ b/client/src/curriculum/topic-icon.tsx @@ -4,6 +4,8 @@ import { ReactComponent as StandardsSVG } from "../../public/assets/curriculum/c import { ReactComponent as StylingSVG } from "../../public/assets/curriculum/cur-topic-styling.svg"; import { ReactComponent as PracticesSVG } from "../../public/assets/curriculum/cur-topic-practices.svg"; +import "./topic-icon.scss"; + // Using this import fails the build... //import { Topic } from "../../../libs/types/curriculum"; enum Topic { From 44c1329756b69f1e03b06fc2a01cd606b86242f5 Mon Sep 17 00:00:00 2001 From: Claas Augner Date: Wed, 31 Jan 2024 16:41:58 +0100 Subject: [PATCH 016/102] fixup! chore(curriculum): style header --- client/src/curriculum/module.scss | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 368a7ba59315..e3b67916c0f2 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -64,23 +64,25 @@ header { align-items: center; + column-gap: 1.5rem; display: grid; grid-template-areas: "icon heading" "nothing category"; justify-content: flex-start; justify-items: flex-start; .topic-icon { - background-color: #eee; grid-area: icon; height: 4rem; width: 4rem; } + h1 { grid-area: heading; - margin-bottom: 0rem; + margin-bottom: 0; } + p { - font-weight: 400; + font-size: var(--type-smaller-font-size); grid-area: category; margin: 0; @@ -132,6 +134,7 @@ + ul { padding-left: 0.25rem; + > li { list-style-type: none; @@ -139,8 +142,8 @@ display: inline-block; height: 1.5rem; margin-right: 0.25rem; - width: 1.5rem; vertical-align: bottom; + width: 1.5rem; } &:not(.external)::before { From 650baf39448748b405ffac94a6607acfa4a54d79 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 31 Jan 2024 16:55:54 +0100 Subject: [PATCH 017/102] move colors --- client/src/curriculum/index.scss | 28 +++++++++++++++++++++++++ client/src/curriculum/index.tsx | 5 ++++- client/src/curriculum/module.scss | 2 +- client/src/curriculum/module.tsx | 5 ++++- client/src/curriculum/modules-list.scss | 27 ------------------------ client/src/curriculum/overview.tsx | 5 ++++- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index d00801faa69e..85f8d73b65bd 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -2,6 +2,34 @@ --background-toc-active: #fcefe2; --category-color: #e3642a; + --cur-bg-color-topic: var(--cur-bg-color); + --cur-color-topic: var(--cur-color); + + .topic-standards { + --cur-bg-color-topic: var(--cur-bg-color-topic-standards); + --cur-color-topic: var(--cur-color-topic-standards); + } + + .topic-styling { + --cur-bg-color-topic: var(--cur-bg-color-topic-styling); + --cur-color-topic: var(--cur-color-topic-styling); + } + + .topic-scripting { + --cur-bg-color-topic: var(--cur-bg-color-topic-scripting); + --cur-color-topic: var(--cur-color-topic-scripting); + } + + .topic-tooling { + --cur-bg-color-topic: var(--cur-bg-color-topic-tooling); + --cur-color-topic: var(--cur-color-topic-tooling); + } + + .topic-practices { + --cur-bg-color-topic: var(--cur-bg-color-topic-practices); + --cur-color-topic: var(--cur-color-topic-practices); + } + .curriculum-content { .modules { input[type="radio"]:not(:checked) ~ ol { diff --git a/client/src/curriculum/index.tsx b/client/src/curriculum/index.tsx index ec67b554a2a7..66874eecae95 100644 --- a/client/src/curriculum/index.tsx +++ b/client/src/curriculum/index.tsx @@ -15,6 +15,7 @@ import { CurriculumModule } from "./module"; import "./index.scss"; import { TopNavigation } from "../ui/organisms/top-navigation"; import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; +import { topic2css } from "./utils"; export function Curriculum(appProps: HydrationData) { return ( @@ -63,7 +64,9 @@ export function CurriculumLanding(props: HydrationData) { -
          +
          -
          +
          -
          +
          {PLACEMENT_ENABLED && }
          - {doc.sidebar && } + {doc.sidebar && ( + + )}
          diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index af9179576454..35481e98ab35 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -58,7 +58,9 @@ export function CurriculumModule(props: HydrationData) { {PLACEMENT_ENABLED && }
          - {doc.sidebar && } + {doc.sidebar && ( + + )}
          diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index d60acc05dc0d..cf72ab3c68cd 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -59,7 +59,9 @@ export function CurriculumModuleOverview( {PLACEMENT_ENABLED && } - {doc.sidebar && } + {doc.sidebar && ( + + )}
          diff --git a/client/src/curriculum/sidebar.tsx b/client/src/curriculum/sidebar.tsx index d64e06e58c26..0c0521c94579 100644 --- a/client/src/curriculum/sidebar.tsx +++ b/client/src/curriculum/sidebar.tsx @@ -1,19 +1,29 @@ import { ModuleIndexEntry } from "../../../libs/types/curriculum"; import "./module.scss"; -export function Sidebar({ sidebar = [] }: { sidebar: ModuleIndexEntry[] }) { +export function Sidebar({ + current = "", + sidebar = [], +}: { + current: string; + sidebar: ModuleIndexEntry[]; +}) { return ( -
          diff --git a/client/src/ui/atoms/icon/index.scss b/client/src/ui/atoms/icon/index.scss index 9b5f0026d04e..364e233f9e39 100644 --- a/client/src/ui/atoms/icon/index.scss +++ b/client/src/ui/atoms/icon/index.scss @@ -1,17 +1,17 @@ $icons: "add-filled", "add", "altname", "bell", "bell-filled", "bell-ring", "bookmark-filled", "bookmark", "cancel", "chatgpt", "checkmark", "chevron", - "chrome", "critical", "deno", "deprecated", "desktop", "disabled", "edge", - "edit", "edit-filled", "ellipses", "experimental", "external", "eye-filled", - "eye", "feed", "filter", "footnote", "github-mark-small", "ie", "information", - "highlight", "history", "language", "mastodon", "menu-filled", "menu", - "mobile", "more", "theme-dark", "new-topic", "next", "no", "nodejs", - "nonstandard", "note-info", "note-warning", "note-deprecated", "opera", - "padlock", "partial", "play", "prefix", "preview", "previous", "queue", - "queued", "quote", "return", "safari", "samsunginternet", "search", "send", - "server", "sidebar", "simple-firefox", "small-arrow", "theme-light", - "star-filled", "star", "theme-os-default", "thumbs-down", "thumbs-up", "trash", - "trash-filled", "twitter", "unknown", "warning", "webview", "yes", - "yes-circle"; + "chrome", "critical", "cur-next", "cur-prev", "deno", "deprecated", "desktop", + "disabled", "edge", "edit", "edit-filled", "ellipses", "experimental", + "external", "eye-filled", "eye", "feed", "filter", "footnote", + "github-mark-small", "ie", "information", "highlight", "history", "language", + "mastodon", "menu-filled", "menu", "mobile", "more", "theme-dark", "new-topic", + "next", "no", "nodejs", "nonstandard", "note-info", "note-warning", + "note-deprecated", "opera", "padlock", "partial", "play", "prefix", "preview", + "previous", "queue", "queued", "quote", "return", "safari", "samsunginternet", + "search", "send", "server", "sidebar", "simple-firefox", "small-arrow", + "theme-light", "star-filled", "star", "theme-os-default", "thumbs-down", + "thumbs-up", "trash", "trash-filled", "twitter", "unknown", "warning", + "webview", "yes", "yes-circle"; .icon { --size: var(--icon-size, 1rem); diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index bdb95ba705e9..c01388f1a577 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -435,11 +435,11 @@ --cur-color-topic-tooling: #{$mdn-color-light-theme-green-40}; --cur-color-topic-practices: #{$mdn-color-light-theme-violet-40}; --cur-bg-color: #664b33; - --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-70}; - --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-70}; - --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-70}; - --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-70}; - --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-70}; + --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-50}30; + --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-50}30; + --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; + --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-50}30; + --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-50}30; --cur-category-color: #e3642a; color-scheme: dark; From f9bb7be02099bbffb968cb7a905b8d5c124197c8 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 1 Feb 2024 22:54:31 +0100 Subject: [PATCH 036/102] overview prev next --- build/curriculum.ts | 18 ++++++++++++++-- client/src/curriculum/module.scss | 12 ----------- client/src/curriculum/module.tsx | 25 ++-------------------- client/src/curriculum/overview.tsx | 2 ++ client/src/curriculum/prev-next.scss | 12 +++++++++++ client/src/curriculum/prev-next.tsx | 31 ++++++++++++++++++++++++++++ 6 files changed, 63 insertions(+), 37 deletions(-) create mode 100644 client/src/curriculum/prev-next.scss create mode 100644 client/src/curriculum/prev-next.tsx diff --git a/build/curriculum.ts b/build/curriculum.ts index 85880f4b4ba1..e56c67218bf7 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -110,7 +110,19 @@ export async function buildSidebar(): Promise { return index; } -export async function buildPrevNext(slug: string): Promise { +export async function buildPrevNextOverview(slug: string): Promise { + const index = (await buildModuleIndex()).filter((x) => x?.children?.length); + const i = index.findIndex((x) => x.slug === slug); + const prev = i > 0 ? index[i - 1] : undefined; + const next = i < index.length - 1 ? index[i + 1] : undefined; + + prev && delete prev.children; + next && delete next.children; + + return { prev, next }; +} + +export async function buildPrevNextModule(slug: string): Promise { const index = await buildIndex(); const i = index.findIndex((x) => x.slug === slug); return { @@ -181,7 +193,9 @@ async function readModule( )?.children; } if (attributes.template === Template.module) { - prevNext = await buildPrevNext(slug); + prevNext = await buildPrevNextModule(slug); + } else if (attributes.template === Template.overview) { + prevNext = await buildPrevNextOverview(slug); } sidebar = await buildSidebar(); diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 501c1698fed1..3cfbba873bf9 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -269,16 +269,4 @@ } } } - - .curriculum-prev-next { - display: flex; - flex-wrap: wrap; - gap: 0 1rem; - justify-content: space-between; - width: 100%; - - a { - margin: 0.5rem 0; - } - } } diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 5211d540c6c1..5bea411d6486 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -12,7 +12,7 @@ import { ArticleActionsContainer } from "../ui/organisms/article-actions-contain import { TopicIcon } from "./topic-icon"; import { topic2css, useDocTitle } from "./utils"; import { SidebarContainer } from "../document/organisms/sidebar"; -import { Button } from "../ui/atoms/button"; +import { PrevNext } from "./prev-next"; export function CurriculumModule(props: HydrationData) { const dataURL = `./index.json`; @@ -82,28 +82,7 @@ export function CurriculumModule(props: HydrationData) { {doc?.topic &&

          {doc.topic}

          }
          -
          - {doc.prevNext?.prev && ( - - )} - {doc.prevNext?.next && ( - - )} -
          +
          diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index c4fcd4ed7709..64eb7b75ecd4 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -11,6 +11,7 @@ import { topic2css, useDocTitle } from "./utils"; import "./no-side.scss"; import "./overview.scss"; +import { PrevNext } from "./prev-next"; export function CurriculumModuleOverview( props: HydrationData @@ -72,6 +73,7 @@ export function CurriculumModuleOverview(

          Module Contents:

          {doc.modules && }
        + diff --git a/client/src/curriculum/prev-next.scss b/client/src/curriculum/prev-next.scss new file mode 100644 index 000000000000..bcf29c2c01ae --- /dev/null +++ b/client/src/curriculum/prev-next.scss @@ -0,0 +1,12 @@ +.curriculum-prev-next { + display: flex; + flex-wrap: wrap; + gap: 0 1rem; + justify-content: space-between; + margin-top: 2rem; + width: 100%; + + a { + margin: 0.5rem 0; + } +} diff --git a/client/src/curriculum/prev-next.tsx b/client/src/curriculum/prev-next.tsx new file mode 100644 index 000000000000..9f2a2f8bfd85 --- /dev/null +++ b/client/src/curriculum/prev-next.tsx @@ -0,0 +1,31 @@ +import { CurriculumDoc } from "../../../libs/types/curriculum"; +import { Button } from "../ui/atoms/button"; + +import "./prev-next.scss"; + +export function PrevNext({ doc }: { doc: CurriculumDoc }) { + return ( +
        + {doc.prevNext?.prev && ( + + )} + {doc.prevNext?.next && ( + + )} +
        + ); +} From fb48443c2c6ee532e26b56c33e0f80139cf92b7c Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 1 Feb 2024 23:38:25 +0100 Subject: [PATCH 037/102] landing --- .../assets/curriculum/cur-landing-top.svg | 246 ++++++------------ client/src/assets/icons/cur-mdn-resource.png | Bin 569 -> 0 bytes client/src/curriculum/index.tsx | 74 +----- client/src/curriculum/landing.scss | 5 + client/src/curriculum/landing.tsx | 77 ++++++ client/src/curriculum/modules-list.scss | 19 +- client/src/curriculum/modules-list.tsx | 10 +- 7 files changed, 188 insertions(+), 243 deletions(-) delete mode 100644 client/src/assets/icons/cur-mdn-resource.png create mode 100644 client/src/curriculum/landing.scss create mode 100644 client/src/curriculum/landing.tsx diff --git a/client/public/assets/curriculum/cur-landing-top.svg b/client/public/assets/curriculum/cur-landing-top.svg index 95c1b01fd2ec..67c9f22f0dc4 100644 --- a/client/public/assets/curriculum/cur-landing-top.svg +++ b/client/public/assets/curriculum/cur-landing-top.svg @@ -1,166 +1,82 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-mdn-resource.png b/client/src/assets/icons/cur-mdn-resource.png deleted file mode 100644 index 22d353908c96544652397408b0d57a673c674eb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 569 zcmV-90>=G`P)Px$^GQTOR7gwhmA^~FKpe%tSK8{}4?-Ojj16{Dr0VF@bWn756pDG>q$8fPvnd0bd?h;gjLi6xZhkjjgBVguv--Y;O+V>5Y+(UJ|~vdAx!`;H;q!A zfyFiPv}2{CK=5H}nQ$KipfCXDqQ*p%W+(ugpZ2%g0(7|Qm7a+X;6zkNp9G^_n;L=)9 zL1(~M>$U()_d?wBa?>24LR1Ef{}{Ob0bmNfPo{gB6(T!}H~sTjt1p!no~wd7P`619 zTCG3?Y`PcXt@LtJm3V5_hBbQEsFsCipjqVQW^AH*1^%1vxj0_{h>na~k>P};zjQwU z_%E3BzmdT%5zi1YTV~PiV3YGLUF3HV&q)8}LR5y1V#J*9iW5;aYD|b6F&Z5Mix9AH zk3Mj+GU5_~wOH457-CP@$=Z_-4j!Q0x1lG1PWJr+x;ED*XanvU*xO^L00000NkvXX Hu0mjfrcC~L diff --git a/client/src/curriculum/index.tsx b/client/src/curriculum/index.tsx index 53dea1ccc0b8..b21486006e24 100644 --- a/client/src/curriculum/index.tsx +++ b/client/src/curriculum/index.tsx @@ -3,22 +3,14 @@ import { Route, Routes } from "react-router-dom"; import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; import { HydrationData } from "../../../libs/types/hydration"; -import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError, RenderDocumentBody } from "../document"; -import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; -import { SidePlacement } from "../ui/organisms/placement"; -import { ModulesListList } from "./modules-list"; import { CurriculumModuleOverview } from "./overview"; import { CurriculumModule } from "./module"; +import { CurriculumAbout } from "./about"; +import { CurriculumLanding } from "./landing"; import "./index.scss"; import "./no-side.scss"; -import { TopNavigation } from "../ui/organisms/top-navigation"; -import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -import { topic2css, useDocTitle } from "./utils"; -import { CurriculumAbout } from "./about"; - export function Curriculum(appProps: HydrationData) { return ( @@ -32,65 +24,3 @@ export function Curriculum(appProps: HydrationData) { ); } - -export function CurriculumLanding(props: HydrationData) { - const dataURL = `./index.json`; - const { data } = useSWR( - dataURL, - async (url) => { - const response = await fetch(url); - - if (!response.ok) { - switch (response.status) { - case 404: - throw new HTTPError(response.status, url, "Page not found"); - } - - const text = await response.text(); - throw new HTTPError(response.status, url, text); - } - - return await response.json(); - }, - { - fallbackData: props as ModuleData, - revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.blogMeta, - } - ); - const { doc }: { doc?: CurriculumDoc } = data || props || {}; - useDocTitle(doc); - return ( - <> - {doc && ( - <> -
        - - -
        -
        -
        -
        - {PLACEMENT_ENABLED && } -
        -
        -
        -
        - -

        {doc?.title}

        - {doc?.topic &&

        {doc.topic}

        } -
        - -
        -

        Modules

        - {doc.modules && } -
        -
        -
        - - )} - - ); -} diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss new file mode 100644 index 000000000000..de3878d7889a --- /dev/null +++ b/client/src/curriculum/landing.scss @@ -0,0 +1,5 @@ +.curriculum-landing { + header > svg { + width: 50%; + } +} diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx new file mode 100644 index 000000000000..ca98d8e69b6e --- /dev/null +++ b/client/src/curriculum/landing.tsx @@ -0,0 +1,77 @@ +import useSWR from "swr"; + +import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; +import { HydrationData } from "../../../libs/types/hydration"; +import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; +import { HTTPError, RenderDocumentBody } from "../document"; +import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; +import { SidePlacement } from "../ui/organisms/placement"; +import { ModulesListList } from "./modules-list"; + +import "./index.scss"; +import "./no-side.scss"; +import "./landing.scss"; + +import { TopNavigation } from "../ui/organisms/top-navigation"; +import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; +import { topic2css, useDocTitle } from "./utils"; + +export function CurriculumLanding(props: HydrationData) { + const dataURL = `./index.json`; + const { data } = useSWR( + dataURL, + async (url) => { + const response = await fetch(url); + + if (!response.ok) { + switch (response.status) { + case 404: + throw new HTTPError(response.status, url, "Page not found"); + } + + const text = await response.text(); + throw new HTTPError(response.status, url, text); + } + + return await response.json(); + }, + { + fallbackData: props as ModuleData, + revalidateOnFocus: WRITER_MODE, + revalidateOnMount: !props.blogMeta, + } + ); + const { doc }: { doc?: CurriculumDoc } = data || props || {}; + useDocTitle(doc); + return ( + <> + {doc && ( + <> +
        + + +
        +
        +
        +
        + {PLACEMENT_ENABLED && } +
        +
        +
        +
        + +

        {doc?.title}

        + {doc?.topic &&

        {doc.topic}

        } +
        + +
        +

        Modules

        + {doc.modules && } +
        +
        +
        + + )} + + ); +} diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 47a380600405..65ccfbc1f418 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -6,6 +6,7 @@ .curriculum-content { .modules { + input[type="radio"]:not(:checked) ~ a, input[type="radio"]:not(:checked) ~ ol { display: none; } @@ -20,9 +21,11 @@ ol.modules-list-list { display: grid; grid-template-areas: - "a b c spacer" - "h h h h" - "x x x x"; + "a b c spacer" + "hr hr hr hr" + "mod mod mod mod" + "t t t t"; + grid-template-columns: max-content max-content max-content auto; margin: 0; padding: 0; @@ -30,7 +33,7 @@ hr { border: none; border-top: 1px solid var(--text-primary); - grid-area: h; + grid-area: hr; margin: 0 0 1.5rem; width: 100%; } @@ -74,10 +77,16 @@ } > ol { - grid-area: x; + grid-area: mod; margin: 0; padding: 0; } + + > a { + grid-area: t; + margin-top: 2rem; + width: fit-content; + } } } diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 716a1f564705..86a9a83f084b 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -4,6 +4,7 @@ import { topic2css } from "./utils"; import "./modules-list.scss"; import { useState } from "react"; +import { Button } from "../ui/atoms/button"; export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { const [tab, setTab] = useState(1); @@ -22,7 +23,14 @@ export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { onChange={() => setTab(i)} /> - {c.children && } + {c.children && ( + <> + + + + )}
      3. ); })} From 707e3fe2fe2b93cb323e6f699264f51b025f31c5 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 1 Feb 2024 23:58:13 +0100 Subject: [PATCH 038/102] lint --- client/src/curriculum/index.tsx | 2 -- client/src/curriculum/landing.tsx | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/client/src/curriculum/index.tsx b/client/src/curriculum/index.tsx index b21486006e24..980b559944a8 100644 --- a/client/src/curriculum/index.tsx +++ b/client/src/curriculum/index.tsx @@ -1,7 +1,5 @@ -import useSWR from "swr"; import { Route, Routes } from "react-router-dom"; -import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumModuleOverview } from "./overview"; import { CurriculumModule } from "./module"; diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index ca98d8e69b6e..e1e3580c1b4a 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -14,7 +14,7 @@ import "./landing.scss"; import { TopNavigation } from "../ui/organisms/top-navigation"; import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -import { topic2css, useDocTitle } from "./utils"; +import { useDocTitle } from "./utils"; export function CurriculumLanding(props: HydrationData) { const dataURL = `./index.json`; From fada63610221de299cf0c128320498f3470a69e1 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 10:58:21 +0100 Subject: [PATCH 039/102] colors --- client/src/ui/base/_themes.scss | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index c01388f1a577..c2b5a49e06ad 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -208,11 +208,11 @@ --baseline-limited-cross: #ea8600; --cur-bg-color: #fcefe2; - --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-10}; - --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-10}; - --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-10}; - --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-10}; - --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-10}; + --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-50}30; + --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-50}30; + --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; + --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-50}30; + --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-50}30; --cur-category-color: #e3642a; --cur-color: #d47d55; --cur-color-topic-standards: #{$mdn-color-light-theme-red-60}; From 1b2073f878a2fb75a47bb42866edeab1b811ca7c Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 11:02:47 +0100 Subject: [PATCH 040/102] center module copy --- client/src/curriculum/modules-list.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 65ccfbc1f418..b24f75499cdf 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -159,11 +159,11 @@ p { margin: 0; + text-align: center; } p:last-child { color: var(--cur-color-topic); - text-align: center; } } } From c1fb57f6a51c155e6accde751399ad9a61743890 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 14:09:12 +0100 Subject: [PATCH 041/102] landing about --- .../assets/curriculum/cur-topic-practices.svg | 2 +- .../assets/curriculum/cur-topic-scripting.svg | 4 +- .../assets/curriculum/cur-topic-standards.svg | 4 +- .../assets/curriculum/cur-topic-styling.svg | 5 +- .../assets/curriculum/cur-topic-tooling.svg | 4 +- .../icons/cur-landing-about-beginner.svg | 4 + .../assets/icons/cur-landing-about-bullet.svg | 8 + .../assets/icons/cur-landing-about-free.svg | 6 + .../assets/icons/cur-landing-about-pace.svg | 6 + client/src/curriculum/about.tsx | 5 +- client/src/curriculum/body.tsx | 44 +++++ client/src/curriculum/landing.scss | 158 +++++++++++++++- client/src/curriculum/landing.tsx | 82 +++++++-- client/src/curriculum/module.scss | 174 +++++++++--------- client/src/curriculum/module.tsx | 12 +- client/src/curriculum/overview.tsx | 5 +- 16 files changed, 398 insertions(+), 125 deletions(-) create mode 100644 client/src/assets/icons/cur-landing-about-beginner.svg create mode 100644 client/src/assets/icons/cur-landing-about-bullet.svg create mode 100644 client/src/assets/icons/cur-landing-about-free.svg create mode 100644 client/src/assets/icons/cur-landing-about-pace.svg create mode 100644 client/src/curriculum/body.tsx diff --git a/client/public/assets/curriculum/cur-topic-practices.svg b/client/public/assets/curriculum/cur-topic-practices.svg index 5e8e3f6e57c9..fb77081860aa 100644 --- a/client/public/assets/curriculum/cur-topic-practices.svg +++ b/client/public/assets/curriculum/cur-topic-practices.svg @@ -2,5 +2,5 @@ + fill="#356A1C" /> diff --git a/client/public/assets/curriculum/cur-topic-scripting.svg b/client/public/assets/curriculum/cur-topic-scripting.svg index afc18e11a523..aab342cdb780 100644 --- a/client/public/assets/curriculum/cur-topic-scripting.svg +++ b/client/public/assets/curriculum/cur-topic-scripting.svg @@ -1,6 +1,6 @@ + d="M22.4805 38.127C21.888 38.127 21.3548 38.0762 20.8809 37.9746C20.4154 37.873 20.1826 37.6868 20.1826 37.416C20.1826 37.3568 20.2038 37.2214 20.2461 37.0098C20.2884 36.7982 20.3434 36.6035 20.4111 36.4258C20.4873 36.248 20.5804 36.1592 20.6904 36.1592C20.7074 36.1592 20.8005 36.1761 20.9697 36.21C21.1898 36.2607 21.3802 36.3031 21.541 36.3369C21.7103 36.3623 21.9007 36.375 22.1123 36.375C23.2295 36.375 24.0335 36.1549 24.5244 35.7148C25.0238 35.2747 25.2734 34.568 25.2734 33.5947V22.6514C25.2734 22.3128 25.5739 22.1436 26.1748 22.1436H26.3525C26.9619 22.1436 27.2666 22.3128 27.2666 22.6514V33.3662C27.2666 34.8643 26.8815 36.0322 26.1113 36.8701C25.3496 37.708 24.1393 38.127 22.4805 38.127ZM34.1553 38.127C33.3258 38.127 32.5514 38.0381 31.832 37.8604C31.1211 37.6742 30.5498 37.4541 30.1182 37.2002C29.695 36.9378 29.4834 36.7008 29.4834 36.4893C29.4834 36.3708 29.5299 36.2142 29.623 36.0195C29.7246 35.8249 29.8389 35.6514 29.9658 35.499C30.0928 35.3467 30.1943 35.2705 30.2705 35.2705C30.3382 35.2705 30.4863 35.3382 30.7148 35.4736C31.2396 35.7445 31.7601 35.9688 32.2764 36.1465C32.7926 36.3242 33.4189 36.4131 34.1553 36.4131C34.7308 36.4131 35.2428 36.3031 35.6914 36.083C36.14 35.863 36.487 35.554 36.7324 35.1562C36.9863 34.75 37.1133 34.2845 37.1133 33.7598C37.1133 33.2012 36.9609 32.7399 36.6562 32.376C36.36 32.0036 35.9961 31.7116 35.5645 31.5C35.1413 31.2799 34.5234 31.0091 33.7109 30.6875C32.8307 30.349 32.1325 30.0358 31.6162 29.748C31.1084 29.4518 30.6725 29.0244 30.3086 28.4658C29.9531 27.9072 29.7754 27.1667 29.7754 26.2441C29.7754 25.4401 29.9827 24.7207 30.3975 24.0859C30.8122 23.4427 31.4004 22.9434 32.1621 22.5879C32.9238 22.2324 33.7998 22.0547 34.79 22.0547C35.2386 22.0547 35.7507 22.1182 36.3262 22.2451C36.9017 22.3636 37.3926 22.5286 37.7988 22.7402C38.2135 22.9518 38.4209 23.1846 38.4209 23.4385C38.4209 23.5485 38.3743 23.7008 38.2812 23.8955C38.1966 24.0817 38.0951 24.251 37.9766 24.4033C37.8581 24.5557 37.765 24.6318 37.6973 24.6318C37.6211 24.6318 37.4688 24.5684 37.2402 24.4414C36.8594 24.2383 36.4827 24.0775 36.1104 23.959C35.738 23.832 35.2852 23.7686 34.752 23.7686C33.8802 23.7686 33.1735 23.9928 32.6318 24.4414C32.0986 24.89 31.832 25.5163 31.832 26.3203C31.832 26.8027 31.9505 27.2005 32.1875 27.5137C32.4245 27.8268 32.7249 28.0765 33.0889 28.2627C33.4528 28.4489 33.9606 28.6647 34.6123 28.9102C34.6546 28.9186 34.752 28.9525 34.9043 29.0117C35.8014 29.3587 36.5335 29.6973 37.1006 30.0273C37.6761 30.349 38.1628 30.8145 38.5605 31.4238C38.9668 32.0332 39.1699 32.8118 39.1699 33.7598C39.1699 34.6484 38.9626 35.4229 38.5479 36.083C38.1416 36.7432 37.5576 37.251 36.7959 37.6064C36.0426 37.9535 35.1624 38.127 34.1553 38.127Z" + fill="#6A621C" /> diff --git a/client/public/assets/curriculum/cur-topic-standards.svg b/client/public/assets/curriculum/cur-topic-standards.svg index 3dd7e8e457ba..cd09db253b67 100644 --- a/client/public/assets/curriculum/cur-topic-standards.svg +++ b/client/public/assets/curriculum/cur-topic-standards.svg @@ -1,6 +1,6 @@ + d="M31.1121 18.75L33.5621 19.25L28.8871 41.25L26.4371 40.75L31.1121 18.75ZM39.4871 30L34.9996 25.5125V21.975L43.0246 30L34.9996 38.0125V34.475L39.4871 30ZM16.9746 30L24.9996 21.975V25.5125L20.5121 30L24.9996 34.475V38.0125L16.9746 30Z" + fill="#C1283E" /> diff --git a/client/public/assets/curriculum/cur-topic-styling.svg b/client/public/assets/curriculum/cur-topic-styling.svg index cd69f02e1fe4..628ef89d8216 100644 --- a/client/public/assets/curriculum/cur-topic-styling.svg +++ b/client/public/assets/curriculum/cur-topic-styling.svg @@ -1,5 +1,6 @@ - + diff --git a/client/public/assets/curriculum/cur-topic-tooling.svg b/client/public/assets/curriculum/cur-topic-tooling.svg index b9a306d2f273..ef7b45bf0440 100644 --- a/client/public/assets/curriculum/cur-topic-tooling.svg +++ b/client/public/assets/curriculum/cur-topic-tooling.svg @@ -1,6 +1,6 @@ + d="M32.5695 33.7684C32.3782 33.9643 32.38 34.2777 32.5737 34.4713L39.3665 41.2642C39.5634 41.461 39.8832 41.4592 40.0777 41.26L42.0164 39.2754C42.2078 39.0795 42.2059 38.7661 42.0123 38.5724L35.2194 31.7796C35.0226 31.5827 34.7028 31.5846 34.5082 31.7838L32.5695 33.7684ZM36.8742 27.6219C36.5051 27.6219 36.1144 27.586 35.7674 27.4927C35.571 27.4398 35.355 27.4782 35.2108 27.6217L21.5653 41.2074C21.3699 41.4019 21.0539 41.4016 20.8589 41.2066L18.928 39.2757C18.7327 39.0803 18.7328 38.7635 18.9282 38.5683L27.4837 30.0244C27.6788 29.8296 27.6793 29.5136 27.4849 29.3181L25.9728 27.7975C25.7797 27.6032 25.4662 27.6005 25.2697 27.7915L25.0728 27.983C24.8787 28.1717 24.5697 28.1717 24.3757 27.983L23.7603 27.3845C23.4433 27.0763 22.9117 27.3009 22.9117 27.743V29.9273C22.9117 30.0599 22.859 30.1871 22.7653 30.2808L22.3923 30.6538C22.1962 30.8499 21.8781 30.849 21.6832 30.6518L17.9863 26.9129C17.7929 26.7173 17.7938 26.4023 17.9883 26.2078L18.3653 25.8308C18.459 25.7371 18.5862 25.6844 18.7188 25.6844H20.8232C21.2678 25.6844 21.4912 25.1476 21.178 24.8321L20.6253 24.2754C20.4312 24.08 20.4317 23.7643 20.6265 23.5696L24.7242 19.4719C26.0685 18.1276 28.1625 18.0189 29.628 19.1458C29.8451 19.3127 29.8453 19.6295 29.6539 19.8254L27.7083 21.8171C27.5164 22.0135 27.5188 22.3279 27.7136 22.5213L28.7681 23.5683C28.9646 23.7634 28.9652 24.0809 28.7694 24.2767L28.5913 24.4548C28.3956 24.6505 28.3961 24.9678 28.5923 25.1629L30.1149 26.6771C30.3126 26.8736 30.6328 26.8706 30.8267 26.6703L32.5188 24.9224C32.6585 24.7781 32.695 24.565 32.6405 24.3717C32.5426 24.0244 32.4992 23.6363 32.4992 23.2844C32.4992 20.8219 34.4492 18.8844 36.8742 18.8844C37.3783 18.8844 37.8415 18.9661 38.2718 19.1296C38.5764 19.2454 38.6254 19.6332 38.3949 19.8637L35.8653 22.3933C35.67 22.5886 35.67 22.9052 35.8653 23.1004L37.0332 24.2683C37.2284 24.4636 37.545 24.4636 37.7403 24.2683L40.2699 21.7387C40.5004 21.5082 40.889 21.5567 41.0054 21.8612C41.1679 22.2865 41.2492 22.7477 41.2492 23.2844C41.2492 25.6844 39.3117 27.6219 36.8742 27.6219Z" + fill="#481C6A" /> diff --git a/client/src/assets/icons/cur-landing-about-beginner.svg b/client/src/assets/icons/cur-landing-about-beginner.svg new file mode 100644 index 000000000000..076b9856274b --- /dev/null +++ b/client/src/assets/icons/cur-landing-about-beginner.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-about-bullet.svg b/client/src/assets/icons/cur-landing-about-bullet.svg new file mode 100644 index 000000000000..b8d39998bc56 --- /dev/null +++ b/client/src/assets/icons/cur-landing-about-bullet.svg @@ -0,0 +1,8 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-about-free.svg b/client/src/assets/icons/cur-landing-about-free.svg new file mode 100644 index 000000000000..6ba513e3749b --- /dev/null +++ b/client/src/assets/icons/cur-landing-about-free.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-about-pace.svg b/client/src/assets/icons/cur-landing-about-pace.svg new file mode 100644 index 000000000000..dbc10c33c659 --- /dev/null +++ b/client/src/assets/icons/cur-landing-about-pace.svg @@ -0,0 +1,6 @@ + + + + diff --git a/client/src/curriculum/about.tsx b/client/src/curriculum/about.tsx index c6c7dc6db0d7..cfccea5b5b78 100644 --- a/client/src/curriculum/about.tsx +++ b/client/src/curriculum/about.tsx @@ -2,7 +2,7 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError, RenderDocumentBody } from "../document"; +import { HTTPError } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { SidePlacement } from "../ui/organisms/placement"; @@ -15,6 +15,7 @@ import { ArticleActionsContainer } from "../ui/organisms/article-actions-contain import { topic2css, useDocTitle } from "./utils"; import { SidebarContainer } from "../document/organisms/sidebar"; import { TOC } from "../document/organisms/toc"; +import { RenderCurriculumBody } from "./body"; export function CurriculumAbout(props: HydrationData) { const dataURL = `./index.json`; @@ -77,7 +78,7 @@ export function CurriculumAbout(props: HydrationData) { {coloredTitle} {restTitle.join(" ")} - + diff --git a/client/src/curriculum/body.tsx b/client/src/curriculum/body.tsx new file mode 100644 index 000000000000..4465f87ccbc8 --- /dev/null +++ b/client/src/curriculum/body.tsx @@ -0,0 +1,44 @@ +import { useMemo } from "react"; +import { DisplayH2, DisplayH3 } from "../document/ingredients/utils"; +import { CurriculumDoc } from "../../../libs/types/curriculum"; +import { Section } from "../../../libs/types/document"; + +function Render({ section }) { + const { id } = section; + const html = useMemo(() => ({ __html: section.content }), [section.content]); + + if (!id) { + return ( +
        + ); + } + + const DisplayHx = section.isH3 ? DisplayH3 : DisplayH2; + + return ( +
        + +
        +
        + ); +} + +export function RenderCurriculumBody({ + doc, + renderer = () => null, +}: { + doc: CurriculumDoc; + renderer?: (section: Section, i: number) => null | JSX.Element; +}) { + return doc.body.map((section, i) => { + return renderer(section, i) || ; + }); +} diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index de3878d7889a..4b9905043bf2 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -1,5 +1,157 @@ -.curriculum-landing { - header > svg { - width: 50%; +@use "../ui/vars" as *; + +.curriculum-content-container.curriculum-landing { + margin: 0; + max-width: 100%; + padding: 0; + width: 100%; + + > article { + > header, + > section { + margin: 0 auto 3rem; + max-width: min(var(--max-width), 74rem); + padding-left: var(--gutter); + padding-right: var(--gutter); + width: 100%; + } + } + + .curriculum-content { + ol.modules-list { + @media screen and (min-width: $screen-sm) { + grid-template-columns: 1fr 1fr; + } + @media screen and (min-width: $screen-md) { + grid-template-columns: 1fr 1fr 1fr; + } + @media screen and (min-width: $screen-lg) { + grid-template-columns: 1fr 1fr 1fr 1fr; + } + } + } + + header.landing-header { + display: flex; + flex-direction: row-reverse; + flex-wrap: wrap; + justify-content: space-between; + + > svg { + width: 40%; + } + + > section { + max-width: 30rem; + min-width: 20rem; + padding-right: 1rem; + width: 60%; + + h1 { + color: var(--cur-color-topic); + margin-bottom: 1rem; + } + + h2 { + margin-bottom: 2rem; + margin-top: 1rem; + } + + p:last-child { + color: var(--text-secondary); + } + } + } + + .landing-about-container { + background-color: var(--cur-bg-color); + margin: 0; + max-width: 100%; + + .landing-about { + display: grid; + grid-template-areas: + "li li " + "h2 p " + "h2 p " + "h2 p "; + grid-template-columns: 1fr 1fr; + margin: 0 auto 3rem; + max-width: min(var(--max-width), 74rem); + + h2 { + grid-area: h2; + } + + > div { + display: contents; + + ul { + align-items: center; + background-color: var(--background-primary); + box-shadow: var(--module-shadow); + display: flex; + grid-area: li; + height: 5rem; + justify-content: space-around; + margin: auto; + transform: translateY(-1rem); + width: 100%; + + > li { + align-items: center; + display: inline-flex; + gap: 2rem; + + &::before { + height: 4rem; + width: 4rem; + } + + &:nth-child(1)::before { + content: url("../assets/icons/cur-landing-about-beginner.svg"); + } + + &:nth-child(2)::before { + content: url("../assets/icons/cur-landing-about-pace.svg"); + } + + &:nth-child(3)::before { + content: url("../assets/icons/cur-landing-about-free.svg"); + } + } + } + + p { + display: inline-grid; + grid-template-columns: auto auto; + + &::before { + display: block; + height: 4rem; + width: 4rem; + } + + &:nth-child(2)::before { + content: url("../assets/icons/cur-landing-about-bullet.svg"); + } + + &:nth-child(3)::before { + content: url("../assets/icons/cur-landing-about-bullet.svg"); + } + + a { + color: var(--text-primary); + font-weight: var(--font-body-strong-weight); + text-decoration: underline; + + &:hover, + &:active { + text-decoration: none; + } + } + } + } + } } } diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index e1e3580c1b4a..2ba3ac2becc8 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -3,9 +3,8 @@ import useSWR from "swr"; import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError, RenderDocumentBody } from "../document"; -import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; -import { SidePlacement } from "../ui/organisms/placement"; +import { HTTPError } from "../document"; +import { WRITER_MODE } from "../env"; import { ModulesListList } from "./modules-list"; import "./index.scss"; @@ -15,6 +14,9 @@ import "./landing.scss"; import { TopNavigation } from "../ui/organisms/top-navigation"; import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; import { useDocTitle } from "./utils"; +import { RenderCurriculumBody } from "./body"; +import { useMemo } from "react"; +import { DisplayH2 } from "../document/ingredients/utils"; export function CurriculumLanding(props: HydrationData) { const dataURL = `./index.json`; @@ -51,23 +53,35 @@ export function CurriculumLanding(props: HydrationData) {
        -
        -
        -
        - {PLACEMENT_ENABLED && } -
        -
        +
        -
        - -

        {doc?.title}

        - {doc?.topic &&

        {doc.topic}

        } -
        - -
        -

        Modules

        - {doc.modules && } -
        + { + if (i === 0) { + return
        ; + } + if (section.value.id === "about_curriculum") { + return About({ section }); + } + if (section.value.id === "modules") { + const { title, titleAsText, id } = section.value as any; + return ( +
        + + {doc.modules && ( + + )} +
        + ); + } + return null; + }} + />
        @@ -75,3 +89,33 @@ export function CurriculumLanding(props: HydrationData) { ); } + +function Header({ section, h1 }: { section: any; h1?: string }) { + const html = useMemo( + () => ({ __html: section.value?.content }), + [section.value?.content] + ); + return ( +
        + +
        +

        {h1}

        +

        {section.value.title}

        +
        +
        +
        + ); +} + +function About({ section }) { + const { title, content, titleAsText, id } = section.value; + const html = useMemo(() => ({ __html: content }), [content]); + return ( +
        +
        + +
        +
        +
        + ); +} diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 3cfbba873bf9..83c9f37e9e23 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -59,7 +59,7 @@ } } - .curriculum-content { + .curriculum-content.curriculum-module { grid-area: main; > header { @@ -159,113 +159,115 @@ } } - @media screen and (min-width: $screen-md) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - padding-left: 1.5rem; - padding-right: 3rem; - } + &.curriculum-module { + @media screen and (min-width: $screen-md) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + padding-left: 1.5rem; + padding-right: 3rem; + } - @media screen and (min-width: $screen-xl) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main toc"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); - padding-left: 1rem; - padding-right: 1rem; + @media screen and (min-width: $screen-xl) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main toc"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); + padding-left: 1rem; + padding-right: 1rem; - .toc { - --offset: var(--sticky-header-with-actions-height); + .toc { + --offset: var(--sticky-header-with-actions-height); - display: block; - grid-area: toc; - height: fit-content; - padding-bottom: 0; - } + display: block; + grid-area: toc; + height: fit-content; + padding-bottom: 0; + } - .in-nav-toc { - display: none; + .in-nav-toc { + display: none; + } } - } - .sidebar-container { - --offset: var(--sticky-header-with-actions-height); - --max-height: calc(100vh - var(--offset)); + .sidebar-container { + --offset: var(--sticky-header-with-actions-height); + --max-height: calc(100vh - var(--offset)); - @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { - display: flex; - flex-direction: column; - } + @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { + display: flex; + flex-direction: column; + } - max-height: var(--max-height); - position: sticky; - top: var(--offset); - z-index: var(--z-index-sidebar-mobile); + max-height: var(--max-height); + position: sticky; + top: var(--offset); + z-index: var(--z-index-sidebar-mobile); - @media screen and (min-width: $screen-md) { - z-index: auto; - - .curriculum-sidebar { - mask-image: linear-gradient( - to bottom, - rgb(0, 0, 0) 0% calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - } + @media screen and (min-width: $screen-md) { + z-index: auto; - @media screen and not (min-height: $screen-height-place-limit) { - overflow: auto; - } - } + .curriculum-sidebar { + mask-image: linear-gradient( + to bottom, + rgb(0, 0, 0) 0% calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + } - &.toc-container, - .toc-container { - grid-area: toc; + @media screen and not (min-height: $screen-height-place-limit) { + overflow: auto; + } + } - .place { + &.toc-container, + .toc-container { grid-area: toc; - margin: 0; - } - @media screen and (min-width: $screen-xl) { - display: flex; - flex-direction: column; - gap: 0; - height: calc(100vh - var(--offset)); - mask-image: linear-gradient( - to bottom, - rgba(0, 0, 0, 0) 0%, - rgb(0, 0, 0) 3rem calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - overflow: auto; - position: sticky; - top: var(--offset); .place { - margin: 1rem 0; - padding-bottom: 3rem; + grid-area: toc; + margin: 0; + } + @media screen and (min-width: $screen-xl) { + display: flex; + flex-direction: column; + gap: 0; + height: calc(100vh - var(--offset)); + mask-image: linear-gradient( + to bottom, + rgba(0, 0, 0, 0) 0%, + rgb(0, 0, 0) 3rem calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + overflow: auto; + position: sticky; + top: var(--offset); + + .place { + margin: 1rem 0; + padding-bottom: 3rem; + } } } - } - @media screen and (max-width: #{$screen-md - 1}) { - .toc-container { - display: none; + @media screen and (max-width: #{$screen-md - 1}) { + .toc-container { + display: none; + } } - } - @media screen and (min-width: #{$screen-md}) { - #sidebar-quicklinks { - display: none; + @media screen and (min-width: #{$screen-md}) { + #sidebar-quicklinks { + display: none; + } } - } - @media screen and (min-width: $screen-xl) { - display: contents; + @media screen and (min-width: $screen-xl) { + display: contents; - .sidebar { - mask-image: none; + .sidebar { + mask-image: none; + } } } } diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 5bea411d6486..ae08c0b182e8 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -1,7 +1,7 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError, RenderDocumentBody } from "../document"; +import { HTTPError } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { TOC } from "../document/organisms/toc"; import { SidePlacement } from "../ui/organisms/placement"; @@ -13,6 +13,7 @@ import { TopicIcon } from "./topic-icon"; import { topic2css, useDocTitle } from "./utils"; import { SidebarContainer } from "../document/organisms/sidebar"; import { PrevNext } from "./prev-next"; +import { RenderCurriculumBody } from "./body"; export function CurriculumModule(props: HydrationData) { const dataURL = `./index.json`; @@ -51,7 +52,7 @@ export function CurriculumModule(props: HydrationData) {
        @@ -75,13 +76,16 @@ export function CurriculumModule(props: HydrationData) { /> )}
        -
        +
        {doc.topic && }

        {doc?.title}

        {doc?.topic &&

        {doc.topic}

        }
        - +
        diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index 64eb7b75ecd4..fc9bf39fc430 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -1,7 +1,7 @@ import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError, RenderDocumentBody } from "../document"; +import { HTTPError } from "../document"; import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; import { SidePlacement } from "../ui/organisms/placement"; import { ModulesList } from "./modules-list"; @@ -12,6 +12,7 @@ import { topic2css, useDocTitle } from "./utils"; import "./no-side.scss"; import "./overview.scss"; import { PrevNext } from "./prev-next"; +import { RenderCurriculumBody } from "./body"; export function CurriculumModuleOverview( props: HydrationData @@ -68,7 +69,7 @@ export function CurriculumModuleOverview( {coloredTitle} {restTitle.join(" ")} - +

        Module Contents:

        {doc.modules && } From 68890332cf157ffb621acbb33dcbe36fb631aae1 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 14:52:26 +0100 Subject: [PATCH 042/102] fix landing about --- client/src/curriculum/landing.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 4b9905043bf2..62aadbd3c05b 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -81,6 +81,7 @@ h2 { grid-area: h2; + margin: 1rem 0; } > div { @@ -123,6 +124,7 @@ } p { + align-items: center; display: inline-grid; grid-template-columns: auto auto; From bcb32742362d3bc5ea9402e539434064c29af905 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 16:53:20 +0000 Subject: [PATCH 043/102] wip(curriculum): rm colon from module contents --- client/src/curriculum/overview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index fc9bf39fc430..5538855a0b4f 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -71,7 +71,7 @@ export function CurriculumModuleOverview(
        -

        Module Contents:

        +

        Module Contents

        {doc.modules && }
        From 2ad0280c14857d1585ece73d87d417d4f7164081 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 16:54:15 +0000 Subject: [PATCH 044/102] wip(curriculum): remove phantom empty item from TOC --- build/utils.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/build/utils.ts b/build/utils.ts index 213827cbe290..861e4ffa94de 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -324,13 +324,12 @@ export function makeTOC(doc, withH3 = false) { return doc.body .map((section) => { if ( - ((section.type === "prose" || + (section.type === "prose" || section.type === "browser_compatibility" || section.type === "specifications") && - section.value.id && - section.value.title && - !section.value.isH3) || - withH3 + section.value.id && + section.value.title && + (!section.value.isH3 || withH3) ) { return { text: section.value.title, id: section.value.id }; } From d8388ddfd5529b600a0ce15f0bc79897610a65c5 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 16:58:33 +0000 Subject: [PATCH 045/102] wip(curriculum): fix weird spacing in nested lists --- client/src/curriculum/module.scss | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 83c9f37e9e23..11c9bb8ce464 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -128,6 +128,11 @@ ul { margin: 1rem 0 2rem; padding-left: 2rem; + + ol, + ul { + margin: 0; + } } li { From 0afaab03059335a39c044c10f69ce1ff85177cf8 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 17:03:01 +0000 Subject: [PATCH 046/102] wip(curriculum): show 'in this module' above toc --- client/src/curriculum/module.tsx | 4 +++- client/src/document/organisms/toc/index.tsx | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index ae08c0b182e8..531d3d40562b 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -63,7 +63,9 @@ export function CurriculumModule(props: HydrationData) {
        {PLACEMENT_ENABLED && } diff --git a/client/src/document/organisms/toc/index.tsx b/client/src/document/organisms/toc/index.tsx index 26f3ca38eb5f..dd2f7bb1dec2 100644 --- a/client/src/document/organisms/toc/index.tsx +++ b/client/src/document/organisms/toc/index.tsx @@ -6,7 +6,7 @@ import { useFirstVisibleElement } from "../../hooks"; import { useGleanClick } from "../../../telemetry/glean-context"; import { TOC_CLICK } from "../../../telemetry/constants"; -export function TOC({ toc }: { toc: Toc[] }) { +export function TOC({ toc, title }: { toc: Toc[]; title?: string }) { const [currentViewedTocItem, setCurrentViewedTocItem] = useState(""); const observedElements = React.useCallback(() => { @@ -44,7 +44,9 @@ export function TOC({ toc }: { toc: Toc[] }) {
        -

        In this article

        +

        + {title || "In this article"} +

          {toc.map((item) => { From 7ea3eee31aca706714468c65b8240290c04db3af Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 17:21:19 +0000 Subject: [PATCH 047/102] wip(curriculum): hacky fix to broken about and overview pages --- client/src/curriculum/module.scss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 11c9bb8ce464..96a90b966838 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -59,7 +59,7 @@ } } - .curriculum-content.curriculum-module { + &:not(.curriculum-landing) .curriculum-content { grid-area: main; > header { @@ -164,7 +164,7 @@ } } - &.curriculum-module { + &:not(.curriculum-landing) { @media screen and (min-width: $screen-md) { display: grid; gap: 3rem; From 55d4cf57b8d84a1b70674ab494b4cde5042a0998 Mon Sep 17 00:00:00 2001 From: Leo McArdle Date: Fri, 2 Feb 2024 17:27:15 +0000 Subject: [PATCH 048/102] wip(curriculum): add toc to about and overview pages --- client/src/curriculum/about.tsx | 16 ++++++++++++++-- client/src/curriculum/overview.tsx | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/client/src/curriculum/about.tsx b/client/src/curriculum/about.tsx index cfccea5b5b78..571e100f2c8b 100644 --- a/client/src/curriculum/about.tsx +++ b/client/src/curriculum/about.tsx @@ -16,6 +16,7 @@ import { topic2css, useDocTitle } from "./utils"; import { SidebarContainer } from "../document/organisms/sidebar"; import { TOC } from "../document/organisms/toc"; import { RenderCurriculumBody } from "./body"; +import { Sidebar } from "./sidebar"; export function CurriculumAbout(props: HydrationData) { const dataURL = `./index.json`; @@ -58,16 +59,27 @@ export function CurriculumAbout(props: HydrationData) { >
          - <> + {doc.sidebar && ( + + )}
          {PLACEMENT_ENABLED && }
          + {doc.sidebar && ( + + )}
          @@ -56,9 +58,21 @@ export function CurriculumModuleOverview( className={`curriculum-content-container curriculum-no-side container topic-${topic2css(doc.topic)}`} >
          + + {doc.sidebar && ( + + )} +
          {PLACEMENT_ENABLED && }
          + {doc.sidebar && ( + + )}
          Date: Fri, 2 Feb 2024 21:23:58 +0100 Subject: [PATCH 049/102] getting started --- build/curriculum.ts | 13 ++- build/utils.ts | 4 +- .../icons/cur-landing-started-advanced.svg | 11 +++ .../icons/cur-landing-started-beginner.svg | 13 +++ .../icons/cur-landing-started-educator.svg | 13 +++ .../icons/cur-landing-started-employment.svg | 13 +++ client/src/curriculum/landing.scss | 92 +++++++++++++++++++ client/src/curriculum/landing.tsx | 2 +- 8 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 client/src/assets/icons/cur-landing-started-advanced.svg create mode 100644 client/src/assets/icons/cur-landing-started-beginner.svg create mode 100644 client/src/assets/icons/cur-landing-started-educator.svg create mode 100644 client/src/assets/icons/cur-landing-started-employment.svg diff --git a/build/curriculum.ts b/build/curriculum.ts index e56c67218bf7..db625aa995e1 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -262,7 +262,7 @@ export async function buildModule(document: BuildData): Promise { $("[data-token]").removeAttr("data-token"); $("[data-flaw-src]").removeAttr("data-flaw-src"); - doc.title = metadata.title || ""; + doc.title = (metadata.title || "").replace(/^\d+\s+/, ""); doc.mdn_url = document.url; doc.locale = metadata.locale as string; doc.native = LANGUAGES_RAW[DEFAULT_LOCALE]?.native; @@ -274,7 +274,12 @@ export async function buildModule(document: BuildData): Promise { syntaxHighlight($, doc); injectNoTranslate($); injectLoadingLazyAttributes($); - postProcessCurriculumLinks($, document.url); + postProcessCurriculumLinks($, (p: string) => { + const slug = fileToSlug( + path.normalize(path.join(path.dirname(document.fileInfo.path), p)) + ).replace(/\/$/, ""); + return `/${DEFAULT_LOCALE}/${slug}/`; + }); postProcessExternalLinks($); postLocalFileLinks($, doc); postProcessSmallerHeadingIDs($); @@ -293,7 +298,9 @@ export async function buildModule(document: BuildData): Promise { doc.pageTitle = `${doc.title} | MDN Curriculum`; doc.noIndexing = false; - doc.toc = makeTOC(doc, true); + doc.toc = makeTOC(doc, true).map(({ text, id }) => { + return { text: text.replace(/^[\d.]+\s+/, ""), id }; + }); doc.sidebar = metadata.sidebar; doc.modules = metadata.modules; doc.prevNext = metadata.prevNext; diff --git a/build/utils.ts b/build/utils.ts index 861e4ffa94de..0c9e7fe0adc3 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -245,11 +245,11 @@ export function postProcessExternalLinks($) { * @param {Cheerio document instance} $ * @param {current url} url */ -export function postProcessCurriculumLinks($, url) { +export function postProcessCurriculumLinks($, toUrl) { $("a[href^=./]").each((_, element) => { // Expand relative links (TODO: fix) const $a = $(element); - $a.attr("href", $a.attr("href").replace(/^\.\//, `${url}`)); + $a.attr("href", toUrl($a.attr("href"))); }); $("a[href^=/en-US/curriculum]").each((_, element) => { const $a = $(element); diff --git a/client/src/assets/icons/cur-landing-started-advanced.svg b/client/src/assets/icons/cur-landing-started-advanced.svg new file mode 100644 index 000000000000..c41d6f1b6629 --- /dev/null +++ b/client/src/assets/icons/cur-landing-started-advanced.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-started-beginner.svg b/client/src/assets/icons/cur-landing-started-beginner.svg new file mode 100644 index 000000000000..66a48795c263 --- /dev/null +++ b/client/src/assets/icons/cur-landing-started-beginner.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-started-educator.svg b/client/src/assets/icons/cur-landing-started-educator.svg new file mode 100644 index 000000000000..5b58a19e4c2f --- /dev/null +++ b/client/src/assets/icons/cur-landing-started-educator.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-started-employment.svg b/client/src/assets/icons/cur-landing-started-employment.svg new file mode 100644 index 000000000000..5cfad955e8dc --- /dev/null +++ b/client/src/assets/icons/cur-landing-started-employment.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 62aadbd3c05b..386ec584226a 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -156,4 +156,96 @@ } } } + + #don’t_know_where_to_start { + margin: 1rem auto 5rem; + text-decoration-color: var(--cur-color); + text-decoration-line: underline; + text-decoration-thickness: 0.25rem; + text-underline-offset: 1rem; + width: fit-content; + + ~ div { + > ul { + display: grid; + gap: 3rem 8rem; + grid-template-areas: + "beginner advanced" + "employ educator"; + margin: 0 auto; + max-width: 52rem; + + > li { + align-items: center; + display: grid; + gap: 1rem 2rem; + grid-template-areas: + "i h" + "i p" + "i c"; + + &::before { + align-self: start; + display: inline-block; + grid-area: i; + height: 5rem; + width: 5rem; + } + + &:nth-child(1)::before { + content: url("../assets/icons/cur-landing-started-beginner.svg"); + } + + &:nth-child(2)::before { + content: url("../assets/icons/cur-landing-started-advanced.svg"); + } + + &:nth-child(3)::before { + content: url("../assets/icons/cur-landing-started-employment.svg"); + } + + &:nth-child(4)::before { + content: url("../assets/icons/cur-landing-started-educator.svg"); + } + + h3 { + font-weight: var(--font-body-strong-weight); + margin-top: 0; + } + + a { + --button-bg: var(--button-primary-default); + --button-bg-hover: var(--button-primary-hover); + --button-bg-active: var(--button-primary-active); + --button-border-color: var(--button-primary-default); + --button-focus-effect: var(--focus-effect); + --button-height: var(--form-elem-height, 2rem); + --button-color: var(--background-primary); + --button-font: var(--type-emphasis-m); + --button-padding: 0.5rem; + --button-radius: var(--elem-radius, 0.25rem); + align-items: center; + background-color: var(--button-bg); + border: 1px solid var(--button-border-color); + border-radius: var(--button-radius); + color: var(--button-color); + cursor: pointer; + display: flex; + font: var(--button-font); + gap: 0.25rem; + height: var(--button-height); + justify-content: center; + padding-left: var(--button-padding); + padding-right: var(--button-padding); + position: relative; + width: fit-content; + + &:hover { + background-color: var(--button-bg-hover, var(--button-bg)); + } + } + } + } + } + } } diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index 2ba3ac2becc8..c9845804ab92 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -61,7 +61,7 @@ export function CurriculumLanding(props: HydrationData) { if (i === 0) { return
          ; } - if (section.value.id === "about_curriculum") { + if (section.value.id === "about_the_curriculum") { return About({ section }); } if (section.value.id === "modules") { From 846ae539963d5b071330293b4b6c3abc4f3be6f5 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 22:02:48 +0100 Subject: [PATCH 050/102] ladder --- .../assets/curriculum/cur-landing-ladder.svg | 189 ++++++++++++++++++ client/src/curriculum/landing.scss | 21 ++ client/src/curriculum/landing.tsx | 28 ++- 3 files changed, 228 insertions(+), 10 deletions(-) create mode 100644 client/public/assets/curriculum/cur-landing-ladder.svg diff --git a/client/public/assets/curriculum/cur-landing-ladder.svg b/client/public/assets/curriculum/cur-landing-ladder.svg new file mode 100644 index 000000000000..a7fb4c7d368f --- /dev/null +++ b/client/public/assets/curriculum/cur-landing-ladder.svg @@ -0,0 +1,189 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + How can you boost + + + your employability + + + with the MDN + + + Curriculum? + + + + Learn about research collaboration and other essential soft skills + + Balance between modern tooling and long-term best practices + + Get access to hight-quality recommened resrouces + + + Get guidance from trusted voices + + diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 386ec584226a..e9605b528f49 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -157,6 +157,27 @@ } } + .landing-ladder { + background-color: var(--background-secondary); + margin: 0; + max-width: 100%; + + > div { + margin: 0 auto 3rem; + max-width: min(var(--max-width), 74rem); + padding: 2rem; + padding-left: var(--gutter); + padding-right: var(--gutter); + width: 100%; + + > svg { + #text69 { + font: var(--type-heading-h2); + } + } + } + } + #don’t_know_where_to_start { margin: 1rem auto 5rem; text-decoration-color: var(--cur-color); diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index c9845804ab92..e6aecc42888e 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -1,6 +1,7 @@ import useSWR from "swr"; import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; +import { ReactComponent as LandingLadderSVG } from "../../public/assets/curriculum/cur-landing-ladder.svg"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; import { HTTPError } from "../document"; @@ -67,16 +68,23 @@ export function CurriculumLanding(props: HydrationData) { if (section.value.id === "modules") { const { title, titleAsText, id } = section.value as any; return ( -
          - - {doc.modules && ( - - )} -
          + <> +
          + + {doc.modules && ( + + )} +
          +
          +
          + +
          +
          + ); } return null; From 3821fe2a070e037ebf2756ead544616bd9cf8085 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 2 Feb 2024 22:18:51 +0100 Subject: [PATCH 051/102] fix anchor links --- build/curriculum.ts | 5 +++-- build/utils.ts | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index db625aa995e1..85cceb22da1b 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -275,10 +275,11 @@ export async function buildModule(document: BuildData): Promise { injectNoTranslate($); injectLoadingLazyAttributes($); postProcessCurriculumLinks($, (p: string) => { + const [head, hash] = p.split("#"); const slug = fileToSlug( - path.normalize(path.join(path.dirname(document.fileInfo.path), p)) + path.normalize(path.join(path.dirname(document.fileInfo.path), head)) ).replace(/\/$/, ""); - return `/${DEFAULT_LOCALE}/${slug}/`; + return `/${DEFAULT_LOCALE}/${slug}/${hash ? `#${hash}` : ""}`; }); postProcessExternalLinks($); postLocalFileLinks($, doc); diff --git a/build/utils.ts b/build/utils.ts index 0c9e7fe0adc3..302b1304405b 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -246,7 +246,7 @@ export function postProcessExternalLinks($) { * @param {current url} url */ export function postProcessCurriculumLinks($, toUrl) { - $("a[href^=./]").each((_, element) => { + $("a[href^=.]").each((_, element) => { // Expand relative links (TODO: fix) const $a = $(element); $a.attr("href", toUrl($a.attr("href"))); @@ -261,7 +261,8 @@ export function postProcessCurriculumLinks($, toUrl) { }); $("a[href^=/en-US/curriculum]").each((_, element) => { const $a = $(element); - $a.attr("href", $a.attr("href").replace(/\d+-/g, "")); + const [head, hash] = $a.attr("href").split("#"); + $a.attr("href", `${head.replace(/\d+-/g, "")}${hash ? `#${hash}` : ""}`); }); } From 75dbc5edbb7011d176fefc709e4a15265759538f Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sat, 3 Feb 2024 01:51:36 +0100 Subject: [PATCH 052/102] mobile fixes --- client/src/curriculum/landing.scss | 34 ++++++++++++++++++------ client/src/curriculum/modules-list.scss | 35 ++++++++++++++++++------- 2 files changed, 52 insertions(+), 17 deletions(-) diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index e9605b528f49..c5d23c6901e7 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -71,13 +71,22 @@ .landing-about { display: grid; grid-template-areas: - "li li " - "h2 p " - "h2 p " - "h2 p "; - grid-template-columns: 1fr 1fr; + "li" + "h2" + "p" + "p" + "p"; + grid-template-columns: 1fr; margin: 0 auto 3rem; max-width: min(var(--max-width), 74rem); + @media screen and (min-width: $screen-md) { + grid-template-areas: + "li li " + "h2 p " + "h2 p " + "h2 p "; + grid-template-columns: 1fr 1fr; + } h2 { grid-area: h2; @@ -92,10 +101,12 @@ background-color: var(--background-primary); box-shadow: var(--module-shadow); display: flex; + flex-wrap: wrap; grid-area: li; - height: 5rem; justify-content: space-around; margin: auto; + min-height: 5rem; + padding: 1rem; transform: translateY(-1rem); width: 100%; @@ -191,10 +202,17 @@ display: grid; gap: 3rem 8rem; grid-template-areas: - "beginner advanced" - "employ educator"; + "beginner" + "advanced" + "employ" + "educator"; margin: 0 auto; max-width: 52rem; + @media screen and (min-width: $screen-md) { + grid-template-areas: + "beginner advanced" + "employ educator"; + } > li { align-items: center; diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index b24f75499cdf..51368ec0f4e3 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -21,21 +21,34 @@ ol.modules-list-list { display: grid; grid-template-areas: - "a b c spacer" - "hr hr hr hr" - "mod mod mod mod" - "t t t t"; - - grid-template-columns: max-content max-content max-content auto; + "a" + "b" + "c" + "hr" + "mod" + "t"; + + grid-template-columns: auto; margin: 0; padding: 0; + @media screen and (min-width: $screen-md) { + grid-template-areas: + "a b c spacer" + "hr hr hr hr" + "mod mod mod mod" + "t t t t"; + + grid-template-columns: max-content max-content max-content auto; + } hr { border: none; - border-top: 1px solid var(--text-primary); grid-area: hr; margin: 0 0 1.5rem; width: 100%; + @media screen and (min-width: $screen-md) { + border-top: 1px solid var(--text-primary); + } } li { @@ -64,7 +77,9 @@ > label, > input { grid-area: b; - margin-left: 2rem; + @media screen and (min-width: $screen-md) { + margin-left: 2rem; + } } } @@ -72,7 +87,9 @@ > label, > input { grid-area: c; - margin-left: 2rem; + @media screen and (min-width: $screen-md) { + margin-left: 2rem; + } } } From 5ceb14b9b5323955fe432e16c5d74a044a73fefc Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sun, 4 Feb 2024 00:54:19 +0100 Subject: [PATCH 053/102] landing color and mobile --- .../curriculum/cur-landing-ladder-1.svg | 97 ++++++++++++++++++ .../curriculum/cur-landing-ladder-2.svg | 99 +++++++++++++++++++ .../assets/curriculum/cur-landing-ladder.svg | 16 +-- client/src/curriculum/landing.scss | 43 ++++++-- client/src/curriculum/landing.tsx | 6 +- 5 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 client/public/assets/curriculum/cur-landing-ladder-1.svg create mode 100644 client/public/assets/curriculum/cur-landing-ladder-2.svg diff --git a/client/public/assets/curriculum/cur-landing-ladder-1.svg b/client/public/assets/curriculum/cur-landing-ladder-1.svg new file mode 100644 index 000000000000..722c65a7b4c0 --- /dev/null +++ b/client/public/assets/curriculum/cur-landing-ladder-1.svg @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + How can you boost + + + your employability + + + with the MDN + + + Curriculum? + + + diff --git a/client/public/assets/curriculum/cur-landing-ladder-2.svg b/client/public/assets/curriculum/cur-landing-ladder-2.svg new file mode 100644 index 000000000000..263fd93b0125 --- /dev/null +++ b/client/public/assets/curriculum/cur-landing-ladder-2.svg @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Learn about research collaboration and other essential soft skills + + Balance between modern tooling and long-term best practices + + Get access to hight-quality recommened resrouces + + + Get guidance from trusted voices + + diff --git a/client/public/assets/curriculum/cur-landing-ladder.svg b/client/public/assets/curriculum/cur-landing-ladder.svg index a7fb4c7d368f..d5bf48846aba 100644 --- a/client/public/assets/curriculum/cur-landing-ladder.svg +++ b/client/public/assets/curriculum/cur-landing-ladder.svg @@ -164,26 +164,26 @@ - How can you boost + How can you boost - your employability + your employability - with the MDN + with the MDN - Curriculum? + Curriculum? - + Learn about research collaboration and other essential soft skills - + Balance between modern tooling and long-term best practices - + Get access to hight-quality recommened resrouces - + Get guidance from trusted voices diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index c5d23c6901e7..40a338bd0881 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -42,10 +42,10 @@ } > section { - max-width: 30rem; - min-width: 20rem; + margin-right: auto; + min-width: min(30rem, 90vw); padding-right: 1rem; - width: 60%; + width: 30rem; h1 { color: var(--cur-color-topic); @@ -100,15 +100,19 @@ align-items: center; background-color: var(--background-primary); box-shadow: var(--module-shadow); - display: flex; - flex-wrap: wrap; + display: grid; + gap: 1rem; grid-area: li; + grid-template-columns: auto; justify-content: space-around; margin: auto; min-height: 5rem; padding: 1rem; transform: translateY(-1rem); width: 100%; + @media screen and (min-width: $screen-md) { + grid-template-columns: auto auto auto; + } > li { align-items: center; @@ -174,6 +178,9 @@ max-width: 100%; > div { + display: flex; + flex-wrap: wrap; + justify-content: center; margin: 0 auto 3rem; max-width: min(var(--max-width), 74rem); padding: 2rem; @@ -182,15 +189,37 @@ width: 100%; > svg { + &:nth-child(1) { + min-width: min(18rem, 90vw); + transform: translateX(2vw); + width: 38%; + } + + &:nth-child(2) { + min-width: min(32rem, 90vw); + transform: translateX(-2vw); + width: 62%; + } + #text69 { font: var(--type-heading-h2); } + + text { + fill: var(--text-primary); + } + + .color { + fill: var(--cur-color); + } } } } #don’t_know_where_to_start { + line-height: 3rem; margin: 1rem auto 5rem; + text-align: center; text-decoration-color: var(--cur-color); text-decoration-line: underline; text-decoration-thickness: 0.25rem; @@ -272,11 +301,13 @@ display: flex; font: var(--button-font); gap: 0.25rem; - height: var(--button-height); justify-content: center; + min-height: var(--button-height); + padding: 0.5rem; padding-left: var(--button-padding); padding-right: var(--button-padding); position: relative; + text-align: center; width: fit-content; &:hover { diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index e6aecc42888e..a9b34927f661 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -1,7 +1,8 @@ import useSWR from "swr"; import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; -import { ReactComponent as LandingLadderSVG } from "../../public/assets/curriculum/cur-landing-ladder.svg"; +import { ReactComponent as LandingLadderSVG1 } from "../../public/assets/curriculum/cur-landing-ladder-1.svg"; +import { ReactComponent as LandingLadderSVG2 } from "../../public/assets/curriculum/cur-landing-ladder-2.svg"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; import { HTTPError } from "../document"; @@ -81,7 +82,8 @@ export function CurriculumLanding(props: HydrationData) {
        - + +
        From 1fa74f53f6ee9129c5264a899a20f00e0d0c229a Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sun, 4 Feb 2024 12:23:17 +0100 Subject: [PATCH 054/102] rename modules title and landing --- build/curriculum.ts | 2 +- client/src/curriculum/landing.scss | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index 85cceb22da1b..1a83bb842843 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -201,7 +201,7 @@ async function readModule( sidebar = await buildSidebar(); parents = await buildParents(url); } else { - title = title.replace(/^\d+\s+/, ""); + title = title.replace(/^\d+\s+/, "").replace(/ modules$/, ""); } return { diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 40a338bd0881..40002974db3a 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -229,7 +229,7 @@ ~ div { > ul { display: grid; - gap: 3rem 8rem; + gap: 5rem 8rem; grid-template-areas: "beginner" "advanced" @@ -246,18 +246,25 @@ > li { align-items: center; display: grid; - gap: 1rem 2rem; - grid-template-areas: - "i h" - "i p" - "i c"; + gap: 1rem; + @media screen and (min-width: $screen-sm) { + align-items: start; + gap: 1rem 2rem; + grid-template-areas: + "i h" + "i p" + "i c"; + grid-template-rows: 4rem auto max-content; + } &::before { align-self: start; display: inline-block; - grid-area: i; height: 5rem; width: 5rem; + @media screen and (min-width: $screen-sm) { + grid-area: i; + } } &:nth-child(1)::before { From f3737f01f06d455ce02f84fff261fd3698306e15 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sun, 4 Feb 2024 12:31:18 +0100 Subject: [PATCH 055/102] begin --- client/src/curriculum/modules-list.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 86a9a83f084b..061960315da5 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -27,7 +27,7 @@ export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { <> )} From 7190d20afe04b19afd77da50fadfc6459944d587 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 5 Feb 2024 13:38:13 +0100 Subject: [PATCH 056/102] clean up react --- client/src/curriculum/about.scss | 4 +- client/src/curriculum/about.tsx | 100 ++++------------------ client/src/curriculum/index.scss | 22 +++++ client/src/curriculum/landing.tsx | 128 +++++++++------------------- client/src/curriculum/module.tsx | 103 ++++------------------ client/src/curriculum/no-side.scss | 46 +++------- client/src/curriculum/overview.scss | 1 - client/src/curriculum/overview.tsx | 106 ++++++----------------- client/src/curriculum/utils.ts | 35 +++++++- 9 files changed, 168 insertions(+), 377 deletions(-) delete mode 100644 client/src/curriculum/overview.scss diff --git a/client/src/curriculum/about.scss b/client/src/curriculum/about.scss index f5a076434917..a0e862cd35f1 100644 --- a/client/src/curriculum/about.scss +++ b/client/src/curriculum/about.scss @@ -1,5 +1,5 @@ -.curriculum-content-container { - .curriculum-content.curriculum-about { +.curriculum-content-container.curriculum-about { + .curriculum-content { // Workaround so last toc item works. margin-bottom: 5rem; diff --git a/client/src/curriculum/about.tsx b/client/src/curriculum/about.tsx index 571e100f2c8b..8ec9638d102d 100644 --- a/client/src/curriculum/about.tsx +++ b/client/src/curriculum/about.tsx @@ -1,99 +1,29 @@ -import useSWR from "swr"; - import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError } from "../document"; -import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; -import { SidePlacement } from "../ui/organisms/placement"; +import { topic2css, useCurriculumDoc, useDocTitle } from "./utils"; +import { RenderCurriculumBody } from "./body"; +import { CurriculumLayout } from "./layout"; import "./index.scss"; -import "./no-side.scss"; import "./about.scss"; -import { TopNavigation } from "../ui/organisms/top-navigation"; -import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -import { topic2css, useDocTitle } from "./utils"; -import { SidebarContainer } from "../document/organisms/sidebar"; -import { TOC } from "../document/organisms/toc"; -import { RenderCurriculumBody } from "./body"; -import { Sidebar } from "./sidebar"; - export function CurriculumAbout(props: HydrationData) { - const dataURL = `./index.json`; - const { data } = useSWR( - dataURL, - async (url) => { - const response = await fetch(url); - - if (!response.ok) { - switch (response.status) { - case 404: - throw new HTTPError(response.status, url, "Page not found"); - } - - const text = await response.text(); - throw new HTTPError(response.status, url, text); - } - - return await response.json(); - }, - { - fallbackData: props as ModuleData, - revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.blogMeta, - } - ); - const { doc }: { doc?: CurriculumDoc } = data || props || {}; - useDocTitle(doc); + const doc = useCurriculumDoc(props as ModuleData); const [coloredTitle, ...restTitle] = doc?.title?.split(" ") || []; return ( <> {doc && ( - <> -
        - - -
        -
        -
        - - {doc.sidebar && ( - - )} - -
        - - {PLACEMENT_ENABLED && } -
        - {doc.sidebar && ( - - )} -
        -
        -
        -

        - {coloredTitle} {restTitle.join(" ")} -

        -
        - -
        -
        - + +
        +

        + {coloredTitle} {restTitle.join(" ")} +

        +
        + +
        )} ); diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 4665810bec94..474734216b4f 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -60,3 +60,25 @@ } } } + +.curriculum-content-container { + &.curriculum-about, + &.curriculum-overview { + .curriculum-content { + > header > h1 { + margin-bottom: 1rem; + + > span { + color: var(--cur-color); + } + } + + .module-contents { + > h2 { + margin-bottom: 2rem; + margin-top: 4rem; + } + } + } + } +} diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index a9b34927f661..04daa23edd6f 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -1,102 +1,56 @@ -import useSWR from "swr"; - import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur-landing-top.svg"; import { ReactComponent as LandingLadderSVG1 } from "../../public/assets/curriculum/cur-landing-ladder-1.svg"; import { ReactComponent as LandingLadderSVG2 } from "../../public/assets/curriculum/cur-landing-ladder-2.svg"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError } from "../document"; -import { WRITER_MODE } from "../env"; import { ModulesListList } from "./modules-list"; - -import "./index.scss"; -import "./no-side.scss"; -import "./landing.scss"; - -import { TopNavigation } from "../ui/organisms/top-navigation"; -import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -import { useDocTitle } from "./utils"; +import { useCurriculumDoc, useDocTitle } from "./utils"; import { RenderCurriculumBody } from "./body"; import { useMemo } from "react"; import { DisplayH2 } from "../document/ingredients/utils"; +import { CurriculumLayout } from "./layout"; -export function CurriculumLanding(props: HydrationData) { - const dataURL = `./index.json`; - const { data } = useSWR( - dataURL, - async (url) => { - const response = await fetch(url); - - if (!response.ok) { - switch (response.status) { - case 404: - throw new HTTPError(response.status, url, "Page not found"); - } - - const text = await response.text(); - throw new HTTPError(response.status, url, text); - } +import "./index.scss"; +import "./landing.scss"; - return await response.json(); - }, - { - fallbackData: props as ModuleData, - revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.blogMeta, - } - ); - const { doc }: { doc?: CurriculumDoc } = data || props || {}; - useDocTitle(doc); +export function CurriculumLanding(appProps: HydrationData) { + const doc = useCurriculumDoc(appProps as ModuleData); return ( - <> - {doc && ( - <> -
        - - -
        -
        -
        - { - if (i === 0) { - return
        ; - } - if (section.value.id === "about_the_curriculum") { - return About({ section }); - } - if (section.value.id === "modules") { - const { title, titleAsText, id } = section.value as any; - return ( - <> -
        - - {doc.modules && ( - - )} -
        -
        -
        - - -
        -
        - - ); - } - return null; - }} - /> -
        -
        - - )} - + + { + if (i === 0) { + return
        ; + } + if (section.value.id === "about_the_curriculum") { + return About({ section }); + } + if (section.value.id === "modules") { + const { title, titleAsText, id } = section.value as any; + return ( + <> +
        + + {doc.modules && } +
        +
        +
        + + +
        +
        + + ); + } + return null; + }} + /> + ); } diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 531d3d40562b..ef45b22f3c3d 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -1,98 +1,27 @@ -import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError } from "../document"; -import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; -import { TOC } from "../document/organisms/toc"; -import { SidePlacement } from "../ui/organisms/placement"; import "./module.scss"; -import { Sidebar } from "./sidebar"; -import { TopNavigation } from "../ui/organisms/top-navigation"; -import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; import { TopicIcon } from "./topic-icon"; -import { topic2css, useDocTitle } from "./utils"; -import { SidebarContainer } from "../document/organisms/sidebar"; import { PrevNext } from "./prev-next"; import { RenderCurriculumBody } from "./body"; +import { CurriculumLayout } from "./layout"; +import { topic2css, useCurriculumDoc } from "./utils"; export function CurriculumModule(props: HydrationData) { - const dataURL = `./index.json`; - const { data } = useSWR( - dataURL, - async (url) => { - const response = await fetch(url); - - if (!response.ok) { - switch (response.status) { - case 404: - throw new HTTPError(response.status, url, "Page not found"); - } - - const text = await response.text(); - throw new HTTPError(response.status, url, text); - } - - return await response.json(); - }, - { - fallbackData: props as ModuleData, - revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.curriculumMeta, - } - ); - const { doc }: { doc?: CurriculumDoc } = data || props || {}; - useDocTitle(doc); - + const doc = useCurriculumDoc(props as ModuleData); + console.log(doc); return ( - <> - {doc && ( - <> -
        - - -
        -
        -
        - - {doc.sidebar && ( - - )} - -
        - - {PLACEMENT_ENABLED && } -
        - {doc.sidebar && ( - - )} -
        -
        -
        - {doc.topic && } -

        {doc?.title}

        - {doc?.topic &&

        {doc.topic}

        } -
        - - -
        -
        - - )} - + +
        + {doc?.topic && } +

        {doc?.title}

        + {doc?.topic &&

        {doc?.topic}

        } +
        + + +
        ); } diff --git a/client/src/curriculum/no-side.scss b/client/src/curriculum/no-side.scss index c29d5743f176..9fece4ab8f31 100644 --- a/client/src/curriculum/no-side.scss +++ b/client/src/curriculum/no-side.scss @@ -1,43 +1,23 @@ @use "../ui/vars" as *; .curriculum-content-container { - .curriculum-content.curriculum-about, - .curriculum-content.curriculum-overview { - > header > h1 { - margin-bottom: 1rem; + &.curriculum-about, + &.curriculum-overview { + .curriculum-content { + > header > h1 { + margin-bottom: 1rem; - > span { - color: var(--cur-color); + > span { + color: var(--cur-color); + } } - } - .module-contents { - > h2 { - margin-bottom: 2rem; - margin-top: 4rem; + .module-contents { + > h2 { + margin-bottom: 2rem; + margin-top: 4rem; + } } } } } - -.curriculum-content-container.curriculum-no-side { - @media screen and (min-width: $screen-md) { - display: grid; - gap: 3rem; - grid-template-areas: "main toc"; - grid-template-columns: minmax(0, 1fr) minmax(0, 12rem); - padding-left: 1.5rem; - padding-right: 3rem; - } - - @media screen and (min-width: $screen-xl) { - display: grid; - gap: 3rem; - grid-template-areas: "main toc"; - grid-template-columns: minmax(0, 62rem) minmax(0, 12rem); - margin: 0 auto; - padding-left: 1rem; - padding-right: 1rem; - width: fit-content; - } -} diff --git a/client/src/curriculum/overview.scss b/client/src/curriculum/overview.scss deleted file mode 100644 index 8f9537e92268..000000000000 --- a/client/src/curriculum/overview.scss +++ /dev/null @@ -1 +0,0 @@ -// nothing yet diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index e091239f164a..54c78c5e9c80 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -1,97 +1,41 @@ -import useSWR from "swr"; import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; -import { HTTPError } from "../document"; -import { PLACEMENT_ENABLED, WRITER_MODE } from "../env"; -import { SidePlacement } from "../ui/organisms/placement"; import { ModulesList } from "./modules-list"; -import { TopNavigation } from "../ui/organisms/top-navigation"; -import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; -import { topic2css, useDocTitle } from "./utils"; - -import "./no-side.scss"; -import "./overview.scss"; +import { topic2css, useCurriculumDoc, useDocTitle } from "./utils"; import { PrevNext } from "./prev-next"; import { RenderCurriculumBody } from "./body"; -import { SidebarContainer } from "../document/organisms/sidebar"; -import { Sidebar } from "./sidebar"; +import { CurriculumLayout } from "./layout"; + +import "./index.scss"; +import "./overview.scss"; export function CurriculumModuleOverview( props: HydrationData ) { - const dataURL = `./index.json`; - const { data } = useSWR( - dataURL, - async (url) => { - const response = await fetch(url); - - if (!response.ok) { - switch (response.status) { - case 404: - throw new HTTPError(response.status, url, "Page not found"); - } - - const text = await response.text(); - throw new HTTPError(response.status, url, text); - } - - return await response.json(); - }, - { - fallbackData: props as ModuleData, - revalidateOnFocus: WRITER_MODE, - revalidateOnMount: !props.blogMeta, - } - ); - const { doc }: { doc?: CurriculumDoc } = data || props || {}; - useDocTitle(doc); + const doc = useCurriculumDoc(props as ModuleData); const [coloredTitle, ...restTitle] = doc?.title?.split(" ") || []; return ( <> {doc && ( - <> -
        - - -
        -
        -
        - - {doc.sidebar && ( - - )} - -
        - {PLACEMENT_ENABLED && } -
        - {doc.sidebar && ( - - )} -
        -
        -
        -

        - {coloredTitle} {restTitle.join(" ")} -

        -
        - -
        -

        Module Contents

        - {doc.modules && } -
        - -
        -
        - + +
        +

        + {coloredTitle} {restTitle.join(" ")} +

        +
        + +
        +

        Module Contents

        + {doc.modules && } +
        + +
        )} ); diff --git a/client/src/curriculum/utils.ts b/client/src/curriculum/utils.ts index 65d1f8761125..990e2ec7f7ac 100644 --- a/client/src/curriculum/utils.ts +++ b/client/src/curriculum/utils.ts @@ -1,7 +1,11 @@ // Using this import fails the build... import { useEffect } from "react"; -import { CurriculumDoc } from "../../../libs/types/curriculum"; +import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; +import { HydrationData } from "../../../libs/types/hydration"; +import useSWR from "swr"; +import { HTTPError } from "../document"; +import { WRITER_MODE } from "../env"; //import { Topic } from "../../../libs/types/curriculum"; export enum Topic { @@ -41,3 +45,32 @@ export function useDocTitle(doc?: CurriculumDoc) { : "MDN Curriculum"; }, [doc]); } + +export function useCurriculumDoc(appProps: ModuleData) { + const dataURL = `./index.json`; + const { data } = useSWR( + dataURL, + async (url) => { + const response = await fetch(url); + + if (!response.ok) { + switch (response.status) { + case 404: + throw new HTTPError(response.status, url, "Page not found"); + } + + const text = await response.text(); + throw new HTTPError(response.status, url, text); + } + + return (await response.json())?.doc; + }, + { + fallbackData: appProps?.doc as CurriculumDoc, + revalidateOnFocus: WRITER_MODE, + revalidateOnMount: !appProps?.doc?.modified, + } + ); + const doc: CurriculumDoc | undefined = data || appProps?.doc || undefined; + return doc; +} From 6893100e6ee273644843bbaa4fe49ab51fccff51 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 5 Feb 2024 14:26:26 +0100 Subject: [PATCH 057/102] more clean up --- build/curriculum.ts | 6 ++---- client/src/curriculum/about.tsx | 4 ++-- client/src/curriculum/index.tsx | 1 - client/src/curriculum/landing.tsx | 4 ++-- client/src/curriculum/module.tsx | 5 ++--- client/src/curriculum/overview.tsx | 5 ++--- client/src/curriculum/utils.ts | 4 ++-- libs/types/curriculum.ts | 2 +- server/index.ts | 1 - 9 files changed, 13 insertions(+), 19 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index 1a83bb842843..1db5e24201be 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -20,7 +20,7 @@ import path from "node:path"; import fs from "node:fs/promises"; import { CurriculumFrontmatter, - ModuleData, + CurriculumData, ModuleMetaData, ModuleIndexEntry, PrevNext, @@ -222,7 +222,7 @@ async function readModule( export async function findModuleBySlug( slug: string -): Promise { +): Promise { let file = await slugToFile(slug); if (!file) { file = await slugToFile(`${slug}${slug ? "/" : ""}README`); @@ -318,8 +318,6 @@ export async function buildCurriculum(options: { const locale = DEFAULT_LOCALE; for (const file of await allFiles()) { - console.log(`building: ${file}`); - const { meta, body } = await readModule(file, { forIndex: false, }); diff --git a/client/src/curriculum/about.tsx b/client/src/curriculum/about.tsx index 8ec9638d102d..7b558abef537 100644 --- a/client/src/curriculum/about.tsx +++ b/client/src/curriculum/about.tsx @@ -1,5 +1,5 @@ import { HydrationData } from "../../../libs/types/hydration"; -import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; +import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; import { topic2css, useCurriculumDoc, useDocTitle } from "./utils"; import { RenderCurriculumBody } from "./body"; import { CurriculumLayout } from "./layout"; @@ -8,7 +8,7 @@ import "./index.scss"; import "./about.scss"; export function CurriculumAbout(props: HydrationData) { - const doc = useCurriculumDoc(props as ModuleData); + const doc = useCurriculumDoc(props as CurriculumData); const [coloredTitle, ...restTitle] = doc?.title?.split(" ") || []; return ( <> diff --git a/client/src/curriculum/index.tsx b/client/src/curriculum/index.tsx index 980b559944a8..777ad4e05a63 100644 --- a/client/src/curriculum/index.tsx +++ b/client/src/curriculum/index.tsx @@ -7,7 +7,6 @@ import { CurriculumAbout } from "./about"; import { CurriculumLanding } from "./landing"; import "./index.scss"; -import "./no-side.scss"; export function Curriculum(appProps: HydrationData) { return ( diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index 04daa23edd6f..33c9c3d17889 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -2,7 +2,7 @@ import { ReactComponent as LandingSVG } from "../../public/assets/curriculum/cur import { ReactComponent as LandingLadderSVG1 } from "../../public/assets/curriculum/cur-landing-ladder-1.svg"; import { ReactComponent as LandingLadderSVG2 } from "../../public/assets/curriculum/cur-landing-ladder-2.svg"; import { HydrationData } from "../../../libs/types/hydration"; -import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; +import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; import { ModulesListList } from "./modules-list"; import { useCurriculumDoc, useDocTitle } from "./utils"; import { RenderCurriculumBody } from "./body"; @@ -14,7 +14,7 @@ import "./index.scss"; import "./landing.scss"; export function CurriculumLanding(appProps: HydrationData) { - const doc = useCurriculumDoc(appProps as ModuleData); + const doc = useCurriculumDoc(appProps as CurriculumData); return ( ) { - const doc = useCurriculumDoc(props as ModuleData); - console.log(doc); + const doc = useCurriculumDoc(props as CurriculumData); return ( ) { - const doc = useCurriculumDoc(props as ModuleData); + const doc = useCurriculumDoc(props as CurriculumData); const [coloredTitle, ...restTitle] = doc?.title?.split(" ") || []; return ( <> diff --git a/client/src/curriculum/utils.ts b/client/src/curriculum/utils.ts index 990e2ec7f7ac..d617abc35816 100644 --- a/client/src/curriculum/utils.ts +++ b/client/src/curriculum/utils.ts @@ -1,7 +1,7 @@ // Using this import fails the build... import { useEffect } from "react"; -import { CurriculumDoc, ModuleData } from "../../../libs/types/curriculum"; +import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; import { HydrationData } from "../../../libs/types/hydration"; import useSWR from "swr"; import { HTTPError } from "../document"; @@ -46,7 +46,7 @@ export function useDocTitle(doc?: CurriculumDoc) { }, [doc]); } -export function useCurriculumDoc(appProps: ModuleData) { +export function useCurriculumDoc(appProps: CurriculumData) { const dataURL = `./index.json`; const { data } = useSWR( dataURL, diff --git a/libs/types/curriculum.ts b/libs/types/curriculum.ts index 09e1c36ae712..3f78790feda4 100644 --- a/libs/types/curriculum.ts +++ b/libs/types/curriculum.ts @@ -54,7 +54,7 @@ export interface CurriculumDoc extends Doc { topic?: Topic; } -export interface ModuleData { +export interface CurriculumData { doc: CurriculumDoc; } diff --git a/server/index.ts b/server/index.ts index 2e0ef1c67000..6929d449b17c 100644 --- a/server/index.ts +++ b/server/index.ts @@ -252,7 +252,6 @@ app.get( ], async (req, res) => { const { slug = "" } = req.params; - console.log(slug); const data = await findModuleBySlug(slug); if (!data) { return res.status(404).send("Nothing here 🤷‍♂️"); From 0def9e3921718aec862195bc34ca663ad2f43a11 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 5 Feb 2024 16:54:25 +0100 Subject: [PATCH 058/102] css clean up --- client/src/curriculum/index.scss | 224 ++++++++++++++++++++++ client/src/curriculum/layout.tsx | 73 ++++++++ client/src/curriculum/module.scss | 301 +++++------------------------- client/src/curriculum/module.tsx | 4 +- 4 files changed, 342 insertions(+), 260 deletions(-) create mode 100644 client/src/curriculum/layout.tsx diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 474734216b4f..5e75e73d5c6d 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -1,3 +1,5 @@ +@use "../ui/vars" as *; + .curriculum { --background-toc-active: var(--cur-bg-color); --category-color: var(--cur-category-color); @@ -62,6 +64,55 @@ } .curriculum-content-container { + h1, + h2, + h3, + h4, + h5, + h6 { + a:link, + a:visited { + color: var(--text-primary); + text-decoration: none; + } + + a:hover, + a:focus { + text-decoration: underline; + } + + a:active { + background-color: transparent; + } + + a[href^="#"] { + &::before { + color: var(--text-inactive); + content: "#"; + display: inline-block; + font-size: 0.7em; + line-height: 1; + margin-left: -0.8em; + text-decoration: none; + visibility: hidden; + width: 0.8em; + } + + &:hover { + &::before { + visibility: visible; + } + } + } + } + + .curriculum-sidebar, + .toc, + .curriculum-content { + padding-bottom: 3rem; + padding-top: 3rem; + } + &.curriculum-about, &.curriculum-overview { .curriculum-content { @@ -81,4 +132,177 @@ } } } + + &.curriculum-module, + &.curriculum-about, + &.curriculum-overview { + .curriculum-content { + grid-area: main; + + section h2:first-of-type { + margin-top: 2rem; + } + + blockquote.curriculum-notes { + background-color: #fcefe299; + border: 0; + border-radius: var(--elem-radius); + margin: 1rem; + padding: 1rem 2rem; + + > :last-child { + margin-bottom: 0; + } + } + + p.curriculum-outcomes { + display: flex; + font-weight: var(--font-body-strong-weight); + margin-bottom: 0.5rem; + + &::before { + content: url("../assets/icons/cur-resources.svg"); + display: block; + height: 24px; + margin-right: 0.5rem; + width: 24px; + } + } + + ol, + ul { + margin: 1rem 0 2rem; + padding-left: 2rem; + + ol, + ul { + margin: 0; + } + } + + li { + list-style-type: disc; + margin: 0.5rem 0; + } + } + @media screen and (min-width: $screen-md) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + padding-left: 1.5rem; + padding-right: 3rem; + } + + @media screen and (min-width: $screen-xl) { + display: grid; + gap: 3rem; + grid-template-areas: "sidebar main toc"; + grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); + padding-left: 1rem; + padding-right: 1rem; + + .toc { + --offset: var(--sticky-header-with-actions-height); + + display: block; + grid-area: toc; + height: fit-content; + padding-bottom: 0; + } + + .in-nav-toc { + display: none; + } + } + + .sidebar-container { + --offset: var(--sticky-header-with-actions-height); + --max-height: calc(100vh - var(--offset)); + + max-height: var(--max-height); + position: sticky; + top: var(--offset); + z-index: var(--z-index-sidebar-mobile); + + > .curriculum-sidebar { + align-self: start; + grid-area: sidebar; + + li li { + margin-left: 1rem; + } + } + + &.toc-container, + .toc-container { + grid-area: toc; + + .place { + grid-area: toc; + margin: 0; + } + @media screen and (min-width: $screen-xl) { + display: flex; + flex-direction: column; + gap: 0; + height: calc(100vh - var(--offset)); + mask-image: linear-gradient( + to bottom, + rgba(0, 0, 0, 0) 0%, + rgb(0, 0, 0) 3rem calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + overflow: auto; + position: sticky; + top: var(--offset); + + .place { + margin: 1rem 0; + padding-bottom: 3rem; + } + } + } + + @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { + display: flex; + flex-direction: column; + } + + @media screen and (min-width: $screen-md) { + z-index: auto; + + .curriculum-sidebar { + mask-image: linear-gradient( + to bottom, + rgb(0, 0, 0) 0% calc(100% - 3rem), + rgba(0, 0, 0, 0) 100% + ); + } + + @media screen and not (min-height: $screen-height-place-limit) { + overflow: auto; + } + } + + @media screen and (max-width: #{$screen-md - 1}) { + .toc-container { + display: none; + } + } + + @media screen and (min-width: #{$screen-md}) { + #sidebar-quicklinks { + display: none; + } + } + @media screen and (min-width: $screen-xl) { + display: contents; + + .sidebar { + mask-image: none; + } + } + } + } } diff --git a/client/src/curriculum/layout.tsx b/client/src/curriculum/layout.tsx new file mode 100644 index 000000000000..c12a664e8b2c --- /dev/null +++ b/client/src/curriculum/layout.tsx @@ -0,0 +1,73 @@ +import { ArticleActionsContainer } from "../ui/organisms/article-actions-container"; +import { TopNavigation } from "../ui/organisms/top-navigation"; +import { CurriculumDoc } from "../../../libs/types/curriculum"; +import { PLACEMENT_ENABLED } from "../env"; +import { useDocTitle } from "./utils"; +import { SidebarContainer } from "../document/organisms/sidebar"; +import { Sidebar } from "./sidebar"; +import { TOC } from "../document/organisms/toc"; +import { SidePlacement } from "../ui/organisms/placement"; +import { ReactNode } from "react"; + +import "./index.scss"; + +export function CurriculumLayout({ + doc, + withSidebar = true, + extraClasses = [], + children, +}: { + doc?: CurriculumDoc; + withSidebar?: boolean; + extraClasses?: string[]; + children: ReactNode; +}) { + useDocTitle(doc); + return ( + doc && ( + <> +
        + + +
        +
        + {withSidebar && ( +
        + + {doc.sidebar && ( + + )} + +
        + + {PLACEMENT_ENABLED && } +
        + {doc.sidebar && ( + + )} +
        + )} +
        + {children} +
        +
        + + ) + ); +} diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 96a90b966838..a06e63008bb6 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -1,279 +1,62 @@ @use "../ui/vars" as *; .curriculum-content-container { - h1, - h2, - h3, - h4, - h5, - h6 { - a:link, - a:visited { - color: var(--text-primary); - text-decoration: none; - } - - a:hover, - a:focus { - text-decoration: underline; - } - - a:active { - background-color: transparent; - } - - a[href^="#"] { - &::before { - color: var(--text-inactive); - content: "#"; - display: inline-block; - font-size: 0.7em; - line-height: 1; - margin-left: -0.8em; - text-decoration: none; - visibility: hidden; - width: 0.8em; - } - - &:hover { - &::before { - visibility: visible; - } - } - } - } - - .curriculum-sidebar, - .toc, - .curriculum-content { - padding-bottom: 3rem; - padding-top: 3rem; - } - - > .sidebar-container > .curriculum-sidebar { - align-self: start; - grid-area: sidebar; - - li li { - margin-left: 1rem; - } - } - - &:not(.curriculum-landing) .curriculum-content { - grid-area: main; - - > header { - column-gap: 1.5rem; - display: grid; - grid-template-areas: "icon heading" "icon category"; - justify-content: flex-start; - - .topic-icon { - --background-primary: var(--cur-bg-color-topic); - align-self: flex-start; - grid-area: icon; - height: 4rem; - width: 4rem; - - + h1 { - grid-area: heading; - margin-bottom: 0; - } - } - - p { - color: var(--cur-color-topic); - font-size: var(--type-smaller-font-size); - grid-area: category; - margin: 0; - margin-top: 0.5rem; - - &::before { - content: "Category: "; - } - } - } - - section h2:first-of-type { - margin-top: 2rem; - } - - blockquote.curriculum-notes { - background-color: #fcefe299; - border: 0; - border-radius: var(--elem-radius); - margin: 1rem; - padding: 1rem 2rem; - - > :last-child { - margin-bottom: 0; - } - } - - p.curriculum-outcomes { - display: flex; - font-weight: var(--font-body-strong-weight); - margin-bottom: 0.5rem; - - &::before { - content: url("../assets/icons/cur-resources.svg"); - display: block; - height: 24px; - margin-right: 0.5rem; - width: 24px; - } - } - - ol, - ul { - margin: 1rem 0 2rem; - padding-left: 2rem; - - ol, - ul { - margin: 0; - } - } - - li { - list-style-type: disc; - margin: 0.5rem 0; - } - - p.curriculum-resources { - margin-bottom: 0.5rem; - - + ul { - padding-left: 2rem; - - > li { - // This is hacky but works here - &::first-line { - vertical-align: super; + &.curriculum-module { + .curriculum-content { + > header { + column-gap: 1.5rem; + display: grid; + grid-template-areas: "icon heading" "icon category"; + justify-content: flex-start; + + .topic-icon { + --background-primary: var(--cur-bg-color-topic); + align-self: flex-start; + grid-area: icon; + height: 4rem; + width: 4rem; + + + h1 { + grid-area: heading; + margin-bottom: 0; } + } - &:not(.external) { - list-style-image: url("../assets/icons/cur-mdn-resource.svg"); - } + p { + color: var(--cur-color-topic); + font-size: var(--type-smaller-font-size); + grid-area: category; + margin: 0; + margin-top: 0.5rem; - &.external { - list-style-image: url("../assets/icons/cur-ext-resource.svg"); + &::before { + content: "Category: "; } } } - } - } - - &:not(.curriculum-landing) { - @media screen and (min-width: $screen-md) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - padding-left: 1.5rem; - padding-right: 3rem; - } - - @media screen and (min-width: $screen-xl) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main toc"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); - padding-left: 1rem; - padding-right: 1rem; - - .toc { - --offset: var(--sticky-header-with-actions-height); - - display: block; - grid-area: toc; - height: fit-content; - padding-bottom: 0; - } - - .in-nav-toc { - display: none; - } - } - - .sidebar-container { - --offset: var(--sticky-header-with-actions-height); - --max-height: calc(100vh - var(--offset)); - - @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { - display: flex; - flex-direction: column; - } - - max-height: var(--max-height); - position: sticky; - top: var(--offset); - z-index: var(--z-index-sidebar-mobile); - @media screen and (min-width: $screen-md) { - z-index: auto; + p.curriculum-resources { + margin-bottom: 0.5rem; - .curriculum-sidebar { - mask-image: linear-gradient( - to bottom, - rgb(0, 0, 0) 0% calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - } + + ul { + padding-left: 2rem; - @media screen and not (min-height: $screen-height-place-limit) { - overflow: auto; - } - } + > li { + // This is hacky but works here + &::first-line { + vertical-align: super; + } - &.toc-container, - .toc-container { - grid-area: toc; - - .place { - grid-area: toc; - margin: 0; - } - @media screen and (min-width: $screen-xl) { - display: flex; - flex-direction: column; - gap: 0; - height: calc(100vh - var(--offset)); - mask-image: linear-gradient( - to bottom, - rgba(0, 0, 0, 0) 0%, - rgb(0, 0, 0) 3rem calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - overflow: auto; - position: sticky; - top: var(--offset); + &:not(.external) { + list-style-image: url("../assets/icons/cur-mdn-resource.svg"); + } - .place { - margin: 1rem 0; - padding-bottom: 3rem; + &.external { + list-style-image: url("../assets/icons/cur-ext-resource.svg"); + } } } } - - @media screen and (max-width: #{$screen-md - 1}) { - .toc-container { - display: none; - } - } - - @media screen and (min-width: #{$screen-md}) { - #sidebar-quicklinks { - display: none; - } - } - @media screen and (min-width: $screen-xl) { - display: contents; - - .sidebar { - mask-image: none; - } - } } } } diff --git a/client/src/curriculum/module.tsx b/client/src/curriculum/module.tsx index 47a7a3f86aa1..81fd8898e03a 100644 --- a/client/src/curriculum/module.tsx +++ b/client/src/curriculum/module.tsx @@ -1,12 +1,14 @@ import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; -import "./module.scss"; import { TopicIcon } from "./topic-icon"; import { PrevNext } from "./prev-next"; import { RenderCurriculumBody } from "./body"; import { CurriculumLayout } from "./layout"; import { topic2css, useCurriculumDoc } from "./utils"; +import "./index.scss"; +import "./module.scss"; + export function CurriculumModule(props: HydrationData) { const doc = useCurriculumDoc(props as CurriculumData); return ( From 45b7408902cbe26d36851eb3392447f6253af280 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 5 Feb 2024 16:56:02 +0100 Subject: [PATCH 059/102] rm --- client/src/curriculum/no-side.scss | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 client/src/curriculum/no-side.scss diff --git a/client/src/curriculum/no-side.scss b/client/src/curriculum/no-side.scss deleted file mode 100644 index 9fece4ab8f31..000000000000 --- a/client/src/curriculum/no-side.scss +++ /dev/null @@ -1,23 +0,0 @@ -@use "../ui/vars" as *; - -.curriculum-content-container { - &.curriculum-about, - &.curriculum-overview { - .curriculum-content { - > header > h1 { - margin-bottom: 1rem; - - > span { - color: var(--cur-color); - } - } - - .module-contents { - > h2 { - margin-bottom: 2rem; - margin-top: 4rem; - } - } - } - } -} From 4e5af47fce1f398f9173cfdfe8ab589c78a6ccfb Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 5 Feb 2024 17:26:02 +0100 Subject: [PATCH 060/102] more css --- client/src/curriculum/index.scss | 15 ++++----------- client/src/curriculum/layout.tsx | 1 + client/src/curriculum/module.scss | 1 + client/src/curriculum/modules-list.scss | 1 + 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 5e75e73d5c6d..c8158d1b31e6 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -113,11 +113,12 @@ padding-top: 3rem; } - &.curriculum-about, - &.curriculum-overview { + &.with-sidebar { .curriculum-content { + grid-area: main; + > header > h1 { - margin-bottom: 1rem; + margin-bottom: 2rem; > span { color: var(--cur-color); @@ -130,14 +131,6 @@ margin-top: 4rem; } } - } - } - - &.curriculum-module, - &.curriculum-about, - &.curriculum-overview { - .curriculum-content { - grid-area: main; section h2:first-of-type { margin-top: 2rem; diff --git a/client/src/curriculum/layout.tsx b/client/src/curriculum/layout.tsx index c12a664e8b2c..b47e0ba627fe 100644 --- a/client/src/curriculum/layout.tsx +++ b/client/src/curriculum/layout.tsx @@ -34,6 +34,7 @@ export function CurriculumLayout({ className={[ "curriculum-content-container", "container", + ...(withSidebar ? ["with-sidebar"] : []), ...extraClasses, ].join(" ")} > diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index a06e63008bb6..83e53c97a49e 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -1,5 +1,6 @@ @use "../ui/vars" as *; +.curriculum-content-container.with-sidebar, .curriculum-content-container { &.curriculum-module { .curriculum-content { diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 51368ec0f4e3..049589eeb687 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -1,5 +1,6 @@ @use "../ui/vars" as *; +.curriculum-content-container.with-sidebar, .curriculum-content-container { --module-shadow: 4px 4px 8px 0 rgba(179, 179, 179, 0.18), -4px 4px 8px 0 rgba(179, 179, 179, 0.15); From bdd25339eca5de93e4efb7e5df4079f7f7bf7b0b Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Tue, 6 Feb 2024 20:03:35 +0100 Subject: [PATCH 061/102] styles 1 --- .../assets/curriculum/cur-landing-top.svg | 200 +++++++++++------- .../icons/cur-landing-about-beginner.svg | 27 ++- .../assets/icons/cur-landing-about-bullet.svg | 31 ++- .../assets/icons/cur-landing-about-free.svg | 27 ++- .../assets/icons/cur-landing-about-pace.svg | 23 +- .../assets/icons/cur-modules-underline-1.svg | 8 + .../assets/icons/cur-modules-underline-2.svg | 8 + .../assets/icons/cur-modules-underline-3.svg | 4 + client/src/curriculum/about.tsx | 2 +- client/src/curriculum/landing.scss | 112 +++++++--- client/src/curriculum/landing.tsx | 2 +- client/src/curriculum/modules-list.scss | 43 +++- client/src/curriculum/overview.tsx | 2 +- client/src/curriculum/utils.ts | 1 - client/src/ui/base/_themes.scss | 18 +- 15 files changed, 363 insertions(+), 145 deletions(-) create mode 100644 client/src/assets/icons/cur-modules-underline-1.svg create mode 100644 client/src/assets/icons/cur-modules-underline-2.svg create mode 100644 client/src/assets/icons/cur-modules-underline-3.svg diff --git a/client/public/assets/curriculum/cur-landing-top.svg b/client/public/assets/curriculum/cur-landing-top.svg index 67c9f22f0dc4..4a1e54e2c7eb 100644 --- a/client/public/assets/curriculum/cur-landing-top.svg +++ b/client/public/assets/curriculum/cur-landing-top.svg @@ -1,82 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-about-beginner.svg b/client/src/assets/icons/cur-landing-about-beginner.svg index 076b9856274b..e63263f765d9 100644 --- a/client/src/assets/icons/cur-landing-about-beginner.svg +++ b/client/src/assets/icons/cur-landing-about-beginner.svg @@ -1,4 +1,25 @@ - - - + + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-about-bullet.svg b/client/src/assets/icons/cur-landing-about-bullet.svg index b8d39998bc56..3cab4ebe3352 100644 --- a/client/src/assets/icons/cur-landing-about-bullet.svg +++ b/client/src/assets/icons/cur-landing-about-bullet.svg @@ -1,8 +1,27 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-about-free.svg b/client/src/assets/icons/cur-landing-about-free.svg index 6ba513e3749b..dd7a97436326 100644 --- a/client/src/assets/icons/cur-landing-about-free.svg +++ b/client/src/assets/icons/cur-landing-about-free.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-about-pace.svg b/client/src/assets/icons/cur-landing-about-pace.svg index dbc10c33c659..41187fb7080e 100644 --- a/client/src/assets/icons/cur-landing-about-pace.svg +++ b/client/src/assets/icons/cur-landing-about-pace.svg @@ -1,6 +1,25 @@ - + + + + + fill="var(--icon)" /> + + + + + + diff --git a/client/src/assets/icons/cur-modules-underline-1.svg b/client/src/assets/icons/cur-modules-underline-1.svg new file mode 100644 index 000000000000..eafa7730ef05 --- /dev/null +++ b/client/src/assets/icons/cur-modules-underline-1.svg @@ -0,0 +1,8 @@ + + + + diff --git a/client/src/assets/icons/cur-modules-underline-2.svg b/client/src/assets/icons/cur-modules-underline-2.svg new file mode 100644 index 000000000000..6af6f1d683e4 --- /dev/null +++ b/client/src/assets/icons/cur-modules-underline-2.svg @@ -0,0 +1,8 @@ + + + + diff --git a/client/src/assets/icons/cur-modules-underline-3.svg b/client/src/assets/icons/cur-modules-underline-3.svg new file mode 100644 index 000000000000..6ec5ecce4ca7 --- /dev/null +++ b/client/src/assets/icons/cur-modules-underline-3.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/src/curriculum/about.tsx b/client/src/curriculum/about.tsx index 7b558abef537..4e4fe40cefec 100644 --- a/client/src/curriculum/about.tsx +++ b/client/src/curriculum/about.tsx @@ -1,6 +1,6 @@ import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; -import { topic2css, useCurriculumDoc, useDocTitle } from "./utils"; +import { topic2css, useCurriculumDoc } from "./utils"; import { RenderCurriculumBody } from "./body"; import { CurriculumLayout } from "./layout"; diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 40002974db3a..b56990b548f8 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -39,6 +39,7 @@ > svg { width: 40%; + z-index: 1; } > section { @@ -57,15 +58,16 @@ margin-top: 1rem; } - p:last-child { + p { color: var(--text-secondary); } } } .landing-about-container { - background-color: var(--cur-bg-color); + background-color: var(--cur-bg-large-color); margin: 0; + margin-top: -6rem; max-width: 100%; .landing-about { @@ -73,24 +75,25 @@ grid-template-areas: "li" "h2" - "p" - "p" - "p"; + "p1" + "p2" + "p3"; grid-template-columns: 1fr; margin: 0 auto 3rem; max-width: min(var(--max-width), 74rem); @media screen and (min-width: $screen-md) { grid-template-areas: "li li " - "h2 p " - "h2 p " - "h2 p "; + "h2 . " + ". p1 " + ". p2" + ". p3"; grid-template-columns: 1fr 1fr; } h2 { grid-area: h2; - margin: 1rem 0; + margin: 1rem 0 0; } > div { @@ -99,48 +102,78 @@ ul { align-items: center; background-color: var(--background-primary); + border-radius: var(--elem-radius); box-shadow: var(--module-shadow); display: grid; gap: 1rem; grid-area: li; grid-template-columns: auto; - justify-content: space-around; + justify-content: center; margin: auto; min-height: 5rem; padding: 1rem; transform: translateY(-1rem); width: 100%; - @media screen and (min-width: $screen-md) { + @media screen and (min-width: $screen-sm) { grid-template-columns: auto auto auto; + justify-content: start; + } + @media screen and (min-width: $screen-lg) { + justify-content: center; } > li { - align-items: center; - display: inline-flex; - gap: 2rem; + margin: 0 1rem; + text-align: center; + @media screen and (min-width: $screen-sm) { + width: max-content; + } + @media screen and (min-width: $screen-md) { + align-items: center; + display: inline-flex; + gap: 1rem; + } &::before { - height: 4rem; - width: 4rem; + display: block; + height: 3rem; + margin: 0 auto; + width: 3rem; + @media screen and (min-width: $screen-md) { + display: initial; + margin: 0; + } } &:nth-child(1)::before { - content: url("../assets/icons/cur-landing-about-beginner.svg"); + content: url("../assets/icons/cur-landing-about-beginner.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-about-beginner.svg#dark"); + } } &:nth-child(2)::before { content: url("../assets/icons/cur-landing-about-pace.svg"); + + .dark & { + content: url("../assets/icons/cur-landing-about-pace.svg#dark"); + } } &:nth-child(3)::before { content: url("../assets/icons/cur-landing-about-free.svg"); + + .dark & { + content: url("../assets/icons/cur-landing-about-free.svg#dark"); + } } } } p { align-items: center; - display: inline-grid; + display: grid; grid-template-columns: auto auto; &::before { @@ -149,22 +182,43 @@ width: 4rem; } - &:nth-child(2)::before { - content: url("../assets/icons/cur-landing-about-bullet.svg"); + &:nth-child(2) { + grid-area: p1; + + &::before { + content: url("../assets/icons/cur-landing-about-bullet.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-about-bullet.svg#dark"); + } + } } - &:nth-child(3)::before { - content: url("../assets/icons/cur-landing-about-bullet.svg"); + &:nth-child(3) { + grid-area: p2; + + &::before { + content: url("../assets/icons/cur-landing-about-bullet.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-about-bullet.svg#dark"); + } + } } - a { - color: var(--text-primary); - font-weight: var(--font-body-strong-weight); - text-decoration: underline; + &:nth-child(4) { + grid-area: p3; + + a { + color: var(--text-primary); + font-weight: var(--font-body-strong-weight); + margin-left: 4rem; + text-decoration: underline; - &:hover, - &:active { - text-decoration: none; + &:hover, + &:active { + text-decoration: none; + } } } } diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index 33c9c3d17889..ad1376f66f03 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -4,7 +4,7 @@ import { ReactComponent as LandingLadderSVG2 } from "../../public/assets/curricu import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; import { ModulesListList } from "./modules-list"; -import { useCurriculumDoc, useDocTitle } from "./utils"; +import { useCurriculumDoc } from "./utils"; import { RenderCurriculumBody } from "./body"; import { useMemo } from "react"; import { DisplayH2 } from "../document/ingredients/utils"; diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 049589eeb687..f2dd8e9f3f26 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -5,6 +5,11 @@ --module-shadow: 4px 4px 8px 0 rgba(179, 179, 179, 0.18), -4px 4px 8px 0 rgba(179, 179, 179, 0.15); + .dark & { + --module-shadow: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), + -4px 4px 8px 0 rgb(36, 36, 36); + } + .curriculum-content { .modules { input[type="radio"]:not(:checked) ~ a, @@ -55,11 +60,9 @@ li { display: contents; - > input:checked + label { - text-decoration-color: var(--cur-color); - text-decoration-line: underline; - text-decoration-thickness: 0.25rem; - text-underline-offset: 0.4rem; + > input:checked + label::before { + position: absolute; + transform: translate3d(-0.3rem, 0.75rem, 0); } > label { @@ -72,6 +75,10 @@ > input { grid-area: a; } + + > input:checked + label::before { + content: url("../assets/icons/cur-modules-underline-1.svg"); + } } &:nth-child(3) { @@ -82,6 +89,10 @@ margin-left: 2rem; } } + + > input:checked + label::before { + content: url("../assets/icons/cur-modules-underline-2.svg"); + } } &:nth-child(4) { @@ -92,6 +103,10 @@ margin-left: 2rem; } } + + > input:checked + label::before { + content: url("../assets/icons/cur-modules-underline-3.svg"); + } } > ol { @@ -143,18 +158,22 @@ max-width: 20rem; width: 100%; + .dark & { + background-color: #000; + } + > header { a { align-items: center; background-color: var(--cur-bg-color-topic); display: flex; flex-direction: column; - height: 12rem; + height: 10rem; padding: 1rem 2rem; .topic-icon { - height: 5rem; - width: 5rem; + height: 4rem; + width: 4rem; } > span { @@ -176,6 +195,7 @@ padding: 1rem 1.5rem; p { + color: var(--text-secondary); margin: 0; text-align: center; } @@ -185,6 +205,13 @@ } } } + + + a.button { + > span { + padding-left: 1rem; + padding-right: 1rem; + } + } } } } diff --git a/client/src/curriculum/overview.tsx b/client/src/curriculum/overview.tsx index 8efb2aefde9a..f4e3c4f9b89f 100644 --- a/client/src/curriculum/overview.tsx +++ b/client/src/curriculum/overview.tsx @@ -1,7 +1,7 @@ import { HydrationData } from "../../../libs/types/hydration"; import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; import { ModulesList } from "./modules-list"; -import { topic2css, useCurriculumDoc, useDocTitle } from "./utils"; +import { topic2css, useCurriculumDoc } from "./utils"; import { PrevNext } from "./prev-next"; import { RenderCurriculumBody } from "./body"; import { CurriculumLayout } from "./layout"; diff --git a/client/src/curriculum/utils.ts b/client/src/curriculum/utils.ts index d617abc35816..b3f3e9bd2bfe 100644 --- a/client/src/curriculum/utils.ts +++ b/client/src/curriculum/utils.ts @@ -2,7 +2,6 @@ import { useEffect } from "react"; import { CurriculumDoc, CurriculumData } from "../../../libs/types/curriculum"; -import { HydrationData } from "../../../libs/types/hydration"; import useSWR from "swr"; import { HTTPError } from "../document"; import { WRITER_MODE } from "../env"; diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index c2b5a49e06ad..4510968b0459 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -208,6 +208,7 @@ --baseline-limited-cross: #ea8600; --cur-bg-color: #fcefe2; + --cur-bg-large-color: #fcefe2; --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-50}30; --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-50}30; --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; @@ -431,15 +432,16 @@ --cur-color: #e3642a; --cur-color-topic-standards: #{$mdn-color-light-theme-red-30}; --cur-color-topic-styling: #{$mdn-color-light-theme-blue-30}; - --cur-color-topic-scripting: #{$mdn-color-light-theme-yellow-40}; - --cur-color-topic-tooling: #{$mdn-color-light-theme-green-40}; - --cur-color-topic-practices: #{$mdn-color-light-theme-violet-40}; + --cur-color-topic-scripting: #cfc23f; + --cur-color-topic-tooling: #ce93fa; + --cur-color-topic-practices: #55ab2d; --cur-bg-color: #664b33; - --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-50}30; - --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-50}30; - --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; - --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-50}30; - --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-50}30; + --cur-bg-large-color: #b25c35; + --cur-bg-color-topic-standards: #994b53; + --cur-bg-color-topic-styling: #4e609e; + --cur-bg-color-topic-scripting: #7d683d; + --cur-bg-color-topic-tooling: #584280; + --cur-bg-color-topic-practices: #3d7c4b; --cur-category-color: #e3642a; color-scheme: dark; From 14e942be8b220a80269fc523fba9882161be22a4 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 7 Feb 2024 09:53:35 +0100 Subject: [PATCH 062/102] style fixes --- client/src/curriculum/index.scss | 5 +++++ client/src/curriculum/landing.scss | 1 - client/src/curriculum/modules-list.scss | 9 +-------- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index c8158d1b31e6..61d2c5f72881 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -106,6 +106,11 @@ } } + &, + .button { + --button-padding: 1rem; + } + .curriculum-sidebar, .toc, .curriculum-content { diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index b56990b548f8..e758d83f5d47 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -351,7 +351,6 @@ --button-height: var(--form-elem-height, 2rem); --button-color: var(--background-primary); --button-font: var(--type-emphasis-m); - --button-padding: 0.5rem; --button-radius: var(--elem-radius, 0.25rem); align-items: center; background-color: var(--button-bg); diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index f2dd8e9f3f26..c8aa5cede0c8 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -62,7 +62,7 @@ > input:checked + label::before { position: absolute; - transform: translate3d(-0.3rem, 0.75rem, 0); + transform: translate3d(-0.75rem, 0.75rem, 0); } > label { @@ -205,13 +205,6 @@ } } } - - + a.button { - > span { - padding-left: 1rem; - padding-right: 1rem; - } - } } } } From 8643231d08f4a49b3cd5261b14dec819101b8370 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 7 Feb 2024 13:17:36 +0100 Subject: [PATCH 063/102] more svg --- .../assets/curriculum/cur-landing-top.svg | 197 ++++++++++-------- .../icons/cur-landing-started-advanced.svg | 32 ++- .../icons/cur-landing-started-beginner.svg | 32 ++- .../icons/cur-landing-started-educator.svg | 32 ++- .../icons/cur-landing-started-employment.svg | 32 ++- client/src/curriculum/landing.scss | 47 ++++- client/src/curriculum/modules-list.scss | 10 +- 7 files changed, 238 insertions(+), 144 deletions(-) diff --git a/client/public/assets/curriculum/cur-landing-top.svg b/client/public/assets/curriculum/cur-landing-top.svg index 4a1e54e2c7eb..39db255cd5f8 100644 --- a/client/public/assets/curriculum/cur-landing-top.svg +++ b/client/public/assets/curriculum/cur-landing-top.svg @@ -1,120 +1,137 @@ - - - - + + + - - - - - + + d="M301.616 293.28s-.567-.073-.917 0c-1.573.327 0 3.86 0 3.86l4.585 1.716 5.502 2.144h7.336l6.878-7.291-2.751-.429-4.127-12.437s-3.209-3.001-3.209-.858 1.375 10.722 1.375 10.722h-.917l-4.585-16.727s-.567-.072-.917 0c-.39.081-.46.425-.917.427-.458.002.459-.853-.917-1.284-1.375-.431-2.106.338-2.751 1.286-.886 1.303.917 3.86.917 3.86s-1.83-.517-2.751 0c-1.535.862 0 4.289 0 4.289s-1.834-1.713-1.834 0z" + id="path7" /> + d="M270.059 181.265c-4.758 14.306-5.624 16.041-17.737 20.81-10.816-3.902-15.575-5.201-16.873-21.677 3.461-16.473 14.255-22.898 24.051-22.898 6.057 3.035 13.5 8 10.559 23.765" + id="path8" /> + d="m239.776 195.57 21.631 2.168s0 9.538 3.461 14.307 1.731 19.942 1.731 19.942l-44.128-16.04s7.008-8.151 11.681-11.272c3.893-2.602 5.624-9.105 5.624-9.105" + id="path9" /> - - + d="M247.996 189.07c4.046 2.981 6.472 3.853 11.248 3.035m-5.191-4.77h5.192l-.433-9.971c.676-.678 1.143-1.472 1.73-2.168.732-.867.973-.926 1.731-1.301 1.818-.898 5.191 0 5.191 0l.866 2.168m-24.227-.433s2.003-1.336 3.461-1.735c1.956-.534 3.296-.721 5.191 0 1.359.517 3.028 2.168 3.028 2.168m-7.787 3.035c2.091-1.206 3.213-.958 4.759 0m-9.085 18.642s4.596 4.175 8.22 4.335c1.887.084 4.759-.867 4.759-.867" + id="path10" /> + + - - + d="M249.789 146.513c-2.142-3.268-6.906-4.65-11.521-3.09-5.312 1.795-8.416 6.808-6.933 11.196.505 1.494 1.477 2.723 2.749 3.623-1.773 3.378-2.785 7.194-2.785 11.061 0 1.978.036 4.526.883 4.854 1.552 0 2.552-.329 3.409-.908l.122.024s1.276 9.19-.883 15.008q-.184.5-.35.971c-.492 1.39-.927 2.617-1.857 3.884-1.816 2.475-7.062 5.739-7.062 5.739s4.551-.291 6.179-.883c3.216-1.169 4.425-3.462 5.739-6.621.481-1.159.882-3.09.882-3.09v-9.27c0-1.389 1.766-3.089 1.766-3.089l1.732-8.227q.465-.33.959-.672l12.857-7.105c1.416-.482 2.734-.766 3.874-.767 1.761 0 2.923 1.795 4.004 3.466.575.889 1.128 1.742 1.735 2.271 1.333 1.164 2.467 2.412 3.423 3.532.348.408.672.799.974 1.163l.548.657c.248 1.046.333 2.655-.018 5.127-.955 6.739-.883 9.27-.883 9.27s1.252-2.09 2.135-3.414c.748-1.122.597-7.402.534-9.291.758.294 1.083-.805 1.083-4.389 0-2.828-.548-5.526-1.542-7.992 2.603-.744 4.687-2.482 5.515-4.932 1.483-4.388-1.62-9.401-6.932-11.196-4.95-1.673-10.07.038-11.945 3.829a20.7 20.7 0 0 0-6.043-.895q-1.191 0-2.348.156" + clip-rule="evenodd" id="path11" /> + + + d="m212.449 267.696-1.572-14.755-5.377 6.559h4.853l-1.176 8.75L207.5 275l-22 10.5s-5.373 2.997-8.5 1c-3.114-1.989-4-4.576-4-4.576l4-22.424 4.5-15s8.75-20.782 19.945-28.447c6.747-4.62 10.585-6.52 18.055-9.053 6.057-2.054 16-3.5 16-3.5l8.916 5.702s3.751 4.514 5.241 7.905c3.517 8.002 0 22.381 0 22.381s4.559-12.303 5.478-15.89c.868-3.388 2.382-14.396 2.382-14.396L262 207l11.763 1.148s9.456 3.279 14.149 7.378c5.84 5.1 10.481 16.863 10.481 16.863h-31.967l-5.764 48.481-26.613 2.433c-.531.048-.627.783-.127.967l25.168 9.247 29.87-.527-.524 16.336c-.837 9.159-49.26 14.755-78.083 4.743l1.048-32.145V273z" + id="path14" /> + d="M174.239 286.157c-5.714-8.934 3.531-26.925 3.531-26.925s6.729-.678 11.035-.445c4.529.244 11.477 1.769 11.477 1.769l11.035-3.09.883-2.648c1.324-3.97 3.973-5.296 3.973-5.296s1.765-5.964 4.414-6.621 2.648.734 2.648 3.972c0 3.971-2.207 6.621-2.207 6.621l9.711-2.207s7.734-3.531 5.738 7.946-2.648 11.035-2.648 11.035-11.035 3.531-15.008 3.531S215 273 215 273l-31.933 14.479s-6.66 2.069-8.828-1.322" + id="path15" /> + d="M220.5 273.5s11.424-.732 13.5-3.5c1.5-2 3-13 3-13s.491-3.68-1-5c-1.065-.942-3.5-1-3.5-1l-11.5 2.5 2-4s1.634-4.321 0-6c-.491-.505-1.5-.5-1.5-.5" + id="path16" /> + d="M246.947 70.007s13.077.594 21.332 1.967c20.21 3.362 31.687 7.368 49.452 17.706 20.24 11.779 27.635 22.135 40.24 40.333 5.034 7.267 8.422 13.347 12.606 21.148 2.359 4.4 4.567 6.347 6.787 10.821 8.041 16.2 5.445 28.129 4.364 46.234-2.536 42.462-17.093 67.191-45.089 98.861-22.93 25.94-39.997 39.602-72.724 50.169-11.252 3.633-17.795 5.548-29.574 6.394-22.742 1.634-36.427-2.292-57.209-11.804-19.985-9.148-29.729-18.066-45.089-33.938-11.726-12.118-19.627-18.804-26.18-34.429-5.147-12.271-5.09-20.222-6.788-33.446-2.983-23.237-5.085-37.147 0-60.005 2.835-12.743 5.911-19.547 11.151-31.479 10.113-23.024 15.639-37.545 33.938-54.595 19.457-18.13 34.857-24.487 60.603-30.495 16.105-3.757 42.18-3.442 42.18-3.442Z" + id="path17" /> + d="M243.947 70.007s13.077.594 21.332 1.967c20.21 3.362 31.687 7.368 49.452 17.706 20.24 11.779 27.635 22.135 40.24 40.333 5.034 7.267 8.422 13.347 12.606 21.148 2.359 4.4 4.567 6.347 6.787 10.821 8.041 16.2 5.444 28.129 4.364 46.234-2.536 42.462-17.093 67.191-45.089 98.861-22.93 25.94-39.997 39.602-72.724 50.169-11.252 3.633-17.795 5.548-29.574 6.394-22.742 1.634-36.427-2.292-57.209-11.804-19.985-9.148-29.729-18.066-45.089-33.938-11.726-12.118-19.627-18.804-26.18-34.429-5.147-12.271-5.09-20.222-6.788-33.446-2.983-23.237-5.085-37.147 0-60.005 2.835-12.743 5.911-19.547 11.151-31.479 10.113-23.024 15.639-37.545 33.938-54.595 19.457-18.13 34.857-24.487 60.603-30.495 16.105-3.757 42.18-3.442 42.18-3.442Z" + id="path18" /> + d="M270 429.497s6.998-.707 10.909-.435c3.822.266 9.091 1.726 9.091 1.726l-1.364 10.319L270 451zm67-2.161s6.089-1.578 10-1.304c3.822.268 10 2.604 10 2.604l-.909 11.694L337 449z" + id="path19" /> + d="M271.467 445.627v5.738s.691-4.235 2.648-5.738c1.042-.8 2.088-.477 3.09-1.324.949-.803.826-1.835 1.766-2.649.874-.757 1.536-1.006 2.648-1.324 1.658-.474 2.724-.338 4.414 0 1.069.214 2.649.883 2.649.883s1.572 1.421.883 1.765c-.309.155-.883 0-.883 0s-1.574-.699-2.649-.882c-1.189-.204-2.207-.003-3.09 0-.882.003-1.117.296-1.324.882-.115.325 0 .883 0 .883v1.324l-3.531 1.325-2.207 2.648-3.973 4.856-.883 1.324v.438l.442 5.297s.441 1.766 2.207 1.766 3.09-.883 3.09-.883l10.594.883 11.918 5.297s8.386 1.324 9.711 1.324c1.324 0-4.856-2.207-4.856-2.207v-2.649h8.387v1.766h3.09l1.324-.883s2.168-.714 3.531-.441c1.927.385 3.053 1.353 3.973 3.09 1.048 1.98.658 3.596 0 5.738-.759 2.472-3.973 5.297-3.973 5.297l-14.125 3.531H294.42l-25.16-2.648-6.18-1.766v-9.27s1.766-2.207 3.973-1.324 9.189 6.284 16.773 10.594l21.188 1.766 11.918-3.973v-3.531l-6.621 2.648h-9.27v-.883l-14.125-7.945s-3.09-1.324-4.414-.883c-1.277.426-1.074 1.922-2.207 2.649-2.032 1.302-6.18 0-6.18 0s-1.97-.639-3.09-1.325c-.735-.449-1.765-1.324-1.765-1.324v-9.711l-.883-2.204v-7.062z" + id="path20" /> + d="m263.08 469.024 5.297-15.891.883 2.648v9.711l9.711 3.09s2.207-3.973 3.972-3.973 2.446.741 3.973 1.325c5.993 2.29 14.125 8.386 14.125 8.386.883 1.325 5.411.931 8.828.442 2.861-.41 4.414-1.766 7.063-2.207 2.648-.442 4.414.883 0 3.531s-7.042 3.49-11.918 4.414c-8.342 1.581-13.611.586-21.629-2.207-7.679-2.675-17.656-11.035-17.656-11.035z" + id="path21" /> + d="M281.177 453.124s-3.531-.44-6.18-.44 3.09-6.181 3.09-6.181 3.532-1.764 4.856-1.323c1.325.441 13.683 10.592 13.683 10.592s1.766 1.528 3.09.883c1.429-.695.442-3.088 1.325-3.088s7.503 4.416 6.179 6.18-12.358 1.324-14.566 0c-2.207-1.324-11.477-6.623-11.477-6.623" + id="path22" /> + d="M281.619 457.538s-8.828-2.648-9.711-3.09-1.324 3.532-1.324 3.532c3.103 1.896 4.414 3.972 7.945 4.855s4.971 1.531 7.504.442c1.362-.586 2.041-1.296 2.649-2.649.494-1.101 0-3.531 0-3.531l-4.856-2.648s.622 2.026 0 2.648c-.621.622-2.207.441-2.207.441" + id="path23" /> + d="m337.236 448.715-1.324-4.414-2.207 5.297 2.207 2.648 4.414-5.297 7.946-3.972-8.829 1.324zm-8.386 15.449.882 1.766-.882-2.207 11.476 11.918 11.035 3.09s10.787 2.673 17.657 1.765c2.984-.394 4.759-.528 7.504-1.765 2.049-.924 4.855-3.09 4.855-3.09l-.883-4.856-7.062 2.649s-6.18-.442-7.504-1.324-12.36-8.829-14.567-9.27-11.035 1.324-11.035 1.324l-5.297-1.324v-4.856h.883l1.324 2.207 4.414-1.324 9.711 1.324 15.891 7.946 9.27.883-7.504-2.207-.883-2.649h5.297l5.738 2.649s4.092-1.211 6.18 0c1.375.797 2.004 1.636 2.648 3.089.908 2.049.832 3.658 0 5.739-1.295 3.241-7.504 4.855-7.504 4.855s-11.266 1.838-18.539 1.766c-13.929-.139-34.871-7.504-34.871-7.504v-5.738z" + id="path24" /> + d="m329.732 465.93-.882-1.766-1.766 4.856v5.738s20.942 7.365 34.871 7.504c7.273.072 18.539-1.766 18.539-1.766s6.209-1.614 7.504-4.855c.832-2.081.908-3.69 0-5.739-.644-1.453-1.273-2.292-2.648-3.089-2.088-1.211-6.18 0-6.18 0l-5.738-2.649h-5.297l.883 2.649 7.504 2.207-9.27-.883-15.891-7.946-9.711-1.324-4.414 1.324-1.324-2.207h-.883v4.856l5.297 1.324s8.828-1.765 11.035-1.324 13.243 8.387 14.567 9.27 7.504 1.324 7.504 1.324l7.062-2.649.883 4.856s-2.806 2.166-4.855 3.09c-2.745 1.237-4.52 1.371-7.504 1.765-6.87.908-17.657-1.765-17.657-1.765l-11.035-3.09m-10.594-9.711 10.594 9.711m-10.594-9.711-.882-2.207 11.476 11.918m-4.414-31.34 1.324 4.414 2.207-4.414 8.829-1.324-7.946 3.972-4.414 5.297-2.207-2.648z" + id="path25" /> + d="M301.481 453.124c-.441-1.324-6.621-7.945-8.828-8.828s-8.291 1.766-7.946 2.207 1.325.883 1.325.883 4.549-2.467 6.621-.883c.387.296 1.324.883.883.883s-6.256.979-5.739 1.324l1.325.883c.517.345 6.621-.883 6.621-.883l1.324 1.766-5.738 1.324s.441 1.766 1.324 1.324 5.297-1.324 5.297-1.324l2.207 3.973s1.765-1.324 1.324-2.649m65.783-1.142c-.441-1.324-6.621-7.946-8.828-8.828-2.207-.883-8.747.703-8.401 1.144.345.441 1.78 1.946 1.78 1.946s4.549-2.468 6.621-.883c.387.296 2.221.883.883.883s-6.711.359-6.194.703c.517.345 1.263 1.159 1.78 1.504.517.344 6.607-.181 6.607-.181l.441.442-5.738.883s1.338 2.828 2.221 2.387c.883-.442 4.4-1.063 4.4-1.063l2.207 3.972s2.663-1.585 2.221-2.909" + id="path26" /> + d="m329.289 465.926 4.856-17.215 1.765 3.531-.883 10.594 5.739 1.324s3.972-.883 5.738-.883 3.328-.583 4.855 0c5.993 2.291 14.126 8.829 14.126 8.829.882 1.324 4.809 1.572 7.945 1.324 2.88-.228 1.766 0 7.062-2.207s.883 4.414.883 4.414-3.065 2.222-5.297 3.09c-2.773 1.078-7.504 1.324-7.504 1.324s-15.376.144-23.394-2.649c-7.679-2.674-15.891-11.476-15.891-11.476" + id="path27" /> + d="M346.504 454.929s-8.828-2.649-9.711-3.09-1.324 3.531-1.324 3.531c3.103 1.896 4.414 3.973 7.945 4.856 3.531.882 4.97 1.531 7.504.441 1.362-.586 2.04-1.296 2.648-2.648.495-1.101 0-3.531 0-3.531l-4.855-2.649s.622 2.027 0 2.649-2.207.441-2.207.441" + id="path28" /> - - - - - - + d="M346.488 451.932s-3.391-.492-5.934-.492 2.967-6.907 2.967-6.907 3.391-1.97 4.663-1.477 12.886 10.956 12.886 10.956 1.949 2.586 3.221 1.866c1.372-.777.424-3.45 1.272-3.451s7.205 4.935 5.934 6.905c-1.272 1.971-11.868 1.48-13.988.001s-11.021-7.401-11.021-7.401" + id="path29" /> + - - - + d="M40.679 365.665c-.363.176-.589.272-.589.272s.222-.11.589-.272m26.037-13.306c1.524-.795 3.157-3.029 3.157-3.029s-1.964 1.43-3.157 3.029" + id="path35" /> + d="m270 429.5 1-22c9.561 3.548 14.546 3.506 23 2.5l-4 21c-8.675-1.699-12.931-1.917-20-1.5m67 .5-3-23.5c9.561 3.548 17.046-.494 25.5-1.5l-2.5 26.5c-8.675-1.699-12.931-1.917-20-1.5" + id="path37" /> + d="m212.127 314.291-.621-.162-.005.642.5.004-.5-.004v.003l-.001.007v.14a74 74 0 0 0 .027 1.985c.033 1.32.105 3.152.264 5.199.315 4.076.974 9.067 2.368 12.553 2.306 5.767 4.56 8.818 9.036 13.132 3.349 3.228 7.959 5.251 12.945 6.483 4.99 1.234 10.395 1.685 15.373 1.742 4.981.056 9.549-.282 12.871-.634 1.662-.176 3.013-.356 3.95-.491q.53-.078.877-.133v48.654c0 2.403 1.974 3.932 4.363 4.909 2.423.991 5.496 1.515 8.149 1.808 2.988.329 6.336.61 9.147.063 2.837-.553 5.219-1.974 6.08-5.092 3.169-11.479 3.56-25.535 3.166-36.694a222 222 0 0 0-.937-13.929 177 177 0 0 0-.55-4.875l27.325 4.999 3.596 16.746 2.621 33.659.021.27.238.13.239-.439-.239.439.002.001.006.003.021.012.082.043q.107.058.312.164a55 55 0 0 0 5.103 2.296c3.144 1.223 7.167 2.427 10.486 2.206 2.714-.181 5.931-1.38 8.432-2.507a54 54 0 0 0 4.045-2.035l.246-.14.065-.038.017-.009.004-.003.002-.001-.253-.431.253.431.27-.158-.025-.312-3.671-46.637v-.003l-.001-.01v-.001l-.002-.035-.008-.14q-.011-.186-.036-.534c-.035-.462-.09-1.13-.175-1.955a78 78 0 0 0-.942-6.448c-.955-5.016-2.677-11.081-5.763-15.001-3.749-4.763-10.663-8.821-16.571-11.674a111 111 0 0 0-10.062-4.248q-.424-.153-.651-.232l-.171-.059-.044-.015-.011-.004-.003-.001h-.001l-.158.465.158-.465-.008-.003-35.676-11.403-.95-.304.325.943c.147.429-.002 1.06-.774 1.907-.756.827-2.012 1.745-3.753 2.678-3.475 1.862-8.773 3.73-15.535 5.069-13.516 2.678-32.807 3.231-54.888-2.526Z" + id="path38" /> - + d="M287 326.069s3.226-.588 6.858 1.675c4.736 2.95 5.679 22.816 6.642 37.756.565 8.769 0 22.5 0 22.5s-1 15.5-3.5 19-5.5 3-5.5 3" + id="path39" /> + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - diff --git a/client/src/assets/icons/cur-landing-started-advanced.svg b/client/src/assets/icons/cur-landing-started-advanced.svg index c41d6f1b6629..5f826f0a369b 100644 --- a/client/src/assets/icons/cur-landing-started-advanced.svg +++ b/client/src/assets/icons/cur-landing-started-advanced.svg @@ -1,11 +1,25 @@ - - - - - + + - - - + + + + - + + + + + diff --git a/client/src/assets/icons/cur-landing-started-beginner.svg b/client/src/assets/icons/cur-landing-started-beginner.svg index 66a48795c263..7482b3b7ab09 100644 --- a/client/src/assets/icons/cur-landing-started-beginner.svg +++ b/client/src/assets/icons/cur-landing-started-beginner.svg @@ -1,13 +1,25 @@ - - - - - + + - - - + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-started-educator.svg b/client/src/assets/icons/cur-landing-started-educator.svg index 5b58a19e4c2f..0875580d6316 100644 --- a/client/src/assets/icons/cur-landing-started-educator.svg +++ b/client/src/assets/icons/cur-landing-started-educator.svg @@ -1,13 +1,25 @@ - - - - - + + - - - + + + + + + + + diff --git a/client/src/assets/icons/cur-landing-started-employment.svg b/client/src/assets/icons/cur-landing-started-employment.svg index 5cfad955e8dc..7782a007ebef 100644 --- a/client/src/assets/icons/cur-landing-started-employment.svg +++ b/client/src/assets/icons/cur-landing-started-employment.svg @@ -1,13 +1,25 @@ - - - - - + + - - - + + + + + + + + diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index e758d83f5d47..03dec582839c 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -10,6 +10,7 @@ > header, > section { margin: 0 auto 3rem; + margin-bottom: 4rem; max-width: min(var(--max-width), 74rem); padding-left: var(--gutter); padding-right: var(--gutter); @@ -40,6 +41,14 @@ > svg { width: 40%; z-index: 1; + + #icons-bg { + fill: var(--cur-bg-color); + } + + .laptop { + fill: var(--cur-color); + } } > section { @@ -94,6 +103,7 @@ h2 { grid-area: h2; margin: 1rem 0 0; + text-align: center; } > div { @@ -270,16 +280,19 @@ } } - #don’t_know_where_to_start { + #don’t_know_where_toget_started { line-height: 3rem; margin: 1rem auto 5rem; text-align: center; - text-decoration-color: var(--cur-color); - text-decoration-line: underline; - text-decoration-thickness: 0.25rem; - text-underline-offset: 1rem; width: fit-content; + &::after { + content: url("../assets/icons/cur-started-underline.svg"); + position: absolute; + transform: translate3d(-6em, 1.25rem, 0); + width: 6em; + } + ~ div { > ul { display: grid; @@ -322,19 +335,35 @@ } &:nth-child(1)::before { - content: url("../assets/icons/cur-landing-started-beginner.svg"); + content: url("../assets/icons/cur-landing-started-beginner.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-started-beginner.svg#dark"); + } } &:nth-child(2)::before { - content: url("../assets/icons/cur-landing-started-advanced.svg"); + content: url("../assets/icons/cur-landing-started-advanced.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-started-advanced.svg#dark"); + } } &:nth-child(3)::before { - content: url("../assets/icons/cur-landing-started-employment.svg"); + content: url("../assets/icons/cur-landing-started-employment.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-started-employment.svg#dark"); + } } &:nth-child(4)::before { - content: url("../assets/icons/cur-landing-started-educator.svg"); + content: url("../assets/icons/cur-landing-started-educator.svg#light"); + + .dark & { + content: url("../assets/icons/cur-landing-started-educator.svg#dark"); + } } h3 { diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index c8aa5cede0c8..01e52a3166ea 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -27,12 +27,10 @@ ol.modules-list-list { display: grid; grid-template-areas: - "a" - "b" - "c" - "hr" - "mod" - "t"; + "a b c" + "hr hr hr" + "mod mod mod" + "t t t"; grid-template-columns: auto; margin: 0; From 32631196bcdfee3b1f0a1f24aa6b1cff0c60378f Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 7 Feb 2024 13:33:22 +0100 Subject: [PATCH 064/102] minor --- client/src/curriculum/landing.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 03dec582839c..9f8d1fd4ef16 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -314,6 +314,7 @@ align-items: center; display: grid; gap: 1rem; + color: var(--text-secondary); @media screen and (min-width: $screen-sm) { align-items: start; gap: 1rem 2rem; @@ -369,6 +370,7 @@ h3 { font-weight: var(--font-body-strong-weight); margin-top: 0; + color: var(--text-primary); } a { From dc9dbc44e236b7c9ea047e14828097be526aa422 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 7 Feb 2024 14:22:27 +0100 Subject: [PATCH 065/102] reuse layout --- .../assets/icons/cur-started-underline.svg | 5 + client/src/curriculum/index.scss | 119 ------------------ client/src/curriculum/landing.scss | 6 +- client/src/curriculum/layout.tsx | 21 ++-- .../src/document/organisms/sidebar/index.tsx | 14 ++- 5 files changed, 26 insertions(+), 139 deletions(-) create mode 100644 client/src/assets/icons/cur-started-underline.svg diff --git a/client/src/assets/icons/cur-started-underline.svg b/client/src/assets/icons/cur-started-underline.svg new file mode 100644 index 000000000000..e1e1be93ce51 --- /dev/null +++ b/client/src/assets/icons/cur-started-underline.svg @@ -0,0 +1,5 @@ + + + diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 61d2c5f72881..f43eaa6a3ae8 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -183,124 +183,5 @@ margin: 0.5rem 0; } } - @media screen and (min-width: $screen-md) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - padding-left: 1.5rem; - padding-right: 3rem; - } - - @media screen and (min-width: $screen-xl) { - display: grid; - gap: 3rem; - grid-template-areas: "sidebar main toc"; - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 15rem); - padding-left: 1rem; - padding-right: 1rem; - - .toc { - --offset: var(--sticky-header-with-actions-height); - - display: block; - grid-area: toc; - height: fit-content; - padding-bottom: 0; - } - - .in-nav-toc { - display: none; - } - } - - .sidebar-container { - --offset: var(--sticky-header-with-actions-height); - --max-height: calc(100vh - var(--offset)); - - max-height: var(--max-height); - position: sticky; - top: var(--offset); - z-index: var(--z-index-sidebar-mobile); - - > .curriculum-sidebar { - align-self: start; - grid-area: sidebar; - - li li { - margin-left: 1rem; - } - } - - &.toc-container, - .toc-container { - grid-area: toc; - - .place { - grid-area: toc; - margin: 0; - } - @media screen and (min-width: $screen-xl) { - display: flex; - flex-direction: column; - gap: 0; - height: calc(100vh - var(--offset)); - mask-image: linear-gradient( - to bottom, - rgba(0, 0, 0, 0) 0%, - rgb(0, 0, 0) 3rem calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - overflow: auto; - position: sticky; - top: var(--offset); - - .place { - margin: 1rem 0; - padding-bottom: 3rem; - } - } - } - - @media screen and (min-width: $screen-md) and (min-height: $screen-height-place-limit) { - display: flex; - flex-direction: column; - } - - @media screen and (min-width: $screen-md) { - z-index: auto; - - .curriculum-sidebar { - mask-image: linear-gradient( - to bottom, - rgb(0, 0, 0) 0% calc(100% - 3rem), - rgba(0, 0, 0, 0) 100% - ); - } - - @media screen and not (min-height: $screen-height-place-limit) { - overflow: auto; - } - } - - @media screen and (max-width: #{$screen-md - 1}) { - .toc-container { - display: none; - } - } - - @media screen and (min-width: #{$screen-md}) { - #sidebar-quicklinks { - display: none; - } - } - @media screen and (min-width: $screen-xl) { - display: contents; - - .sidebar { - mask-image: none; - } - } - } } } diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 9f8d1fd4ef16..56cdd30d653b 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -10,7 +10,6 @@ > header, > section { margin: 0 auto 3rem; - margin-bottom: 4rem; max-width: min(var(--max-width), 74rem); padding-left: var(--gutter); padding-right: var(--gutter); @@ -52,6 +51,7 @@ } > section { + margin-bottom: 4rem; margin-right: auto; min-width: min(30rem, 90vw); padding-right: 1rem; @@ -312,9 +312,9 @@ > li { align-items: center; + color: var(--text-secondary); display: grid; gap: 1rem; - color: var(--text-secondary); @media screen and (min-width: $screen-sm) { align-items: start; gap: 1rem 2rem; @@ -368,9 +368,9 @@ } h3 { + color: var(--text-primary); font-weight: var(--font-body-strong-weight); margin-top: 0; - color: var(--text-primary); } a { diff --git a/client/src/curriculum/layout.tsx b/client/src/curriculum/layout.tsx index b47e0ba627fe..1d116174f81d 100644 --- a/client/src/curriculum/layout.tsx +++ b/client/src/curriculum/layout.tsx @@ -34,16 +34,18 @@ export function CurriculumLayout({ className={[ "curriculum-content-container", "container", - ...(withSidebar ? ["with-sidebar"] : []), + ...(withSidebar ? ["with-sidebar", "main-wrapper"] : []), ...extraClasses, ].join(" ")} > - {withSidebar && ( + {withSidebar && doc.sidebar && (
        - - {doc.sidebar && ( - - )} + +
        {PLACEMENT_ENABLED && }
        - {doc.sidebar && ( - - )}
        )}
        diff --git a/client/src/document/organisms/sidebar/index.tsx b/client/src/document/organisms/sidebar/index.tsx index c908134b2ea1..283acccff216 100644 --- a/client/src/document/organisms/sidebar/index.tsx +++ b/client/src/document/organisms/sidebar/index.tsx @@ -14,10 +14,12 @@ export function SidebarContainer({ doc, label, children, + tocTitle, }: { doc: any; label?: string; children: React.ReactNode; + tocTitle?: string; }) { const { isSidebarOpen, setIsSidebarOpen } = useUIStatus(); const [classes, setClasses] = useState("sidebar"); @@ -65,12 +67,16 @@ export function SidebarContainer({ aria-label="Collapse sidebar" />
        @@ -75,7 +86,7 @@ function About({ section }) { const { title, content, titleAsText, id } = section.value; const html = useMemo(() => ({ __html: content }), [content]); return ( -
        +
        diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index e4331f73948d..0e90bce6ea37 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -57,8 +57,16 @@ display: contents; > input:checked + label::before { + height: 0; position: absolute; transform: translate3d(-0.75rem, 0.75rem, 0); + width: 0; + } + + > input:checked:focus-visible + label { + outline-color: var(--accent-primary); + outline-offset: 1px; + outline-style: auto; } > label { @@ -73,7 +81,7 @@ } > input:checked + label::before { - content: url("../assets/icons/cur-modules-underline-1.svg"); + content: url("../assets/icons/cur-modules-underline.svg#1"); } } @@ -87,7 +95,7 @@ } > input:checked + label::before { - content: url("../assets/icons/cur-modules-underline-2.svg"); + content: url("../assets/icons/cur-modules-underline.svg#2"); } } @@ -101,7 +109,7 @@ } > input:checked + label::before { - content: url("../assets/icons/cur-modules-underline-3.svg"); + content: url("../assets/icons/cur-modules-underline.svg#3"); } } @@ -130,21 +138,9 @@ overflow: scroll; padding: 0; scroll-snap-type: inline mandatory; - @media screen and (min-width: $screen-sm) { - grid-template-columns: 1fr 1fr; - } - @media screen and (min-width: $screen-md) { - grid-template-columns: 1fr 1fr; - } - @media screen and (min-width: $screen-xxl) { - grid-template-columns: 1fr 1fr 1fr; - } - @container module-list (width >= 25rem) { - grid-template-columns: 1fr 1fr; - } - @container module-list (width >= 38rem) { - grid-template-columns: 1fr 1fr 1fr; + :focus-visible { + outline-offset: -2px; } .module-list-item { @@ -172,9 +168,23 @@ height: 10rem; padding: 1rem 2rem; - .topic-icon { + .dark & { + background-color: var(--cur-bg-color-grey); + } + + svg.topic-icon { height: 4rem; width: 4rem; + + .dark & { + circle { + fill: var(--cur-bg-color-topic); + } + + path { + fill: #000; + } + } } > span { @@ -203,9 +213,26 @@ p:last-child { color: var(--cur-color-topic); + font-weight: 600; } } } + @media screen and (min-width: $screen-sm) { + grid-template-columns: 1fr 1fr; + } + @media screen and (min-width: $screen-md) { + grid-template-columns: 1fr 1fr; + } + @media screen and (min-width: $screen-xxl) { + grid-template-columns: 1fr 1fr 1fr; + } + + @container module-list (width >= 25rem) { + grid-template-columns: 1fr 1fr; + } + @container module-list (width >= 38rem) { + grid-template-columns: 1fr 1fr 1fr; + } } } } diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 061960315da5..497f4d74b179 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -13,7 +13,7 @@ export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) {
        {modules.map((c, i) => { return ( -
      4. +
      5. { return (
      6. diff --git a/client/src/curriculum/sidebar.tsx b/client/src/curriculum/sidebar.tsx index 47c08dcf5430..8b4fa202f782 100644 --- a/client/src/curriculum/sidebar.tsx +++ b/client/src/curriculum/sidebar.tsx @@ -17,13 +17,13 @@ export function Sidebar({ >
          {sidebar.map((o, i) => ( -
        1. +
        2. {o.children && (
            {o.children.map((c, j) => { return ( -
          1. +
          2. Date: Fri, 9 Feb 2024 16:08:20 +0100 Subject: [PATCH 069/102] landing grid --- client/src/curriculum/landing.scss | 51 ++++++++++++++++++------- client/src/curriculum/landing.tsx | 2 +- client/src/curriculum/modules-list.scss | 18 +++++---- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 7684e5c38bfa..8ffca0931b50 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -18,6 +18,7 @@ } .curriculum-content { + padding-top: 0; ol.modules-list { @media screen and (min-width: $screen-sm) { grid-template-columns: 1fr 1fr; @@ -32,16 +33,23 @@ } header.landing-header { - display: flex; - flex-direction: row-reverse; - flex-wrap: wrap-reverse; - justify-content: space-between; + display: grid; + grid-template-areas: "copy" "svg"; + @media screen and (min-width: $screen-md) { + grid-template-areas: "copy svg"; + grid-template-columns: 30rem auto; + } > svg { + grid-area: svg; z-index: 1; width: 100%; - @media screen and (min-width: $screen-sm) { - width: 40%; + max-width: 28rem; + justify-self: end; + align-self: end; + margin-bottom: 3rem; + @media screen and (min-width: $screen-md) { + margin-bottom: 0; } #icons-bg { @@ -57,20 +65,32 @@ } > section { - margin-bottom: 4rem; + grid-area: copy; + @media screen and (min-width: $screen-md) { + margin-bottom: 4rem; + } + margin-top: 3rem; margin-right: auto; - min-width: min(30rem, 90vw); padding-right: 1rem; - width: 30rem; + max-width: 30rem; h1 { color: var(--cur-color-topic); - margin-bottom: 1rem; + font-size: 2rem; + margin-bottom: 0.5rem; + @media screen and (min-width: $screen-md) { + font-size: 2.5rem; + } } h2 { - margin-bottom: 2rem; - margin-top: 1rem; + font-size: 1.25rem; + margin-bottom: 1.5rem; + margin-top: 0.5rem; + @media screen and (min-width: $screen-md) { + font-size: 2rem; + margin-bottom: 2rem; + } } p { @@ -119,7 +139,6 @@ display: contents; ul { - align-items: center; background-color: var(--background-primary); border-radius: var(--elem-radius); box-shadow: var(--module-shadow); @@ -133,9 +152,13 @@ transform: translateY(-1rem); color: var(--text-secondary); width: 100%; + align-items: start; @media screen and (min-width: $screen-sm) { - justify-content: start; gap: 1rem; + align-items: center; + } + @media screen and (min-width: $screen-md) { + justify-content: start; } @media screen and (min-width: $screen-lg) { justify-content: center; diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index a63f38ff466c..b51d72e496ae 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -72,12 +72,12 @@ function Header({ section, h1 }: { section: any; h1?: string }) { ); return (
            -

            {h1}

            {section.value.title}

            +
            ); } diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 0e90bce6ea37..645519a01bc5 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -47,7 +47,7 @@ hr { border: none; - border-top: 1px solid var(--text-secondary); + border-top: 1px solid var(--text-inactive); grid-area: hr; margin: 0 0 1.5rem; width: 100%; @@ -56,11 +56,15 @@ li { display: contents; - > input:checked + label::before { - height: 0; - position: absolute; - transform: translate3d(-0.75rem, 0.75rem, 0); - width: 0; + > input:checked + label { + color: var(--text-primary); + + &::before { + height: 0; + position: absolute; + transform: translate3d(-0.75rem, 0.75rem, 0); + width: 0; + } } > input:checked:focus-visible + label { @@ -70,7 +74,7 @@ } > label { - color: var(--text-secondary); + color: var(--text-inactive); cursor: pointer; } From 7c3dabb1f66bb03dd026bfc05f4ee2428a4d6529 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 9 Feb 2024 16:11:25 +0100 Subject: [PATCH 070/102] svgo --- .../curriculum/cur-landing-ladder-1.svg | 78 ++--- .../curriculum/cur-landing-ladder-2-small.svg | 79 ++--- .../curriculum/cur-landing-ladder-2.svg | 10 +- .../assets/curriculum/cur-landing-ladder.svg | 287 +++++++----------- .../assets/curriculum/cur-landing-top.svg | 228 ++++++-------- .../assets/curriculum/cur-topic-practices.svg | 9 +- .../assets/curriculum/cur-topic-scripting.svg | 9 +- .../assets/curriculum/cur-topic-standards.svg | 9 +- .../assets/curriculum/cur-topic-styling.svg | 9 +- .../assets/curriculum/cur-topic-tooling.svg | 9 +- 10 files changed, 288 insertions(+), 439 deletions(-) diff --git a/client/public/assets/curriculum/cur-landing-ladder-1.svg b/client/public/assets/curriculum/cur-landing-ladder-1.svg index 18731256fea5..7488a0ec1f51 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-1.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-1.svg @@ -1,68 +1,54 @@ - - - + + - - - + d="M87.786 315.778c1.482-2.222.988-2.778.988-2.778h8.398s-.317 3.08 0 5c.302 1.822 1.24 2.611 1.483 4.444.17 1.288.683 2.283 0 3.334-.614.943-2.47 1.111-2.47 1.111H78.892v-5.556s7.41-3.333 8.893-5.555M74.446 328v-5s-1.634.417-2.47 1.111c-1.118.93-1.976 3.333-1.976 3.333zm60.054-10c1.5-2 .5-5 .5-5h9s.678 1.772 1 3.5c.305 1.64 0 3.5 3.5 6 .953.681 1.192 3.055.5 4-.621.849-2.5 1-2.5 1l-19.5.5v-5.5s6-2.5 7.5-4.5m-10 10.5V324s-1.654.375-2.5 1c-1.132.837-2 3-2 3zM111 135v-2.5l6.5-1.5.5 4h4.5s-4.657 7.172-7 6-5.157-4.828-7.5-6z" /> + + + d="m110.001 178.5-.056 10s12.055 4 13.556 3.5.499-.5.499-.5m3.5-10s1.502.5-.499 1-9 .5-9 .5M129 185s1.001.5-.499 1-10-.5-10-.5m8.5 2.5s1.001 1-1 1-8-1.5-8-1.5m-2.001-8s1.971-1.039 3-2c.914-.853 2-2.5 2-2.5" /> + d="M110.001 178.499s12.308-6.862 10.5-3c-.39.834-1.17 1.595-2 2.225-1.426 1.082-3 1.775-3 1.775l11.5 1.5s2.001 1 0 1.5-9 .5-9 .5l10.5 1.5s1.5 1 0 1.5-10-.5-10-.5l8 1.5s1.501 2-.5 2-8-1.5-8-1.5l6 3s1.001 1-.5 1.5-13.556-3.5-13.556-3.5z" /> + d="m161.025 143.251 7.477 8.749s11.828-6.866 12.777-8.339.098-.743.098-.743m-3.541-10.139s1.601-.715.228 1.122-7.316 6.936-7.316 6.936m10.641-6.495s1.176-.35.228 1.123-8.816 6.905-8.816 6.905m8.844-4.295s1.501.03-.197 1.488c-1.699 1.457-7.77 4.689-7.77 4.689" /> + d="M162.118 143.6s-5.011-10.514-1.118-8.593c1 .493 5.5 4.06 5.5 4.06l10-6.567s2.986-.795 1.724 1.068-6.871 7.099-6.871 7.099l9.438-6.76s1.885-.391 1.024 1.097-8.355 7.116-8.355 7.116l7.435-4.889s2.567.339.964 1.836-7.435 4.889-7.435 4.889l6.856-2.296s1.484-.018.623 1.47c-.862 1.489-13.402 8.359-13.402 8.359z" /> + d="M168.971 145.526s.054-2.064-.31-3.424c-.323-1.208-2.118-2.938-2.118-2.938M94 160.5v15" /> + d="M76.086 262.22c1.118-24.967 15.414-63.693 15.414-63.693s-1.43 4.472 21.043 4.473c22.474.001 24.971-5 24.971-5s-1.489 29.793 0 48.787C139.571 273.018 150 313 150 313h-30.964l-11.487-74.178-7.491 23.398 9.988 50.78H81.579s-6.386-30.854-5.493-50.78" /> - + d="M91.868 199.965S91.33 202.999 113.5 203s24.184-5 24.184-5-1.469 29.41 0 48.16C139.712 272.054 150 311.522 150 311.522m-67 1.475s8.404.007 13.794 0c5.583-.007 13.302 0 13.302 0L105.5 287l-5-25 7.625-23.703M109.5 178.5 87 175" /> + + d="M123.717 119.888c-3.144 9.028-3.194 10.114-11.196 13.124-7.143-2.463-10.287-3.282-11.144-13.679 2.286-10.394 8.633-14.958 15.103-14.958 4.001 1.915 9.895 5.721 7.237 15.513" /> - - + d="M109.547 124.211c2.6 1.916 4.159 2.476 7.228 1.95m-3.338-3.056h3.336l-.278-6.408c.434-.435.734-.946 1.112-1.393.47-.557.625-.595 1.112-.836 1.168-.577 3.336 0 3.336 0l.556 1.393m-15.569-.278s1.287-.859 2.224-1.115c1.257-.343 2.118-.463 3.337 0 .873.333 1.946 1.393 1.946 1.393m-11.61 10.387s3.125 5.772 9.107 6.33c1.209.112 3.059-.558 3.059-.558" /> + + - + clip-rule="evenodd" /> + - - + d="m70.61 326-.5 1 30.5-.5s.5 1.195.5 2-.5 2-.5 2h-31s-.385-.579-.5-1c-.154-.565-.139-.931 0-1.5.23-.949 1.5-2 1.5-2" /> + - - - + d="M124.61 323.5s-1.823.791-1 .5c.39-.138.924-1.515 2-2 1.513-.682 3.108-1 3.108-1l.002 8h-4.5z" /> + + + How can you - - boost your employability + + boost your employability - + with the MDN - + Curriculum? diff --git a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg index aba5188b78e0..909ea67b7805 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg @@ -1,75 +1,58 @@ - - + + + d="M72.627 394.5c-6.589 4-41.455 3.5-41.455 3.5v-3.5zm0 0c6.589-4 1.53-66.777 5.173-70.516 3.644-3.738 30.616-4.264 32.437-9.5 1.822-5.235 1.726-62.513 3.548-73 1.822-10.486 48.656-8.5 48.656-8.5 0-33.331 4.055-52 6.589-62.466s11.007-13.627 20.78-16.049c9.215-2.284 138.282 4.495 141.406 0" /> + d="M30.664 297.99s38.012-10.004 56.765-35.004c13.228-17.635 33.441-84.5 0-88.998-13.137-1.767-20.39 12.492-15.713 25.001 7.886 21.091 46.953 5.955 59.301-10.505 9.374-12.495 20.272-41.498 20.272-41.498m0 0-6.08 1.498m6.08-1.498 3.043 4.998" /> - - + d="M127.142 50.53c-8.362 15.957 12.26 20.065 3.898 36.021l205.822-44.627s-6.223-18.062-12.88-24.957c-12.772-13.23-26.142 13.422-40.277 4.558-7.163-4.492-16.059-9.16-23.088-14.175-17.206-12.278-21.821 2.704-40.577 1.678-13.647-.747-30.704-13.265-41.538 0-7.534 9.225-9.59 17.643-17.254 26.586-8.448 9.857-25.744-1.04-34.106 14.917" /> + + - - - - - + d="M259.486 39.148c-12.201-22.28-25.582 3.921-25.582 3.921V94s13.769-20.017 23.899-19.589c7.815.331 11.121 10.789 18.85 13.06 15.54 4.566 23.339-20.073 39.045-18.936 7.191.52 18.177 5.876 18.177 5.876l-13.464-24.159 10.771-16.324s-9.387-3.661-15.484-3.918c-15.78-.663-44.768 30.036-56.212 9.138" /> + + + + + + d="m185.173 51.79-1.624-2.071m17.865 17.403-.325 2.9m-33.132-5.386-2.273 2.9m76.007 19.476v3.314m0-20.303-3.248 2.9m-30.208 2.072 1.624 3.73" /> + d="M238.5 81.088c-5.506 3.548-10.388-1.257-16.84 0-1.663.324-3.158 1.558-3.158 1.558l-3.157-1.558s-3.31.288-5.263 1.038c-4.2 1.614-4.033 8.81-8.42 7.788-4.309-1.003-4.21-10.383-4.21-10.383l-7.368 3.634s1.684 15.872 8.946 16.094c5.682.174 11.052-9.345 11.052-9.345l-1.052 15.056 18.419 1.557-1.579-16.613s11.558.546 17.367-3.115c4.171-2.63 8.42-9.345 8.42-9.345l-6.841-4.673s-2.874 6.09-6.316 8.307" /> + d="m191.137 70.698-1.053 6.23v2.077l1.579 3.634 4.21-2.077v-.52l1.579-2.594-1.053-1.558h-2.105l1.579-4.672s-1.053-2.596-1.579-.52-2.105 5.191-2.105 5.191.526-3.635.526-5.191-1.578 0-1.578 0m55.784.519-.527 2.596 4.21 3.116s1.334-2.447 2.106-3.116c1.464-1.27 2.337-.167 3.683-1.558 1.987-2.053.77-4.215-.526-6.75-.593-1.158-2.946-1.193-4.21-1.556-1.248-.358-3.997.508-4.736 1.563-.702 1-.27 4.518 0 5.705" /> - + d="m177.451 116.422 4.211 3.634s-2.924 8.159-4.211 5.711c-.662-1.26 0-3.634 0-3.634s-2.765 3.876-5.262 3.634c-1.372-.133-3.158-1.558-3.158-1.558z" /> + - + d="m232.876 154.046-2.36-5.004s6.019-6.295 6.192-3.543c.089 1.417-1.49 3.324-1.49 3.324s4.119-2.441 6.303-1.223c1.2.669 2.249 2.684 2.249 2.684z" /> + - + d="m202.716 120.025 6.315-15.056 17.893 1.557 8.947 20.767 3.157 16.614-9.473 5.711-5.789-20.248-7.367-10.903-12.631 12.98-26.313-3.115 5.789-9.865z" /> + + d="M224.126 73.584c-.748 3.888-.685 4.325-4.193 6.26-3.545-.325-5.084-.363-6.32-4.429.237-4.353 2.844-6.755 5.876-7.35 2.029.397 5.096 1.372 4.637 5.52" /> + d="M218.131 77.164c1.066 1.13 2.513.32 3.442-.393z" /> + d="m219.565 75.803 1.564-.306-.689-1.671m.868-1.02c-.041-.201.178-.457.403-.66.307-.278.631-.542 1.002-.356.297.148.393.745.393.745m-6.583 1.21s.043-.485.462-.673c.561-.253.694-.328 1.302-.256.436.053.78.51.78.51m-4.168 4.694s1.928 2.014 4.775 1.686c.576-.066 1.389-.503 1.389-.503" /> + clip-rule="evenodd" /> + d="M215.347 81.099s-.526-.52-5.262 1.038c-4.737 1.558-2.632 5.194-6.316 7.269-3.683 2.074-5.789-4.675-5.789-4.675" /> + d="M192.98 70.204a.26.26 0 0 0-.517-.048zm-.785 5.687-.258-.024.502.114zm3.684-4.672.246.083.025-.073-.019-.074zM194.3 75.89l-.246-.083-.158.47.476-.138zm2.105 0 .128-.226zm-.526 4.153-.207-.156-.052.07v.087zm-3.416-9.888-.526 5.711.517.048.526-5.711zm-.268 5.735.244.09v-.001l.001-.003.005-.012.018-.048.067-.182.245-.653c.206-.543.485-1.271.78-2.016s.606-1.504.876-2.107c.134-.302.257-.562.361-.761.111-.211.184-.32.217-.352l-.364-.37c-.1.098-.207.28-.312.48-.112.213-.24.485-.377.791-.273.613-.587 1.38-.884 2.127a149 149 0 0 0-1.114 2.91l-.005.013-.001.003v.001zm2.814-6.045c.024-.024.016-.005-.015-.009-.017-.002-.005-.007.037.034.085.084.184.255.281.478.094.215.173.448.229.63.028.09.049.167.064.22l.017.063.004.016.001.003.001.001.251-.063.252-.064-.001-.002-.001-.005-.005-.019-.018-.068a7 7 0 0 0-.318-.919c-.1-.23-.231-.481-.393-.64a.6.6 0 0 0-.343-.18.5.5 0 0 0-.407.154zm.624 1.29-1.579 4.672.492.166 1.579-4.672zM194.3 75.89l.072.25h.001l.002-.001.01-.003.042-.011a5 5 0 0 1 .688-.128c.433-.05.884-.038 1.163.12l.255-.453c-.435-.245-1.036-.234-1.477-.183a6 6 0 0 0-.76.141l-.049.013-.013.004-.004.001h-.002zm1.978.226c.283.16.516.39.678.637.163.25.242.5.242.695h.52c0-.323-.126-.67-.328-.98a2.5 2.5 0 0 0-.857-.804zm.92 1.332v.003l-.001.01-.008.034q-.012.046-.039.115a3 3 0 0 1-.166.336 12 12 0 0 1-.531.848 26 26 0 0 1-.714 1.004l-.049.066-.013.017-.004.004v.001h-.001l.207.157.207.157.001-.001.004-.005.013-.018.051-.068a27 27 0 0 0 .729-1.023c.199-.295.401-.61.554-.888a4 4 0 0 0 .193-.392 1 1 0 0 0 .087-.357zm-1.578 2.596v.519h.519v-.52z" /> - + d="m209.035 105.5-6.315 14.537-19.472-1.558m68.42-41.01s-4.329 7.422-8.947 9.864c-2.291 1.212-6.315 2.077-6.315 2.077m14.726-25.45c.527 2.078-3.685 2.078-2.105 3.116s2.105 2.596 2.105 2.596" /> + - - + Get Guidance from trusted voices. diff --git a/client/public/assets/curriculum/cur-landing-ladder-2.svg b/client/public/assets/curriculum/cur-landing-ladder-2.svg index 348bdfc9d099..10e4057cef34 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2.svg @@ -6,7 +6,7 @@ + d="m834 100.328-1 6v2.001l1.5 3.499 4-2v-.5l1.5-2.499-1-1.5-2-.001 1.5-4.499s-1-2.5-1.5-.501-2 5-2 5 .5-3.5.5-5-1.5 0-1.5 0m53 .5-.5 2.5 4 3.002s1.267-2.357 2-3.001c1.392-1.223 2.221-.161 3.5-1.501 1.888-1.977.731-4.06-.5-6.5-.563-1.116-2.799-1.15-4-1.499-1.186-.345-3.797.49-4.5 1.505-.667.963-.256 4.351 0 5.494" /> @@ -26,19 +26,19 @@ clip-rule="evenodd" /> + d="M835.749 99.853a.25.25 0 0 0-.498-.046zM835 105.33l-.249-.023.484.108zm3.5-4.5.237.079.023-.069-.017-.071zm-1.5 4.5-.237-.079-.151.453.458-.134zm2 0 .124-.217zm-.5 4-.2-.15-.05.067v.083zm-3.249-9.523-.5 5.5.498.045.5-5.5zM835 105.33l.235.085v-.001l.001-.003.005-.011.016-.046.065-.175a138 138 0 0 1 .973-2.571 57 57 0 0 1 .832-2.03c.128-.291.245-.541.344-.732.105-.204.175-.309.205-.34l-.352-.353c-.095.094-.197.27-.297.463-.106.205-.228.466-.357.761-.26.591-.559 1.329-.84 2.049a138 138 0 0 0-.978 2.58l-.064.176-.017.046-.004.012-.002.003v.001zm2.676-5.823c.024-.023.015-.004-.018-.007-.018-.002-.007-.01.032.03.081.082.175.246.268.461a6 6 0 0 1 .278.82l.016.06.004.015.001.004v.001l.243-.061.243-.061h-.001v-.002l-.001-.005-.005-.018-.017-.065-.066-.226a7 7 0 0 0-.236-.659c-.095-.222-.22-.463-.373-.617a.56.56 0 0 0-.329-.174.47.47 0 0 0-.391.15zm.587 1.244-1.5 4.5.474.158 1.5-4.5zM837 105.33l.07.24h.001l.002-.001.009-.003.04-.01.15-.037c.129-.029.306-.063.503-.086.411-.048.838-.036 1.101.114l.248-.434c-.415-.237-.988-.226-1.407-.177a6 6 0 0 0-.555.095l-.167.041-.047.013-.013.003-.004.001-.001.001zm1.876.217a1.9 1.9 0 0 1 .643.612c.155.241.231.482.231.671h.5c0-.31-.119-.644-.311-.942a2.4 2.4 0 0 0-.815-.775zm.874 1.283v.003l-.001.01-.008.034a1 1 0 0 1-.038.11q-.054.137-.157.324c-.135.248-.318.538-.504.817a24 24 0 0 1-.679.967l-.047.063-.012.017-.003.004-.001.001.2.15.2.15v-.001l.001-.001.004-.004.012-.018.049-.065a30 30 0 0 0 .692-.986 12 12 0 0 0 .527-.855c.073-.133.137-.262.183-.377a1 1 0 0 0 .082-.343zm-1.5 2.5v.5h.5v-.5z" /> + d="m851 133.828-6 14-18.5-1.5m65-39.5s-4.113 7.148-8.5 9.5c-2.177 1.167-6 2-6 2m13.999-24.5c.501 2-3.501 2-2 3s2 2.5 2 2.5" /> - + + d="m849.18 61.525 2.768-.374-2.081 3.082zm46.179 4.372-3.953-2.153 5.589-2.04z" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - How can you boost + + + How can you boost + - - your employability + + your employability - - with the MDN + + with the MDN - - Curriculum? + + Curriculum? - - - Learn about research collaboration and other essential soft skills - - Balance between modern tooling and long-term best practices - + + Learn about research collaboration and other essential soft skills + Balance between modern tooling and long-term best practices Get access to hight-quality recommened resrouces - - + Get guidance from trusted voices diff --git a/client/public/assets/curriculum/cur-landing-top.svg b/client/public/assets/curriculum/cur-landing-top.svg index 39db255cd5f8..ac9e3efa170f 100644 --- a/client/public/assets/curriculum/cur-landing-top.svg +++ b/client/public/assets/curriculum/cur-landing-top.svg @@ -1,137 +1,95 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/public/assets/curriculum/cur-topic-practices.svg b/client/public/assets/curriculum/cur-topic-practices.svg index fb77081860aa..a25e0dbe0f8f 100644 --- a/client/public/assets/curriculum/cur-topic-practices.svg +++ b/client/public/assets/curriculum/cur-topic-practices.svg @@ -1,6 +1,5 @@ - - - + + + diff --git a/client/public/assets/curriculum/cur-topic-scripting.svg b/client/public/assets/curriculum/cur-topic-scripting.svg index aab342cdb780..706d7dca179b 100644 --- a/client/public/assets/curriculum/cur-topic-scripting.svg +++ b/client/public/assets/curriculum/cur-topic-scripting.svg @@ -1,6 +1,5 @@ - - - + + + diff --git a/client/public/assets/curriculum/cur-topic-standards.svg b/client/public/assets/curriculum/cur-topic-standards.svg index cd09db253b67..67d8810a284b 100644 --- a/client/public/assets/curriculum/cur-topic-standards.svg +++ b/client/public/assets/curriculum/cur-topic-standards.svg @@ -1,6 +1,5 @@ - - - + + + diff --git a/client/public/assets/curriculum/cur-topic-styling.svg b/client/public/assets/curriculum/cur-topic-styling.svg index 628ef89d8216..3782a9fcd4e2 100644 --- a/client/public/assets/curriculum/cur-topic-styling.svg +++ b/client/public/assets/curriculum/cur-topic-styling.svg @@ -1,6 +1,5 @@ - - - + + + diff --git a/client/public/assets/curriculum/cur-topic-tooling.svg b/client/public/assets/curriculum/cur-topic-tooling.svg index ef7b45bf0440..9639c697ed43 100644 --- a/client/public/assets/curriculum/cur-topic-tooling.svg +++ b/client/public/assets/curriculum/cur-topic-tooling.svg @@ -1,6 +1,5 @@ - - - + + + From fce8536dc858d261d73edcd449de2ba2be8494a9 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 9 Feb 2024 17:44:45 +0100 Subject: [PATCH 071/102] misc --- build/curriculum.ts | 15 ++-- .../curriculum/cur-landing-ladder-2-small.svg | 2 +- client/src/curriculum/landing.scss | 73 ++++++++++--------- client/src/curriculum/modules-list.scss | 12 ++- client/src/ui/base/_themes.scss | 5 +- 5 files changed, 63 insertions(+), 44 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index 1db5e24201be..031820eb494a 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -84,19 +84,19 @@ export async function buildModuleIndex( ): Promise { const index = await buildIndex(); - const s = index.reduce((sidebar, meta) => { + const s = index.reduce((item, meta) => { const currentLvl = meta.slug.split("/").length; - const last = sidebar.length ? sidebar[sidebar.length - 1] : null; + const last = item.length ? item[item.length - 1] : null; const entry = mapper(meta); if (currentLvl > 2) { if (last) { last.children.push(entry); - return sidebar; + return item; } } - sidebar.push({ children: [], ...entry }); - return sidebar; + item.push({ children: [], ...entry }); + return item; }, []); return s; @@ -201,7 +201,10 @@ async function readModule( sidebar = await buildSidebar(); parents = await buildParents(url); } else { - title = title.replace(/^\d+\s+/, "").replace(/ modules$/, ""); + title = title + .replace(/^\d+\s+/, "") // Strip number prefix. + .replace(/ modules$/, "") // Strip "modules" suffix. + .replace(/Extension \d+:/, ""); // Strip "Extension" prefix. } return { diff --git a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg index 909ea67b7805..c178c9ef1f33 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg @@ -1,4 +1,4 @@ - + diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 8ffca0931b50..140131702dd5 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -19,6 +19,7 @@ .curriculum-content { padding-top: 0; + ol.modules-list { @media screen and (min-width: $screen-sm) { grid-template-columns: 1fr 1fr; @@ -41,13 +42,13 @@ } > svg { + align-self: end; grid-area: svg; - z-index: 1; - width: 100%; - max-width: 28rem; justify-self: end; - align-self: end; margin-bottom: 3rem; + max-width: 28rem; + width: 100%; + z-index: 1; @media screen and (min-width: $screen-md) { margin-bottom: 0; } @@ -58,21 +59,22 @@ .laptop { fill: var(--cur-category-color); + .dark & { - fill: var(--cur-bg-large-color); + fill: var(--cur-bg-color-orange); } } } > section { grid-area: copy; + margin-right: auto; + margin-top: 3rem; + max-width: 30rem; + padding-right: 1rem; @media screen and (min-width: $screen-md) { margin-bottom: 4rem; } - margin-top: 3rem; - margin-right: auto; - padding-right: 1rem; - max-width: 30rem; h1 { color: var(--cur-color-topic); @@ -101,9 +103,6 @@ .landing-about-container { background-color: var(--cur-bg-large-color); - .dark & { - background-color: var(--cur-bg-color-grey); - } margin: 0; margin-top: -6rem; max-width: 100%; @@ -139,9 +138,11 @@ display: contents; ul { + align-items: start; background-color: var(--background-primary); border-radius: var(--elem-radius); box-shadow: var(--module-shadow); + color: var(--text-secondary); display: grid; grid-area: li; grid-template-columns: auto auto auto; @@ -150,12 +151,10 @@ min-height: 5rem; padding: 1rem; transform: translateY(-1rem); - color: var(--text-secondary); width: 100%; - align-items: start; @media screen and (min-width: $screen-sm) { - gap: 1rem; align-items: center; + gap: 1rem; } @media screen and (min-width: $screen-md) { justify-content: start; @@ -216,15 +215,15 @@ p { align-items: center; - display: grid; color: var(--text-secondary); + display: grid; grid-template-columns: auto auto; &::before { + align-self: start; display: block; height: 4rem; width: 4rem; - align-self: start; } &:nth-child(2) { @@ -279,6 +278,8 @@ > div { display: grid; grid-template-areas: "a" "b"; + grid-template-columns: auto; + grid-template-rows: auto auto; justify-content: center; margin: 0 auto 3rem; max-width: min(var(--max-width), 74rem); @@ -293,24 +294,29 @@ > svg { &:nth-child(1) { + font-size: 2rem; grid-area: a; transform: translateX(2vw); + width: 100%; } &:nth-child(2) { - grid-area: b; display: none; + grid-area: b; + transform: translateX(-5vw); + width: 100%; @media screen and (min-width: $screen-md) { display: initial; } - transform: translateX(-5vw); } + &:nth-child(3) { grid-area: b; + max-width: 100%; + width: 100%; @media screen and (min-width: $screen-md) { display: none; } - max-width: 100%; } #text29 { @@ -318,7 +324,7 @@ } text { - fill: var(--text-primary); + fill: var(--text-secondary); } .color { @@ -362,8 +368,9 @@ } > li { - scroll-snap-align: center; align-items: center; + background-color: var(--cur-bg-large-color); + border-radius: var(--elem-radius); color: var(--text-secondary); display: grid; gap: 1rem; @@ -371,27 +378,26 @@ "i h" "p p" "c c"; - grid-template-rows: 4rem minmax(7rem, max-content) max-content; grid-template-columns: 3rem 1fr; + grid-template-rows: 4rem minmax(7rem, max-content) max-content; height: max-content; - background-color: var(--cur-bg-large-color); padding: 1rem 0.5rem; - border-radius: var(--elem-radius); + scroll-snap-align: center; width: 80vw; @media screen and (min-width: $screen-md) { - width: initial; - background-color: initial; - padding: 0; align-items: start; + background-color: initial; gap: 1rem 2rem; grid-template-areas: "i h" "i p" "i c"; - grid-template-rows: 4rem auto max-content; grid-template-columns: auto auto; + grid-template-rows: 4rem auto max-content; height: initial; + padding: 0; + width: initial; } &::before { @@ -445,8 +451,8 @@ } em { - grid-area: p; align-self: start; + grid-area: p; } a { @@ -468,7 +474,10 @@ display: flex; font: var(--button-font); gap: 0.25rem; + + grid-area: c; justify-content: center; + justify-self: center; min-height: var(--button-height); padding: 0.5rem; padding-left: var(--button-padding); @@ -476,12 +485,10 @@ position: relative; text-align: center; width: fit-content; - - grid-area: c; - justify-self: center; @media screen and (min-width: $screen-md) { justify-self: start; } + &:hover { background-color: var(--button-bg-hover, var(--button-bg)); } diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 645519a01bc5..63186e7a4e99 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -120,7 +120,6 @@ > ol { grid-area: mod; margin: 0; - padding: 0; } > a { @@ -139,8 +138,12 @@ gap: 1rem; grid-template-columns: 1fr 1fr 1fr; margin: 0; + padding: 0.5rem; overflow: scroll; - padding: 0; + @media screen and (min-width: $screen-md) { + padding: 0; + overflow: inherit; + } scroll-snap-type: inline mandatory; :focus-visible { @@ -156,6 +159,11 @@ justify-self: center; max-width: 20rem; min-width: 15rem; + padding: 0; + overflow: auto; + @media screen and (min-width: $screen-md) { + min-width: initial; + } scroll-snap-align: center; width: 100%; diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index 265c34e55079..c3ae855083c2 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -436,14 +436,15 @@ --cur-color-topic-tooling: #ce93fa; --cur-color-topic-practices: #55ab2d; --cur-bg-color: #664b33; - --cur-bg-large-color: #b25c35; + --cur-bg-large-color: #343434; --cur-bg-color-topic-standards: #994b53; --cur-bg-color-topic-styling: #4e609e; --cur-bg-color-topic-scripting: #7d683d; --cur-bg-color-topic-tooling: #584280; --cur-bg-color-topic-practices: #3d7c4b; --cur-category-color: #e3642a; - --cur-bg-color-grey: #343434; + --cur-bg-color-grey: #1f1c1a; + --cur-bg-color-orange: #b25c35; color-scheme: dark; } From f9933510310d62878aba78c8350af133f524fdc5 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Fri, 9 Feb 2024 17:46:14 +0100 Subject: [PATCH 072/102] lint --- client/src/curriculum/modules-list.scss | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 63186e7a4e99..3bbbfde91314 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -138,13 +138,13 @@ gap: 1rem; grid-template-columns: 1fr 1fr 1fr; margin: 0; - padding: 0.5rem; overflow: scroll; + padding: 0.5rem; + scroll-snap-type: inline mandatory; @media screen and (min-width: $screen-md) { - padding: 0; overflow: inherit; + padding: 0; } - scroll-snap-type: inline mandatory; :focus-visible { outline-offset: -2px; @@ -159,13 +159,13 @@ justify-self: center; max-width: 20rem; min-width: 15rem; - padding: 0; overflow: auto; + padding: 0; + scroll-snap-align: center; + width: 100%; @media screen and (min-width: $screen-md) { min-width: initial; } - scroll-snap-align: center; - width: 100%; .dark & { background-color: #000; From 0b98b5241c5ea29a1afa0ea18934a9c1d062716b Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sat, 10 Feb 2024 16:14:02 +0100 Subject: [PATCH 073/102] dark mode fixes --- .../curriculum/cur-landing-ladder-2-small.svg | 4 +- .../icons/cur-landing-started-advanced.svg | 12 ++++ .../icons/cur-landing-started-beginner.svg | 12 ++++ .../icons/cur-landing-started-educator.svg | 12 ++++ .../icons/cur-landing-started-employment.svg | 12 ++++ client/src/curriculum/index.scss | 35 ++++++++++ client/src/curriculum/landing.scss | 62 +++-------------- client/src/curriculum/modules-list.scss | 33 +++------ client/src/ui/base/_themes.scss | 68 +++++++++++++++++++ 9 files changed, 172 insertions(+), 78 deletions(-) diff --git a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg index c178c9ef1f33..f4d7729fbe70 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg @@ -4,7 +4,7 @@ d="M72.627 394.5c-6.589 4-41.455 3.5-41.455 3.5v-3.5zm0 0c6.589-4 1.53-66.777 5.173-70.516 3.644-3.738 30.616-4.264 32.437-9.5 1.822-5.235 1.726-62.513 3.548-73 1.822-10.486 48.656-8.5 48.656-8.5 0-33.331 4.055-52 6.589-62.466s11.007-13.627 20.78-16.049c9.215-2.284 138.282 4.495 141.406 0" /> - @@ -46,7 +46,7 @@ - + diff --git a/client/src/assets/icons/cur-landing-started-advanced.svg b/client/src/assets/icons/cur-landing-started-advanced.svg index 5f826f0a369b..3797232321ea 100644 --- a/client/src/assets/icons/cur-landing-started-advanced.svg +++ b/client/src/assets/icons/cur-landing-started-advanced.svg @@ -5,10 +5,18 @@ --path: #E3642A; } + .small.light { + --circle: #FFF; + } + .dark { --circle: #B25C354D; --path: #E3642A; } + + .small.dark { + --circle: #000; + } @@ -22,4 +30,8 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-started-beginner.svg b/client/src/assets/icons/cur-landing-started-beginner.svg index 7482b3b7ab09..158aabe1761d 100644 --- a/client/src/assets/icons/cur-landing-started-beginner.svg +++ b/client/src/assets/icons/cur-landing-started-beginner.svg @@ -5,10 +5,18 @@ --path: #E3642A; } + .small.light { + --circle: #FFF; + } + .dark { --circle: #B25C354D; --path: #E3642A; } + + .small.dark { + --circle: #000; + } @@ -22,4 +30,8 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-started-educator.svg b/client/src/assets/icons/cur-landing-started-educator.svg index 0875580d6316..a76acc3f0b97 100644 --- a/client/src/assets/icons/cur-landing-started-educator.svg +++ b/client/src/assets/icons/cur-landing-started-educator.svg @@ -5,10 +5,18 @@ --path: #E3642A; } + .small.light { + --circle: #FFF; + } + .dark { --circle: #B25C354D; --path: #E3642A; } + + .small.dark { + --circle: #000; + } @@ -22,4 +30,8 @@ + + + + diff --git a/client/src/assets/icons/cur-landing-started-employment.svg b/client/src/assets/icons/cur-landing-started-employment.svg index 7782a007ebef..9750529fb3d4 100644 --- a/client/src/assets/icons/cur-landing-started-employment.svg +++ b/client/src/assets/icons/cur-landing-started-employment.svg @@ -5,10 +5,18 @@ --path: #E3642A; } + .small.light { + --circle: #FFF; + } + .dark { --circle: #B25C354D; --path: #E3642A; } + + .small.dark { + --circle: #000; + } @@ -22,4 +30,8 @@ + + + + diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index f43eaa6a3ae8..7061f55c838b 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -10,26 +10,61 @@ .topic-standards { --cur-bg-color-topic: var(--cur-bg-color-topic-standards); --cur-color-topic: var(--cur-color-topic-standards); + --cur-bg-color-list-item-header: var( + --cur-bg-color-list-item-topic-standards + ); + --cur-color-list-item-icon: var(--cur-color-list-item-icon-topic-standards); + --cur-bg-color-list-item-icon: var( + --cur-bg-color-list-item-icon-topic-standards + ); } .topic-styling { --cur-bg-color-topic: var(--cur-bg-color-topic-styling); --cur-color-topic: var(--cur-color-topic-styling); + --cur-bg-color-list-item-header: var( + --cur-bg-color-list-item-topic-styling + ); + --cur-color-list-item-icon: var(--cur-color-list-item-icon-topic-styling); + --cur-bg-color-list-item-icon: var( + --cur-bg-color-list-item-icon-topic-styling + ); } .topic-scripting { --cur-bg-color-topic: var(--cur-bg-color-topic-scripting); --cur-color-topic: var(--cur-color-topic-scripting); + --cur-bg-color-list-item-header: var( + --cur-bg-color-list-item-topic-scripting + ); + --cur-color-list-item-icon: var(--cur-color-list-item-icon-topic-scripting); + --cur-bg-color-list-item-icon: var( + --cur-bg-color-list-item-icon-topic-scripting + ); } .topic-tooling { --cur-bg-color-topic: var(--cur-bg-color-topic-tooling); --cur-color-topic: var(--cur-color-topic-tooling); + --cur-bg-color-list-item-header: var( + --cur-bg-color-list-item-topic-tooling + ); + --cur-color-list-item-icon: var(--cur-color-list-item-icon-topic-tooling); + --cur-bg-color-list-item-icon: var( + --cur-bg-color-list-item-icon-topic-tooling + ); } .topic-practices { --cur-bg-color-topic: var(--cur-bg-color-topic-practices); --cur-color-topic: var(--cur-color-topic-practices); + --cur-bg-color-list-item-header: var( + --cur-bg-color-list-item-topic-practices + ); + --cur-color-list-item-icon: var(--cur-color-list-item-icon-topic-practices); + --cur-bg-color-list-item-icon: var( + --cur-bg-color-list-item-icon-topic-practices + ); } .curriculum-content { diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 140131702dd5..33954a458421 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -58,11 +58,7 @@ } .laptop { - fill: var(--cur-category-color); - - .dark & { - fill: var(--cur-bg-color-orange); - } + fill: var(--cur-color-landing-laptop); } } @@ -141,7 +137,7 @@ align-items: start; background-color: var(--background-primary); border-radius: var(--elem-radius); - box-shadow: var(--module-shadow); + box-shadow: var(--cur-shadow); color: var(--text-secondary); display: grid; grid-area: li; @@ -188,27 +184,15 @@ } &:nth-child(1)::before { - content: url("../assets/icons/cur-landing-about-beginner.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-about-beginner.svg#dark"); - } + content: var(--cur-landing-about-beginner); } &:nth-child(2)::before { - content: url("../assets/icons/cur-landing-about-pace.svg"); - - .dark & { - content: url("../assets/icons/cur-landing-about-pace.svg#dark"); - } + content: var(--cur-landing-about-pace); } &:nth-child(3)::before { - content: url("../assets/icons/cur-landing-about-free.svg"); - - .dark & { - content: url("../assets/icons/cur-landing-about-free.svg#dark"); - } + content: var(--cur-landing-about-free); } } } @@ -230,11 +214,7 @@ grid-area: p1; &::before { - content: url("../assets/icons/cur-landing-about-bullet.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-about-bullet.svg#dark"); - } + content: var(--cur-landing-about-bullet); } } @@ -242,11 +222,7 @@ grid-area: p2; &::before { - content: url("../assets/icons/cur-landing-about-bullet.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-about-bullet.svg#dark"); - } + content: var(--cur-landing-about-bullet); } } @@ -413,35 +389,19 @@ } &:nth-child(1)::before { - content: url("../assets/icons/cur-landing-started-beginner.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-started-beginner.svg#dark"); - } + content: var(--cur-landing-started-beginner); } &:nth-child(2)::before { - content: url("../assets/icons/cur-landing-started-advanced.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-started-advanced.svg#dark"); - } + content: var(--cur-landing-started-advanced); } &:nth-child(3)::before { - content: url("../assets/icons/cur-landing-started-employment.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-started-employment.svg#dark"); - } + content: var(--cur-landing-started-employment); } &:nth-child(4)::before { - content: url("../assets/icons/cur-landing-started-educator.svg#light"); - - .dark & { - content: url("../assets/icons/cur-landing-started-educator.svg#dark"); - } + content: var(--cur-landing-started-educator); } h3 { diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 3bbbfde91314..ed91505d5508 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -2,14 +2,6 @@ .curriculum-content-container.with-sidebar, .curriculum-content-container { - --module-shadow: 4px 4px 8px 0 rgba(179, 179, 179, 0.18), - -4px 4px 8px 0 rgba(179, 179, 179, 0.15); - - .dark & { - --module-shadow: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), - -4px 4px 8px 0 rgb(36, 36, 36); - } - .curriculum-content { .modules { input[type="radio"]:not(:checked) ~ a, @@ -151,9 +143,10 @@ } .module-list-item { + background-color: var(--cur-bg-color-list-item-body); border: 0; border-radius: var(--elem-radius); - box-shadow: var(--module-shadow); + box-shadow: var(--cur-shadow); display: flex; flex-direction: column; justify-self: center; @@ -167,35 +160,25 @@ min-width: initial; } - .dark & { - background-color: #000; - } - > header { a { align-items: center; - background-color: var(--cur-bg-color-topic); + background-color: var(--cur-bg-color-list-item-header); display: flex; flex-direction: column; height: 10rem; padding: 1rem 2rem; - .dark & { - background-color: var(--cur-bg-color-grey); - } - svg.topic-icon { height: 4rem; width: 4rem; - .dark & { - circle { - fill: var(--cur-bg-color-topic); - } + circle { + fill: var(--cur-bg-color-list-item-icon); + } - path { - fill: #000; - } + path { + fill: var(--cur-color-list-item-icon); } } diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index c3ae855083c2..e8b4db15db69 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -221,6 +221,40 @@ --cur-color-topic-scripting: #{$mdn-color-light-theme-yellow-60}; --cur-color-topic-tooling: #{$mdn-color-light-theme-green-60}; --cur-color-topic-practices: #{$mdn-color-light-theme-violet-60}; + --cur-color-landing-laptop: #e3642a; + --cur-bg-color-list-item-body: #fff; + --cur-color-list-item-icon-topic-standards: #{$mdn-color-light-theme-red-60}; + --cur-color-list-item-icon-topic-styling: #{$mdn-color-light-theme-blue-60}; + --cur-color-list-item-icon-topic-scripting: #{$mdn-color-light-theme-yellow-60}; + --cur-color-list-item-icon-topic-tooling: #{$mdn-color-light-theme-green-60}; + --cur-color-list-item-icon-topic-practices: #{$mdn-color-light-theme-violet-60}; + --cur-bg-color-list-item-icon-topic-standards: #fff; + --cur-bg-color-list-item-icon-topic-styling: #fff; + --cur-bg-color-list-item-icon-topic-scripting: #fff; + --cur-bg-color-list-item-icon-topic-tooling: #fff; + --cur-bg-color-list-item-icon-topic-practices: #fff; + --cur-bg-color-list-item-topic-standards: #{$mdn-color-light-theme-red-50}30; + --cur-bg-color-list-item-topic-styling: #{$mdn-color-light-theme-blue-50}30; + --cur-bg-color-list-item-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; + --cur-bg-color-list-item-topic-tooling: #{$mdn-color-light-theme-green-50}30; + --cur-bg-color-list-item-topic-practices: #{$mdn-color-light-theme-violet-50}30; + --cur-shadow: 4px 4px 8px 0 rgba(179, 179, 179, 0.18), + -4px 4px 8px 0 rgba(179, 179, 179, 0.15); + + --cur-landing-about-beginner: url("../../assets/icons/cur-landing-about-beginner.svg#light"); + --cur-landing-about-pace: url("../../assets/icons/cur-landing-about-pace.svg#light"); + --cur-landing-about-free: url("../../assets/icons/cur-landing-about-free.svg#light"); + --cur-landing-about-bullet: url("../../assets/icons/cur-landing-about-bullet.svg#light"); + --cur-landing-started-beginner: url("../../assets/icons/cur-landing-started-beginner.svg#small-light"); + --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#small-light"); + --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#small-light"); + --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#small-light"); + @media screen and (min-width: $screen-md) { + --cur-landing-started-beginner: url("../../assets/icons/cur-landing-started-beginner.svg#light"); + --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#light"); + --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#light"); + --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#light"); + } color-scheme: light; } @@ -445,6 +479,40 @@ --cur-category-color: #e3642a; --cur-bg-color-grey: #1f1c1a; --cur-bg-color-orange: #b25c35; + --cur-color-landing-laptop: #b25c35; + --cur-bg-color-list-item-body: #000; + --cur-color-list-item-icon-topic-standards: #000; + --cur-color-list-item-icon-topic-styling: #000; + --cur-color-list-item-icon-topic-scripting: #000; + --cur-color-list-item-icon-topic-tooling: #000; + --cur-color-list-item-icon-topic-practices: #000; + --cur-bg-color-list-item-topic-standards: #343434; + --cur-bg-color-list-item-topic-styling: #343434; + --cur-bg-color-list-item-topic-scripting: #343434; + --cur-bg-color-list-item-topic-tooling: #343434; + --cur-bg-color-list-item-topic-practices: #343434; + --cur-bg-color-list-item-icon-topic-standards: #994b53; + --cur-bg-color-list-item-icon-topic-styling: #4e609e; + --cur-bg-color-list-item-icon-topic-scripting: #7d683d; + --cur-bg-color-list-item-icon-topic-tooling: #584280; + --cur-bg-color-list-item-icon-topic-practices: #3d7c4b; + --cur-shadow: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), + -4px 4px 8px 0 rgb(36, 36, 36); + + --cur-landing-about-beginner: url("../../assets/icons/cur-landing-about-beginner.svg#dark"); + --cur-landing-about-pace: url("../../assets/icons/cur-landing-about-pace.svg#dark"); + --cur-landing-about-free: url("../../assets/icons/cur-landing-about-free.svg#dark"); + --cur-landing-about-bullet: url("../../assets/icons/cur-landing-about-bullet.svg#dark"); + --cur-landing-started-beginner: url("../../assets/icons/cur-landing-started-beginner.svg#small-dark"); + --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#small-dark"); + --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#small-dark"); + --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#small-dark"); + @media screen and (min-width: $screen-md) { + --cur-landing-started-beginner: url("../../assets/icons/cur-landing-started-beginner.svg#dark"); + --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#dark"); + --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#dark"); + --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#dark"); + } color-scheme: dark; } From 1de3c86c0240bf63582ef7cb56c1411968ecac6a Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Sat, 10 Feb 2024 17:58:27 +0100 Subject: [PATCH 074/102] no sidebar on mobile landing --- client/src/curriculum/layout.tsx | 5 ++++- .../article-actions-container/index.tsx | 22 +++++++++++-------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/client/src/curriculum/layout.tsx b/client/src/curriculum/layout.tsx index 1d116174f81d..bafc8cb69673 100644 --- a/client/src/curriculum/layout.tsx +++ b/client/src/curriculum/layout.tsx @@ -28,7 +28,10 @@ export function CurriculumLayout({ <>
            - +
            { const { isSidebarOpen, setIsSidebarOpen } = useUIStatus(); return (
            -
            )} -
            +
            {children}
            From b23e0dbe3094b382fbdb78fa43002c4a566e5041 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 12 Feb 2024 13:43:13 +0100 Subject: [PATCH 077/102] sidebar overview --- client/src/curriculum/sidebar.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/curriculum/sidebar.tsx b/client/src/curriculum/sidebar.tsx index c7696f7fa90f..245874a2370e 100644 --- a/client/src/curriculum/sidebar.tsx +++ b/client/src/curriculum/sidebar.tsx @@ -27,13 +27,13 @@ export function Sidebar({ o.children.some((c) => c.url === current) || o.url === current } > - {o.title} + {o.title} module
            1. {o.children.map((c, j) => { From e24a4eadf99cd3b4452356f3a0ba9c695bd43d99 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 12 Feb 2024 15:33:06 +0100 Subject: [PATCH 078/102] dark mode --- .../curriculum/cur-landing-ladder-1.svg | 2 +- .../assets/curriculum/cur-landing-ladder.svg | 116 ------------------ .../assets/curriculum/cur-landing-top.svg | 6 +- .../icons/cur-landing-about-beginner.svg | 2 +- .../assets/icons/cur-landing-about-bullet.svg | 2 +- .../assets/icons/cur-landing-about-free.svg | 2 +- .../assets/icons/cur-landing-about-pace.svg | 2 +- client/src/assets/icons/cur-mdn-resource.svg | 31 ++++- client/src/curriculum/index.scss | 2 +- client/src/curriculum/landing.scss | 7 +- client/src/curriculum/module.scss | 2 +- client/src/ui/base/_themes.scss | 26 +++- 12 files changed, 60 insertions(+), 140 deletions(-) delete mode 100644 client/public/assets/curriculum/cur-landing-ladder.svg diff --git a/client/public/assets/curriculum/cur-landing-ladder-1.svg b/client/public/assets/curriculum/cur-landing-ladder-1.svg index 7488a0ec1f51..c554946557c6 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-1.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-1.svg @@ -1,5 +1,5 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - How can you boost - - - - your employability - - - with the MDN - - - Curriculum? - - - Learn about research collaboration and other essential soft skills - Balance between modern tooling and long-term best practices - Get access to hight-quality recommened resrouces - - Get guidance from trusted voices - - diff --git a/client/public/assets/curriculum/cur-landing-top.svg b/client/public/assets/curriculum/cur-landing-top.svg index ac9e3efa170f..d4c94059be9c 100644 --- a/client/public/assets/curriculum/cur-landing-top.svg +++ b/client/public/assets/curriculum/cur-landing-top.svg @@ -66,10 +66,10 @@ - - + - diff --git a/client/src/assets/icons/cur-landing-about-bullet.svg b/client/src/assets/icons/cur-landing-about-bullet.svg index 3cab4ebe3352..ca5768e931a5 100644 --- a/client/src/assets/icons/cur-landing-about-bullet.svg +++ b/client/src/assets/icons/cur-landing-about-bullet.svg @@ -7,7 +7,7 @@ .dark { --circle: black; - --arrow: white; + --arrow: #B25C35; } diff --git a/client/src/assets/icons/cur-landing-about-free.svg b/client/src/assets/icons/cur-landing-about-free.svg index dd7a97436326..2f3d5e5bb9f3 100644 --- a/client/src/assets/icons/cur-landing-about-free.svg +++ b/client/src/assets/icons/cur-landing-about-free.svg @@ -6,7 +6,7 @@ } .dark { - --circle: #664b33; + --circle: rgba(178, 92, 53, 0.3); --icon: #E3642A; } diff --git a/client/src/assets/icons/cur-landing-about-pace.svg b/client/src/assets/icons/cur-landing-about-pace.svg index 41187fb7080e..8fa9ba891349 100644 --- a/client/src/assets/icons/cur-landing-about-pace.svg +++ b/client/src/assets/icons/cur-landing-about-pace.svg @@ -6,7 +6,7 @@ } .dark { - --circle: #664b33; + --circle: rgba(178, 92, 53, 0.3); --icon: #E3642A; } diff --git a/client/src/assets/icons/cur-mdn-resource.svg b/client/src/assets/icons/cur-mdn-resource.svg index 85cb2ecacaad..f265ba45cb8a 100644 --- a/client/src/assets/icons/cur-mdn-resource.svg +++ b/client/src/assets/icons/cur-mdn-resource.svg @@ -1,8 +1,27 @@ - - + + + + + + + + + + + diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 7061f55c838b..f1fec758b059 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -177,7 +177,7 @@ } blockquote.curriculum-notes { - background-color: #fcefe299; + background-color: var(--cur-bg-color-note); border: 0; border-radius: var(--elem-radius); margin: 1rem; diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index 33954a458421..c1576d4a5aaf 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -1,6 +1,7 @@ @use "../ui/vars" as *; .curriculum-content-container.curriculum-landing { + background-color: var(--cur-bg-color-landing); margin: 0; max-width: 100%; padding: 0; @@ -54,7 +55,7 @@ } #icons-bg { - fill: var(--cur-bg-color); + fill: var(--cur-bg-color-landing-top-icon); } .laptop { @@ -135,9 +136,9 @@ ul { align-items: start; - background-color: var(--background-primary); + background-color: var(--cur-bg-color-landing-about-ul); border-radius: var(--elem-radius); - box-shadow: var(--cur-shadow); + box-shadow: var(--cur-shadow-landing-about-ul); color: var(--text-secondary); display: grid; grid-area: li; diff --git a/client/src/curriculum/module.scss b/client/src/curriculum/module.scss index 83e53c97a49e..fc9d2261ed80 100644 --- a/client/src/curriculum/module.scss +++ b/client/src/curriculum/module.scss @@ -49,7 +49,7 @@ } &:not(.external) { - list-style-image: url("../assets/icons/cur-mdn-resource.svg"); + list-style-image: var(--cur-module-mdn-resource); } &.external { diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index e8b4db15db69..c40fc05c5a4f 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -208,12 +208,17 @@ --baseline-limited-cross: #ea8600; --cur-bg-color: #fcefe2; + --cur-bg-color-note: rgba(252, 239, 226, 0.5); --cur-bg-large-color: #fcefe2; --cur-bg-color-topic-standards: #{$mdn-color-light-theme-red-50}30; --cur-bg-color-topic-styling: #{$mdn-color-light-theme-blue-50}30; --cur-bg-color-topic-scripting: #{$mdn-color-light-theme-yellow-50}30; --cur-bg-color-topic-tooling: #{$mdn-color-light-theme-green-50}30; --cur-bg-color-topic-practices: #{$mdn-color-light-theme-violet-50}30; + --cur-bg-color-landing: #fff; + --cur-bg-color-landing-about-ul: #fff; + --cur-bg-color-landing-top-icon: #fcefe2; + --cur-bg-color-landing-ladder-floor: #fcefe2; --cur-category-color: #e3642a; --cur-color: #d47d55; --cur-color-topic-standards: #{$mdn-color-light-theme-red-60}; @@ -240,6 +245,8 @@ --cur-bg-color-list-item-topic-practices: #{$mdn-color-light-theme-violet-50}30; --cur-shadow: 4px 4px 8px 0 rgba(179, 179, 179, 0.18), -4px 4px 8px 0 rgba(179, 179, 179, 0.15); + --cur-shadow-landing-about-ul: 0 4px 10px 0 rgba(227, 100, 42, 0.06), + 0 -2px 4px 0 rgba(178, 92, 53, 0.06); --cur-landing-about-beginner: url("../../assets/icons/cur-landing-about-beginner.svg#light"); --cur-landing-about-pace: url("../../assets/icons/cur-landing-about-pace.svg#light"); @@ -254,6 +261,7 @@ --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#light"); --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#light"); --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#light"); + --cur-module-mdn-resource: url("../../assets/icons/cur-mdn-resource.svg#light"); } color-scheme: light; @@ -470,12 +478,17 @@ --cur-color-topic-tooling: #ce93fa; --cur-color-topic-practices: #55ab2d; --cur-bg-color: #664b33; + --cur-bg-color-note: #664b33; --cur-bg-large-color: #343434; --cur-bg-color-topic-standards: #994b53; --cur-bg-color-topic-styling: #4e609e; --cur-bg-color-topic-scripting: #7d683d; --cur-bg-color-topic-tooling: #584280; --cur-bg-color-topic-practices: #3d7c4b; + --cur-bg-color-landing: #0e0b0a; + --cur-bg-color-landing-about-ul: #000; + --cur-bg-color-landing-top-icon: rgba(178, 92, 53, 0.3); + --cur-bg-color-landing-ladder-floor: rgba(137, 91, 51, 1); --cur-category-color: #e3642a; --cur-bg-color-grey: #1f1c1a; --cur-bg-color-orange: #b25c35; @@ -486,11 +499,11 @@ --cur-color-list-item-icon-topic-scripting: #000; --cur-color-list-item-icon-topic-tooling: #000; --cur-color-list-item-icon-topic-practices: #000; - --cur-bg-color-list-item-topic-standards: #343434; - --cur-bg-color-list-item-topic-styling: #343434; - --cur-bg-color-list-item-topic-scripting: #343434; - --cur-bg-color-list-item-topic-tooling: #343434; - --cur-bg-color-list-item-topic-practices: #343434; + --cur-bg-color-list-item-topic-standards: #1f1c1a; + --cur-bg-color-list-item-topic-styling: #1f1c1a; + --cur-bg-color-list-item-topic-scripting: #1f1c1a; + --cur-bg-color-list-item-topic-tooling: #1f1c1a; + --cur-bg-color-list-item-topic-practices: #1f1c1a; --cur-bg-color-list-item-icon-topic-standards: #994b53; --cur-bg-color-list-item-icon-topic-styling: #4e609e; --cur-bg-color-list-item-icon-topic-scripting: #7d683d; @@ -498,6 +511,8 @@ --cur-bg-color-list-item-icon-topic-practices: #3d7c4b; --cur-shadow: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), -4px 4px 8px 0 rgb(36, 36, 36); + --cur-shadow-landing-about-ul: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), + -4px 4px 8px 0 rgb(36, 36, 36); --cur-landing-about-beginner: url("../../assets/icons/cur-landing-about-beginner.svg#dark"); --cur-landing-about-pace: url("../../assets/icons/cur-landing-about-pace.svg#dark"); @@ -512,6 +527,7 @@ --cur-landing-started-advanced: url("../../assets/icons/cur-landing-started-advanced.svg#dark"); --cur-landing-started-employment: url("../../assets/icons/cur-landing-started-employment.svg#dark"); --cur-landing-started-educator: url("../../assets/icons/cur-landing-started-educator.svg#dark"); + --cur-module-mdn-resource: url("../../assets/icons/cur-mdn-resource.svg#dark"); } color-scheme: dark; From 226960c76c54f03da5c0f5f2715908e2ea37ffd9 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Tue, 13 Feb 2024 13:14:31 +0100 Subject: [PATCH 079/102] fixes --- client/src/curriculum/index.scss | 2 +- client/src/ui/base/_themes.scss | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index f1fec758b059..3eb0b12ca617 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -181,7 +181,7 @@ border: 0; border-radius: var(--elem-radius); margin: 1rem; - padding: 1rem 2rem; + padding: 0.5rem 2rem; > :last-child { margin-bottom: 0; diff --git a/client/src/ui/base/_themes.scss b/client/src/ui/base/_themes.scss index c40fc05c5a4f..3b9d4a239a86 100644 --- a/client/src/ui/base/_themes.scss +++ b/client/src/ui/base/_themes.scss @@ -475,16 +475,16 @@ --cur-color-topic-standards: #{$mdn-color-light-theme-red-30}; --cur-color-topic-styling: #{$mdn-color-light-theme-blue-30}; --cur-color-topic-scripting: #cfc23f; - --cur-color-topic-tooling: #ce93fa; - --cur-color-topic-practices: #55ab2d; + --cur-color-topic-tooling: #55ab2d; + --cur-color-topic-practices: #ce93fa; --cur-bg-color: #664b33; - --cur-bg-color-note: #664b33; + --cur-bg-color-note: #332e2b; --cur-bg-large-color: #343434; --cur-bg-color-topic-standards: #994b53; --cur-bg-color-topic-styling: #4e609e; --cur-bg-color-topic-scripting: #7d683d; - --cur-bg-color-topic-tooling: #584280; - --cur-bg-color-topic-practices: #3d7c4b; + --cur-bg-color-topic-tooling: #3d7c4b; + --cur-bg-color-topic-practices: #584280; --cur-bg-color-landing: #0e0b0a; --cur-bg-color-landing-about-ul: #000; --cur-bg-color-landing-top-icon: rgba(178, 92, 53, 0.3); @@ -507,8 +507,8 @@ --cur-bg-color-list-item-icon-topic-standards: #994b53; --cur-bg-color-list-item-icon-topic-styling: #4e609e; --cur-bg-color-list-item-icon-topic-scripting: #7d683d; - --cur-bg-color-list-item-icon-topic-tooling: #584280; - --cur-bg-color-list-item-icon-topic-practices: #3d7c4b; + --cur-bg-color-list-item-icon-topic-tooling: #3d7c4b; + --cur-bg-color-list-item-icon-topic-practices: #584280; --cur-shadow: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), -4px 4px 8px 0 rgb(36, 36, 36); --cur-shadow-landing-about-ul: 4px 4px 8px 0 rgba(36, 36, 36, 0.15), From 363d35a9c91646ae5bddfa6b4d701132168f08b6 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Wed, 14 Feb 2024 15:09:56 +0100 Subject: [PATCH 080/102] more fixes --- build/curriculum.ts | 15 ++++++++------- client/src/curriculum/modules-list.scss | 15 ++++----------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index 031820eb494a..00142aeb87ed 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -110,9 +110,7 @@ export async function buildSidebar(): Promise { return index; } -export async function buildPrevNextOverview(slug: string): Promise { - const index = (await buildModuleIndex()).filter((x) => x?.children?.length); - const i = index.findIndex((x) => x.slug === slug); +function prevNextFromIndex(i, index): PrevNext { const prev = i > 0 ? index[i - 1] : undefined; const next = i < index.length - 1 ? index[i + 1] : undefined; @@ -122,13 +120,16 @@ export async function buildPrevNextOverview(slug: string): Promise { return { prev, next }; } +export async function buildPrevNextOverview(slug: string): Promise { + const index = (await buildModuleIndex()).filter((x) => x?.children?.length); + const i = index.findIndex((x) => x.slug === slug); + return prevNextFromIndex(i, index); +} + export async function buildPrevNextModule(slug: string): Promise { const index = await buildIndex(); const i = index.findIndex((x) => x.slug === slug); - return { - prev: i > 0 ? index[i - 1] : undefined, - next: i < index.length - 2 ? index[i + 1] : undefined, - }; + return prevNextFromIndex(i, index); } function breadPath(url: string, cur: ModuleIndexEntry[]): DocParent[] | null { diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index ed91505d5508..038076c2be62 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -27,14 +27,14 @@ grid-template-columns: auto; margin: 0; padding: 0; - @media screen and (min-width: $screen-md) { + @media screen and (min-width: $screen-sm) { grid-template-areas: "a b c spacer" "hr hr hr hr" "mod mod mod mod" "t t t t"; - grid-template-columns: max-content max-content max-content auto; + grid-template-columns: auto auto auto 1fr; } hr { @@ -85,7 +85,7 @@ > label, > input { grid-area: b; - @media screen and (min-width: $screen-md) { + @media screen and (min-width: $screen-sm) { margin-left: 2rem; } } @@ -99,7 +99,7 @@ > label, > input { grid-area: c; - @media screen and (min-width: $screen-md) { + @media screen and (min-width: $screen-sm) { margin-left: 2rem; } } @@ -221,13 +221,6 @@ @media screen and (min-width: $screen-xxl) { grid-template-columns: 1fr 1fr 1fr; } - - @container module-list (width >= 25rem) { - grid-template-columns: 1fr 1fr; - } - @container module-list (width >= 38rem) { - grid-template-columns: 1fr 1fr 1fr; - } } } } From 56fdf3c2b1b1aef3cca7f241f5038f3d1756d9d5 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 15 Feb 2024 11:47:02 +0100 Subject: [PATCH 081/102] align button --- client/src/curriculum/modules-list.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 038076c2be62..4c9119cb3709 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -116,8 +116,12 @@ > a { grid-area: t; + margin-left: 0.5rem; margin-top: 2rem; width: fit-content; + @media screen and (min-width: $screen-md) { + margin-left: 0; + } } } } From a9e0ad10a3c4483ff25d9332e5998e38b4c2a7f8 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Thu, 15 Feb 2024 15:08:33 +0100 Subject: [PATCH 082/102] colors and svgs --- client/src/assets/icons/cur-about-covered.svg | 27 ++++++++++++--- client/src/assets/icons/cur-about-detail.svg | 27 ++++++++++++--- .../src/assets/icons/cur-about-educators.svg | 27 ++++++++++++--- client/src/assets/icons/cur-about-not.svg | 27 ++++++++++++--- .../src/assets/icons/cur-about-students.svg | 27 ++++++++++++--- client/src/assets/icons/cur-bullet.svg | 33 +++++++++++++++---- client/src/assets/icons/cur-ext-resource.svg | 2 +- client/src/assets/icons/cur-mdn-resource.svg | 2 +- client/src/assets/icons/cur-next.svg | 6 ++-- client/src/assets/icons/cur-prev.svg | 6 ++-- client/src/curriculum/about.scss | 12 +++---- client/src/curriculum/module.scss | 3 -- client/src/curriculum/modules-list.scss | 5 ++- client/src/ui/base/_themes.scss | 32 +++++++++++++----- 14 files changed, 182 insertions(+), 54 deletions(-) diff --git a/client/src/assets/icons/cur-about-covered.svg b/client/src/assets/icons/cur-about-covered.svg index 66c0d04e4131..7fdd6eac2c69 100644 --- a/client/src/assets/icons/cur-about-covered.svg +++ b/client/src/assets/icons/cur-about-covered.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-about-detail.svg b/client/src/assets/icons/cur-about-detail.svg index b8ee53f825cc..bec56ae1fc54 100644 --- a/client/src/assets/icons/cur-about-detail.svg +++ b/client/src/assets/icons/cur-about-detail.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-about-educators.svg b/client/src/assets/icons/cur-about-educators.svg index 3a8ea45819f8..1559e79b2bf3 100644 --- a/client/src/assets/icons/cur-about-educators.svg +++ b/client/src/assets/icons/cur-about-educators.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-about-not.svg b/client/src/assets/icons/cur-about-not.svg index 82bc751b75c0..3521556201fe 100644 --- a/client/src/assets/icons/cur-about-not.svg +++ b/client/src/assets/icons/cur-about-not.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-about-students.svg b/client/src/assets/icons/cur-about-students.svg index d28328daa198..7548b7417da1 100644 --- a/client/src/assets/icons/cur-about-students.svg +++ b/client/src/assets/icons/cur-about-students.svg @@ -1,6 +1,25 @@ - - + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-bullet.svg b/client/src/assets/icons/cur-bullet.svg index 0f7edbde316d..808ff1afb3d9 100644 --- a/client/src/assets/icons/cur-bullet.svg +++ b/client/src/assets/icons/cur-bullet.svg @@ -1,8 +1,27 @@ - - - + + + + + + + + + + + + diff --git a/client/src/assets/icons/cur-ext-resource.svg b/client/src/assets/icons/cur-ext-resource.svg index 7c0a90e6a719..9ceac6e87cea 100644 --- a/client/src/assets/icons/cur-ext-resource.svg +++ b/client/src/assets/icons/cur-ext-resource.svg @@ -1,4 +1,4 @@ - + +

              {section.value.title}

      7. - + ); } diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index c27570736914..409ab1c6459a 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -163,6 +163,7 @@ @media screen and (min-width: $screen-md) { min-width: initial; } + &:hover { border-color: rgba(227, 100, 42, 0.7); } @@ -175,6 +176,11 @@ flex-direction: column; height: 10rem; padding: 1rem 2rem; + text-decoration: none; + + &:hover { + text-decoration: underline; + } svg.topic-icon { height: 4rem; diff --git a/client/src/curriculum/topic-icon.tsx b/client/src/curriculum/topic-icon.tsx index fdd67d40561f..936388c7469f 100644 --- a/client/src/curriculum/topic-icon.tsx +++ b/client/src/curriculum/topic-icon.tsx @@ -20,15 +20,21 @@ enum Topic { export function TopicIcon({ topic }: { topic: Topic }) { switch (topic) { case Topic.WebStandards: - return ; + return ( + + ); case Topic.Styling: - return ; + return ; case Topic.Scripting: - return ; + return ( + + ); case Topic.Tooling: - return ; + return ; case Topic.BestPractices: - return ; + return ( + + ); default: return <>; } From 17a069ebaf2deed0bec83aacaafb0fd9bc164990 Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 19 Feb 2024 12:42:25 +0100 Subject: [PATCH 085/102] responsive ladder --- .../curriculum/cur-landing-ladder-1.svg | 15 +- .../curriculum/cur-landing-ladder-2-small.svg | 21 +-- .../curriculum/cur-landing-ladder-2.svg | 8 +- client/src/curriculum/landing.scss | 142 +++++++++++++++--- client/src/curriculum/landing.tsx | 34 ++++- 5 files changed, 151 insertions(+), 69 deletions(-) diff --git a/client/public/assets/curriculum/cur-landing-ladder-1.svg b/client/public/assets/curriculum/cur-landing-ladder-1.svg index c554946557c6..df80f6c2c8b5 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-1.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-1.svg @@ -38,18 +38,5 @@ d="M124.61 323.5s-1.823.791-1 .5c.39-.138.924-1.515 2-2 1.513-.682 3.108-1 3.108-1l.002 8h-4.5z" /> - - - How can you - - - boost your employability - - - with the MDN - - - Curriculum? - - + diff --git a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg index f4d7729fbe70..142005af5b4c 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2-small.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2-small.svg @@ -52,24 +52,5 @@ - - - Get Guidance from - trusted voices. - - - Get access to high- - qualtiy resources. - - - Balance knowledge of modern - tooling with long-testm best - practices. - - - Learn about research, - collaboration, and other - essential soft skills. - - + diff --git a/client/public/assets/curriculum/cur-landing-ladder-2.svg b/client/public/assets/curriculum/cur-landing-ladder-2.svg index 10e4057cef34..b11c8cae6cbf 100644 --- a/client/public/assets/curriculum/cur-landing-ladder-2.svg +++ b/client/public/assets/curriculum/cur-landing-ladder-2.svg @@ -52,11 +52,5 @@ - - Learn about research collaboration and other essential soft skills - Balance between modern tooling and long-term best practices - Get access to hight-quality recommened resrouces - - Get guidance from trusted voices - + diff --git a/client/src/curriculum/landing.scss b/client/src/curriculum/landing.scss index ed02613bcd8e..4bb133574c31 100644 --- a/client/src/curriculum/landing.scss +++ b/client/src/curriculum/landing.scss @@ -253,6 +253,7 @@ max-width: 100%; > div { + color: var(--text-secondary); display: grid; grid-template-areas: "a" "b"; grid-template-columns: auto; @@ -264,48 +265,139 @@ padding-left: var(--gutter); padding-right: var(--gutter); width: 100%; + @media screen and (min-width: $screen-md) { grid-template-areas: "a b"; grid-template-columns: 1fr 1.4fr; } - > svg { - &:nth-child(1) { - font-size: 2rem; - grid-area: a; - transform: translateX(2vw); + > #lad1-container { + --fs: clamp(1rem, calc(2 * calc(100vw / 100)), 1.75rem); + grid-area: a; + margin: 0; + position: relative; + transform: translateX(2vw); + width: 100%; + + svg { width: 100%; } - &:nth-child(2) { - display: none; - grid-area: b; - transform: translateX(-5vw); - width: 100%; - @media screen and (min-width: $screen-md) { - display: initial; + #lad1 { + font-size: var(--fs); + left: 32%; + position: absolute; + top: 18%; + + > span { + display: block; + line-height: calc(1.25 * var(--fs)); + text-wrap: nowrap; } - } - &:nth-child(3) { - grid-area: b; - max-width: 100%; - width: 100%; - @media screen and (min-width: $screen-md) { - display: none; + .color { + color: var(--cur-color); } } + } - #text29 { - font: var(--type-heading-h2); + > #lad2-container { + --fs: clamp(0.825rem, calc(1.25 * calc(100vw / 100)), 1rem); + @media screen and (min-width: $screen-md) { + --fs: clamp(0.75rem, calc(100vw / 100), 0.825rem); } + grid-area: b; + position: relative; + transform: translateX(-5vw); + + #lad2 { + font-size: var(--fs); + height: 100%; + left: 0; + margin: 0; + overflow: scroll; + position: absolute; + top: 0; + width: calc(100% + 5vw); + + > span { + display: block; + line-height: calc(1.25 * var(--fs)); + max-width: 10rem; + position: absolute; + text-wrap: nowrap; + text-wrap: wrap; + @media screen and (min-width: $screen-md) { + max-width: initial; + text-wrap: nowrap; + } + } + + #stair-1 { + left: 47%; + top: 36%; + } + + #stair-2 { + left: 33%; + top: 52%; + } + + #stair-3 { + left: 23%; + top: 71%; + } + + #stair-4 { + left: 8%; + top: 86%; + } + @media screen and (min-width: $screen-md) { + #stair-1 { + left: 35%; + top: 53%; + } - text { - fill: var(--text-secondary); + #stair-2 { + left: 27%; + top: 65%; + } + + #stair-3 { + left: 13%; + top: 77%; + } + + #stair-4 { + left: 0%; + top: 90%; + } + } } - .color { - fill: var(--cur-color); + svg { + &:nth-child(1) { + display: none; + grid-area: b; + width: 100%; + @media screen and (min-width: $screen-md) { + display: initial; + } + } + + &:nth-child(2) { + grid-area: b; + max-width: 100%; + width: 100%; + @media screen and (min-width: $screen-md) { + display: none; + } + } + + text { + fill: var(--text-secondary); + opacity: 0.5; + } } } } diff --git a/client/src/curriculum/landing.tsx b/client/src/curriculum/landing.tsx index 6d454fa22b7e..2dbcee42362a 100644 --- a/client/src/curriculum/landing.tsx +++ b/client/src/curriculum/landing.tsx @@ -50,9 +50,37 @@ export function CurriculumLanding(appProps: HydrationData) { className="landing-ladder" >
        - - - +
        + +

        + How can you + + boost your employability{" "} + + with the MDN + Curriculum? +

        +
        +
        + + +

        + + Learn about research collaboration and other essential + soft skills. + + + Balance between modern tooling and long-term best + practices. + + + Get access to hight-quality recommended resources. + + + Get guidance from trusted voices. + +

        +
        From 3baea2c477e127fca6c13d4e47cf6f0be30fe72a Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 19 Feb 2024 12:46:48 +0100 Subject: [PATCH 086/102] remove underline --- client/src/curriculum/modules-list.scss | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 409ab1c6459a..87d073a9366e 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -118,6 +118,7 @@ grid-area: t; margin-left: 0.5rem; margin-top: 2rem; + text-decoration: none; width: fit-content; @media screen and (min-width: $screen-md) { margin-left: 0; From 33a9fd8842ed6bc51c53098240fc3f02bf748cfc Mon Sep 17 00:00:00 2001 From: Florian Dieminger Date: Mon, 19 Feb 2024 15:57:42 +0100 Subject: [PATCH 087/102] fix links and clean up --- build/curriculum.ts | 73 +++++++++++++++---------- build/utils.ts | 9 ++- client/src/curriculum/index.scss | 4 ++ client/src/curriculum/modules-list.scss | 1 - client/src/curriculum/modules-list.tsx | 10 +++- client/src/curriculum/sidebar.tsx | 4 +- client/src/document/preloading.tsx | 18 ------ client/src/placement-context.tsx | 2 +- libs/types/curriculum.ts | 24 ++++---- libs/types/hydration.ts | 4 +- server/index.ts | 12 +--- 11 files changed, 81 insertions(+), 80 deletions(-) diff --git a/build/curriculum.ts b/build/curriculum.ts index d57c8befa143..4a79ffb10909 100644 --- a/build/curriculum.ts +++ b/build/curriculum.ts @@ -21,13 +21,13 @@ import fs from "node:fs/promises"; import { CurriculumFrontmatter, CurriculumData, - ModuleMetaData, - ModuleIndexEntry, + CurriculumMetaData, + CurriculumIndexEntry, PrevNext, Template, CurriculumDoc, ReadCurriculum, - BuildData, + CurriculumBuildData, } from "../libs/types/curriculum.js"; import frontmatter from "front-matter"; import { HydrationData } from "../libs/types/hydration.js"; @@ -50,7 +50,12 @@ export const buildIndex = memoize(async () => { const modules = await Promise.all( files.map( async (file) => - (await readModule(file, { previousNext: false, forIndex: true })).meta + ( + await readCurriculumPage(file, { + previousNext: false, + forIndex: true, + }) + ).meta ) ); return modules; @@ -79,9 +84,9 @@ export async function slugToFile(slug) { }); } -export async function buildModuleIndex( - mapper: (x: ModuleMetaData) => Partial = (x) => x -): Promise { +export async function buildCurriculumIndex( + mapper: (x: CurriculumMetaData) => Partial = (x) => x +): Promise { const index = await buildIndex(); const s = index.reduce((item, meta) => { @@ -102,8 +107,8 @@ export async function buildModuleIndex( return s; } -export async function buildSidebar(): Promise { - const index = await buildModuleIndex(({ url, slug, title }) => { +async function buildCurriculumSidebar(): Promise { + const index = await buildCurriculumIndex(({ url, slug, title }) => { return { url, slug, title }; }); @@ -120,19 +125,24 @@ function prevNextFromIndex(i, index): PrevNext { return { prev, next }; } -export async function buildPrevNextOverview(slug: string): Promise { - const index = (await buildModuleIndex()).filter((x) => x?.children?.length); +async function buildPrevNextOverview(slug: string): Promise { + const index = (await buildCurriculumIndex()).filter( + (x) => x?.children?.length + ); const i = index.findIndex((x) => x.slug === slug); return prevNextFromIndex(i, index); } -export async function buildPrevNextModule(slug: string): Promise { +async function buildPrevNextModule(slug: string): Promise { const index = await buildIndex(); const i = index.findIndex((x) => x.slug === slug); return prevNextFromIndex(i, index); } -function breadPath(url: string, cur: ModuleIndexEntry[]): DocParent[] | null { +function breadPath( + url: string, + cur: CurriculumIndexEntry[] +): DocParent[] | null { for (const entry of cur) { if (entry.url === url) { return [{ uri: entry.url, title: entry.title }]; @@ -147,8 +157,8 @@ function breadPath(url: string, cur: ModuleIndexEntry[]): DocParent[] | null { return null; } -export async function buildParents(url: string): Promise { - const index = await buildModuleIndex(({ url, title }) => { +async function buildParents(url: string): Promise { + const index = await buildCurriculumIndex(({ url, title }) => { return { url, title }; }); const parents = breadPath(url, index); @@ -163,7 +173,7 @@ export async function buildParents(url: string): Promise { return []; } -async function readModule( +async function readCurriculumPage( file: string, options?: { previousNext?: boolean; @@ -179,17 +189,18 @@ async function readModule( const slug = fileToSlug(file); const url = `/${DEFAULT_LOCALE}/${slug}/`; - let sidebar: ModuleIndexEntry[]; + let sidebar: CurriculumIndexEntry[]; let parents: DocParent[]; - // For module overview and landing page set modules. - let modules: ModuleIndexEntry[]; + let modules: CurriculumIndexEntry[]; let prevNext: PrevNext; if (!options?.forIndex) { if (attributes.template === Template.landing) { - modules = (await buildModuleIndex())?.filter((x) => x.children?.length); + modules = (await buildCurriculumIndex())?.filter( + (x) => x.children?.length + ); } else if (attributes.template === Template.overview) { - modules = (await buildModuleIndex())?.find( + modules = (await buildCurriculumIndex())?.find( (x) => x.slug === slug )?.children; } @@ -199,7 +210,7 @@ async function readModule( prevNext = await buildPrevNextOverview(slug); } - sidebar = await buildSidebar(); + sidebar = await buildCurriculumSidebar(); parents = await buildParents(url); } else { title = title @@ -224,7 +235,7 @@ async function readModule( }; } -export async function findModuleBySlug( +export async function findCurriculumPageBySlug( slug: string ): Promise { let file = await slugToFile(slug); @@ -233,14 +244,14 @@ export async function findModuleBySlug( } let module; try { - module = await readModule(file, { forIndex: false }); + module = await readCurriculumPage(file, { forIndex: false }); } catch (e) { console.error(`No file found for ${slug}`, e); return; } const { body, meta } = module; - const d: BuildData = { + const d: CurriculumBuildData = { url: meta.url, rawBody: body, metadata: { locale: DEFAULT_LOCALE, ...meta }, @@ -250,11 +261,13 @@ export async function findModuleBySlug( }, }; - const doc = await buildModule(d); + const doc = await buildCurriculumPage(d); return { doc }; } -export async function buildModule(document: BuildData): Promise { +export async function buildCurriculumPage( + document: CurriculumBuildData +): Promise { const { metadata } = document; const doc = { locale: DEFAULT_LOCALE } as Partial; @@ -322,11 +335,11 @@ export async function buildCurriculum(options: { const locale = DEFAULT_LOCALE; for (const file of await allFiles()) { - const { meta, body } = await readModule(file, { + const { meta, body } = await readCurriculumPage(file, { forIndex: false, }); - const renderDoc: BuildData = { + const renderDoc: CurriculumBuildData = { url: meta.url, rawBody: body, metadata: { locale, ...meta }, @@ -335,7 +348,7 @@ export async function buildCurriculum(options: { path: file, }, }; - const builtDoc = await buildModule(renderDoc); + const builtDoc = await buildCurriculumPage(renderDoc); const { doc } = { doc: { ...builtDoc, summary: meta.summary, mdn_url: meta.url }, }; diff --git a/build/utils.ts b/build/utils.ts index 302b1304405b..70bb1f923d4d 100644 --- a/build/utils.ts +++ b/build/utils.ts @@ -246,19 +246,26 @@ export function postProcessExternalLinks($) { * @param {current url} url */ export function postProcessCurriculumLinks($, toUrl) { + // expand relative links $("a[href^=.]").each((_, element) => { - // Expand relative links (TODO: fix) const $a = $(element); $a.attr("href", toUrl($a.attr("href"))); }); + + // remove trailing .md for /en-US/curriculum/* $("a[href^=/en-US/curriculum]").each((_, element) => { const $a = $(element); $a.attr("href", $a.attr("href").replace(/(.*)\.md(#.*|$)/, "$1/$2")); }); + + // remove trailing .md and add locale for /curriculum/* $("a[href^=/curriculum]").each((_, element) => { const $a = $(element); $a.attr("href", $a.attr("href").replace(/(.*)\.md(#.*|$)/, "/en-US$1/$2")); }); + + // remove leading numbers for /en-US/curriculum/* + // /en-US/curriculum/2-core/ -> /en-US/curriculum/core/ $("a[href^=/en-US/curriculum]").each((_, element) => { const $a = $(element); const [head, hash] = $a.attr("href").split("#"); diff --git a/client/src/curriculum/index.scss b/client/src/curriculum/index.scss index 9c2f7f780c40..8001266986f3 100644 --- a/client/src/curriculum/index.scss +++ b/client/src/curriculum/index.scss @@ -162,6 +162,10 @@ &:link, &:visited { text-decoration: underline; + + &.button { + text-decoration: none; + } } &:hover, diff --git a/client/src/curriculum/modules-list.scss b/client/src/curriculum/modules-list.scss index 87d073a9366e..409ab1c6459a 100644 --- a/client/src/curriculum/modules-list.scss +++ b/client/src/curriculum/modules-list.scss @@ -118,7 +118,6 @@ grid-area: t; margin-left: 0.5rem; margin-top: 2rem; - text-decoration: none; width: fit-content; @media screen and (min-width: $screen-md) { margin-left: 0; diff --git a/client/src/curriculum/modules-list.tsx b/client/src/curriculum/modules-list.tsx index 497f4d74b179..6111b008d60a 100644 --- a/client/src/curriculum/modules-list.tsx +++ b/client/src/curriculum/modules-list.tsx @@ -1,4 +1,4 @@ -import { ModuleIndexEntry } from "../../../libs/types/curriculum"; +import { CurriculumIndexEntry } from "../../../libs/types/curriculum"; import { TopicIcon } from "./topic-icon"; import { topic2css } from "./utils"; @@ -6,7 +6,11 @@ import "./modules-list.scss"; import { useState } from "react"; import { Button } from "../ui/atoms/button"; -export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { +export function ModulesListList({ + modules, +}: { + modules: CurriculumIndexEntry[]; +}) { const [tab, setTab] = useState(1); return (
          @@ -38,7 +42,7 @@ export function ModulesListList({ modules }: { modules: ModuleIndexEntry[] }) { ); } -export function ModulesList({ modules }: { modules: ModuleIndexEntry[] }) { +export function ModulesList({ modules }: { modules: CurriculumIndexEntry[] }) { return (
            {modules.map((c, j) => { diff --git a/client/src/curriculum/sidebar.tsx b/client/src/curriculum/sidebar.tsx index 245874a2370e..59037e857b41 100644 --- a/client/src/curriculum/sidebar.tsx +++ b/client/src/curriculum/sidebar.tsx @@ -1,4 +1,4 @@ -import { ModuleIndexEntry } from "../../../libs/types/curriculum"; +import { CurriculumIndexEntry } from "../../../libs/types/curriculum"; import "./module.scss"; export function Sidebar({ @@ -8,7 +8,7 @@ export function Sidebar({ }: { current: string; extraClasses?: string; - sidebar: ModuleIndexEntry[]; + sidebar: CurriculumIndexEntry[]; }) { return (