Added Blockquote Component
This commit is contained in:
27
src/components/Content/Blockquote/Blockquote.module.css
Normal file
27
src/components/Content/Blockquote/Blockquote.module.css
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
70
src/components/Content/Blockquote/index.tsx
Normal file
70
src/components/Content/Blockquote/index.tsx
Normal file
@@ -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 (
|
||||
<blockquote className={styles.blockquote}>
|
||||
<div
|
||||
className={styles.quote}
|
||||
dangerouslySetInnerHTML={{ __html: marked.parse(quote) }}
|
||||
/>
|
||||
{showFooter && (
|
||||
<footer className={styles.footer}>
|
||||
{hasAttribution && (
|
||||
<cite className={styles.attribution}>
|
||||
{attributionLinked ? (
|
||||
<a
|
||||
href={url}
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{attribution}
|
||||
</a>
|
||||
) : (
|
||||
attribution
|
||||
)}
|
||||
</cite>
|
||||
)}
|
||||
{hasSource && (
|
||||
<cite className={styles.source}>
|
||||
{' '}
|
||||
–
|
||||
{sourceLinked ? (
|
||||
<a
|
||||
href={url}
|
||||
className={styles.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{source}
|
||||
</a>
|
||||
) : (
|
||||
source
|
||||
)}
|
||||
</cite>
|
||||
)}
|
||||
</footer>
|
||||
)}
|
||||
</blockquote>
|
||||
);
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
34
src/keystatic/components/general/blockquote.ts
Normal file
34
src/keystatic/components/general/blockquote.ts
Normal file
@@ -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;
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user