Refactored ArticleHeader
This commit is contained in:
@@ -11,8 +11,6 @@ type Props = {
|
|||||||
size?: FigureSize
|
size?: FigureSize
|
||||||
effect?: ImageEffect
|
effect?: ImageEffect
|
||||||
ratio?: AspectRatio
|
ratio?: AspectRatio
|
||||||
eager?: boolean
|
|
||||||
class?: string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const LAYOUT: Record<FigureSize, { widths: number[]; sizes: string }> = {
|
const LAYOUT: Record<FigureSize, { widths: number[]; sizes: string }> = {
|
||||||
@@ -25,11 +23,9 @@ const {
|
|||||||
alt,
|
alt,
|
||||||
caption,
|
caption,
|
||||||
credit,
|
credit,
|
||||||
eager,
|
|
||||||
size = 'inline',
|
size = 'inline',
|
||||||
effect = 'none',
|
effect = 'none',
|
||||||
ratio = 'original',
|
ratio = 'original',
|
||||||
class: className,
|
|
||||||
} = Astro.props
|
} = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -39,10 +35,9 @@ const {
|
|||||||
`figure--${size}`,
|
`figure--${size}`,
|
||||||
effect !== 'none' && `effect--${effect}`,
|
effect !== 'none' && `effect--${effect}`,
|
||||||
ratio !== 'original' && `ratio--${ratio}`,
|
ratio !== 'original' && `ratio--${ratio}`,
|
||||||
className,
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<ContentImage src={image} alt={alt} eager={eager} {...LAYOUT[size]} />
|
<ContentImage src={image} alt={alt} {...LAYOUT[size]} />
|
||||||
{(caption || credit) && (
|
{(caption || credit) && (
|
||||||
<figcaption class:list={['figure__caption', size !== 'inline' && 'dark']}>
|
<figcaption class:list={['figure__caption', size !== 'inline' && 'dark']}>
|
||||||
{caption && <span class="figure__text">{caption}</span>}
|
{caption && <span class="figure__text">{caption}</span>}
|
||||||
|
|||||||
@@ -18,13 +18,15 @@ const crumbs = trailOf(article)
|
|||||||
const published = article.published
|
const published = article.published
|
||||||
---
|
---
|
||||||
|
|
||||||
<header>
|
<header class="article-header">
|
||||||
<Overline
|
<Overline
|
||||||
crumbs={crumbs}
|
crumbs={crumbs}
|
||||||
stamp={published ? toMilitaryDTG(published) : 'No publication date set'}
|
stamp={published ? toMilitaryDTG(published) : 'No publication date set'}
|
||||||
datetime={published?.toISOString()}
|
datetime={published?.toISOString()}
|
||||||
/>
|
/>
|
||||||
|
<div class="article-header__panel">
|
||||||
<Title title={article.title} subtitle={article.subtitle} />
|
<Title title={article.title} subtitle={article.subtitle} />
|
||||||
<Cover cover={article.summary.cover} />
|
|
||||||
<Meta article={article} />
|
<Meta article={article} />
|
||||||
|
<Cover cover={article.summary.cover} />
|
||||||
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
@@ -1,10 +1,34 @@
|
|||||||
---
|
---
|
||||||
import Figure from '@/components/media/Figure.astro'
|
import ContentImage from '@/components/media/ContentImage.astro'
|
||||||
import type { Article } from '@/lib/site/types'
|
import type { Article } from '@/lib/site/types'
|
||||||
|
|
||||||
type Props = { cover: Article['summary']['cover'] }
|
type Props = {
|
||||||
|
cover: Article['summary']['cover']
|
||||||
|
}
|
||||||
|
|
||||||
const { image, ...rest } = Astro.props.cover
|
const { image, alt, caption, credit, effect, ratio } = Astro.props.cover
|
||||||
---
|
---
|
||||||
|
|
||||||
{image && <Figure image={image} {...rest} size="wide" eager />}
|
{image && (
|
||||||
|
<figure
|
||||||
|
class:list={[
|
||||||
|
'article-header__cover',
|
||||||
|
effect !== 'none' && `effect--${effect}`,
|
||||||
|
ratio !== 'original' && `ratio--${ratio}`,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<ContentImage
|
||||||
|
src={image}
|
||||||
|
alt={alt}
|
||||||
|
widths={[800, 1600, 2400]}
|
||||||
|
sizes="(min-width: 80rem) 74rem, 100vw"
|
||||||
|
eager
|
||||||
|
/>
|
||||||
|
{(caption || credit) && (
|
||||||
|
<figcaption class="article-header__caption dark">
|
||||||
|
{caption && <span>{caption}</span>}
|
||||||
|
{credit && <span class="article-header__credit">{credit}</span>}
|
||||||
|
</figcaption>
|
||||||
|
)}
|
||||||
|
</figure>
|
||||||
|
)}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
---
|
---
|
||||||
|
import StageBadge from '@/components/post/Header/StageBadge.astro'
|
||||||
import { toMilitaryDTG } from '@/lib/content/dates'
|
import { toMilitaryDTG } from '@/lib/content/dates'
|
||||||
import { getSite } from '@/lib/site'
|
import { getSite } from '@/lib/site'
|
||||||
import type { Article } from '@/lib/site/types'
|
import type { Article } from '@/lib/site/types'
|
||||||
@@ -11,40 +12,62 @@ const { article } = Astro.props
|
|||||||
const site = await getSite()
|
const site = await getSite()
|
||||||
const tags = article.tags.map((id) => site.tags.get(id)).filter((tag) => tag !== undefined)
|
const tags = article.tags.map((id) => site.tags.get(id)).filter((tag) => tag !== undefined)
|
||||||
const date = article.updated ?? article.published
|
const date = article.updated ?? article.published
|
||||||
const label = article.updated ? 'Updated' : 'Published'
|
const dateLabel = article.updated ? 'Updated' : 'Published'
|
||||||
const machine = date?.toISOString()
|
|
||||||
const display = date && toMilitaryDTG(date)
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<dl class="meta">
|
<dl class="article-header__meta">
|
||||||
<div class="section">
|
<div class="article-header__cell">
|
||||||
<dt class="label">Author</dt>
|
<dt class="article-header__label">
|
||||||
<dd class="item">Dave Damage</dd>
|
<span class="article-header__index" aria-hidden="true">
|
||||||
</div>
|
02
|
||||||
{tags.length > 0 && (
|
</span>
|
||||||
<div class="section">
|
State
|
||||||
<dt class="label">Tags</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
<ul class="tags">
|
<StageBadge stage={article.stage} />
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div class="article-header__cell">
|
||||||
|
<dt class="article-header__label">
|
||||||
|
<span class="article-header__index" aria-hidden="true">
|
||||||
|
03
|
||||||
|
</span>
|
||||||
|
{dateLabel}
|
||||||
|
</dt>
|
||||||
|
<dd class="article-header__value">
|
||||||
|
{date ? <time datetime={date.toISOString()}>{toMilitaryDTG(date)}</time> : 'Undated'}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
<div class="article-header__cell">
|
||||||
|
<dt class="article-header__label">
|
||||||
|
<span class="article-header__index" aria-hidden="true">
|
||||||
|
04
|
||||||
|
</span>
|
||||||
|
Author
|
||||||
|
</dt>
|
||||||
|
<dd class="article-header__value">Dave Damage</dd>
|
||||||
|
</div>
|
||||||
|
<div class="article-header__cell">
|
||||||
|
<dt class="article-header__label">
|
||||||
|
<span class="article-header__index" aria-hidden="true">
|
||||||
|
05
|
||||||
|
</span>
|
||||||
|
Tags
|
||||||
|
</dt>
|
||||||
|
<dd class="article-header__value">
|
||||||
|
{tags.length > 0 ? (
|
||||||
|
<ul class="article-header__tags">
|
||||||
{tags.map((tag) => (
|
{tags.map((tag) => (
|
||||||
<li class="tag">
|
<li>
|
||||||
<a href={tag.path} rel="tag">
|
<a class="article-header__tag" href={tag.path} rel="tag">
|
||||||
{tag.title}
|
{tag.title}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
) : (
|
||||||
|
'None'
|
||||||
|
)}
|
||||||
</dd>
|
</dd>
|
||||||
</div>
|
</div>
|
||||||
)}
|
|
||||||
{display && (
|
|
||||||
<div class="section">
|
|
||||||
<dt class="label">{label}</dt>
|
|
||||||
<dd>
|
|
||||||
<time class="item" datetime={machine}>
|
|
||||||
{display}
|
|
||||||
</time>
|
|
||||||
</dd>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
13
src/components/post/Header/StageBadge.astro
Normal file
13
src/components/post/Header/StageBadge.astro
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
import { STAGE_OPTIONS, type Stage } from '@/lib/constants/stage'
|
||||||
|
|
||||||
|
type props = {
|
||||||
|
stage: Stage
|
||||||
|
}
|
||||||
|
|
||||||
|
const { stage } = Astro.props
|
||||||
|
|
||||||
|
const label = STAGE_OPTIONS.find((option) => option.value === stage)?.label ?? stage
|
||||||
|
---
|
||||||
|
|
||||||
|
<span class:list={['stage-badge', `stage-badge--${stage}`]}>{label}</span>
|
||||||
@@ -7,7 +7,11 @@ type Props = {
|
|||||||
const { title, subtitle } = Astro.props
|
const { title, subtitle } = Astro.props
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="wrapper content">
|
<div class="article-header__designation">
|
||||||
<h1 class="title">{title}</h1>
|
<p class="article-header__label" aria-hidden="true">
|
||||||
{subtitle && <p class="subtitle">{subtitle}</p>}
|
<span class="article-header__index">01</span>
|
||||||
|
Designation
|
||||||
|
</p>
|
||||||
|
<h1 class="article-header__title">{title}</h1>
|
||||||
|
{subtitle && <p class="article-header__subtitle">{subtitle}</p>}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { collection, fields } from '@keystatic/core'
|
import { collection, fields } from '@keystatic/core'
|
||||||
|
|
||||||
import { base } from '@/keystatic/fields/content/base'
|
import { base, stage } from '@/keystatic/fields/content/base'
|
||||||
import { content } from '@/keystatic/fields/content/content'
|
import { content } from '@/keystatic/fields/content/content'
|
||||||
import { dates } from '@/keystatic/fields/content/dates'
|
import { dates } from '@/keystatic/fields/content/dates'
|
||||||
import { articleRoute } from '@/keystatic/fields/content/route'
|
import { articleRoute } from '@/keystatic/fields/content/route'
|
||||||
@@ -15,9 +15,10 @@ export const articles = collection({
|
|||||||
contentField: 'content',
|
contentField: 'content',
|
||||||
},
|
},
|
||||||
entryLayout: 'content',
|
entryLayout: 'content',
|
||||||
columns: ['title', 'status'],
|
columns: ['title', 'status', 'stage'],
|
||||||
schema: {
|
schema: {
|
||||||
...base,
|
...base,
|
||||||
|
stage,
|
||||||
route: articleRoute,
|
route: articleRoute,
|
||||||
summary: articleSummary(ARTICLES),
|
summary: articleSummary(ARTICLES),
|
||||||
dates,
|
dates,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { fields } from '@keystatic/core'
|
import { fields } from '@keystatic/core'
|
||||||
|
|
||||||
|
import { STAGE_OPTIONS } from '@/lib/constants/stage'
|
||||||
import { STATUS_OPTIONS } from '@/lib/constants/status'
|
import { STATUS_OPTIONS } from '@/lib/constants/status'
|
||||||
import { SEGMENT, SEGMENT_MESSAGE, slugify } from '@/lib/content/slug'
|
import { SEGMENT, SEGMENT_MESSAGE, slugify } from '@/lib/content/slug'
|
||||||
|
|
||||||
@@ -33,6 +34,13 @@ export const status = fields.select({
|
|||||||
defaultValue: 'draft',
|
defaultValue: 'draft',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const stage = fields.select({
|
||||||
|
label: 'Stage',
|
||||||
|
description: 'How finished the text is. Separate from status, which controls visibility',
|
||||||
|
options: STAGE_OPTIONS,
|
||||||
|
defaultValue: 'stub',
|
||||||
|
})
|
||||||
|
|
||||||
export const noindex = fields.checkbox({
|
export const noindex = fields.checkbox({
|
||||||
label: 'Hide from search engines',
|
label: 'Hide from search engines',
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const meta = metaOf(article)
|
|||||||
|
|
||||||
<BaseLayout {...meta}>
|
<BaseLayout {...meta}>
|
||||||
<article class="article">
|
<article class="article">
|
||||||
<!--<ArticleHeader article={article} />-->
|
<ArticleHeader article={article} />
|
||||||
<div class="frame">
|
<div class="frame">
|
||||||
<div class="rail">
|
<div class="rail">
|
||||||
<ToC headings={rendered.headings} />
|
<ToC headings={rendered.headings} />
|
||||||
|
|||||||
20
src/lib/constants/stage.ts
Normal file
20
src/lib/constants/stage.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
export const STAGE_OPTIONS = [
|
||||||
|
{
|
||||||
|
label: 'Stub',
|
||||||
|
value: 'stub',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Developing',
|
||||||
|
value: 'developing',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Complete',
|
||||||
|
value: 'complete',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Ongoing',
|
||||||
|
value: 'ongoing',
|
||||||
|
},
|
||||||
|
] as const
|
||||||
|
|
||||||
|
export type Stage = (typeof STAGE_OPTIONS)[number]['value']
|
||||||
@@ -35,7 +35,7 @@ export async function render(
|
|||||||
|
|
||||||
for (const { lines, error } of Markdoc.validate(node, config)) {
|
for (const { lines, error } of Markdoc.validate(node, config)) {
|
||||||
const level = LEVEL[error.level as keyof typeof LEVEL]
|
const level = LEVEL[error.level as keyof typeof LEVEL]
|
||||||
if (level) problems[level](collection, id, `Text line ${lines[0] + 1}: ${error.message}`)
|
if (level) problems[level](collection, id, `Content line ${lines[0] + 1}: ${error.message}`)
|
||||||
}
|
}
|
||||||
const tree = Markdoc.transform(node, config)
|
const tree = Markdoc.transform(node, config)
|
||||||
for (const { level, message } of state.problems) problems[level](collection, id, message)
|
for (const { level, message } of state.problems) problems[level](collection, id, message)
|
||||||
|
|||||||
11
src/styles/components/blocks/index.css
Normal file
11
src/styles/components/blocks/index.css
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
@import url("quote.css");
|
||||||
|
@import url("lead.css");
|
||||||
|
@import url("callout.css");
|
||||||
|
@import url("reveal.css");
|
||||||
|
@import url("table-wrapper.css");
|
||||||
|
@import url("footnote.css");
|
||||||
|
@import url("sidenote.css");
|
||||||
|
@import url("figure.css");
|
||||||
|
@import url("code.css");
|
||||||
|
@import url("terms.css");
|
||||||
|
@import url("spoiler.css");
|
||||||
@@ -61,7 +61,6 @@
|
|||||||
.quote__source {
|
.quote__source {
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@media (--bp-desktop) {
|
@media (--bp-desktop) {
|
||||||
.quote {
|
.quote {
|
||||||
@@ -77,3 +76,4 @@
|
|||||||
align-self: end;
|
align-self: end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
@@ -1,12 +1,3 @@
|
|||||||
@import url("prose.css");
|
@import url("prose/index.css");
|
||||||
@import url("quote.css");
|
@import url("blocks/index.css");
|
||||||
@import url("lead.css");
|
@import url("post/index.css");
|
||||||
@import url("callout.css");
|
|
||||||
@import url("reveal.css");
|
|
||||||
@import url("table-wrapper.css");
|
|
||||||
@import url("footnote.css");
|
|
||||||
@import url("sidenote.css");
|
|
||||||
@import url("figure.css");
|
|
||||||
@import url("code.css");
|
|
||||||
@import url("terms.css");
|
|
||||||
@import url("spoiler.css");
|
|
||||||
|
|||||||
171
src/styles/components/post/article-header.css
Normal file
171
src/styles/components/post/article-header.css
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
@layer components.blocks {
|
||||||
|
.article-header__panel {
|
||||||
|
@mixin mx auto;
|
||||||
|
@mixin mt var(--size-10);
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: minmax(0, 1fr);
|
||||||
|
gap: var(--border-card);
|
||||||
|
|
||||||
|
width: min(100% - 2 * var(--layout-page-margin), var(--layout-wrapper-width));
|
||||||
|
border: var(--border-card) solid var(--color-border-strong);
|
||||||
|
|
||||||
|
background-color: var(--color-border-strong);
|
||||||
|
|
||||||
|
@media (--bp-desktop) {
|
||||||
|
grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__designation {
|
||||||
|
@mixin pa var(--size-9);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--size-10);
|
||||||
|
background-color: var(--color-surface-elevated-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__label {
|
||||||
|
@mixin typo_eyebrow;
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__index {
|
||||||
|
&::after {
|
||||||
|
content: "⟫" / "";
|
||||||
|
margin-inline: var(--size-2);
|
||||||
|
font-family: var(--font-body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__title {
|
||||||
|
@mixin mt auto;
|
||||||
|
@mixin mb var(--size-0);
|
||||||
|
|
||||||
|
font-family: var(--font-display);
|
||||||
|
font-size: clamp(var(--type-9), 5vw, var(--size-14));
|
||||||
|
font-weight: var(--font-weight-display);
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
letter-spacing: var(--tracking-display);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__subtitle {
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
|
||||||
|
font-family: var(--font-header);
|
||||||
|
font-size: var(--type-1);
|
||||||
|
font-weight: var(--font-weight-body);
|
||||||
|
line-height: var(--leading-1);
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: var(--tracking-subtitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__meta {
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
gap: var(--border-card);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__cell {
|
||||||
|
@mixin pa var(--size-9);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--size-8);
|
||||||
|
background-color: var(--color-surface-elevated-1);
|
||||||
|
|
||||||
|
& dd {
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__value {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--type-0);
|
||||||
|
line-height: var(--leading-0);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
& time {
|
||||||
|
font-weight: var(--font-weight-emphasis);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__tags {
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
@mixin pa var(--size-0);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--size-2);
|
||||||
|
align-items: flex-start;
|
||||||
|
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__tag {
|
||||||
|
@mixin py var(--size-1);
|
||||||
|
@mixin px var(--size-3);
|
||||||
|
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
font-size: var(--type--2);
|
||||||
|
font-weight: var(--font-weight-emphasis);
|
||||||
|
line-height: var(--leading--2);
|
||||||
|
color: var(--color-text-inverse);
|
||||||
|
letter-spacing: var(--tracking-tag);
|
||||||
|
|
||||||
|
background-color: var(--color-surface-inverse);
|
||||||
|
|
||||||
|
transition: background-color var(--motion-fast) var(--ease-out);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--color-text-on-accent);
|
||||||
|
background-color: var(--color-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus-visible {
|
||||||
|
@mixin focus-ring;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__cover {
|
||||||
|
@mixin ma var(--size-0);
|
||||||
|
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
|
||||||
|
& img {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
aspect-ratio: var(--figure-ratio, auto);
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__caption {
|
||||||
|
@mixin typo_code;
|
||||||
|
@mixin py var(--size-4);
|
||||||
|
@mixin px var(--size-9);
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--size-2) var(--size-6);
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
background-color: var(--color-surface-base);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article-header__credit {
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
src/styles/components/post/index.css
Normal file
2
src/styles/components/post/index.css
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
@import url("article-header.css");
|
||||||
|
@import url("stage-badge.css");
|
||||||
52
src/styles/components/post/stage-badge.css
Normal file
52
src/styles/components/post/stage-badge.css
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
@layer components.blocks {
|
||||||
|
.stage-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
gap: var(--size-3);
|
||||||
|
align-items: baseline;
|
||||||
|
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--type--1);
|
||||||
|
line-height: 1;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: var(--tracking-tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-badge--stub,
|
||||||
|
.stage-badge--developing {
|
||||||
|
@mixin py var(--size-2);
|
||||||
|
@mixin px var(--size-3);
|
||||||
|
|
||||||
|
color: var(--color-text-on-accent);
|
||||||
|
background-color: var(--color-tertiary);
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: "";
|
||||||
|
width: 1cap;
|
||||||
|
height: 1cap;
|
||||||
|
background-color: currentcolor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-badge--stub {
|
||||||
|
&::before {
|
||||||
|
clip-path: polygon(
|
||||||
|
evenodd,
|
||||||
|
50% 0,
|
||||||
|
100% 100%,
|
||||||
|
0 100%,
|
||||||
|
50% 0,
|
||||||
|
50% 36%,
|
||||||
|
21% 86%,
|
||||||
|
79% 86%,
|
||||||
|
50% 36%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stage-badge--developing {
|
||||||
|
&::before {
|
||||||
|
clip-path: polygon(50% 0, 100% 100%, 0 100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/styles/components/prose/index.css
Normal file
1
src/styles/components/prose/index.css
Normal file
@@ -0,0 +1 @@
|
|||||||
|
@import url("prose.css");
|
||||||
@@ -99,3 +99,12 @@
|
|||||||
line-height: var(--leading-prose-tight);
|
line-height: var(--leading-prose-tight);
|
||||||
letter-spacing: var(--tracking--1);
|
letter-spacing: var(--tracking--1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@define-mixin typo_eyebrow {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: var(--type--3);
|
||||||
|
font-weight: var(--font-weight-body);
|
||||||
|
line-height: var(--leading--3);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: var(--tracking-eyebrow);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user