Skip to content

Commit

Permalink
feat: add Qwik blog (#7173)
Browse files Browse the repository at this point in the history
  • Loading branch information
gioboa authored Dec 27, 2024
1 parent d5ccb9f commit 19b24c3
Show file tree
Hide file tree
Showing 13 changed files with 417 additions and 1 deletion.
9 changes: 9 additions & 0 deletions packages/docs/src/components/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ export const Header = component$(() => {
<span>Shop</span>
</a>
</li>
{/* <li>
<a
href="/blog/"
class={{ active: pathname.startsWith('/blog') }}
aria-label="Qwik blog"
>
<span>Blog</span>
</a>
</li> */}
<li>
<DocSearch
appId={import.meta.env.VITE_ALGOLIA_APP_ID}
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/src/components/router-head/router-head.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export const RouterHead = component$(() => {
<>
<title>{title}</title>
<meta name="description" content={description} />
<link rel="canonical" href={url.href} />
<link rel="canonical" href={head.frontmatter?.canonical || url.href} />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="apple-mobile-web-app-title" content="Qwik" />
<meta name="application-name" content="Qwik" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
title: 'Example'
authorName: 'The Qwik Team'
tags: ['Web development']
date: 'Dec 16, 2024'
---

import { ArticleBlock } from '~/routes/(blog)/blog/components/mdx/article-block/article-block';
import CodeSandbox from '~/components/code-sandbox/index.tsx';

<ArticleBlock
imageSrc="https://placehold.co/1200x400"
authorLink="https://bsky.app/profile/qwik.dev"
>

# H1

## H2

### H3

Example:

1. foo
1. bar
1. baz

![mock](https://placehold.co/600x400)

<CodeSandbox src="/src/routes/demo/cookbook/leaflet-map/index.tsx" style={{ height: '30em' }}>
```tsx
import { component$ } from '@builder.io/qwik';

export default component$(() => {
console.log('render');
return <button onClick$={() => console.log('hello')}>Hello Qwik</button>;
});
```
</CodeSandbox>


</ArticleBlock>
51 changes: 51 additions & 0 deletions packages/docs/src/routes/(blog)/blog/components/articles-grid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Image } from 'qwik-image';
import { blogArticles } from '../../data';
import { ClockIcon } from '../icons/clock-icon';
import { component$ } from '@builder.io/qwik';

export const ArticlesGrid = component$(() => {
return (
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{blogArticles.map((post, key) => (
<article
key={key}
class="group bg-[color:var(--text-color)] rounded-xl overflow-hidden shadow-sm hover:shadow-xl transition-shadow duration-300 cursor-pointer"
>
<a href={post.path}>
<div class="relative h-48 overflow-hidden">
<Image
layout="constrained"
class="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500"
src={post.image}
alt={post.title}
/>
</div>

<div class="p-6">
<h3 class="pb-4 text-xl font-bold text-[color:var(--bg-color)] group-hover:opacity-70 transition-colors">
{post.title}
</h3>

<div class="pb-2">
{blogArticles[0].tags.map((tag, key) => (
<span
key={key}
class="px-3 py-1 mr-2 text-xs font-semibold text-[color:var(--text-color)] bg-[color:var(--bg-color)] rounded-full"
>
{tag}
</span>
))}
</div>
<div class="flex items-center space-x-4 text-sm text-[color:var(--bg-color)]">
<div class="flex items-center">
<ClockIcon />
<span>5 min read</span>
</div>
</div>
</div>
</a>
</article>
))}
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Image } from 'qwik-image';
import { ClockIcon } from '../icons/clock-icon';
import { blogArticles } from '../../data';
import { component$ } from '@builder.io/qwik';

export const FeaturedArticle = component$(() => {
return (
<article class="relative group cursor-pointer">
<a href={blogArticles[0].path}>
<div class="relative h-96 overflow-hidden rounded-xl">
<Image
layout="constrained"
class="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500"
src={blogArticles[0].featuredImage}
alt={blogArticles[0].title}
/>
</div>

<div class="absolute bottom-0 p-6 text-white">
<h2 class="pb-4 text-3xl font-bold leading-tight hover:text-slate-200 transition-colors">
{blogArticles[0].title}
</h2>
<div class="pb-2">
{blogArticles[0].tags.map((tag, key) => (
<span
key={key}
class="mb-4 px-3 py-1 mr-2 text-xs text-[color:var(--text-color)] bg-[color:var(--bg-color)] rounded-full backdrop-blur-sm"
>
{tag}
</span>
))}
</div>
<div class="mb-4 flex items-center space-x-4 text-sm">
<div class="flex items-center">
<ClockIcon />
<span>5 min read</span>
</div>
</div>
</div>
</a>
</article>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { component$, Slot } from '@builder.io/qwik';
import { ArticleHero } from '../article-hero/article-hero';

type Props = { imageSrc: string; authorLink: string };

export const ArticleBlock = component$<Props>(({ imageSrc, authorLink }) => {
return (
<div class="docs">
<ArticleHero imageSrc={imageSrc} authorLink={authorLink} />
<article>
<Slot />
</article>
</div>
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { component$ } from '@builder.io/qwik';
import { useDocumentHead } from '@builder.io/qwik-city';
import { Image } from 'qwik-image';

type Props = { imageSrc: string; authorLink: string };

export const ArticleHero = component$<Props>(({ imageSrc, authorLink }) => {
const { title, frontmatter } = useDocumentHead();

if (!frontmatter.authorName || !frontmatter.tags || !frontmatter.date) {
return <>Missing frontmatter props</>;
}

return (
<>
<div class="pt-4">
<a
class="text-[color:var(--text-color)] flex items-center space-x-1 pl-2"
rel="noopener"
href="/blog"
>
<svg
aria-hidden="true"
height="16"
viewBox="0 0 16 16"
version="1.1"
width="16"
data-view-component="true"
fill="currentcolor"
>
<path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path>
</svg>
<span class="text-xl">Back to blog</span>
</a>
</div>
<div class="max-w-[1000px] pb-8 mx-auto">
<div class="flex flex-col justify-center">
<h4 class="text-xl text-[color:var(--qwik-blue)] font-semibold uppercase text-center pt-6 tracking-wide">
{frontmatter.tags.map((tag: string) => (
<span class="pr-2">{tag}</span>
))}
</h4>
<h1 class="text-[48px] text-[color:var(--text-color)] font-bold text-center tracking-wide pt-6">
{title}
</h1>
<div class="flex justify-center pt-8 pb-10 text-[color:var(--text-color)] text-xl">
<h4 class="font-semibold uppercase text-center">{frontmatter.date}</h4>
<div class="border border-[color:var(--text-color)] mx-4"></div>
<div class="font-semibold uppercase text-center">
Written By{' '}
<a
class="text-[color:var(--qwik-blue)]"
target="_blank"
rel="noopener"
href={authorLink}
>
{frontmatter.authorName}
</a>
</div>
</div>
</div>
</div>
<div class="relative h-[400px] w-full bg-[color:var(--text-color)] mb-8">
<Image class="w-full h-full object-cover" alt={title} src={imageSrc} layout="fullWidth" />
</div>
</>
);
});
30 changes: 30 additions & 0 deletions packages/docs/src/routes/(blog)/blog/components/newsletter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { component$ } from '@builder.io/qwik';
import { SendIcon } from '../icons/send-icon';

export const Newsletter = component$(() => {
return (
<section class="bg-slate-900 text-white py-16 px-4 sm:px-6 lg:px-8 rounded-xl">
<div class="max-w-2xl mx-auto text-center">
<h2 class="text-3xl font-bold">Stay Updated</h2>
<p class="mt-4 text-slate-300">
Get the latest articles and insights delivered straight to your inbox.
</p>

<form class="mt-8 flex flex-col sm:flex-row gap-4 justify-center">
<input
type="email"
placeholder="Enter your email"
class="px-4 py-3 rounded-lg bg-white/10 border border-white/20 focus:outline-none focus:ring-2 focus:ring-white/50 flex-grow max-w-md placeholder:text-slate-400"
/>
<button
type="submit"
class="inline-flex items-center justify-center px-6 py-3 rounded-lg bg-white text-slate-900 hover:bg-slate-100 transition-colors font-medium"
>
Subscribe
<SendIcon />
</button>
</form>
</div>
</section>
);
});
17 changes: 17 additions & 0 deletions packages/docs/src/routes/(blog)/blog/icons/clock-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const ClockIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4 mr-1"
>
<circle cx="12" cy="12" r="10"></circle>
<polyline points="12 6 12 12 16 14"></polyline>
</svg>
);
17 changes: 17 additions & 0 deletions packages/docs/src/routes/(blog)/blog/icons/send-icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const SendIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="w-4 h-4 ml-2"
>
<path d="m22 2-7 20-4-9-9-4Z"></path>
<path d="M22 2 11 13"></path>
</svg>
);
57 changes: 57 additions & 0 deletions packages/docs/src/routes/(blog)/blog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { component$, useStyles$ } from '@builder.io/qwik';
import type { DocumentHead } from '@builder.io/qwik-city';
import { FeaturedArticle } from './components/featured-article';
import { ArticlesGrid } from './components/articles-grid';
import { Newsletter } from './components/newsletter';

export default component$(() => {
useStyles$(`
.blog .purple-gradient {
position: fixed;
pointer-events: none;
width: 1400px;
height: 800px;
top: 100px;
right: -400px;
background: radial-gradient(
57.58% 57.58% at 48.79% 42.42%,
rgba(24, 180, 244, 0.5) 0%,
rgba(46, 55, 114, 0) 63.22%
);
transform: rotate(5deg);
}
.blog .blue-gradient {
position: fixed;
pointer-events: none;
width: 1400px;
height: 1200px;
top: 600px;
left: -200px;
background: radial-gradient(
50% 50% at 50% 50%,
rgba(172, 127, 244, 0.5) 0%,
rgba(21, 25, 52, 0) 100%
);
transform: rotate(-5deg);
}`);

return (
<div class="py-8">
<section class="pb-8">
<FeaturedArticle />
</section>
<section>
<h2 class="pb-4 text-2xl font-bold text-[color:var(--text-color)]">Latest Articles</h2>
<ArticlesGrid />
</section>
<section class="py-8">
<Newsletter />
</section>
</div>
);
});

export const head: DocumentHead = {
title: 'Qwik Blog',
};
Loading

0 comments on commit 19b24c3

Please sign in to comment.