Skip to content

Instantly share code, notes, and snippets.

@mornir
Created December 29, 2025 14:28
Show Gist options
  • Select an option

  • Save mornir/4ad778bfd7f1777dc83df9b118887bbc to your computer and use it in GitHub Desktop.

Select an option

Save mornir/4ad778bfd7f1777dc83df9b118887bbc to your computer and use it in GitHub Desktop.
BSV Article
---
import type {
GetArticleQueryResult,
BlockContent,
} from '../sanity/sanity.types'
import RichText from '@/components/portable-text/RichText.astro'
import { Icon } from 'astro-icon/components'
interface Props {
article: GetArticleQueryResult
}
const { article } = Astro.props
if (!article) return Astro.redirect('/404')
function countDistinctItems(blockContent: BlockContent | undefined) {
if (!blockContent) {
return 0
}
let count = 0
let lastWasBullet = false
for (let item of blockContent) {
// @ts-ignore
if (item?.children?.some((el) => el._type === 'table')) {
count++
}
// @ts-ignore
if (item.listItem === 'bullet' || item.listItem === 'number') {
if (!lastWasBullet) {
count++
}
lastWasBullet = true
} else {
count++
lastWasBullet = false
}
}
return count
}
const colsLaw = countDistinctItems(article.law.de)
const colsExp = countDistinctItems(article.exp?.de)
// Explicitly type the languages array
const languages: Array<'de' | 'fr' | 'it'> = ['de', 'fr', 'it']
const titles = {
de: article.name.de,
fr: article.name.fr,
it: article.name.it,
}
const laws = {
de: article.law.de,
fr: article.law.fr,
it: article.law.it,
}
const explanations = {
de: article?.exp?.de,
fr: article?.exp?.fr,
it: article?.exp?.it,
}
const references = [`${article.title.number}. Titel`]
if (article.chapter?.number) {
references.push(`${article.chapter.number}. Kapitel`)
}
if (article.section?.number) {
references.push(`${article.section.number}. Abschnitt`)
}
---
<article
class="prose scroll-mt-12 prose-stone prose-p:my-2 prose-ol:mt-0 prose-ol:mb-2 prose-ul:mt-0 prose-ul:mb-2 prose-thead:font-semibold"
:class="languages.length === 1 ? 'mx-auto' : 'max-w-none prose-sm'"
id={`art-${article.number}`}
x-cloak
>
<header class="relative mt-6 flex items-baseline justify-between">
<button
x-data={`{ link: '${Astro.site}art/${article.number}', copied: false}`}
@click="navigator.clipboard.writeText(link); copied = true"
class="absolute top-1/2 -left-10 cursor-pointer"
>
<Icon
name="mdi:link"
class="text-xl text-gray-500 hover:text-accent"
x-show="!copied"
/>
<Icon name="mdi:check" class="text-xl text-gray-500" x-show="copied" />
</button>
<h3>Art. {article.number}</h3>
<h4 class="text-xs font-semibold text-gray-500">
{references.join(', ')}
</h4>
</header>
<!-- Article Title -->
<div class="grid auto-cols-fr grid-flow-col grid-rows-1 gap-x-8">
{
languages.map((lang) => (
<h2 x-show={`languages.includes('${lang}')`} class="mt-0 mb-2">
<a
href={`/art/${article.number}`}
class="text-lg font-semibold no-underline decoration-accent hover:underline"
>
{titles[lang]}
</a>
</h2>
))
}
</div>
<div
class="grid auto-cols-fr grid-flow-col gap-x-8"
style={`grid-template-rows: repeat(${colsLaw}, auto)`}
>
{
languages.map((lang) => (
<div x-show={`languages.includes('${lang}')`} class="c-law contents">
<RichText blocks={laws[lang]} />
</div>
))
}
</div>
{
explanations.de && (
<details x-show="exp === 'toggle'">
<summary class="cursor-pointer">Erläuterung anzeigen</summary>
<div
class="grid auto-cols-fr grid-flow-col gap-x-8 text-blue-600"
style={`grid-template-rows: repeat(${colsExp}, auto)`}
>
{languages.map(
(lang) =>
explanations[lang] && (
<div x-show={`languages.includes('${lang}')`} class="contents">
<RichText blocks={explanations[lang]} />
</div>
)
)}
</div>
</details>
)
}
{
explanations.de && (
<div
class="grid auto-cols-fr grid-flow-col gap-x-8 text-blue-600"
style={`grid-template-rows: repeat(${colsExp}, auto)`}
x-show="exp === 'show'"
>
{languages.map(
(lang) =>
explanations[lang] && (
<div x-show={`languages.includes('${lang}')`} class="contents">
<RichText blocks={explanations[lang]} />
</div>
)
)}
</div>
)
}
</article>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment