diff --git a/src/components/markdoc/Node.astro b/src/components/markdoc/Node.astro index a80a566..2d78904 100644 --- a/src/components/markdoc/Node.astro +++ b/src/components/markdoc/Node.astro @@ -9,12 +9,14 @@ import Figure from '../media/Figure.astro' import Callout from './blocks/general/Callout.astro' import Lead from './blocks/general/Lead.astro' import Quote from './blocks/general/Quote.astro' +import Reveal from './blocks/general/Reveal.astro' import TableWrapper from './blocks/general/TableWrapper.astro' type Props = { node: RenderableTreeNode | RenderableTreeNode[] } const COMPONENTS: Record = { Callout, + Reveal, Figure, TableWrapper, Quote, diff --git a/src/components/markdoc/blocks/general/Callout.astro b/src/components/markdoc/blocks/general/Callout.astro index 7250942..23b040b 100644 --- a/src/components/markdoc/blocks/general/Callout.astro +++ b/src/components/markdoc/blocks/general/Callout.astro @@ -1,5 +1,5 @@ --- -import type { CalloutType } from '@/lib/constants/blocks/notes' +import { NOTE_TYPES, type CalloutType } from '@/lib/constants/blocks/notes' type Props = { type?: CalloutType @@ -7,11 +7,15 @@ type Props = { } const { type = 'default', title } = Astro.props + +const kind = NOTE_TYPES.find((option) => option.value === type)?.label ?? type --- diff --git a/src/components/markdoc/blocks/general/Reveal.astro b/src/components/markdoc/blocks/general/Reveal.astro new file mode 100644 index 0000000..4143f4a --- /dev/null +++ b/src/components/markdoc/blocks/general/Reveal.astro @@ -0,0 +1,12 @@ +--- +type Props = { summary?: string } + +const { summary = 'Spoiler' } = Astro.props +--- + +
+ {summary} +
+ +
+
diff --git a/src/content/general/articles/prima-materia.mdoc b/src/content/general/articles/prima-materia.mdoc index 7ad1438..0c9b635 100644 --- a/src/content/general/articles/prima-materia.mdoc +++ b/src/content/general/articles/prima-materia.mdoc @@ -67,7 +67,11 @@ All things are poison, and nothing is without poison; the dosage alone makes it ## Callouts -{% callout type="default" title="Note" %} +{% callout type="default" title="TITA TITLE" %} +I AM DONE WITH THIS SHIT! SO COMPLETELY AND TOTALLY DONE! +{% /callout %} + +{% callout type="optional" title="Note" %} A default callout with a [link](https://example.com) and `code` inside it. {% /callout %} @@ -78,6 +82,10 @@ An example callout containing a list: - two {% /callout %} +{% reveal summary="Spoiler" %} +Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. This first paragraph is the lead, so it should be larger and carry the drop cap. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. A sentence with *emphasis*, **strong text**, `inline code`, ~~struck text~~ and an [external link](https://example.com). +{% /reveal %} + ## Code ```js diff --git a/src/keystatic/blocks/general/index.ts b/src/keystatic/blocks/general/index.ts index 21b85a9..15199ef 100644 --- a/src/keystatic/blocks/general/index.ts +++ b/src/keystatic/blocks/general/index.ts @@ -3,6 +3,7 @@ import { figure } from './figure' import { footnote } from './footnote' import { lead } from './lead' import { quote } from './quote' +import { reveal } from './reveal' import { sidenote } from './sidenote' import { tableWrapper } from './table-wrapper' import { xref } from './xref' @@ -15,5 +16,6 @@ export const generalBlocks = (collection: string) => ({ sidenote, tableWrapper, quote, + reveal, xref: xref(), }) diff --git a/src/keystatic/blocks/general/reveal.ts b/src/keystatic/blocks/general/reveal.ts new file mode 100644 index 0000000..6980079 --- /dev/null +++ b/src/keystatic/blocks/general/reveal.ts @@ -0,0 +1,14 @@ +import { fields } from '@keystatic/core' +import { wrapper } from '@keystatic/core/content-components' + +export const reveal = wrapper({ + label: 'Reveal', + description: 'A spoiler around any content, closed until the reader opens it', + schema: { + summary: fields.text({ + label: 'Label', + description: 'What the reader sees before opening.', + defaultValue: 'Spoiler', + }), + }, +}) diff --git a/src/lib/constants/blocks/notes.ts b/src/lib/constants/blocks/notes.ts index 5b4e439..7390b7f 100644 --- a/src/lib/constants/blocks/notes.ts +++ b/src/lib/constants/blocks/notes.ts @@ -1,12 +1,16 @@ export const NOTE_TYPES = [ { - label: 'Default', + label: 'Note', value: 'default', }, { label: 'Example', value: 'example', }, + { + label: 'Optional', + value: 'optional', + }, ] as const export type CalloutType = (typeof NOTE_TYPES)[number]['value'] diff --git a/src/lib/markdoc/tags.ts b/src/lib/markdoc/tags.ts index 79cb697..1e00e30 100644 --- a/src/lib/markdoc/tags.ts +++ b/src/lib/markdoc/tags.ts @@ -64,6 +64,7 @@ const generated = figure: 'Figure', tableWrapper: 'TableWrapper', quote: 'Quote', + reveal: 'Reveal', }, }, }).tags ?? {} diff --git a/src/styles/base/primitives.css b/src/styles/base/primitives.css index b0aa106..25f1915 100644 --- a/src/styles/base/primitives.css +++ b/src/styles/base/primitives.css @@ -183,6 +183,7 @@ --slot-prose-marker: 1.625rem; --slot-prose-gap: var(--size-6); --slot-prose-bar: var(--size-8); + --slot-callout-cell: 8.5rem; /* ═══ MOTION ═══ */ --motion-fast: 150ms; /* state change: hover, focus, press */ diff --git a/src/styles/components/callout.css b/src/styles/components/callout.css new file mode 100644 index 0000000..0f8eab5 --- /dev/null +++ b/src/styles/components/callout.css @@ -0,0 +1,90 @@ +@layer components { + .callout { + @mixin my var(--space-9); + counter-increment: box; + + display: grid; + grid-template-columns: var(--slot-callout-cell) minmax(0, 1fr); + + border: var(--border-card) solid var(--color-border-strong); + + background-color: var(--color-surface-elevated-1); + box-shadow: var(--shadow-card); + } + + .callout__kind { + @mixin typo_label; + @mixin ma var(--size-0); + @mixin py var(--size-6); + @mixin px var(--size-7); + + display: flex; + flex-direction: column; + justify-content: space-between; + + border-inline-end: var(--border-card) solid var(--color-border-strong); + + color: var(--color-text-primary); + + background-color: var(--color-surface-base); + + &::after { + content: "Box " counter(sec, upper-roman) "." counter(box); + + font-family: var(--font-mono); + font-size: var(--type--3); + font-weight: var(--font-weight-body); + color: var(--color-text-quarternary); + } + } + + .callout__title { + @mixin typo_heading-4; + @mixin mt var(--size-0); + @mixin mb var(--size-5); + + font-size: var(--type-0); + } + + .callout__body { + @mixin py var(--size-6); + @mixin px var(--size-8); + + & > :first-child { + margin-block-start: var(--size-0); + } + + & > :last-child { + margin-block-end: var(--size-0); + } + } + + .callout--example { + & .callout__kind { + background-color: var(--color-surface-elevated-3); + } + } + + .callout--optional { + border-width: var(--border-hairline); + background-color: transparent; + box-shadow: none; + + & .callout__kind { + border-inline-end: var(--border-hairline) solid var(--color-border-normal); + color: var(--color-text-primary); + background-color: transparent; + + &::after { + color: var(--color-text-quiet); + } + } + + & .callout__title { + @mixin typo_label; + + font-size: var(--type--2); + color: var(--color-text-quiet); + } + } +} diff --git a/src/styles/components/index.css b/src/styles/components/index.css index 5c4ec0f..15d21e2 100644 --- a/src/styles/components/index.css +++ b/src/styles/components/index.css @@ -1,3 +1,4 @@ @import url("prose.css"); @import url("quote.css"); @import url("lead.css"); +@import url("callout.css"); diff --git a/src/styles/components/prose.css b/src/styles/components/prose.css index 0b12526..d068975 100644 --- a/src/styles/components/prose.css +++ b/src/styles/components/prose.css @@ -8,7 +8,7 @@ .prose { @mixin typo_body; - counter-reset: sec sub tbl fig; + counter-reset: sec sub tbl fig box; & > :first-child { margin-block-start: var(--size-0); @@ -35,7 +35,7 @@ @mixin mt var(--space-11); @mixin mb var(--space-8); @mixin ps var(--size-9); - counter-set: sub 0 fig 0; + counter-set: sub 0 fig 0 box 0; counter-increment: sec; clear: both;