diff --git a/api/functions/graphql/nexus-typegen.ts b/api/functions/graphql/nexus-typegen.ts index 9c435de..b0d01f0 100644 --- a/api/functions/graphql/nexus-typegen.ts +++ b/api/functions/graphql/nexus-typegen.ts @@ -665,7 +665,7 @@ export interface NexusGenArgTypes { } getFeed: { // args skip?: number | null; // Int - sortBy: string | null; // String + sortBy?: string | null; // String take: number | null; // Int topic?: number | null; // Int } diff --git a/api/functions/graphql/schema.graphql b/api/functions/graphql/schema.graphql index 2c56478..3c67804 100644 --- a/api/functions/graphql/schema.graphql +++ b/api/functions/graphql/schema.graphql @@ -149,7 +149,7 @@ type Query { getAllHackathons(sortBy: String, topic: Int): [Hackathon!]! getCategory(id: Int!): Category! getDonationsStats: DonationsStats! - getFeed(skip: Int = 0, sortBy: String = "all", take: Int = 10, topic: Int = 0): [Post!]! + getFeed(skip: Int = 0, sortBy: String, take: Int = 10, topic: Int = 0): [Post!]! getLnurlDetailsForProject(project_id: Int!): LnurlDetails! getPostById(id: Int!, type: POST_TYPE!): Post! getProject(id: Int!): Project! diff --git a/api/functions/graphql/types/post.js b/api/functions/graphql/types/post.js index 8bcd06c..a26088f 100644 --- a/api/functions/graphql/types/post.js +++ b/api/functions/graphql/types/post.js @@ -14,6 +14,7 @@ const { paginationArgs } = require('./helpers'); const { prisma } = require('../../../prisma'); const { getUserByPubKey } = require('../../../auth/utils/helperFuncs'); const { ApolloError } = require('apollo-server-lambda'); +const { marked } = require('marked'); const POST_TYPE = enumType({ @@ -189,7 +190,8 @@ const createStory = extendType({ // Preprocess & insert - const excerpt = body.replace(/<[^>]+>/g, '').slice(0, 120); + const htmlBody = marked.parse(body); + const excerpt = htmlBody.replace(/<[^>]+>/g, '').slice(0, 120); if (id) return prisma.story.update({ @@ -395,9 +397,7 @@ const getFeed = extendType({ type: "Post", args: { ...paginationArgs({ take: 10 }), - sortBy: stringArg({ - default: "all" - }), // all, popular, trending, newest + sortBy: stringArg(), // all, popular, trending, newest topic: intArg({ default: 0 }) @@ -405,8 +405,15 @@ const getFeed = extendType({ resolve(_, { take, skip, topic, sortBy, }) { + let orderBy = { createdAt: "desc" }; + + if (sortBy === 'popular') + orderBy = { votes_count: 'desc' }; + else if (sortBy === 'newest') + orderBy = { createdAt: "desc" }; + return prisma.story.findMany({ - orderBy: { createdAt: "desc" }, + orderBy: orderBy, where: { topic_id: topic ? topic : undefined, }, diff --git a/public/assets/images/stw2.jfif b/public/assets/images/stw2.jfif new file mode 100644 index 0000000..c54e9e0 Binary files /dev/null and b/public/assets/images/stw2.jfif differ diff --git a/src/Components/Inputs/TextEditor/SaveModule.tsx b/src/Components/Inputs/TextEditor/SaveModule.tsx index c7bbe93..af03581 100644 --- a/src/Components/Inputs/TextEditor/SaveModule.tsx +++ b/src/Components/Inputs/TextEditor/SaveModule.tsx @@ -18,7 +18,10 @@ export default function SaveModule(props: Props) { const changeCallback = useDebouncedCallback(ctx => { const { state } = ctx; - onChange(getHTML(state)); + const md = getMarkdown(state); + console.log(md); + + onChange(md); }, [], 500) useRemirrorContext(changeCallback) diff --git a/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx b/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx index 265bbb5..999a1bb 100644 --- a/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx +++ b/src/Components/Inputs/TextEditor/Toolbar/Toolbar.tsx @@ -9,17 +9,17 @@ export default function Toolbar() { - -
- + {/* - + */} + + - + {/* */}
diff --git a/src/Components/Navbar/NavDesktop.tsx b/src/Components/Navbar/NavDesktop.tsx index 2891a60..819907a 100644 --- a/src/Components/Navbar/NavDesktop.tsx +++ b/src/Components/Navbar/NavDesktop.tsx @@ -74,7 +74,8 @@ export default function NavDesktop() { className='!p-16 font-medium flex gap-16 hover:bg-gray-100 !rounded-12 ' >
- + {/* */} + ✍🏼

@@ -87,10 +88,10 @@ export default function NavDesktop() {

- + 💬

@@ -110,7 +111,7 @@ export default function NavDesktop() { className='!p-16 font-medium flex gap-16 hover:bg-gray-100 !rounded-12' >

- + 🏆

diff --git a/src/Components/Navbar/NavMobile.tsx b/src/Components/Navbar/NavMobile.tsx index 7d7ff38..1bbf402 100644 --- a/src/Components/Navbar/NavMobile.tsx +++ b/src/Components/Navbar/NavMobile.tsx @@ -181,7 +181,7 @@ export default function NavMobile() { className='font-medium flex gap-16 !rounded-12 ' >

- + ✍🏼

@@ -197,7 +197,7 @@ export default function NavMobile() { className='font-medium flex gap-16 !rounded-12 opacity-60' >

- + 💬

@@ -214,7 +214,7 @@ export default function NavMobile() { className='font-medium flex gap-16 !rounded-12' >

- + 🏆

diff --git a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx index c8875d0..fb7ba5a 100644 --- a/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx +++ b/src/features/Hackathons/pages/HackathonsPage/HackathonsPage.tsx @@ -39,6 +39,7 @@ export default function HackathonsPage() { top: `${navHeight + 16}px`, maxHeight: `calc(100vh - ${navHeight}px - 16px)`, }}> +

Hackathons 🏆

diff --git a/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx index 20bc706..19c9b65 100644 --- a/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx +++ b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx @@ -36,7 +36,7 @@ export default function StoryCard({ story }: Props) {

{story.title}

-

{story.excerpt}

+

{story.excerpt}...


diff --git a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx index b8c7074..5b5bc67 100644 --- a/src/features/Posts/Components/TrendingCard/TrendingCard.tsx +++ b/src/features/Posts/Components/TrendingCard/TrendingCard.tsx @@ -11,7 +11,7 @@ export default function TrendingCard() { return ( -
+

Trending on BOLT.FUN

    { diff --git a/src/features/Posts/pages/CreatePostPage/Components/BountyForm/BountyForm.tsx b/src/features/Posts/pages/CreatePostPage/Components/BountyForm/BountyForm.tsx index 1a90e8c..017bd37 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/BountyForm/BountyForm.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/BountyForm/BountyForm.tsx @@ -156,7 +156,7 @@ export default function BountyForm() { Tags

    {errors.tags &&

    diff --git a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx index 223a0df..a9830c7 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/ContentEditor.tsx @@ -40,16 +40,6 @@ interface Props { export default function ContentEditor({ placeholder, initialContent, name }: Props) { - const linkExtension = useMemo(() => { - const extension = new LinkExtension({ autoLink: true }); - extension.addHandler('onClick', (_, data) => { - window.open(data.href, '_blank')?.focus(); - return true; - }); - return extension; - }, []); - - const onError: InvalidContentHandler = useCallback(({ json, invalidContent, transformers }) => { // Automatically remove all invalid nodes and marks. return transformers.remove(json, invalidContent); @@ -59,7 +49,13 @@ export default function ContentEditor({ placeholder, initialContent, name }: Pro const extensions = useCallback( () => [ new PlaceholderExtension({ placeholder }), - linkExtension, + new LinkExtension({ + autoLink: true, + defaultTarget: "_blank", + extraAttributes: { + rel: 'noopener noreferrer' + } + }), new BoldExtension(), // new StrikeExtension(), new UnderlineExtension(), @@ -78,7 +74,7 @@ export default function ContentEditor({ placeholder, initialContent, name }: Pro new IframeExtension(), // new TrailingNodeExtension(), // new TableExtension(), - new MarkdownExtension({ copyAsMarkdown: false }), + new MarkdownExtension({ copyAsMarkdown: true, }), new NodeFormattingExtension(), /** * `HardBreakExtension` allows us to create a newline inside paragraphs. @@ -86,7 +82,7 @@ export default function ContentEditor({ placeholder, initialContent, name }: Pro */ new HardBreakExtension(), ], - [linkExtension, placeholder], + [placeholder], ); diff --git a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/Toolbar.tsx b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/Toolbar.tsx index 394a11b..997322f 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/Toolbar.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/Toolbar.tsx @@ -7,19 +7,19 @@ interface Props { export default function Toolbar() { return ( -

    +
    - -
    - + {/* - + */} + + diff --git a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/styles.module.scss b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/styles.module.scss index 62837de..8ec37c4 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/styles.module.scss +++ b/src/features/Posts/pages/CreatePostPage/Components/ContentEditor/styles.module.scss @@ -1,28 +1,33 @@ .wrapper { - - :global{ + :global { + .ProseMirror { + overflow: hidden; + border-bottom-left-radius: inherit; + border-bottom-right-radius: inherit; + min-height: var(--rmr-space-7); - .ProseMirror { - overflow: hidden; - border-bottom-left-radius: inherit; - border-bottom-right-radius: inherit; - min-height: var(--rmr-space-7); + a { + color: rgb(54, 139, 236); - a{ - color: rgb(54, 139, 236); - - &:hover{ - text-decoration: underline; - cursor: pointer; - } - } - } - - .ProseMirror, - .ProseMirror:active, - .ProseMirror:focus{ - box-shadow: none; + &:hover { + text-decoration: underline; + cursor: pointer; } + } + } + .remirror-editor-wrapper { + height: 60vh; + overflow-y: scroll; + + &::-webkit-scrollbar { + width: 8px; + } } -} \ No newline at end of file + .ProseMirror, + .ProseMirror:active, + .ProseMirror:focus { + box-shadow: none; + } + } +} diff --git a/src/features/Posts/pages/CreatePostPage/Components/QuestionForm/QuestionForm.tsx b/src/features/Posts/pages/CreatePostPage/Components/QuestionForm/QuestionForm.tsx index 63f8dbf..7a5d86f 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/QuestionForm/QuestionForm.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/QuestionForm/QuestionForm.tsx @@ -96,7 +96,7 @@ export default function QuestionForm() { Tags

    {errors.tags &&

    diff --git a/src/features/Posts/pages/CreatePostPage/Components/StoryForm/StoryForm.tsx b/src/features/Posts/pages/CreatePostPage/Components/StoryForm/StoryForm.tsx index 3f8a55b..4d216a0 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/StoryForm/StoryForm.tsx +++ b/src/features/Posts/pages/CreatePostPage/Components/StoryForm/StoryForm.tsx @@ -108,7 +108,7 @@ export default function StoryForm() { createStory({ variables: { data: { - id: null, + id: data.id, title: data.title, body: data.body, tags: data.tags.map(t => t.title), @@ -127,7 +127,7 @@ export default function StoryForm() { onSubmit={handleSubmit(onSubmit)} >

    + className='bg-white border-2 border-gray-100 rounded-12 overflow-hidden'>
    {errors.tags &&

    diff --git a/src/features/Posts/pages/CreatePostPage/Components/StoryForm/createStory.graphql b/src/features/Posts/pages/CreatePostPage/Components/StoryForm/createStory.graphql index 89b9ff0..17ad596 100644 --- a/src/features/Posts/pages/CreatePostPage/Components/StoryForm/createStory.graphql +++ b/src/features/Posts/pages/CreatePostPage/Components/StoryForm/createStory.graphql @@ -1,6 +1,22 @@ mutation createStory($data: StoryInputType) { createStory(data: $data) { id + title + createdAt + body + tags { + id + title + } + topic { + id + title + icon + } + votes_count + type + cover_image + comments_count } } diff --git a/src/features/Posts/pages/CreatePostPage/CreatePostPage.tsx b/src/features/Posts/pages/CreatePostPage/CreatePostPage.tsx index 12fe4c2..ddd48f3 100644 --- a/src/features/Posts/pages/CreatePostPage/CreatePostPage.tsx +++ b/src/features/Posts/pages/CreatePostPage/CreatePostPage.tsx @@ -1,6 +1,7 @@ import { useState } from "react"; import { Helmet } from "react-helmet"; -import { useParams } from "react-router-dom"; +import { FiArrowLeft } from "react-icons/fi"; +import { useNavigate, useParams } from "react-router-dom"; import BountyForm from "./Components/BountyForm/BountyForm"; import QuestionForm from "./Components/QuestionForm/QuestionForm"; import StoryForm from "./Components/StoryForm/StoryForm"; @@ -15,19 +16,29 @@ export default function CreatePostPage() { const { type } = useParams() const [postType, setPostType] = useState<'story' | 'bounty' | 'question'>((type as any) ?? 'story'); + const navigate = useNavigate(); return (<> Create Post

    -
    - +
    + {/* */} +
    -
    +
    {postType === 'story' && <>

    Write a Story diff --git a/src/features/Posts/pages/FeedPage/FeedPage.tsx b/src/features/Posts/pages/FeedPage/FeedPage.tsx index ce2b3bd..3a6519a 100644 --- a/src/features/Posts/pages/FeedPage/FeedPage.tsx +++ b/src/features/Posts/pages/FeedPage/FeedPage.tsx @@ -11,6 +11,7 @@ import SortBy from './SortBy/SortBy' import styles from './styles.module.scss' import { Helmet } from "react-helmet"; import Button from 'src/Components/Button/Button' +import { FaDiscord } from 'react-icons/fa' export default function FeedPage() { @@ -45,7 +46,21 @@ export default function FeedPage() {
    -
    diff --git a/src/features/Posts/pages/FeedPage/PopularTopicsFilter/PopularTopicsFilter.tsx b/src/features/Posts/pages/FeedPage/PopularTopicsFilter/PopularTopicsFilter.tsx index 74bb0bb..57fd32c 100644 --- a/src/features/Posts/pages/FeedPage/PopularTopicsFilter/PopularTopicsFilter.tsx +++ b/src/features/Posts/pages/FeedPage/PopularTopicsFilter/PopularTopicsFilter.tsx @@ -28,8 +28,8 @@ export default function PopularTopicsFilter({ filterChanged }: Props) { return (
    {isMdScreen ? -
    -

    Topics

    +
    +

    Explore Categories

      {topicsQuery.loading ? Array(3).fill(0).map((_, idx) =>
    • >(filters[0].value); + const [selected, setSelected] = useState>(null); const filterClicked = (_newValue: string | null) => { const newValue = selected !== _newValue ? _newValue : null; @@ -31,42 +31,20 @@ export default function SortBy({ filterChanged }: Props) { filterChanged?.(newValue); } - - const isMdScreen = useMediaQuery(MEDIA_QUERIES.isMedium) - - - return ( - <> - { - isMdScreen ? -
      - < p className="text-body2 font-bolder text-black mb-16" > Sort By

      -
        - {filters.map((f, idx) =>
      • filterClicked(f.value)} - role='button' - > - {f.text} -
      • )} -
      -
      - : - filterClicked(o ? o.value : null)} /> - } +
        + {filters.map((f, idx) =>
      • filterClicked(f.value)} + role='button' + > + {f.text} +
      • )} +
      ) } diff --git a/src/features/Posts/pages/FeedPage/styles.module.scss b/src/features/Posts/pages/FeedPage/styles.module.scss index 763140a..21ac30e 100644 --- a/src/features/Posts/pages/FeedPage/styles.module.scss +++ b/src/features/Posts/pages/FeedPage/styles.module.scss @@ -1,32 +1,114 @@ +// .grid { +// display: grid; +// grid-template-columns: 100%; +// gap: 24px; +// > aside:last-of-type { +// display: none; +// } + +// @media screen and (min-width: 768px) { +// grid-template-columns: repeat(4, 1fr); + +// > aside:first-of-type { +// grid-column: 1/2; +// } +// > main { +// grid-column: 2/-1; +// } +// } + +// @media screen and (min-width: 1024px) { +// > aside:first-of-type { +// grid-column: 1/2; +// } +// > main { +// grid-column: 2/-2; +// } +// > aside:last-of-type { +// display: block; +// grid-column: -1/-2; +// } +// } +// } + +@import "/src/styles/mixins"; + .grid { display: grid; - grid-template-columns: 100%; - gap: 24px; - > aside:last-of-type { - display: none; + // grid-template-columns: 1fr; + gap: 32px; + + & > * { + min-width: 0; + } + + grid-template-areas: + "title" + "sort-by" + "categories" + "content"; + + :global { + #title { + grid-area: title; + } + + #sort-by { + grid-area: sort-by; + } + #categories { + grid-area: categories; + } + #content { + grid-area: content; + } + #side { + grid-area: side; + display: none; + } } @media screen and (min-width: 768px) { grid-template-columns: repeat(4, 1fr); - > aside:first-of-type { - grid-column: 1/2; - } - > main { - grid-column: 2/-1; + grid-template-areas: + "categories title title side" + "categories sort-by sort-by side" + "categories content content side"; + + :global { + #side { + display: block; + } } } - @media screen and (min-width: 1024px) { - > aside:first-of-type { - grid-column: 1/2; - } - > main { - grid-column: 2/-2; - } - > aside:last-of-type { - display: block; - grid-column: -1/-2; - } - } + // @media screen and (min-width: 1024px) { + // > aside:first-of-type { + // grid-column: 1/2; + // } + // > main { + // grid-column: 2/-2; + // } + // > aside:last-of-type { + // display: block; + // grid-column: -1/-2; + // } + // } + + // @include gt-md { + // grid-template-columns: auto 1fr; + // grid-template-areas: + // "actions content" + // ". author" + // ". comments"; + // } + + // @include gt-lg { + // grid-template-columns: auto 1fr calc(min(30%, 326px)); + // grid-template-areas: + // "actions content author" + // ". comments ." + // ". . ."; + // } } diff --git a/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx b/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx index aa91839..922487c 100644 --- a/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx +++ b/src/features/Posts/pages/PostDetailsPage/Components/AuthorCard/AuthorCard.tsx @@ -15,7 +15,7 @@ interface Props { export default function AuthorCard({ author }: Props) { return ( -
      +
      diff --git a/src/features/Posts/pages/PostDetailsPage/Components/PageContent/styles.module.css b/src/features/Posts/pages/PostDetailsPage/Components/PageContent/styles.module.css index 3f94af8..1afeebc 100644 --- a/src/features/Posts/pages/PostDetailsPage/Components/PageContent/styles.module.css +++ b/src/features/Posts/pages/PostDetailsPage/Components/PageContent/styles.module.css @@ -35,6 +35,13 @@ margin-bottom: 1.5em; } +.body a { + color: rgb(107, 107, 249); +} +.body a:hover { + text-decoration: underline; +} + .body pre { background-color: #2b2b2b; padding: 16px; diff --git a/src/features/Posts/pages/PostDetailsPage/Components/PostActions/PostActions.tsx b/src/features/Posts/pages/PostDetailsPage/Components/PostActions/PostActions.tsx index 072532d..ff5b9af 100644 --- a/src/features/Posts/pages/PostDetailsPage/Components/PostActions/PostActions.tsx +++ b/src/features/Posts/pages/PostDetailsPage/Components/PostActions/PostActions.tsx @@ -38,20 +38,20 @@ export default function PostActions({ post, isPreview }: Props) { return (
      - {/*
        + {/*
        */} -
          +
            {actions.map((action, idx) =>
          • -
            +
            {curUser?.id === story.author.id && }> @@ -54,14 +54,14 @@ export default function StoryPageContent({ story }: Props) { {tag.title} )}
            } -
            + {/*
            {numberFormatter(story.votes_count)} votes
            {story.comments_count} Comments
            -
            +
            */}
            diff --git a/src/features/Posts/pages/PreviewPostPage/PreviewPostContent/PreviewPostContent.tsx b/src/features/Posts/pages/PreviewPostPage/PreviewPostContent/PreviewPostContent.tsx index c5ae1c6..76f7fe2 100644 --- a/src/features/Posts/pages/PreviewPostPage/PreviewPostContent/PreviewPostContent.tsx +++ b/src/features/Posts/pages/PreviewPostPage/PreviewPostContent/PreviewPostContent.tsx @@ -2,9 +2,6 @@ import Header from "src/features/Posts/Components/PostCard/Header/Header" import { marked } from 'marked'; import styles from '../../PostDetailsPage/Components/PageContent/styles.module.css' import Badge from "src/Components/Badge/Badge"; -import { BiComment } from "react-icons/bi"; -import { RiFlashlightLine } from "react-icons/ri"; -import { numberFormatter } from "src/utils/helperFunctions"; import { Post } from "src/graphql"; @@ -31,17 +28,9 @@ export default function PreviewPostContent({ post }: Props) { {tag.title} )}
            } -
            -
            - {numberFormatter(123)} votes -
            -
            - {17} Comments -
            -
      -
      +
      {/*
      diff --git a/src/graphql/index.tsx b/src/graphql/index.tsx index b1525b4..8fe7e9f 100644 --- a/src/graphql/index.tsx +++ b/src/graphql/index.tsx @@ -465,7 +465,7 @@ export type CreateStoryMutationVariables = Exact<{ }>; -export type CreateStoryMutation = { __typename?: 'Mutation', createStory: { __typename?: 'Story', id: number } | null }; +export type CreateStoryMutation = { __typename?: 'Mutation', createStory: { __typename?: 'Story', id: number, title: string, createdAt: any, body: string, votes_count: number, type: string, cover_image: string, comments_count: number, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, topic: { __typename?: 'Topic', id: number, title: string, icon: string } } | null }; export type DeleteStoryMutationVariables = Exact<{ deleteStoryId: Scalars['Int']; @@ -927,6 +927,22 @@ export const CreateStoryDocument = gql` mutation createStory($data: StoryInputType) { createStory(data: $data) { id + title + createdAt + body + tags { + id + title + } + topic { + id + title + icon + } + votes_count + type + cover_image + comments_count } } `; diff --git a/tailwind.config.js b/tailwind.config.js index 7324c82..5676e3a 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -31,7 +31,7 @@ module.exports = { }, fontSize: { h1: ["48px", "54px"], - h2: ["36px", "50px"], + h2: ["32px", "44px"], h3: ["29px", "40px"], h4: ["22px", "31px"], h5: ["19px", "26px"],