From 5cb4bd57824e60468f049f7cb6863817bbcd23cb Mon Sep 17 00:00:00 2001 From: Dave Date: Sun, 5 Oct 2025 10:52:40 +0200 Subject: [PATCH] Added Blockquote Component --- content/meta/index.mdoc | 6 ++ .../Content/Blockquote/Blockquote.module.css | 27 +++++++ src/components/Content/Blockquote/index.tsx | 70 +++++++++++++++++++ .../Content/Sidenote/Item/Item.module.css | 4 ++ src/components/Content/index.ts | 2 + .../components/general/blockquote.ts | 34 +++++++++ src/keystatic/components/general/index.ts | 2 + src/lib/markdoc/tags.ts | 18 +++++ 8 files changed, 163 insertions(+) create mode 100644 src/components/Content/Blockquote/Blockquote.module.css create mode 100644 src/components/Content/Blockquote/index.tsx create mode 100644 src/keystatic/components/general/blockquote.ts diff --git a/content/meta/index.mdoc b/content/meta/index.mdoc index 5b5b433..2a7b436 100644 --- a/content/meta/index.mdoc +++ b/content/meta/index.mdoc @@ -73,6 +73,12 @@ Puer meus. Nam et ego homo sum sub potestate constitutus, habens sub me milites, Erit. Si autem oculus tuus fuerit nequam, totum corpus tuum tenebrosum erit. Si ergo lumen, quod in te est, tenebræ sunt ipsæ tenebræ quantæ erunt? Nemo potest duobus dominis servire aut enim unum odio habebit, et alterum diliget aut unum sustinebit, et alterum contemnet. Non potestis Deo servire et mammonæ. Ideo dico vobis, ne solliciti sitis animæ vestræ quid manducetis, neque corpori vestro quid induamini. Nonne anima plus est quam esca, et corpus plus quam vestimentum? Respicite volatilia cæli, quoniam non serunt, neque metunt, neque congregant in horrea et Pater vester cælestis pascit illa. Nonne vos magis pluris estis illis? Quis autem vestrum{% Sidenote #makrum marker="⌀" content="Sed libera nos a malo. Amen. Si enim dimiseritis hominibus peccata eorum dimittet et vobis Pater vester cælestis delicta vestra. Si autem non dimiseritis hominibus nec Pater vester dimittet vobis peccata vestra. Cum autem jejunatis, nolite fieri sicut hypocritæ, tristes. Exterminant enim facies suas, ut appareant hominibus jejunantes. Amen dico vobis, quia receperunt mercedem **autem jesus** suam. Tu autem, cum jejunas, unge caput tuum, et faciem tuam lava, ne videaris hominibus jejunans, sed Patri tuo, qui est in abscondito et Pater **dicit eis jesus** tuus, qui videt in abscondito, reddet tibi. Nolite thesaurizare vobis thesauros in." type="default" /%} cogitans potest adjicere ad staturam suam cubitum unum? Et de vestimento quid solliciti estis? Considerate lilia agri quomodo crescunt non laborant, neque nent. Dico autem vobis, quoniam nec Salomon in omni gloria sua coopertus est sicut unum ex istis. Si autem fœnum agri, quod hodie est, et cras in clibanum mittitur, Deus sic vestit, quanto. +{% Blockquote + quote="Est regnum cælorum. Beati estis cum maledixerint vobis, et persecuti vos fuerint, et dixerint omne malum adversum vos mentientes, propter me gaudete, et exsultate, quoniam merces vestra copiosa est in cælis. Sic enim _galil vidit duos_ persecuti sunt prophetas, qui fuerunt ante vos. Vos estis sal terræ. Quod si sal **zonam pelliceam** evanuerit, in quo **extendens** salietur? ad nihilum valet ultra, nisi ut mittatur foras, et conculcetur ab hominibus. Vos estis lux mundi. _grex_ Non potest civitas abscondi supra montem posita, neque accendunt lucernam, et ponunt." + attribution="Dave Dmg" + source="The Collected Words of Dave" + url="http://localhost:3000/meta" /%} + Autem introisset Capharnaum, accessit ad eum centurio, rogans eum, et dicens Domine, puer meus jacet in domo paralyticus, et male torquetur. Et ait illi Jesus Ego veniam, et curabo eum. Et respondens centurio, ait Domine, non sum dignus ut intres sub tectum meum sed tantum dic verbo, et sanabitur puer meus. Nam et ego homo sum sub potestate constitutus, habens sub me milites, et dico huic Vade, et vadit et alii Veni, et venit et servo meo [Ad eum discipuli](https://example.com/suamt/andi) Fac hoc, et facit. Audiens autem Jesus miratus est, et sequentibus se dixit Amen dico vobis, non inveni tantam fidem in Israël. Dico autem vobis, quod multi ab oriente et occidente venient, et recumbent [Qui dictus est](https://example.com/autem/etmalo) cum Abraham, et Isaac, et ==facies suas== Jacob [Modic fidei tunc surgens imperavit ventis](https://example.com/eating/adimple) in regno cælorum filii autem regni ejicientur in tenebras exteriores ibi erit fletus et stridor dentium. Et dixit Jesus centurioni Vade, et sicut credidisti, fiat tibi. Et sanatus est puer in illa hora. Et cum venisset Jesus in domum Petri, vidit socrum ejus jacentem, et febricitantem et tetigit manum ejus, et dimisit eam febris, et. {% Accordion %} diff --git a/src/components/Content/Blockquote/Blockquote.module.css b/src/components/Content/Blockquote/Blockquote.module.css new file mode 100644 index 0000000..951a0ae --- /dev/null +++ b/src/components/Content/Blockquote/Blockquote.module.css @@ -0,0 +1,27 @@ +.container { + margin-block: var(--el-p-vspace-top) var(--el-p-vspace-bottom); + padding: var(--spacing-snug) 0 var(--spacing-snug) var(--spacing-comfortable); + border-left: var(--size-4) solid var(--color-text-tertiary); +} + +.quote { + font-family: var(--el-blockquote-font-family), serif; + font-size: var(--el-blockquote-font-size); + font-weight: var(--el-blockquote-font-weight); + font-style: var(--el-blockquote-font-style); + line-height: var(--el-blockquote-line-height); + color: var(--el-blockquote-color); +} + +.attribution, +.source { + font-family: var(--font-mono); +} + +.link { + @mixin anim-txt-typewriter; + + &:hover { + color: var(--color-primary); + } +} \ No newline at end of file diff --git a/src/components/Content/Blockquote/index.tsx b/src/components/Content/Blockquote/index.tsx new file mode 100644 index 0000000..f781f89 --- /dev/null +++ b/src/components/Content/Blockquote/index.tsx @@ -0,0 +1,70 @@ +import { marked } from 'marked'; + +import styles from './Blockquote.module.css'; + +interface BlockquoteProps { + quote: string; + attribution?: string; + source?: string; + url?: string; +} + +export default function Blockquote({ + quote, + attribution, + source, + url, +}: BlockquoteProps) { + const hasAttribution = !!attribution; + const hasSource = !!source; + const hasUrl = !!url; + const showFooter = hasSource || hasAttribution; + const attributionLinked = hasAttribution && hasUrl && !hasSource; + const sourceLinked = hasSource && hasUrl; + return ( +
+
+ {showFooter && ( + + )} +
+ ); +} diff --git a/src/components/Content/Sidenote/Item/Item.module.css b/src/components/Content/Sidenote/Item/Item.module.css index 8c2bc1d..caa8c3b 100644 --- a/src/components/Content/Sidenote/Item/Item.module.css +++ b/src/components/Content/Sidenote/Item/Item.module.css @@ -2,8 +2,12 @@ @mixin px var(--spacing-tight); scroll-margin-top: calc(var(--el-header-height) + var(--spacing-comfortable)); + display: inline-block; + font-weight: var(--typo-weight-black); + color: var(--color-secondary); + transition: color 0.5s ease-in-out; &:hover { diff --git a/src/components/Content/index.ts b/src/components/Content/index.ts index 4b46068..ac69d49 100644 --- a/src/components/Content/index.ts +++ b/src/components/Content/index.ts @@ -5,6 +5,7 @@ import DefinitionList from '@/components/Content/DefinitionList'; import DefinitionItem from '@/components/Content/DefinitionList/DefinitionItem'; import Accordion from '@/components/Content/Accordion'; import AccordionItem from '@/components/Content/Accordion/AccordionItem'; +import Blockquote from '@/components/Content/Blockquote'; const ContentComponents = { Column, @@ -14,6 +15,7 @@ const ContentComponents = { DefinitionItem, Accordion, AccordionItem, + Blockquote, }; export default ContentComponents; diff --git a/src/keystatic/components/general/blockquote.ts b/src/keystatic/components/general/blockquote.ts new file mode 100644 index 0000000..b2ab5d9 --- /dev/null +++ b/src/keystatic/components/general/blockquote.ts @@ -0,0 +1,34 @@ +import { textQuoteIcon } from '@keystar/ui/icon/icons/textQuoteIcon'; +import { block } from '@keystatic/core/content-components'; +import { fields } from '@keystatic/core'; + +const blockquoteComponents = { + Blockquote: block({ + label: 'Blockquote', + icon: textQuoteIcon, + schema: { + quote: fields.text({ + label: 'Quote', + multiline: true, + validation: { + length: { + min: 1, + }, + }, + }), + attribution: fields.text({ + label: 'Attribution', + description: 'Author or Speaker', + }), + source: fields.text({ + label: 'Source', + description: 'Book, article, or document [optional]', + }), + url: fields.url({ + label: 'Source URL', + }), + }, + }), +}; + +export default blockquoteComponents; diff --git a/src/keystatic/components/general/index.ts b/src/keystatic/components/general/index.ts index fc551b9..abcdf45 100644 --- a/src/keystatic/components/general/index.ts +++ b/src/keystatic/components/general/index.ts @@ -2,10 +2,12 @@ import gridComponents from '@/keystatic/components/general/grid'; import sidenoteComponents from '@/keystatic/components/general/sidenote'; import definitionlistComponents from '@/keystatic/components/general/definitionlist'; import accordionComponents from '@/keystatic/components/general/accordion'; +import blockquoteComponents from '@/keystatic/components/general/blockquote'; export const generalComponents = { ...gridComponents, ...sidenoteComponents, ...definitionlistComponents, ...accordionComponents, + ...blockquoteComponents, }; diff --git a/src/lib/markdoc/tags.ts b/src/lib/markdoc/tags.ts index 9472a54..ec544ae 100644 --- a/src/lib/markdoc/tags.ts +++ b/src/lib/markdoc/tags.ts @@ -75,4 +75,22 @@ export const tags: Config['tags'] = { }, }, }, + Blockquote: { + render: 'Blockquote', + attributes: { + quote: { + type: 'String', + required: true, + }, + attribution: { + type: 'String', + }, + source: { + type: 'String', + }, + url: { + type: 'String', + }, + }, + }, };