Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(blog): author header social icons #10222

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,70 @@
* LICENSE file in the root directory of this source tree.
*/

import type {SVGProps} from 'react';
import React from 'react';
import clsx from 'clsx';
import Link, {type Props as LinkProps} from '@docusaurus/Link';

import type {Props} from '@theme/BlogPostItem/Header/Author';
import styles from './styles.module.css';

type SocialProps = SVGProps<SVGSVGElement> & {
user: string;
};

function getUrl(user: string, baseUrl: string) {
return user.startsWith('https') ? user : `${baseUrl}${user}`;
}
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved

function Twitter(props: SocialProps) {
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
const twitterUrl = getUrl(props.user, 'https://x.com/');
return (
// eslint-disable-next-line @docusaurus/no-html-links
<a
href={twitterUrl}
target="_blank"
rel="noreferrer noopener"
className={clsx(styles.socialIcon)}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract AuthorSocialLink component, icon should be received as children

<svg
viewBox="0 0 256 209"
width="1.5em"
height="1.5em"
xmlns="http://www.w3.org/2000/svg"
className={clsx(styles.socialIcon)}
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
preserveAspectRatio="xMidYMid"
{...props}>
<path
d="M256 25.45c-9.42 4.177-19.542 7-30.166 8.27 10.845-6.5 19.172-16.793 23.093-29.057a105.183 105.183 0 0 1-33.351 12.745C205.995 7.201 192.346.822 177.239.822c-29.006 0-52.523 23.516-52.523 52.52 0 4.117.465 8.125 1.36 11.97-43.65-2.191-82.35-23.1-108.255-54.876-4.52 7.757-7.11 16.78-7.11 26.404 0 18.222 9.273 34.297 23.365 43.716a52.312 52.312 0 0 1-23.79-6.57c-.003.22-.003.44-.003.661 0 25.447 18.104 46.675 42.13 51.5a52.592 52.592 0 0 1-23.718.9c6.683 20.866 26.08 36.05 49.062 36.475-17.975 14.086-40.622 22.483-65.228 22.483-4.24 0-8.42-.249-12.529-.734 23.243 14.902 50.85 23.597 80.51 23.597 96.607 0 149.434-80.031 149.434-149.435 0-2.278-.05-4.543-.152-6.795A106.748 106.748 0 0 0 256 25.45"
fill="#55acee"
/>
</svg>
</a>
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
);
}

function Github(props: SocialProps) {
const githubUrl = getUrl(props.user, 'https://github.com/');
return (
// eslint-disable-next-line @docusaurus/no-html-links
<a
href={githubUrl}
target="_blank"
rel="noreferrer noopener"
className={clsx(styles.socialIcon)}>
<svg
className={clsx(styles.socialIcon)}
viewBox="0 0 256 250"
width="1.5em"
height="1.5em"
xmlns="http://www.w3.org/2000/svg"
preserveAspectRatio="xMidYMid"
{...props}>
<path d="M128.001 0C57.317 0 0 57.307 0 128.001c0 56.554 36.676 104.535 87.535 121.46 6.397 1.185 8.746-2.777 8.746-6.158 0-3.052-.12-13.135-.174-23.83-35.61 7.742-43.124-15.103-43.124-15.103-5.823-14.795-14.213-18.73-14.213-18.73-11.613-7.944.876-7.78.876-7.78 12.853.902 19.621 13.19 19.621 13.19 11.417 19.568 29.945 13.911 37.249 10.64 1.149-8.272 4.466-13.92 8.127-17.116-28.431-3.236-58.318-14.212-58.318-63.258 0-13.975 5-25.394 13.188-34.358-1.329-3.224-5.71-16.242 1.24-33.874 0 0 10.749-3.44 35.21 13.121 10.21-2.836 21.16-4.258 32.038-4.307 10.878.049 21.837 1.47 32.066 4.307 24.431-16.56 35.165-13.12 35.165-13.12 6.967 17.63 2.584 30.65 1.255 33.873 8.207 8.964 13.173 20.383 13.173 34.358 0 49.163-29.944 59.988-58.447 63.157 4.591 3.972 8.682 11.762 8.682 23.704 0 17.126-.148 30.91-.148 35.126 0 3.407 2.304 7.398 8.792 6.14C219.37 232.5 256 184.537 256 128.002 256 57.307 198.691 0 128.001 0Zm-80.06 182.34c-.282.636-1.283.827-2.194.39-.929-.417-1.45-1.284-1.15-1.922.276-.655 1.279-.838 2.205-.399.93.418 1.46 1.293 1.139 1.931Zm6.296 5.618c-.61.566-1.804.303-2.614-.591-.837-.892-.994-2.086-.375-2.66.63-.566 1.787-.301 2.626.591.838.903 1 2.088.363 2.66Zm4.32 7.188c-.785.545-2.067.034-2.86-1.104-.784-1.138-.784-2.503.017-3.05.795-.547 2.058-.055 2.861 1.075.782 1.157.782 2.522-.019 3.08Zm7.304 8.325c-.701.774-2.196.566-3.29-.49-1.119-1.032-1.43-2.496-.726-3.27.71-.776 2.213-.558 3.315.49 1.11 1.03 1.45 2.505.701 3.27Zm9.442 2.81c-.31 1.003-1.75 1.459-3.199 1.033-1.448-.439-2.395-1.613-2.103-2.626.301-1.01 1.747-1.484 3.207-1.028 1.446.436 2.396 1.602 2.095 2.622Zm10.744 1.193c.036 1.055-1.193 1.93-2.715 1.95-1.53.034-2.769-.82-2.786-1.86 0-1.065 1.202-1.932 2.733-1.958 1.522-.03 2.768.818 2.768 1.868Zm10.555-.405c.182 1.03-.875 2.088-2.387 2.37-1.485.271-2.861-.365-3.05-1.386-.184-1.056.893-2.114 2.376-2.387 1.514-.263 2.868.356 3.061 1.403Z" />
</svg>
</a>
);
}

function MaybeLink(props: LinkProps): JSX.Element {
if (props.href) {
Expand All @@ -22,8 +81,17 @@ export default function BlogPostItemHeaderAuthor({
author,
className,
}: Props): JSX.Element {
const {name, title, url, imageURL, email} = author;
const {name, title, twitter, github, url, imageURL, email} = author;
const link = url || (email && `mailto:${email}`) || undefined;
const renderSocialMedia = () => (
<div className={clsx(styles.authorSocial, 'avatar__subtitle')}>
{(twitter as string) && <Twitter user={twitter as string} />}
Copy link
Collaborator Author

@OzakIOne OzakIOne Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unknown keys such as twitter and github (and other keys that are not predefined) are typed as unknown which triggers TS to yell Type 'unknown' is not assignable to type 'ReactNode'
However as string might be an ugly solution, otherwise maybe update the Props type in theme classic.d.ts but which key should we define here ? (twitter?github? other random website?)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't use unknown keys in the first place

The type should contain a new "socials" attribute and we should validate those socials for both authors.yml and inline authors front matter

We should cover the most common socials (github, twitter/x, LinkedIn, SO, IG, website...) and allow unknown props (.unknown() in schema, [key: string]: string in type) in case users want to add extra social platforms

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the schema to allow a social object, however i'm not sure about the typing of unknown props if the user add a social website

{(github as string) && <Github user={github as string} />}
</div>
);

const hasSocialMedia = twitter || github;
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved

return (
<div className={clsx('avatar margin-bottom--sm', className)}>
{imageURL && (
Expand All @@ -39,7 +107,11 @@ export default function BlogPostItemHeaderAuthor({
<span>{name}</span>
</MaybeLink>
</div>
{title && <small className="avatar__subtitle">{title}</small>}
{hasSocialMedia ? (
renderSocialMedia()
) : (
<small className="avatar__subtitle">{title}</small>
)}
Comment on lines +75 to +79
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should choose one or the other, but let's discuss and figure this out

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This remains the main thing we need to solve to unblock this PR.

Can you add many dogfood cases of blog posts with single/many authors, with/without socials? We need to see how it would look like.

It would be preferable to keep displaying the author description, but maybe we can't when there are too many authors? 🤷‍♂️

Any multi-author blog inspiration to take a look from?

This Next.js blog only shows basic author info: https://nextjs.org/blog/next-12-3

</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

.authorSocial {
display: flex;
align-items: center;
}

.socialIcon {
width: 1.375em;
height: 1.375em;
margin-right: 0.5em;
}
1 change: 1 addition & 0 deletions website/blog/authors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ slorber:
url: https://thisweekinreact.com
image_url: https://github.com/slorber.png
twitter: sebastienlorber
github: slorber
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
email: [email protected]

yangshun:
Expand Down