Navigate back to the homepage

Cómo agregar share buttons a un theme en Gatsby

Javier Fonseca
January 19th, 2020 · 1 min read

Este blog está hecho usando un theme llamado gatsby-theme-novela, en dicho tema no incluye los botones para compartir en redes sociales.

Para poder agregarlos como un componente de React, se debe editar la vista que contiene el template que renderisa un artículo individual.

Buscando en internet encontré el proyecto react-custom-share

Para instalarlo usa

1yarn add react-custom-share
2yarn add emotion
3yarn add react-icons

Acorde a la ubicaciíon del archivo a modificar en el theme, creé el siguiente directorio dentro de la carpeta `src“

1src
2 @narrative
3 gatsby-theme-novela
4 template
5 article.template.tsx

Dentro del archivo, en caso de copiarlo completo se deben modificar los imports con la ubicación de la dependencia.

Luego agregé lo siguiente

1// import icons
2import { FaTwitter, FaFacebook, FaEnvelope, FaLinkedin } from "react-icons/fa";
3
4// import react-custom-share components
5import { ShareButtonIconOnly, ShareBlockStandard } from "react-custom-share";
1const shareBlockProps = {
2 url: "https://javierfonseca.me" + article.slug,
3 button: ShareButtonIconOnly,
4 buttons: [
5 { network: "Twitter", icon: FaTwitter },
6 { network: "Facebook", icon: FaFacebook },
7 { network: "Email", icon: FaEnvelope },
8 { network: "Linkedin", icon: FaLinkedin }
9 ],
10 text: article.title,
11 longtext: article.excerpt
12 };

Luego ubiqué el siguiente código dentro del componente que renderiza el contenido del artículo

1<ShareBlockStandard {...shareBlockProps} />

Para validar los cambios y que ni haya habido errores en el código, reinicié el servidor usando

1gatsby develop

Ya con esto Gatsby puede hacer shadowing del template del artículo y mostrará los nuevos cambios.

Acá muestro los cambios al archivo completo

1import React, { useRef, useState, useEffect } from "react";
2import styled from "@emotion/styled";
3import throttle from "lodash/throttle";
4import { graphql, useStaticQuery } from "gatsby";
5
6import Layout from "@narative/gatsby-theme-novela/src/components/Layout";
7import MDXRenderer from "@narative/gatsby-theme-novela/src/components/MDX";
8import Progress from "@narative/gatsby-theme-novela/src/components/Progress";
9import Section from "@narative/gatsby-theme-novela/src/components/Section";
10import Subscription from "@narative/gatsby-theme-novela/src/components/Subscription";
11
12import mediaqueries from "@narative/gatsby-theme-novela/src/styles/media";
13import { debounce } from "@narative/gatsby-theme-novela/src/utils";
14
15import ArticleAside from "@narative/gatsby-theme-novela/src/sections/article/Article.Aside";
16import ArticleHero from "@narative/gatsby-theme-novela/src/sections/article/Article.Hero";
17import ArticleControls from "@narative/gatsby-theme-novela/src/sections/article/Article.Controls";
18import ArticlesNext from "@narative/gatsby-theme-novela/src/sections/article/Article.Next";
19import ArticleSEO from "@narative/gatsby-theme-novela/src/sections/article/Article.SEO";
20import ArticleShare from "@narative/gatsby-theme-novela/src/sections/article/Article.Share";
21
22import { Template } from "@narative/gatsby-theme-novela/src/types";
23
24// import icons
25import { FaTwitter, FaFacebook, FaEnvelope, FaLinkedin } from "react-icons/fa";
26
27// import react-custom-share components
28import { ShareButtonIconOnly, ShareBlockStandard } from "react-custom-share";
29
30const siteQuery = graphql`
31 {
32 allSite {
33 edges {
34 node {
35 siteMetadata {
36 name
37 }
38 }
39 }
40 }
41 }
42`;
43
44const Article: Template = ({ pageContext, location }) => {
45 const contentSectionRef = useRef<HTMLElement>(null);
46
47 const [hasCalculated, setHasCalculated] = useState<boolean>(false);
48 const [contentHeight, setContentHeight] = useState<number>(0);
49
50 const results = useStaticQuery(siteQuery);
51 const name = results.allSite.edges[0].node.siteMetadata.name;
52
53 const { article, authors, mailchimp, next } = pageContext;
54
55 const shareBlockProps = {
56 url: "https://javierfonseca.me" + article.slug,
57 button: ShareButtonIconOnly,
58 buttons: [
59 { network: "Twitter", icon: FaTwitter },
60 { network: "Facebook", icon: FaFacebook },
61 { network: "Email", icon: FaEnvelope },
62 { network: "Linkedin", icon: FaLinkedin }
63 ],
64 text: article.title,
65 longtext: article.excerpt
66 };
67
68 useEffect(() => {
69 const calculateBodySize = throttle(() => {
70 const contentSection = contentSectionRef.current;
71
72 if (!contentSection) return;
73
74 /**
75 * If we haven't checked the content's height before,
76 * we want to add listeners to the content area's
77 * imagery to recheck when it's loaded
78 */
79 if (!hasCalculated) {
80 const debouncedCalculation = debounce(calculateBodySize);
81 const $imgs = contentSection.querySelectorAll("img");
82
83 $imgs.forEach($img => {
84 // If the image hasn't finished loading then add a listener
85 if (!$img.complete) $img.onload = debouncedCalculation;
86 });
87
88 // Prevent rerun of the listener attachment
89 setHasCalculated(true);
90 }
91
92 // Set the height and offset of the content area
93 setContentHeight(contentSection.getBoundingClientRect().height);
94 }, 20);
95
96 calculateBodySize();
97 window.addEventListener("resize", calculateBodySize);
98
99 return () => window.removeEventListener("resize", calculateBodySize);
100 }, []);
101
102 return (
103 <Layout>
104 <ArticleSEO article={article} authors={authors} location={location} />
105 <ArticleHero article={article} authors={authors} />
106 <ArticleAside contentHeight={contentHeight}>
107 <Progress contentHeight={contentHeight} />
108 </ArticleAside>
109 <MobileControls>
110 <ArticleControls />
111 </MobileControls>
112 <ArticleBody ref={contentSectionRef}>
113 <MDXRenderer content={article.body}>
114 <ArticleShare />
115 </MDXRenderer>
116 <Section narrow>
117 <p style={center}>Share</p>
118 <ShareBlockStandard {...shareBlockProps} />
119 </Section>
120 </ArticleBody>
121 {mailchimp && article.subscription && <Subscription />}
122 {next.length > 0 && (
123 <NextArticle narrow>
124 <FooterNext>More articles from {name} </FooterNext>
125 <ArticlesNext articles={next} />
126 <FooterSpacer />
127 </NextArticle>
128 )}
129 </Layout>
130 );
131};
132
133export default Article;
134
135const center = {
136 textAlign:"center",
137 paddingBottom: "10px"
138};
139
140const MobileControls = styled.div`
141 position: relative;
142 padding-top: 60px;
143 transition: background 0.2s linear;
144 text-align: center;
145 ${mediaqueries.tablet_up`
146 display: none;
147 `}
148`;
149
150const ArticleBody = styled.article`
151 position: relative;
152 padding: 160px 0 35px;
153 padding-left: 68px;
154 transition: background 0.2s linear;
155 ${mediaqueries.desktop`
156 padding-left: 53px;
157 `}
158
159 ${mediaqueries.tablet`
160 padding: 70px 0 80px;
161 `}
162 ${mediaqueries.phablet`
163 padding: 60px 0;
164 `}
165`;
166
167const HoritzontalRule = styled.div`
168 position: relative;
169 margin: 140px auto 50px;
170 border-bottom: 1px solid ${p => p.theme.colors.horizontalRule};
171 ${mediaqueries.tablet`
172 margin: 60px auto;
173 `}
174 ${mediaqueries.phablet`
175 display: none;
176 `}
177`;
178
179const NextArticle = styled(Section)`
180 display: block;
181`;
182
183const FooterNext = styled.h3`
184 position: relative;
185 opacity: 0.25;
186 margin-bottom: 100px;
187 font-weight: 400;
188 padding-top: 30px;
189 color: ${p => p.theme.colors.primary};
190 ${mediaqueries.tablet`
191 margin-bottom: 60px;
192 `}
193 &::after {
194 content: '';
195 position: absolute;
196 background: ${p => p.theme.colors.grey};
197 width: 100%;
198 height: 1px;
199 right: 0;
200 top: 11px;
201 ${mediaqueries.tablet`
202 width: ${(600 / 1140) * 100}%;
203 `}
204 ${mediaqueries.phablet`
205 width: ${(400 / 1140) * 100}%;
206 `}
207 ${mediaqueries.phone`
208 width: 90px
209 `}
210 }
211`;
212
213const FooterSpacer = styled.div`
214 margin-bottom: 65px;
215`;

Share

More articles from Javier Fonseca's Blog

Estructura Markdown usada por Gatsby

Guía de sintaxis de Markdown en Gatsby

January 18th, 2020 · 1 min read

Crear un blog con Gatsby

La forma sencilla de crear un blog con Gatsby

January 18th, 2020 · 3 min read
© 2020 Javier Fonseca's Blog
Link to $https://twitter.com/fonsecaj89Link to $https://www.facebook.com/FonsecaJ89Link to $https://github.com/Fonsecaj89Link to $https://www.linkedin.com/in/fonseca25t