diff --git a/src/components/common/card/card.module.scss b/src/components/common/card/card.module.scss
index 5fe6e25..1aff0e3 100644
--- a/src/components/common/card/card.module.scss
+++ b/src/components/common/card/card.module.scss
@@ -1,16 +1,139 @@
@import '~/css/helpers';
.card {
+ cursor: pointer;
display: flex;
flex-direction: column;
- cursor: pointer;
padding-bottom: tovw(2px, 'default', 2px);
+ white-space: normal;
width: 100%;
&-blog {
+ border-bottom: none;
+
+ &:hover,
+ &:focus {
+ .read span {
+ &::after {
+ opacity: 0;
+ }
+
+ &::before {
+ opacity: 1;
+ background-image: repeating-linear-gradient(
+ 0deg,
+ currentcolor,
+ currentcolor tovw(4px, 'default', 3px),
+ transparent tovw(4px, 'default', 3px),
+ transparent tovw(8px, 'default', 6px),
+ currentcolor tovw(8px, 'default', 6px)
+ ),
+ repeating-linear-gradient(
+ 90deg,
+ currentcolor,
+ currentcolor tovw(4px, 'default', 3px),
+ transparent tovw(4px, 'default', 3px),
+ transparent tovw(8px, 'default', 6px),
+ currentcolor tovw(8px, 'default', 6px)
+ ),
+ repeating-linear-gradient(
+ currentcolor,
+ currentcolor tovw(4px, 'default', 3px),
+ transparent tovw(4px, 'default', 3px),
+ transparent tovw(8px, 'default', 6px),
+ currentcolor tovw(8px, 'default', 6px)
+ ),
+ repeating-linear-gradient(
+ 270deg,
+ currentcolor,
+ currentcolor tovw(4px, 'default', 3px),
+ transparent tovw(4px, 'default', 3px),
+ transparent tovw(8px, 'default', 6px),
+ currentcolor tovw(8px, 'default', 6px)
+ );
+ }
+ }
+ }
+
+ &::after,
+ &::before {
+ content: none;
+ }
+
.content {
height: auto;
}
+
+ .read {
+ span {
+ position: relative;
+
+ &::before {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ opacity: 0;
+ background-image: repeating-linear-gradient(
+ 0deg,
+ currentcolor,
+ currentcolor 100%,
+ transparent 100%,
+ transparent 100%,
+ currentcolor 100%
+ ),
+ repeating-linear-gradient(
+ 90deg,
+ currentcolor,
+ currentcolor 100%,
+ transparent 100%,
+ transparent 100%,
+ currentcolor 100%
+ ),
+ repeating-linear-gradient(
+ currentcolor,
+ currentcolor 100%,
+ transparent 100%,
+ transparent 100%,
+ currentcolor 100%
+ ),
+ repeating-linear-gradient(
+ 270deg,
+ currentcolor,
+ currentcolor 100%,
+ transparent 100%,
+ transparent 100%,
+ currentcolor 100%
+ );
+ background-position: 0 0, 0 0, 100% 0, 0 100%;
+ background-repeat: no-repeat;
+ background-size: 0 100%, 100% 0, 0 100%, 100% 2px;
+ width: 100%;
+ height: tovw(1px, 'default', 1px);
+ animation: border var(--duration-normal) linear infinite;
+ content: '';
+ pointer-events: none;
+ }
+
+ &::after {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ background: currentcolor;
+ width: 100%;
+ height: tovw(1px);
+ content: '';
+ }
+ }
+
+ svg {
+ height: 10px;
+ width: 10px;
+ }
+ }
+
+ > svg {
+ display: none;
+ }
}
&__header {
@@ -170,3 +293,15 @@
font-size: tovw(18px, 'default', 15px);
}
}
+
+@keyframes border {
+ from {
+ background-position: 0 0, tovw(8px, 'default', 6px) 0,
+ 100% tovw(8px, 'default', 6px), 0 100%;
+ }
+
+ to {
+ background-position: 0 tovw(8px, 'default', 6px), 0 0, 100% 0,
+ tovw(8px, 'default', 6px) 100%;
+ }
+}
diff --git a/src/components/common/card/index.tsx b/src/components/common/card/index.tsx
index 04c3645..dd6347f 100644
--- a/src/components/common/card/index.tsx
+++ b/src/components/common/card/index.tsx
@@ -1,6 +1,7 @@
import clsx from 'clsx'
import NextLink from 'next/link'
+import { ArrowLink } from '~/components/icons/arrow'
import { Calendar, Clock } from '~/components/icons/events'
import Heading from '~/components/primitives/heading'
import Link from '~/components/primitives/link'
@@ -74,7 +75,8 @@ export const BlogCard = ({
horizontal = false
}: BlogCardProps) => {
return (
-
{horizontal &&
{data && getDescription(data)}
}
-
READ ARTICLE
+
-
+
)
}
diff --git a/src/components/sections/blog/post-content/content.module.scss b/src/components/sections/blog/post-content/content.module.scss
index e5de448..05d0bab 100644
--- a/src/components/sections/blog/post-content/content.module.scss
+++ b/src/components/sections/blog/post-content/content.module.scss
@@ -10,6 +10,7 @@ $img-height-mobile: 200px;
@media screen and (max-width: 800px) {
transform: none;
+ padding-bottom: tovw(56px, 'default', 56px);
}
.image__container {
diff --git a/src/components/sections/blog/posts-grid/index.tsx b/src/components/sections/blog/posts-grid/index.tsx
index 8e49d3b..74c727c 100644
--- a/src/components/sections/blog/posts-grid/index.tsx
+++ b/src/components/sections/blog/posts-grid/index.tsx
@@ -5,11 +5,13 @@ import s from './posts-grid.module.scss'
interface PostsGridProps {
children: React.ReactNode
+ title?: string
}
-const PostsGrid = ({ children }: PostsGridProps) => {
+const PostsGrid = ({ children, title }: PostsGridProps) => {
return (
+ {title && {title}
}
{children}
)
diff --git a/src/components/sections/blog/posts-grid/posts-grid.module.scss b/src/components/sections/blog/posts-grid/posts-grid.module.scss
index d4b4c2e..a0aa6fc 100644
--- a/src/components/sections/blog/posts-grid/posts-grid.module.scss
+++ b/src/components/sections/blog/posts-grid/posts-grid.module.scss
@@ -9,6 +9,22 @@
row-gap: tovw(104px, 'default', 81px);
@media screen and (max-width: 800px) {
- grid-template-columns: 1fr;
+ display: flex;
+ flex-direction: column;
+ gap: tovw(80px, 'default', 80px);
+ }
+}
+
+.title {
+ font-family: var(--font-arthemys);
+ font-size: tovw(76px, 'default', 42px);
+ font-weight: 400;
+ line-height: tovw(84px, 'default', 48px);
+ margin-top: 0;
+ margin-bottom: tovw(88px, 'default', 44px);
+ text-align: center;
+
+ @media screen and (max-width: 800px) {
+ letter-spacing: -0.02em;
}
}
diff --git a/src/components/sections/blog/search/search.module.scss b/src/components/sections/blog/search/search.module.scss
index 6905ed1..c10390b 100644
--- a/src/components/sections/blog/search/search.module.scss
+++ b/src/components/sections/blog/search/search.module.scss
@@ -26,6 +26,7 @@
text-decoration: none;
white-space: nowrap;
font-size: tovw(12px, 'default', 12px);
+ line-height: tovw(16px, 'default', 16px);
}
}
}
diff --git a/src/components/sections/blog/shares/icons/discord.js b/src/components/sections/blog/shares/icons/discord.js
new file mode 100644
index 0000000..ec0b4d2
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/discord.js
@@ -0,0 +1,16 @@
+const Discord = (props) => (
+
+)
+
+export default Discord
diff --git a/src/components/sections/blog/shares/icons/facebook.js b/src/components/sections/blog/shares/icons/facebook.js
new file mode 100644
index 0000000..933dcd0
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/facebook.js
@@ -0,0 +1,16 @@
+const Facebook = (props) => (
+
+)
+
+export default Facebook
diff --git a/src/components/sections/blog/shares/icons/instagram.js b/src/components/sections/blog/shares/icons/instagram.js
new file mode 100644
index 0000000..bd10f76
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/instagram.js
@@ -0,0 +1,20 @@
+const Instagram = (props) => (
+
+)
+
+export default Instagram
diff --git a/src/components/sections/blog/shares/icons/reddit.js b/src/components/sections/blog/shares/icons/reddit.js
new file mode 100644
index 0000000..fa6daf3
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/reddit.js
@@ -0,0 +1,18 @@
+const Reddit = (props) => (
+
+)
+
+export default Reddit
diff --git a/src/components/sections/blog/shares/icons/telegram.js b/src/components/sections/blog/shares/icons/telegram.js
new file mode 100644
index 0000000..c3f36fc
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/telegram.js
@@ -0,0 +1,18 @@
+const Telegram = (props) => (
+
+)
+
+export default Telegram
diff --git a/src/components/sections/blog/shares/icons/twitter.js b/src/components/sections/blog/shares/icons/twitter.js
new file mode 100644
index 0000000..b85f613
--- /dev/null
+++ b/src/components/sections/blog/shares/icons/twitter.js
@@ -0,0 +1,16 @@
+const Twitter = (props) => (
+
+)
+
+export default Twitter
diff --git a/src/components/sections/blog/shares/index.tsx b/src/components/sections/blog/shares/index.tsx
new file mode 100644
index 0000000..981f135
--- /dev/null
+++ b/src/components/sections/blog/shares/index.tsx
@@ -0,0 +1,64 @@
+import Link from 'next/link'
+
+import { Container } from '~/components/layout/container'
+import Section from '~/components/layout/section'
+
+import Discord from './icons/discord'
+import Facebook from './icons/facebook'
+import Instagram from './icons/instagram'
+import Reddit from './icons/reddit'
+import Telegram from './icons/telegram'
+import Twitter from './icons/twitter'
+import s from './shares.module.scss'
+
+interface SharesProps {
+ url: string
+}
+
+const Shares = ({ url }: SharesProps) => {
+ const encodedUrl = encodeURIComponent(url)
+
+ return (
+
+
+ SHARE THIS ARTICLE
+
+
+
+ )
+}
+
+export default Shares
diff --git a/src/components/sections/blog/shares/shares.module.scss b/src/components/sections/blog/shares/shares.module.scss
new file mode 100644
index 0000000..189d301
--- /dev/null
+++ b/src/components/sections/blog/shares/shares.module.scss
@@ -0,0 +1,47 @@
+@import '~/css/helpers';
+
+.container {
+ border-top: 1px solid var(--color-white);
+ padding-top: tovw(96px, 'default', 48px);
+ padding-bottom: tovw(243px, 'default', 145px);
+ text-align: center;
+ max-width: tovw(856px, 'default', 856px);
+
+ > p {
+ font-size: tovw(18px, 'default', 12px);
+ line-height: tovw(23px, 'default', 16px);
+ margin-bottom: tovw(56px, 'default', 32px);
+
+ @media screen and (max-width: 800px) {
+ letter-spacing: -0.02em;
+ }
+ }
+
+ > div {
+ display: flex;
+ gap: tovw(32px, 'default', 16px);
+ justify-content: center;
+ flex-wrap: wrap;
+
+ a {
+ align-items: center;
+ background-color: var(--color-black);
+ border: 1px solid var(--color-white);
+ border-radius: 30px;
+ color: var(--color-white);
+ display: flex;
+ height: tovw(56px, 'default', 48px);
+ justify-content: center;
+ transition: filter 0.2s, filter 0.2s;
+ width: tovw(72px, 'default', 64px);
+
+ svg {
+ height: 28px;
+ }
+
+ &:hover {
+ filter: invert(1);
+ }
+ }
+ }
+}
diff --git a/src/lib/blog.ts b/src/lib/blog.ts
index be64803..3192c0e 100644
--- a/src/lib/blog.ts
+++ b/src/lib/blog.ts
@@ -43,13 +43,6 @@ export const getBlogPosts = async ({
export const getBlogPostsCategories = async () => {
const { allCategories } = await cms().GetBlogPostsCategories()
- // Push dummy category
- allCategories.push({
- id: '0',
- slug: 'none',
- title: 'No Category'
- })
-
return allCategories
}
diff --git a/src/lib/cms/fragments/blog-post.gql b/src/lib/cms/fragments/blog-post.gql
index 427307d..1e41084 100644
--- a/src/lib/cms/fragments/blog-post.gql
+++ b/src/lib/cms/fragments/blog-post.gql
@@ -14,6 +14,23 @@ fragment BlogPost on BlogPostRecord {
slug
content {
value
+ blocks {
+ __typename
+ ... on ImageRecord {
+ id
+ title
+ asset {
+ url
+ width
+ height
+ }
+ }
+ ... on CtaRecord {
+ id
+ label
+ url
+ }
+ }
}
image {
...Image
diff --git a/src/lib/cms/generated.ts b/src/lib/cms/generated.ts
index 056e452..c087724 100644
--- a/src/lib/cms/generated.ts
+++ b/src/lib/cms/generated.ts
@@ -99,9 +99,11 @@ export type AuthorRecord_SeoMetaTagsArgs = {
locale?: InputMaybe;
};
+export type BlogPostModelContentBlocksField = CtaRecord | ImageRecord;
+
export type BlogPostModelContentField = {
__typename?: 'BlogPostModelContentField';
- blocks: Array;
+ blocks: Array;
links: Array;
value: Scalars['JsonField'];
};
@@ -317,6 +319,33 @@ export type CreatedAtFilter = {
neq?: InputMaybe;
};
+/** Record of type Cta (cta) */
+export type CtaRecord = {
+ __typename?: 'CtaRecord';
+ _createdAt: Scalars['DateTime'];
+ _firstPublishedAt?: Maybe;
+ _isValid: Scalars['BooleanType'];
+ _modelApiKey: Scalars['String'];
+ _publicationScheduledAt?: Maybe;
+ _publishedAt?: Maybe;
+ /** SEO meta tags */
+ _seoMetaTags: Array;
+ _status: ItemStatus;
+ _unpublishingScheduledAt?: Maybe;
+ _updatedAt: Scalars['DateTime'];
+ createdAt: Scalars['DateTime'];
+ id: Scalars['ItemId'];
+ label?: Maybe;
+ updatedAt: Scalars['DateTime'];
+ url?: Maybe;
+};
+
+
+/** Record of type Cta (cta) */
+export type CtaRecord_SeoMetaTagsArgs = {
+ locale?: InputMaybe;
+};
+
/** Specifies how to filter Date fields */
export type DateFilter = {
/** Search for records with an exact match */
@@ -440,6 +469,33 @@ export type GlobalSeoField = {
twitterAccount?: Maybe;
};
+/** Record of type Image (image) */
+export type ImageRecord = {
+ __typename?: 'ImageRecord';
+ _createdAt: Scalars['DateTime'];
+ _firstPublishedAt?: Maybe;
+ _isValid: Scalars['BooleanType'];
+ _modelApiKey: Scalars['String'];
+ _publicationScheduledAt?: Maybe;
+ _publishedAt?: Maybe;
+ /** SEO meta tags */
+ _seoMetaTags: Array;
+ _status: ItemStatus;
+ _unpublishingScheduledAt?: Maybe;
+ _updatedAt: Scalars['DateTime'];
+ asset?: Maybe;
+ createdAt: Scalars['DateTime'];
+ id: Scalars['ItemId'];
+ title?: Maybe;
+ updatedAt: Scalars['DateTime'];
+};
+
+
+/** Record of type Image (image) */
+export type ImageRecord_SeoMetaTagsArgs = {
+ locale?: InputMaybe;
+};
+
export type ImgixParams = {
/**
* Aspect Ratio
@@ -2512,7 +2568,7 @@ export type FocalPoint = {
export type AuthorFragment = { __typename?: 'AuthorRecord', name?: string | null };
-export type BlogPostFragment = { __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null };
+export type BlogPostFragment = { __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any, blocks: Array<{ __typename: 'CtaRecord', id: any, label?: string | null, url?: string | null } | { __typename: 'ImageRecord', id: any, title?: string | null, asset?: { __typename?: 'FileField', url: string, width?: any | null, height?: any | null } | null }> } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null };
export type CategoryFragment = { __typename?: 'CategoryRecord', id: any, title?: string | null, slug?: string | null };
@@ -2535,7 +2591,7 @@ export type GetBlogPostsQueryVariables = Exact<{
}>;
-export type GetBlogPostsQuery = { __typename?: 'Query', _allBlogPostsMeta: { __typename?: 'CollectionMetadata', count: any }, allBlogPosts: Array<{ __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null }> };
+export type GetBlogPostsQuery = { __typename?: 'Query', _allBlogPostsMeta: { __typename?: 'CollectionMetadata', count: any }, allBlogPosts: Array<{ __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any, blocks: Array<{ __typename: 'CtaRecord', id: any, label?: string | null, url?: string | null } | { __typename: 'ImageRecord', id: any, title?: string | null, asset?: { __typename?: 'FileField', url: string, width?: any | null, height?: any | null } | null }> } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null }> };
export type BlogPostsSlugQueryVariables = Exact<{
skip: Scalars['IntType'];
@@ -2550,7 +2606,7 @@ export type SingleBlogPostQueryVariables = Exact<{
}>;
-export type SingleBlogPostQuery = { __typename?: 'Query', blogPost?: { __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null } | null };
+export type SingleBlogPostQuery = { __typename?: 'Query', blogPost?: { __typename?: 'BlogPostRecord', title?: string | null, date?: any | null, slug?: string | null, _seoMetaTags: Array<{ __typename?: 'Tag', content?: string | null, tag: string, attributes?: any | null }>, category: Array<{ __typename?: 'CategoryRecord', title?: string | null, slug?: string | null }>, author?: { __typename?: 'AuthorRecord', name?: string | null } | null, content?: { __typename?: 'BlogPostModelContentField', value: any, blocks: Array<{ __typename: 'CtaRecord', id: any, label?: string | null, url?: string | null } | { __typename: 'ImageRecord', id: any, title?: string | null, asset?: { __typename?: 'FileField', url: string, width?: any | null, height?: any | null } | null }> } | null, image?: { __typename?: 'FileField', url: string, alt?: string | null, height?: any | null, width?: any | null, title?: string | null } | null } | null };
export const SeoTagsFragmentDoc = gql`
fragment SEOTags on Tag {
@@ -2590,6 +2646,23 @@ export const BlogPostFragmentDoc = gql`
slug
content {
value
+ blocks {
+ __typename
+ ... on ImageRecord {
+ id
+ title
+ asset {
+ url
+ width
+ height
+ }
+ }
+ ... on CtaRecord {
+ id
+ label
+ url
+ }
+ }
}
image {
...Image
diff --git a/src/lib/cms/graphql.schema.json b/src/lib/cms/graphql.schema.json
index 4182a05..6bd4919 100644
--- a/src/lib/cms/graphql.schema.json
+++ b/src/lib/cms/graphql.schema.json
@@ -568,6 +568,27 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "UNION",
+ "name": "BlogPostModelContentBlocksField",
+ "description": null,
+ "fields": null,
+ "inputFields": null,
+ "interfaces": null,
+ "enumValues": null,
+ "possibleTypes": [
+ {
+ "kind": "OBJECT",
+ "name": "CtaRecord",
+ "ofType": null
+ },
+ {
+ "kind": "OBJECT",
+ "name": "ImageRecord",
+ "ofType": null
+ }
+ ]
+ },
{
"kind": "OBJECT",
"name": "BlogPostModelContentField",
@@ -587,8 +608,8 @@
"kind": "NON_NULL",
"name": null,
"ofType": {
- "kind": "SCALAR",
- "name": "String",
+ "kind": "UNION",
+ "name": "BlogPostModelContentBlocksField",
"ofType": null
}
}
@@ -2302,6 +2323,254 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "OBJECT",
+ "name": "CtaRecord",
+ "description": "Record of type Cta (cta)",
+ "fields": [
+ {
+ "name": "_createdAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_firstPublishedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_isValid",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BooleanType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_modelApiKey",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_publicationScheduledAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_publishedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_seoMetaTags",
+ "description": "SEO meta tags",
+ "args": [
+ {
+ "name": "locale",
+ "description": "The locale to use to fetch the field's content",
+ "type": {
+ "kind": "ENUM",
+ "name": "SiteLocale",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Tag",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_status",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ItemStatus",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_unpublishingScheduledAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_updatedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ItemId",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "label",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "url",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
{
"kind": "SCALAR",
"name": "CustomData",
@@ -3276,6 +3545,254 @@
"enumValues": null,
"possibleTypes": null
},
+ {
+ "kind": "OBJECT",
+ "name": "ImageRecord",
+ "description": "Record of type Image (image)",
+ "fields": [
+ {
+ "name": "_createdAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_firstPublishedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_isValid",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "BooleanType",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_modelApiKey",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_publicationScheduledAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_publishedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_seoMetaTags",
+ "description": "SEO meta tags",
+ "args": [
+ {
+ "name": "locale",
+ "description": "The locale to use to fetch the field's content",
+ "type": {
+ "kind": "ENUM",
+ "name": "SiteLocale",
+ "ofType": null
+ },
+ "defaultValue": null,
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "LIST",
+ "name": null,
+ "ofType": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "OBJECT",
+ "name": "Tag",
+ "ofType": null
+ }
+ }
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_status",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "ENUM",
+ "name": "ItemStatus",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_unpublishingScheduledAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "_updatedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "asset",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "OBJECT",
+ "name": "FileField",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "createdAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "id",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "ItemId",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "title",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "SCALAR",
+ "name": "String",
+ "ofType": null
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ },
+ {
+ "name": "updatedAt",
+ "description": null,
+ "args": [],
+ "type": {
+ "kind": "NON_NULL",
+ "name": null,
+ "ofType": {
+ "kind": "SCALAR",
+ "name": "DateTime",
+ "ofType": null
+ }
+ },
+ "isDeprecated": false,
+ "deprecationReason": null
+ }
+ ],
+ "inputFields": null,
+ "interfaces": [],
+ "enumValues": null,
+ "possibleTypes": null
+ },
{
"kind": "INPUT_OBJECT",
"name": "ImgixParams",
diff --git a/src/lib/renderer/blog.module.scss b/src/lib/renderer/blog.module.scss
index 71a0e91..446ab1f 100644
--- a/src/lib/renderer/blog.module.scss
+++ b/src/lib/renderer/blog.module.scss
@@ -1,8 +1,33 @@
@import '~/css/helpers';
.structured {
+ font-family: var(--font-tt-hoves);
max-width: tovw(856px, 'default', 856px);
+ h1 {
+ margin-top: tovw(124px, 'default', 72px);
+ font-family: var(--font-arthemys);
+ font-size: tovw(58px, 'default', 30px);
+ line-height: 1;
+
+ @media screen and (max-width: 800px) {
+ line-height: 124%;
+ }
+ }
+
+ h2 {
+ font-family: var(--font-tt-hoves);
+ font-size: tovw(40px, 'default', 24px);
+ font-weight: 400;
+ line-height: 1;
+ margin-top: tovw(44px, 'default', 40px);
+ margin-bottom: tovw(44px, 'default', 24px);
+
+ @media screen and (max-width: 800px) {
+ line-height: 160%;
+ }
+ }
+
p {
font-family: var(--font-tt-hoves);
font-size: tovw(22px, 'default', 15px);
@@ -10,4 +35,60 @@
letter-spacing: -0.01em;
margin: tovw(44px, 'default', 40px) 0;
}
+
+ blockquote {
+ margin: tovw(76px, 'default', 40px) 0;
+ border-left: 4px solid var(--color-accent);
+ padding-left: tovw(87px, 'default', 22px);
+
+ p {
+ font-size: tovw(28px, 'default', 18px);
+ line-height: tovw(39px, 'default', 29px);
+ }
+
+ footer {
+ font-size: tovw(20px, 'default', 15px);
+ line-height: tovw(32px, 'default', 24px);
+ }
+ }
+
+ ul {
+ margin: tovw(76px, 'default', 40px) 0;
+ padding-left: tovw(72px, 'default', 12px);
+ list-style: none;
+ position: relative;
+
+ li {
+ &::before {
+ content: '';
+ position: absolute;
+ border-radius: 50%;
+ height: 8px;
+ width: 8px;
+ margin-top: 9px;
+ background: var(--color-accent);
+ left: 0;
+ }
+ }
+ }
+
+ code {
+ border: tovw(1px, 'default', 1px) solid var(--color-grey-light);
+ border-radius: tovw(8px, 'default', 4px);
+ background: var(--color-black);
+ display: block;
+ font-family: var(--font-dm-mono), sans-serif;
+ padding: tovw(40px, 'default', 22px);
+ word-break: break-all;
+ white-space: break-spaces;
+ }
+}
+
+.img {
+ margin: tovw(136px, 'default', 72px) auto;
+
+ > img {
+ object-fit: cover;
+ width: 100%;
+ }
}
diff --git a/src/lib/renderer/index.js b/src/lib/renderer/index.js
index 2e97697..fb65140 100644
--- a/src/lib/renderer/index.js
+++ b/src/lib/renderer/index.js
@@ -2,60 +2,31 @@ import { StructuredText } from 'react-datocms'
import Marked from '~/components/common/marked'
import { Container } from '~/components/layout/container'
+import { ButtonLink } from '~/components/primitives/button'
import s from './blog.module.scss'
export const renderBlock = ({ record }) => {
switch (record.__typename) {
+ case 'CalloutRecord':
+ return {record.content ?? ''}
case 'ImageRecord':
return (
-
+
)
- case 'CalloutRecord':
- return
{record.content ?? ''}
- // case 'ShareLinkRecord':
- // return (
- //
- //
- //
- //
- //
- //
- // )
- // case 'CtaRecord':
- // return (
- //
{
- // return {
- // href: link?.href ?? '',
- // as: 'a',
- // children: link?.label ?? '',
- // variant: i === 0 ? 'primary' : 'tertiary',
- // size: 'lg'
- // }
- // }) ?? []
- // }
- // />
- // )
- // case 'TableRecord':
- // return (
- //
- //
- //
- // {record.markdownTable ?? ''}
- //
- //
- //
- // )
+ case 'CtaRecord':
+ return (
+
+ {record.label}
+
+ )
default:
return null
}
diff --git a/src/pages/blog/[slug].tsx b/src/pages/blog/[slug].tsx
index 24a3c35..92445b5 100644
--- a/src/pages/blog/[slug].tsx
+++ b/src/pages/blog/[slug].tsx
@@ -11,6 +11,7 @@ import {
InferGetStaticPropsType
} from 'next'
import Error from 'next/error'
+import { useRouter } from 'next/router'
import { Key } from 'react'
import { BlogCard } from '~/components/common/card'
@@ -18,6 +19,7 @@ import { Meta } from '~/components/common/meta'
import Content from '~/components/sections/blog/post-content'
import Hero from '~/components/sections/blog/post-hero'
import PostsGrid from '~/components/sections/blog/posts-grid'
+import Shares from '~/components/sections/blog/shares'
import { BlogPostFragment } from '~/lib/cms/generated'
const BlogPost = ({
@@ -28,12 +30,17 @@ const BlogPost = ({
return
}
+ const router = useRouter()
+ // `${location.origin}${router.asPath}`
+ const completeUrl = `https://laconic.com${router.asPath}`
+
return (
-
+
+
{latestPosts.map((relatedPost: BlogPostFragment, index: Key) => {
return (