From c9d5f6be49a89fad5a778c0342a27fc3452d863d Mon Sep 17 00:00:00 2001 From: Armand Philippot Date: Mon, 10 Jan 2022 12:36:12 +0100 Subject: refactor(aside): move width from aside to sharing widget Only the Sharing widget needs the "min-content" width. --- src/components/Sharing/Sharing.module.scss | 196 --------------------- src/components/Sharing/Sharing.tsx | 111 ------------ src/components/Widget/Sharing/Sharing.module.scss | 197 ++++++++++++++++++++++ src/components/Widget/Sharing/Sharing.tsx | 111 ++++++++++++ src/components/Widget/index.tsx | 3 +- src/pages/article/[slug].tsx | 3 +- src/styles/pages/Page.module.scss | 1 - 7 files changed, 311 insertions(+), 311 deletions(-) delete mode 100644 src/components/Sharing/Sharing.module.scss delete mode 100644 src/components/Sharing/Sharing.tsx create mode 100644 src/components/Widget/Sharing/Sharing.module.scss create mode 100644 src/components/Widget/Sharing/Sharing.tsx diff --git a/src/components/Sharing/Sharing.module.scss b/src/components/Sharing/Sharing.module.scss deleted file mode 100644 index fe13125..0000000 --- a/src/components/Sharing/Sharing.module.scss +++ /dev/null @@ -1,196 +0,0 @@ -@use "@styles/abstracts/functions" as fun; -@use "@styles/abstracts/mixins" as mix; -@use "@styles/abstracts/placeholders"; - -.wrapper { - max-height: 100vh; - padding-bottom: var(--spacing-sm); - position: sticky; - top: 0; - overflow-y: auto; -} - -.list { - @extend %flex-list; - - gap: var(--spacing-sm); -} - -.link { - display: flex; - flex-flow: row nowrap; - align-items: center; - padding: var(--spacing-2xs) var(--spacing-xs); - border-radius: fun.convert-px(3); - color: var(--color-fg-inverted); - font-weight: 600; - text-decoration: none; - text-shadow: fun.convert-px(2) fun.convert-px(1) fun.convert-px(1) - var(--color-shadow-dark); - transition: all 0.3s ease-in-out 0s; - - @include mix.media("screen") { - @include mix.dimensions("sm") { - font-size: var(--font-size-sm); - } - } - - &:hover, - &:focus { - color: hsl(0, 0%, 100%); - transform: translateX(#{fun.convert-px(-3)}) - translateY(#{fun.convert-px(-3)}); - - @include mix.motion("reduce") { - text-decoration: underline; - } - } - - &:active { - color: hsl(0, 0%, 100%); - transform: translateX(#{fun.convert-px(2)}) translateY(#{fun.convert-px(2)}); - - @include mix.motion("reduce") { - transform: none; - } - } - - &::before { - display: block; - background-repeat: no-repeat; - content: ""; - filter: drop-shadow( - #{fun.convert-px(1)} #{fun.convert-px(1)} #{fun.convert-px(1)} hsl(0, 0%, 0%) - ); - width: fun.convert-px(30); - height: fun.convert-px(30); - } - - &--diaspora { - background: hsl(0, 0%, 13%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(0, 0%, 3%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 hsl(0, 0%, 3%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 hsl(0, 0%, 3%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } - - &--email { - background: hsl(0, 0%, 44%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(0, 0%, 34%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 hsl(0, 0%, 34%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 hsl(0, 0%, 34%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } - - &--facebook { - background: hsl(214, 89%, 52%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(214, 89%, 42%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 - hsl(214, 89%, 42%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 - hsl(214, 89%, 42%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } - - &--journal-du-hacker { - background: hsl(210, 24%, 51%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(210, 24%, 41%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 - hsl(210, 24%, 41%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 - hsl(210, 24%, 41%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } - - &--linkedin { - background: hsl(210, 90%, 40%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(210, 90%, 30%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 - hsl(210, 90%, 30%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 - hsl(210, 90%, 30%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } - - &--twitter { - background: hsl(203, 89%, 53%); - box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(203, 89%, 43%); - - &:hover, - &:focus { - box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 - hsl(203, 89%, 43%); - } - - &:active { - box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 - hsl(203, 89%, 43%); - } - - &::before { - background-image: url(fun.encode-svg( - '' - )); - } - } -} diff --git a/src/components/Sharing/Sharing.tsx b/src/components/Sharing/Sharing.tsx deleted file mode 100644 index 4df8e0d..0000000 --- a/src/components/Sharing/Sharing.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import sharingMedia from '@config/sharing'; -import { t } from '@lingui/macro'; -import { useRouter } from 'next/router'; -import { useEffect, useState } from 'react'; -import styles from './Sharing.module.scss'; - -type Parameters = { - content: string; - image: string; - title: string; - url: string; -}; - -type Website = { - id: string; - name: string; - parameters: Parameters; - url: string; -}; - -const Sharing = ({ excerpt, title }: { excerpt: string; title: string }) => { - const [pageExcerpt, setPageExcerpt] = useState(''); - const [pageUrl, setPageUrl] = useState(''); - const [domainName, setDomainName] = useState(''); - const router = useRouter(); - - useEffect(() => { - const divEl = document.createElement('div'); - divEl.innerHTML = excerpt; - const cleanExcerpt = divEl.textContent!; - setPageExcerpt(cleanExcerpt); - }, [excerpt]); - - useEffect(() => { - const { protocol, hostname, port } = window.location; - const currentPort = port ? `:${port}` : ''; - const fullUrl = `${protocol}//${hostname}${currentPort}${router.asPath}`; - - setDomainName(hostname); - setPageUrl(fullUrl); - }, [router.asPath]); - - const getSharingUrl = (website: Website): string => { - const { id, parameters, url } = website; - let sharingUrl = `${url}?`; - let count = 0; - - for (const [key, value] of Object.entries(parameters)) { - if (!value) continue; - - sharingUrl += count > 0 ? `&${value}=` : `${value}=`; - - switch (key) { - case 'content': - if (id === 'email') { - const intro = t`Introduction:`; - const readMore = t`Read more here:`; - const body = `${intro}\n\n"${pageExcerpt}"\n\n${readMore} ${pageUrl}`; - sharingUrl += encodeURI(body); - } else { - sharingUrl += encodeURI(pageExcerpt); - } - break; - case 'title': - const prefix = id === 'email' ? t`Seen on ${domainName}:` : ''; - sharingUrl += encodeURI(`${prefix} ${title}`); - break; - case 'url': - sharingUrl += encodeURI(pageUrl); - break; - default: - break; - } - - count++; - } - - return sharingUrl; - }; - - const getItems = () => { - const websites: Website[] = sharingMedia; - - return websites.map((website) => { - const { id, name } = website; - const sharingUrl = getSharingUrl(website); - const linkModifier = `link--${id}`; - - return ( -
  • - - {name} - -
  • - ); - }); - }; - - return ( -
    -

    {t`Share`}

    - -
    - ); -}; - -export default Sharing; diff --git a/src/components/Widget/Sharing/Sharing.module.scss b/src/components/Widget/Sharing/Sharing.module.scss new file mode 100644 index 0000000..a1ba094 --- /dev/null +++ b/src/components/Widget/Sharing/Sharing.module.scss @@ -0,0 +1,197 @@ +@use "@styles/abstracts/functions" as fun; +@use "@styles/abstracts/mixins" as mix; +@use "@styles/abstracts/placeholders"; + +.wrapper { + width: min-content; + max-height: 100vh; + padding-bottom: var(--spacing-sm); + position: sticky; + top: 0; + overflow-y: auto; +} + +.list { + @extend %flex-list; + + gap: var(--spacing-sm); +} + +.link { + display: flex; + flex-flow: row nowrap; + align-items: center; + padding: var(--spacing-2xs) var(--spacing-xs); + border-radius: fun.convert-px(3); + color: var(--color-fg-inverted); + font-weight: 600; + text-decoration: none; + text-shadow: fun.convert-px(2) fun.convert-px(1) fun.convert-px(1) + var(--color-shadow-dark); + transition: all 0.3s ease-in-out 0s; + + @include mix.media("screen") { + @include mix.dimensions("sm") { + font-size: var(--font-size-sm); + } + } + + &:hover, + &:focus { + color: hsl(0, 0%, 100%); + transform: translateX(#{fun.convert-px(-3)}) + translateY(#{fun.convert-px(-3)}); + + @include mix.motion("reduce") { + text-decoration: underline; + } + } + + &:active { + color: hsl(0, 0%, 100%); + transform: translateX(#{fun.convert-px(2)}) translateY(#{fun.convert-px(2)}); + + @include mix.motion("reduce") { + transform: none; + } + } + + &::before { + display: block; + background-repeat: no-repeat; + content: ""; + filter: drop-shadow( + #{fun.convert-px(1)} #{fun.convert-px(1)} #{fun.convert-px(1)} hsl(0, 0%, 0%) + ); + width: fun.convert-px(30); + height: fun.convert-px(30); + } + + &--diaspora { + background: hsl(0, 0%, 13%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(0, 0%, 3%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 hsl(0, 0%, 3%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 hsl(0, 0%, 3%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } + + &--email { + background: hsl(0, 0%, 44%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(0, 0%, 34%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 hsl(0, 0%, 34%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 hsl(0, 0%, 34%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } + + &--facebook { + background: hsl(214, 89%, 52%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(214, 89%, 42%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 + hsl(214, 89%, 42%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 + hsl(214, 89%, 42%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } + + &--journal-du-hacker { + background: hsl(210, 24%, 51%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(210, 24%, 41%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 + hsl(210, 24%, 41%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 + hsl(210, 24%, 41%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } + + &--linkedin { + background: hsl(210, 90%, 40%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(210, 90%, 30%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 + hsl(210, 90%, 30%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 + hsl(210, 90%, 30%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } + + &--twitter { + background: hsl(203, 89%, 53%); + box-shadow: #{fun.convert-px(3)} #{fun.convert-px(3)} 0 0 hsl(203, 89%, 43%); + + &:hover, + &:focus { + box-shadow: #{fun.convert-px(6)} #{fun.convert-px(6)} 0 0 + hsl(203, 89%, 43%); + } + + &:active { + box-shadow: #{fun.convert-px(1)} #{fun.convert-px(1)} 0 0 + hsl(203, 89%, 43%); + } + + &::before { + background-image: url(fun.encode-svg( + '' + )); + } + } +} diff --git a/src/components/Widget/Sharing/Sharing.tsx b/src/components/Widget/Sharing/Sharing.tsx new file mode 100644 index 0000000..4df8e0d --- /dev/null +++ b/src/components/Widget/Sharing/Sharing.tsx @@ -0,0 +1,111 @@ +import sharingMedia from '@config/sharing'; +import { t } from '@lingui/macro'; +import { useRouter } from 'next/router'; +import { useEffect, useState } from 'react'; +import styles from './Sharing.module.scss'; + +type Parameters = { + content: string; + image: string; + title: string; + url: string; +}; + +type Website = { + id: string; + name: string; + parameters: Parameters; + url: string; +}; + +const Sharing = ({ excerpt, title }: { excerpt: string; title: string }) => { + const [pageExcerpt, setPageExcerpt] = useState(''); + const [pageUrl, setPageUrl] = useState(''); + const [domainName, setDomainName] = useState(''); + const router = useRouter(); + + useEffect(() => { + const divEl = document.createElement('div'); + divEl.innerHTML = excerpt; + const cleanExcerpt = divEl.textContent!; + setPageExcerpt(cleanExcerpt); + }, [excerpt]); + + useEffect(() => { + const { protocol, hostname, port } = window.location; + const currentPort = port ? `:${port}` : ''; + const fullUrl = `${protocol}//${hostname}${currentPort}${router.asPath}`; + + setDomainName(hostname); + setPageUrl(fullUrl); + }, [router.asPath]); + + const getSharingUrl = (website: Website): string => { + const { id, parameters, url } = website; + let sharingUrl = `${url}?`; + let count = 0; + + for (const [key, value] of Object.entries(parameters)) { + if (!value) continue; + + sharingUrl += count > 0 ? `&${value}=` : `${value}=`; + + switch (key) { + case 'content': + if (id === 'email') { + const intro = t`Introduction:`; + const readMore = t`Read more here:`; + const body = `${intro}\n\n"${pageExcerpt}"\n\n${readMore} ${pageUrl}`; + sharingUrl += encodeURI(body); + } else { + sharingUrl += encodeURI(pageExcerpt); + } + break; + case 'title': + const prefix = id === 'email' ? t`Seen on ${domainName}:` : ''; + sharingUrl += encodeURI(`${prefix} ${title}`); + break; + case 'url': + sharingUrl += encodeURI(pageUrl); + break; + default: + break; + } + + count++; + } + + return sharingUrl; + }; + + const getItems = () => { + const websites: Website[] = sharingMedia; + + return websites.map((website) => { + const { id, name } = website; + const sharingUrl = getSharingUrl(website); + const linkModifier = `link--${id}`; + + return ( +
  • + + {name} + +
  • + ); + }); + }; + + return ( +
    +

    {t`Share`}

    + +
    + ); +}; + +export default Sharing; diff --git a/src/components/Widget/index.tsx b/src/components/Widget/index.tsx index e4e346f..d5374ea 100644 --- a/src/components/Widget/index.tsx +++ b/src/components/Widget/index.tsx @@ -1,5 +1,6 @@ import RecentPosts from './RecentPosts/RecentPosts'; +import Sharing from './Sharing/Sharing'; import ThematicsList from './ThematicsList/ThematicsList'; import TopicsList from './TopicsList/TopicsList'; -export { RecentPosts, ThematicsList, TopicsList }; +export { RecentPosts, Sharing, ThematicsList, TopicsList }; diff --git a/src/pages/article/[slug].tsx b/src/pages/article/[slug].tsx index 889af43..7d25843 100644 --- a/src/pages/article/[slug].tsx +++ b/src/pages/article/[slug].tsx @@ -3,10 +3,8 @@ import CommentsList from '@components/CommentsList/CommentsList'; import { getLayout } from '@components/Layouts/Layout'; import PostFooter from '@components/PostFooter/PostFooter'; import PostHeader from '@components/PostHeader/PostHeader'; -import Sharing from '@components/Sharing/Sharing'; import ToC from '@components/ToC/ToC'; import { config } from '@config/website'; -import { t } from '@lingui/macro'; import { getAllPostsSlug, getPostBySlug } from '@services/graphql/queries'; import { NextPageWithLayout } from '@ts/types/app'; import { ArticleMeta, ArticleProps } from '@ts/types/articles'; @@ -19,6 +17,7 @@ import Prism from 'prismjs'; import { ParsedUrlQuery } from 'querystring'; import { useEffect } from 'react'; import styles from '@styles/pages/Page.module.scss'; +import { Sharing } from '@components/Widget'; const SingleArticle: NextPageWithLayout = ({ post }) => { const { diff --git a/src/styles/pages/Page.module.scss b/src/styles/pages/Page.module.scss index b3615f6..41172a3 100644 --- a/src/styles/pages/Page.module.scss +++ b/src/styles/pages/Page.module.scss @@ -45,7 +45,6 @@ grid-column: 3; grid-row: 2 / 5; align-self: stretch; - max-width: min-content; padding: 0 var(--spacing-sm); } -- cgit v1.2.3