Skip to content

Commit

Permalink
feat(website): app preview (#431)
Browse files Browse the repository at this point in the history
* Add website preview

* Add page seo

* add widget

* Merge SEO props and add previews

* SEO preview

* Drop page SEO

* Apply suggestions from code review

Co-authored-by: Matheus Gaudencio do Rêgo <matheusgr@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Matheus Gaudencio do Rêgo <matheusgr@users.noreply.github.com>

* Drop comments

---------

Co-authored-by: Matheus Gaudencio do Rêgo <matheusgr@users.noreply.github.com>
  • Loading branch information
igorbrasileiro and matheusgr authored Mar 4, 2024
1 parent ae9b691 commit 5e13c82
Show file tree
Hide file tree
Showing 13 changed files with 772 additions and 223 deletions.
17 changes: 17 additions & 0 deletions website/Preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { default as SEOPreview } from "./components/_seo/Preview.tsx";
import { Props as WebsiteAppProps } from "./mod.ts";

interface Props {
state: WebsiteAppProps;
}

export default function Preview(props: Props) {
const { seo } = props.state;

return (
<section>
{seo && <SEOPreview {...seo} />}
{!seo && <p>SEO not configured</p>}
</section>
);
}
15 changes: 7 additions & 8 deletions website/components/_seo/Discord.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,13 @@ function DiscordWebsite(props: PreviewItem) {
const descriptionMaxLength = 300;

return (
<div class="flex ">
<div
class={`flex flex-col w-[4px] bg-[${
regex.test(themeColor) ? themeColor : "#D4DBD7"
}] rounded-l-lg overflow-hidden box-border `}
>
</div>
<div class="bg-discord-bg flex pt-2 pb-4 pl-3 pr-4 rounded-r-md ">
<div
class="overflow-hidden rounded-lg bg-[var(--bg-color)] pl-1"
style={{
"--bg-color": regex.test(themeColor) ? themeColor : "#D4DBD7",
}}
>
<div class="bg-discord-bg flex justify-between pt-2 pb-4 pl-3 pr-4 rounded-l">
<div class=" rounded-r-md max-w-[392px] ">
<h2 class="font-bold leading-[22px] mt-2 text-third max-w-[392px] w-full">
{textShortner(title, titleMaxLength)}
Expand Down
101 changes: 61 additions & 40 deletions website/components/_seo/Facebook.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,76 @@
import Image from "../../components/Image.tsx";
import { PreviewItem } from "./Preview.tsx";
import { Avatar, GlobeIcon, VerifiedIcon } from "./Icons.tsx";
import { PreviewItem, SeoProps } from "./Preview.tsx";
import { textShortner } from "./helpers/textShortner.tsx";

function FacebookBigOpenGraph(props: PreviewItem) {
const { image, title, description, path, width, height } = props;
function FacebookBigOpenGraph(props: PreviewItem & SeoProps) {
const {
image,
title,
description,
width,
height,
canonical = "https://www.example.com",
} = props;
const titleMaxLength = 120;
const url = new URL(canonical);

return (
<div class="">
<Image
src={image}
alt={title}
class="w-full h-[210px] sm:h-[273px] w-[400px] sm:w-[552px] object-cover"
decoding="async"
loading="lazy"
width={width}
height={height}
/>
<div class="px-4 py-3 flex flex-col gap-[3px] bg-facebook-bg ">
<p class="text-xs uppercase font-normal text-common leading-[15px]">
{path}
</p>
<div class="flex flex-col rounded-md border border-light-border bg-white">
<div class="p-4 flex flex-col gap-4">
<div class="flex gap-3">
<div>
<Avatar />
</div>
<div class="flex flex-col">
<span class="flex gap-2 items-center">
<span class="text-sm font-bold">Guilherme Rodrigues</span>
<VerifiedIcon />
</span>
<span class="flex gap-1 items-center">
<span class="text-xs text-[#1e1e1e99]">30m •</span>
<GlobeIcon />
</span>
</div>
</div>

<p class="text-base font-thin text-secondary leading-[19px] ">
{textShortner(title, titleMaxLength)}
<p>
Here is a post you might write with the link of your website:{" "}
<span class="text-[#057EB5]">{canonical}</span>
</p>
<p class="text-sm text-common leading-[19px] overflow-ellipsis
</div>

<div class="">
<Image
src={image}
alt={title}
class="w-full h-[210px] sm:h-[273px] w-[400px] sm:w-[552px] object-cover"
decoding="async"
loading="lazy"
width={width}
height={height}
/>
<div class="px-4 py-3 flex flex-col gap-[3px] bg-facebook-bg ">
<p class="text-xs uppercase font-normal text-common leading-[15px]">
{url.hostname}
</p>

<p class="text-base font-bold text-secondary leading-[19px] ">
{textShortner(title, titleMaxLength)}
</p>
<p class="text-sm text-common leading-[19px] overflow-ellipsis
overflow-hidden max-w-full whitespace-nowrap
">
{title.length < 100 && description}
</p>
{title.length < 100 && description}
</p>
</div>
</div>
<div />
</div>
);
}

function FacebookMediumOpenGraph(props: PreviewItem) {
function _FacebookMediumOpenGraph(props: PreviewItem) {
const { image, title, description, path, width, height } = props;
const titleMaxLength = 90;
const descriptionMaxLength = 110;
Expand Down Expand Up @@ -66,7 +101,7 @@ function FacebookMediumOpenGraph(props: PreviewItem) {
);
}

function FacebookSmallOpenGraph(props: PreviewItem) {
function _FacebookSmallOpenGraph(props: PreviewItem) {
const { image, title, description, path } = props;
const titleMaxLength = 90;
const descriptionMaxLength = 110;
Expand Down Expand Up @@ -98,22 +133,8 @@ function FacebookSmallOpenGraph(props: PreviewItem) {
);
}

function Facebook(props: PreviewItem) {
const { width, height } = props;

if (height < 300 && height !== 0) {
return <FacebookSmallOpenGraph {...props} />;
}

if (width > height) {
return <FacebookBigOpenGraph {...props} />;
}

if (height <= 600 && height >= 300 || height > width) {
return <FacebookMediumOpenGraph {...props} />;
}

return <div />;
function Facebook(props: PreviewItem & SeoProps) {
return <FacebookBigOpenGraph {...props} />;
}

export default Facebook;
62 changes: 49 additions & 13 deletions website/components/_seo/Google.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,57 @@
import { PreviewItem } from "./Preview.tsx";
import { SeoProps } from "./Preview.tsx";
import { textShortner } from "./helpers/textShortner.tsx";

const MAX_DESCRIPTION_LENGTH = 130;

function Google({ title, description, path }: PreviewItem) {
function Google(
{
title,
description,
image,
canonical = "https://www.example.com",
favicon,
}: SeoProps,
) {
const url = new URL(canonical);
return (
<div class="p-6 flex flex-col gap-1 bg-white border border-light-border rounded-lg">
<p class="text-xs font-normal leading-5">
{path}
<span class="text-common ml-2 font-semibold">&#8942;</span>
</p>
<p class="text-xl font-thin text-third leading-5 overflow-ellipsis overflow-hidden max-w-sm whitespace-nowrap break-words">
{title}
</p>
<p class="text-xs font-normal text-common leading-5 max-w-sm break-words">
{description && textShortner(description, MAX_DESCRIPTION_LENGTH)}
</p>
<div class="flex justify-between bg-white border border-light-border rounded-lg p-6">
<div class="flex flex-col gap-1">
<div class="flex gap-3">
<div class="p-2 shrink-0 border-transparent border">
<img
src={favicon}
width={18}
height={18}
class="border-0 border-transparent"
/>
</div>
<div class="flex flex-col">
<span class="text-sm font-normal leading-[18px]">
{url.hostname.replace(/^www./, "")}
</span>
<span class="text-xs font-normal leading-[18px]">
{url.protocol}//{url.hostname}{" "}
<span class="text-common ml-2 font-semibold">&#8942;</span>
</span>
</div>
</div>

<p class="text-xl font-thin text-third leading-5 overflow-ellipsis overflow-hidden max-w-sm whitespace-nowrap break-words">
{title}
</p>
<p class="text-xs font-normal text-common leading-5 max-w-sm break-words">
{description && textShortner(description, MAX_DESCRIPTION_LENGTH)}
</p>
</div>

<div>
<img
src={image}
width={92}
height={92}
class="object-contain rounded-lg"
/>
</div>
</div>
);
}
Expand Down
Loading

0 comments on commit 5e13c82

Please sign in to comment.