feat: new article body stuffz
Signed-off-by: Filipe Medeiros <hello@filipesm.eu>
This commit is contained in:
parent
d42271eb15
commit
09852de001
|
@ -1,8 +1,7 @@
|
|||
import react from '@astrojs/react';
|
||||
import tailwind from '@astrojs/tailwind';
|
||||
import { defineConfig } from 'astro/config';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [react(), tailwind()],
|
||||
integrations: [tailwind()],
|
||||
});
|
||||
|
|
|
@ -6,7 +6,14 @@ export const forBlogPostPage = groq`
|
|||
{
|
||||
"slug": slug.current,
|
||||
title,
|
||||
content,
|
||||
content[]{
|
||||
_type == 'image' => {
|
||||
...,
|
||||
"lqip": @.asset->metadata.lqip,
|
||||
"alt": @.asset->altText
|
||||
},
|
||||
_type != 'image' => @
|
||||
},
|
||||
headerImage,
|
||||
publishDate
|
||||
}`;
|
||||
|
|
10
frontend/lib/cms/urlFor.ts
Normal file
10
frontend/lib/cms/urlFor.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
import urlBuilder from '@sanity/image-url';
|
||||
import type { SanityImageSource } from '@sanity/image-url/lib/types/types';
|
||||
|
||||
import client from './client';
|
||||
|
||||
const builder = urlBuilder(client);
|
||||
|
||||
export default function urlFor(source: SanityImageSource) {
|
||||
return builder.image(source);
|
||||
}
|
|
@ -11,19 +11,16 @@
|
|||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/react": "^2.1.1",
|
||||
"@astrojs/tailwind": "^3.1.1",
|
||||
"@portabletext/react": "^2.0.2",
|
||||
"@sanity/client": "^5.4.2",
|
||||
"@sanity/image-url": "^1.0.2",
|
||||
"astro": "^2.2.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
"astro-portabletext": "^0.8.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@portabletext/types": "^2.0.2",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.1.1",
|
||||
"@types/react": "^18.0.21",
|
||||
"@types/react-dom": "^18.0.6",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"groq": "^3.8.3",
|
||||
"postcss": "^8.4.21",
|
||||
|
|
|
@ -1,9 +1,6 @@
|
|||
lockfileVersion: '6.0'
|
||||
|
||||
dependencies:
|
||||
'@astrojs/react':
|
||||
specifier: ^2.1.1
|
||||
version: 2.1.1(@types/react-dom@18.0.11)(@types/react@18.0.33)(react-dom@18.2.0)(react@18.2.0)
|
||||
'@astrojs/tailwind':
|
||||
specifier: ^3.1.1
|
||||
version: 3.1.1(astro@2.2.1)(tailwindcss@3.3.1)
|
||||
|
@ -13,18 +10,15 @@ dependencies:
|
|||
'@sanity/client':
|
||||
specifier: ^5.4.2
|
||||
version: 5.4.2
|
||||
'@sanity/image-url':
|
||||
specifier: ^1.0.2
|
||||
version: 1.0.2
|
||||
astro:
|
||||
specifier: ^2.2.1
|
||||
version: 2.2.1
|
||||
groq:
|
||||
specifier: ^3.8.3
|
||||
version: 3.8.3
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
react-dom:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0(react@18.2.0)
|
||||
astro-portabletext:
|
||||
specifier: ^0.8.0
|
||||
version: 0.8.0
|
||||
|
||||
devDependencies:
|
||||
'@portabletext/types':
|
||||
|
@ -33,15 +27,12 @@ devDependencies:
|
|||
'@trivago/prettier-plugin-sort-imports':
|
||||
specifier: ^4.1.1
|
||||
version: 4.1.1(prettier@2.8.7)
|
||||
'@types/react':
|
||||
specifier: ^18.0.21
|
||||
version: 18.0.33
|
||||
'@types/react-dom':
|
||||
specifier: ^18.0.6
|
||||
version: 18.0.11
|
||||
autoprefixer:
|
||||
specifier: ^10.4.14
|
||||
version: 10.4.14(postcss@8.4.21)
|
||||
groq:
|
||||
specifier: ^3.8.3
|
||||
version: 3.8.3
|
||||
postcss:
|
||||
specifier: ^8.4.21
|
||||
version: 8.4.21
|
||||
|
@ -118,25 +109,6 @@ packages:
|
|||
prismjs: 1.29.0
|
||||
dev: false
|
||||
|
||||
/@astrojs/react@2.1.1(@types/react-dom@18.0.11)(@types/react@18.0.33)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-nIcDFnn5H4FKGoSBYXZr95RIQvpcTNRcVV1hvUQifO0F5hQsgb0PVyk6TG4JWxiPGY4Jt4MVQb5JaaDQHlHu4w==}
|
||||
engines: {node: '>=16.12.0'}
|
||||
peerDependencies:
|
||||
'@types/react': ^17.0.50 || ^18.0.21
|
||||
'@types/react-dom': ^17.0.17 || ^18.0.6
|
||||
react: ^17.0.2 || ^18.0.0
|
||||
react-dom: ^17.0.2 || ^18.0.0
|
||||
dependencies:
|
||||
'@babel/core': 7.21.4
|
||||
'@babel/plugin-transform-react-jsx': 7.21.0(@babel/core@7.21.4)
|
||||
'@types/react': 18.0.33
|
||||
'@types/react-dom': 18.0.11
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@astrojs/tailwind@3.1.1(astro@2.2.1)(tailwindcss@3.3.1):
|
||||
resolution: {integrity: sha512-Wx/ZtVnmtfqHWGVzvUEYZm8rufVKVgDIef0q6fzwUxoT1EpTTwBkTbpnzooogewMLOh2eTscasGe3Ih2HC1wVA==}
|
||||
peerDependencies:
|
||||
|
@ -754,6 +726,11 @@ packages:
|
|||
eventsource: 2.0.2
|
||||
dev: false
|
||||
|
||||
/@sanity/image-url@1.0.2:
|
||||
resolution: {integrity: sha512-C4+jb2ny3ZbMgEkLd7Z3C75DsxcTEoE+axXQJsQ75ou0AKWGdVsP351hqK6mJUUxn5HCSlu3vznoh7Yljye4cQ==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
dev: false
|
||||
|
||||
/@trivago/prettier-plugin-sort-imports@4.1.1(prettier@2.8.7):
|
||||
resolution: {integrity: sha512-dQ2r2uzNr1x6pJsuh/8x0IRA3CBUB+pWEW3J/7N98axqt7SQSm+2fy0FLNXvXGg77xEDC7KHxJlHfLYyi7PDcw==}
|
||||
peerDependencies:
|
||||
|
@ -851,28 +828,10 @@ packages:
|
|||
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
|
||||
dev: false
|
||||
|
||||
/@types/prop-types@15.7.5:
|
||||
resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==}
|
||||
|
||||
/@types/react-dom@18.0.11:
|
||||
resolution: {integrity: sha512-O38bPbI2CWtgw/OoQoY+BRelw7uysmXbWvw3nLWO21H1HSh+GOlqPuXshJfjmpNlKiiSDG9cc1JZAaMmVdcTlw==}
|
||||
dependencies:
|
||||
'@types/react': 18.0.33
|
||||
|
||||
/@types/react@18.0.33:
|
||||
resolution: {integrity: sha512-sHxzVxeanvQyQ1lr8NSHaj0kDzcNiGpILEVt69g9S31/7PfMvNCKLKcsHw4lYKjs3cGNJjXSP4mYzX43QlnjNA==}
|
||||
dependencies:
|
||||
'@types/prop-types': 15.7.5
|
||||
'@types/scheduler': 0.16.3
|
||||
csstype: 3.1.2
|
||||
|
||||
/@types/resolve@1.20.2:
|
||||
resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==}
|
||||
dev: false
|
||||
|
||||
/@types/scheduler@0.16.3:
|
||||
resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==}
|
||||
|
||||
/@types/unist@2.0.6:
|
||||
resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==}
|
||||
dev: false
|
||||
|
@ -958,6 +917,13 @@ packages:
|
|||
resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==}
|
||||
dev: false
|
||||
|
||||
/astro-portabletext@0.8.0:
|
||||
resolution: {integrity: sha512-2zA5TJ70Uhd4XfLlcTgxFMe202mEyB4V5R81KsjrP0nqBBHZLk1MaWxHPNq8Bz9KrF/u0mNYp+HFMQ/L/TDW7A==}
|
||||
dependencies:
|
||||
'@portabletext/toolkit': 2.0.1
|
||||
'@portabletext/types': 2.0.2
|
||||
dev: false
|
||||
|
||||
/astro@2.2.1:
|
||||
resolution: {integrity: sha512-yYPRzh3su38bi3VBCKmYAUBkQSaFQMKFsu8JAVDzFRoGLbskJ/6JkDX2abSB9/iRug8GAKaH/FWxXOTzIsSQ7Q==}
|
||||
engines: {node: '>=16.12.0', npm: '>=6.14.0'}
|
||||
|
@ -1269,9 +1235,6 @@ packages:
|
|||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
/csstype@3.1.2:
|
||||
resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==}
|
||||
|
||||
/debug@4.3.4:
|
||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
|
@ -1629,7 +1592,7 @@ packages:
|
|||
/groq@3.8.3:
|
||||
resolution: {integrity: sha512-2zB3MseKzoZ+zySVJBB3u/tNYn4nEepF8O3fNa71ojD5UwG0Ra2kzNR9sbojF+eToazCHKcvPW73OfB9yYrYsQ==}
|
||||
engines: {node: '>=14'}
|
||||
dev: false
|
||||
dev: true
|
||||
|
||||
/has-flag@3.0.0:
|
||||
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
|
||||
|
@ -2817,16 +2780,6 @@ packages:
|
|||
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
|
||||
engines: {node: '>=10'}
|
||||
|
||||
/react-dom@18.2.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==}
|
||||
peerDependencies:
|
||||
react: ^18.2.0
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
react: 18.2.0
|
||||
scheduler: 0.23.0
|
||||
dev: false
|
||||
|
||||
/react@18.2.0:
|
||||
resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
@ -3038,12 +2991,6 @@ packages:
|
|||
suf-log: 2.5.3
|
||||
dev: false
|
||||
|
||||
/scheduler@0.23.0:
|
||||
resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==}
|
||||
dependencies:
|
||||
loose-envify: 1.4.0
|
||||
dev: false
|
||||
|
||||
/section-matter@1.0.0:
|
||||
resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==}
|
||||
engines: {node: '>=4'}
|
||||
|
|
|
@ -1,78 +0,0 @@
|
|||
import { PortableText, PortableTextReactComponents } from '@portabletext/react';
|
||||
import type { PortableTextBlock } from '@portabletext/types';
|
||||
|
||||
export interface Props {
|
||||
content: PortableTextBlock[];
|
||||
}
|
||||
|
||||
const components: Partial<PortableTextReactComponents> = {
|
||||
block: {
|
||||
h1: ({ children }) => (
|
||||
<h2 className="mb-2 mt-4 text-3xl font-medium">{children}</h2>
|
||||
),
|
||||
h2: ({ children }) => (
|
||||
<h3 className="mb-2 mt-3 text-2xl font-medium">{children}</h3>
|
||||
),
|
||||
h3: ({ children }) => (
|
||||
<h4 className="mb-2 text-xl font-medium">{children}</h4>
|
||||
),
|
||||
h4: ({ children }) => (
|
||||
<h5 className="mb-2 text-lg font-medium">{children}</h5>
|
||||
),
|
||||
h5: ({ children }) => (
|
||||
<h6 className="mb-2 text-lg underline">{children}</h6>
|
||||
),
|
||||
h6: ({ children }) => <h6 className="mb-2 text-lg">{children}</h6>,
|
||||
normal: ({ children }) => <p className="mb-2">{children}</p>,
|
||||
},
|
||||
marks: {
|
||||
code: ({ children }) => (
|
||||
<code className="bg-stone-800 p-0.5 px-1 text-white">{children}</code>
|
||||
),
|
||||
link: ({ children, value }) => {
|
||||
return (
|
||||
<a
|
||||
className="text-primary-800 underline hover:text-primary-700"
|
||||
href={value.href}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
},
|
||||
},
|
||||
list: {
|
||||
bullet: ({ children }) => (
|
||||
<ul className="list-disc [counter-reset:list-counter]">{children}</ul>
|
||||
),
|
||||
number: ({ children }) => (
|
||||
<ol className="[counter-reset:list-counter]">{children}</ol>
|
||||
),
|
||||
},
|
||||
listItem: {
|
||||
bullet: ({ children }) => <li className="mb-1 ml-5 pl-2">{children}</li>,
|
||||
number: ({ children, value }) => (
|
||||
<li
|
||||
className={`mb-1 pl-2 [counter-increment:list-counter] before:pr-2 before:content-[counter(list-counter)'.'] data-[list-type=lower-latin]:before:content-[counter(list-counter,lower-latin)')'] data-[list-type=lower-roman]:before:content-[counter(list-counter,lower-roman)'.'] ${
|
||||
(value.level ?? 1) !== 1 ? 'ml-5' : ''
|
||||
}`}
|
||||
data-list-type={
|
||||
(value.level ?? 1) % 3 === 1
|
||||
? 'decimal'
|
||||
: (value.level ?? 1) % 3 === 2
|
||||
? 'lower-latin'
|
||||
: 'lower-roman'
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</li>
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
export default function BlogPostContent({ content }: Props) {
|
||||
return (
|
||||
<div className="text-justify">
|
||||
<PortableText components={components} value={content} />
|
||||
</div>
|
||||
);
|
||||
}
|
57
frontend/src/components/portableText/BlogPostContent.astro
Normal file
57
frontend/src/components/portableText/BlogPostContent.astro
Normal file
|
@ -0,0 +1,57 @@
|
|||
---
|
||||
import { PortableText } from 'astro-portabletext';
|
||||
import type { PortableTextBlock } from '@portabletext/types';
|
||||
|
||||
import ShowableFigure from './components/ShowableFigure.astro';
|
||||
import NumberListItem from './components/NumberListItem.astro';
|
||||
import InlineLink from './components/InlineLink.astro';
|
||||
import InlineCode from './components/InlineCode.astro';
|
||||
import BulletList from './components/BulletList.astro';
|
||||
import NumberList from './components/NumberList.astro';
|
||||
import BulletListItem from './components/BulletListItem.astro';
|
||||
import Heading1 from './components/Heading1.astro';
|
||||
import Heading2 from './components/Heading2.astro';
|
||||
import Heading3 from './components/Heading3.astro';
|
||||
import Heading4 from './components/Heading4.astro';
|
||||
import Heading5 from './components/Heading5.astro';
|
||||
import Heading6 from './components/Heading6.astro';
|
||||
import Paragraph from './components/Paragraph.astro';
|
||||
|
||||
export interface Props {
|
||||
content: PortableTextBlock[];
|
||||
}
|
||||
|
||||
const components = {
|
||||
type: {
|
||||
image: ShowableFigure,
|
||||
},
|
||||
block: {
|
||||
h1: Heading1,
|
||||
h2: Heading2,
|
||||
h3: Heading3,
|
||||
h4: Heading4,
|
||||
h5: Heading5,
|
||||
h6: Heading6,
|
||||
normal: Paragraph,
|
||||
},
|
||||
marks: {
|
||||
code: InlineCode,
|
||||
link: InlineLink,
|
||||
},
|
||||
list: {
|
||||
bullet: BulletList,
|
||||
number: NumberList,
|
||||
},
|
||||
listItem: {
|
||||
bullet: BulletListItem,
|
||||
number: NumberListItem,
|
||||
},
|
||||
};
|
||||
|
||||
const { content } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="text-justify">
|
||||
{/* @ts-expect-error */}
|
||||
<PortableText components={components} value={content} />
|
||||
</div>
|
|
@ -0,0 +1,3 @@
|
|||
<ul class="list-disc ps-2 list-inside [counter-reset:list-counter]">
|
||||
<slot />
|
||||
</ul>
|
|
@ -0,0 +1,3 @@
|
|||
<li>
|
||||
<slot />
|
||||
</li>
|
|
@ -0,0 +1,3 @@
|
|||
<h2 class="mb-2 mt-4 text-3xl font-medium">
|
||||
<slot />
|
||||
</h2>
|
|
@ -0,0 +1,3 @@
|
|||
<h3 class="mb-2 mt-3 text-2xl font-medium">
|
||||
<slot />
|
||||
</h3>
|
|
@ -0,0 +1,3 @@
|
|||
<h4 class="mb-2 text-xl font-medium">
|
||||
<slot />
|
||||
</h4>
|
|
@ -0,0 +1,3 @@
|
|||
<h5 class="mb-2 text-lg font-medium">
|
||||
<slot />
|
||||
</h5>
|
|
@ -0,0 +1,3 @@
|
|||
<h6 class="mb-2 text-lg underline">
|
||||
<slot />
|
||||
</h6>
|
|
@ -0,0 +1,3 @@
|
|||
<h6 class="mb-2 text-lg">
|
||||
<slot />
|
||||
</h6>
|
|
@ -0,0 +1,3 @@
|
|||
<code class="bg-stone-800 p-0.5 px-1 text-white">
|
||||
<slot />
|
||||
</code>
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
import type { PortableTextLink } from '@portabletext/types';
|
||||
|
||||
export interface Props {
|
||||
value?: PortableTextLink;
|
||||
}
|
||||
|
||||
const { value } = Astro.props;
|
||||
---
|
||||
|
||||
<a class="text-primary-800 underline hover:text-primary-700" href={value?.href}>
|
||||
<slot />
|
||||
</a>
|
|
@ -0,0 +1,3 @@
|
|||
<ol class="[counter-reset:list-counter] ps-2 list-inside">
|
||||
<slot />
|
||||
</ol>
|
|
@ -0,0 +1,22 @@
|
|||
---
|
||||
import type { PortableTextListItemBlock } from '@portabletext/types';
|
||||
|
||||
export interface Props {
|
||||
node: PortableTextListItemBlock;
|
||||
}
|
||||
|
||||
const { node: value } = Astro.props;
|
||||
---
|
||||
|
||||
<li
|
||||
class:list={[
|
||||
"[counter-increment:list-counter] before:content-[counter(list-counter)'.'] data-[list-type=lower-latin]:before:content-[counter(list-counter,lower-latin)')'] data-[list-type=lower-roman]:before:content-[counter(list-counter,lower-roman)'.']",
|
||||
]}
|
||||
data-list-type={(value.level ?? 1) % 3 === 1
|
||||
? 'decimal'
|
||||
: (value.level ?? 1) % 3 === 2
|
||||
? 'lower-latin'
|
||||
: 'lower-roman'}
|
||||
>
|
||||
<slot />
|
||||
</li>
|
|
@ -0,0 +1,3 @@
|
|||
<p class="mb-2">
|
||||
<slot />
|
||||
</p>
|
|
@ -0,0 +1,31 @@
|
|||
---
|
||||
import { PortableText } from 'astro-portabletext';
|
||||
import ShowableImage from './ShowableImage.astro';
|
||||
import type { Props as ShowableImageProps } from './ShowableImage.astro';
|
||||
import InlineLink from './InlineLink.astro';
|
||||
|
||||
export interface Props extends ShowableImageProps {}
|
||||
|
||||
const { node: value } = Astro.props;
|
||||
---
|
||||
|
||||
{
|
||||
!value.caption ? (
|
||||
<ShowableImage {...Astro.props} />
|
||||
) : (
|
||||
<figure class="flex flex-col gap-1 mb-4 mt-4">
|
||||
<ShowableImage {...Astro.props} />
|
||||
<figcaption class="text-sm text-start">
|
||||
<PortableText
|
||||
components={{
|
||||
mark: {
|
||||
// @ts-expect-error
|
||||
link: InlineLink,
|
||||
},
|
||||
}}
|
||||
value={value.caption}
|
||||
/>
|
||||
</figcaption>
|
||||
</figure>
|
||||
)
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
---
|
||||
import type { PortableTextBlock } from '@portabletext/types';
|
||||
import urlFor from '../../../../lib/cms/urlFor';
|
||||
|
||||
export interface Props {
|
||||
node: BlogPostContentImage;
|
||||
}
|
||||
|
||||
export interface BlogPostContentImage {
|
||||
lqip: string;
|
||||
_type: 'image';
|
||||
asset: {
|
||||
_type: 'reference';
|
||||
ref: string;
|
||||
};
|
||||
caption: PortableTextBlock[];
|
||||
alt: string;
|
||||
}
|
||||
|
||||
const { node: value } = Astro.props;
|
||||
---
|
||||
|
||||
<showable-image>
|
||||
<div class="relative" role="button" class="w-full" data-wrapper>
|
||||
<img
|
||||
src={value.lqip}
|
||||
alt={`${value.alt} Quando esta página carrega, esta imagem está desfocada para poupar dados e energia. Podes carregar na imagem para mostrar a imagem completa.`}
|
||||
class="w-full border-2 border-primary-800"
|
||||
data-url={urlFor(value).url()}
|
||||
/>
|
||||
<div
|
||||
data-tooltip
|
||||
class="text-xs w-10/12 sm:w-1/2 left-1/2 -translate-x-1/2 top-1/2 -translate-y-1/2 text-center absolute leading-tight bg-primary-900/80 text-white p-3"
|
||||
>
|
||||
<p class="mb-1">
|
||||
Para poupar os teus dados e um bocadinho de energia, tens esta
|
||||
pre-visualização da imagem.
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
Clica na pre-visualização para veres a versão completa.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</showable-image>
|
||||
|
||||
<script>
|
||||
class ShowableImage extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
const image = this.querySelector('img')!;
|
||||
const wrapper = this.querySelector('[data-wrapper]')!;
|
||||
const tooltip = this.querySelector('[data-tooltip]')!;
|
||||
|
||||
wrapper.addEventListener('click', () => {
|
||||
image.src = image.dataset.url!;
|
||||
wrapper.role = 'none';
|
||||
tooltip.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('showable-image', ShowableImage);
|
||||
</script>
|
|
@ -2,7 +2,7 @@
|
|||
import type { PortableTextBlock } from '@portabletext/types';
|
||||
import client from '../../../../lib/cms/client';
|
||||
import { forBlogPostPage } from '../../../../lib/cms/queries/blogPosts';
|
||||
import BlogPostContent from '../../../components/BlogPostContent';
|
||||
import BlogPostContent from '../../../components/portableText/BlogPostContent.astro';
|
||||
import ButtonLink from '../../../components/ButtonLink.astro';
|
||||
import PageTitle from '../../../components/PageTitle.astro';
|
||||
import Layout from '../../../layouts/Layout.astro';
|
||||
|
|
Loading…
Reference in a new issue