feat: implement share button

This commit is contained in:
jinhojang6 2023-08-28 22:46:41 +09:00
parent e0e961e886
commit e4869d1c8e
10 changed files with 202 additions and 2 deletions

View File

@ -9,6 +9,7 @@ import { LPE } from '../../../types/lpe.types'
import { ArticleImageBlockWrapper } from '../Article.ImageBlockWrapper'
import ArticleStats from '../Article.Stats'
import ArticleSummary from './Article.Summary'
import { TagsAndSocial } from '@/components/TagsAndSocial'
export type ArticleHeaderProps = LPE.Article.Data
@ -53,7 +54,7 @@ const ArticleHeader = ({
{subtitle}
</ArticleSubtitle>
)}
<Tags tags={tags} className={'articleTags'} />
<TagsAndSocial tags={tags} className={'articleTags'} />
<AuthorsContainer>
<Authors authors={authors} email={true} gap={12} />
</AuthorsContainer>

View File

@ -7,6 +7,8 @@ import EpisodeStats from '../Episode.Stats'
import EpisodePlayer from './Episode.Player'
import Image from 'next/image'
import Link from 'next/link'
import { ShareButton } from '@/components/ShareButton'
import { TagsAndSocial } from '@/components/TagsAndSocial'
export type EpisodeHeaderProps = LPE.Podcast.Document & {
channel: LPE.Podcast.Channel
@ -51,7 +53,7 @@ const EpisodeHeader = ({
</Show>
</CustomLink>
)}
{tags && <Tags tags={tags} />}
<TagsAndSocial tags={tags} />
{channels && <EpisodeChannels channels={channels} />}
{description && (
<EpisodeSubtitle
@ -106,6 +108,7 @@ const Show = styled.div`
const CustomLink = styled(Link)`
text-decoration: none;
width: fit-content;
`
export default EpisodeHeader

View File

@ -0,0 +1,20 @@
import { LsdIcon } from '@acid-info/lsd-react'
export const CopyIcon = LsdIcon(
(props) => (
<svg
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M9.33268 0.583313H2.33268C1.69102 0.583313 1.16602 1.10831 1.16602 1.74998V9.91665H2.33268V1.74998H9.33268V0.583313ZM8.74935 2.91665H4.66602C4.02435 2.91665 3.50518 3.44165 3.50518 4.08331L3.49935 12.25C3.49935 12.8916 4.01852 13.4166 4.66018 13.4166H11.0827C11.7243 13.4166 12.2493 12.8916 12.2493 12.25V6.41665L8.74935 2.91665ZM4.66602 12.25V4.08331H8.16602V6.99998H11.0827V12.25H4.66602Z"
fill="black"
/>
</svg>
),
{ filled: true },
)

View File

@ -0,0 +1 @@
export * from './CopyIcon'

View File

@ -0,0 +1,20 @@
import { LsdIcon } from '@acid-info/lsd-react'
export const ShareIcon = LsdIcon(
(props) => (
<svg
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M10.5 9.37999C10.0567 9.37999 9.66 9.55499 9.35667 9.82916L5.1975 7.40832C5.22667 7.27416 5.25 7.13999 5.25 6.99999C5.25 6.85999 5.22667 6.72582 5.1975 6.59166L9.31 4.19416C9.625 4.48582 10.0392 4.66666 10.5 4.66666C11.4683 4.66666 12.25 3.88499 12.25 2.91666C12.25 1.94832 11.4683 1.16666 10.5 1.16666C9.53167 1.16666 8.75 1.94832 8.75 2.91666C8.75 3.05666 8.77333 3.19082 8.8025 3.32499L4.69 5.72249C4.375 5.43082 3.96083 5.24999 3.5 5.24999C2.53167 5.24999 1.75 6.03166 1.75 6.99999C1.75 7.96832 2.53167 8.74999 3.5 8.74999C3.96083 8.74999 4.375 8.56916 4.69 8.27749L8.84333 10.7042C8.81417 10.8267 8.79667 10.955 8.79667 11.0833C8.79667 12.0225 9.56083 12.7867 10.5 12.7867C11.4392 12.7867 12.2033 12.0225 12.2033 11.0833C12.2033 10.1442 11.4392 9.37999 10.5 9.37999ZM10.5 2.33332C10.8208 2.33332 11.0833 2.59582 11.0833 2.91666C11.0833 3.23749 10.8208 3.49999 10.5 3.49999C10.1792 3.49999 9.91667 3.23749 9.91667 2.91666C9.91667 2.59582 10.1792 2.33332 10.5 2.33332ZM3.5 7.58332C3.17917 7.58332 2.91667 7.32082 2.91667 6.99999C2.91667 6.67916 3.17917 6.41666 3.5 6.41666C3.82083 6.41666 4.08333 6.67916 4.08333 6.99999C4.08333 7.32082 3.82083 7.58332 3.5 7.58332ZM10.5 11.6783C10.1792 11.6783 9.91667 11.4158 9.91667 11.095C9.91667 10.7742 10.1792 10.5117 10.5 10.5117C10.8208 10.5117 11.0833 10.7742 11.0833 11.095C11.0833 11.4158 10.8208 11.6783 10.5 11.6783Z"
fill="black"
/>
</svg>
),
{ filled: true },
)

View File

@ -0,0 +1 @@
export * from './ShareIcon'

View File

@ -0,0 +1,118 @@
import { Tag, Typography } from '@acid-info/lsd-react'
import styled from '@emotion/styled'
import { ShareIcon } from '../Icons/ShareIcon'
import { useRef, useState } from 'react'
import { CopyIcon } from '../Icons/CopyIcon'
import { XIcon } from '../Icons/XIcon'
import Link from 'next/link'
import { useClickAway } from 'react-use'
type Props = {
url: string
}
export default function ShareButton({ url }: Props) {
const [showOptions, setShowOptions] = useState(false)
const [copied, setCopied] = useState(false)
const ref = useRef(null)
useClickAway(ref, () => {
setShowOptions(false)
})
const handleCopyClipBoard = async (text: string) => {
await navigator.clipboard.writeText(text)
setCopied(true)
// TODO : Temporary solution
setTimeout(() => {
setCopied(false)
}, 2000)
}
return (
<Container ref={ref}>
<CustomTag
onClick={() => setShowOptions(!showOptions)}
icon={<ShareIcon width={14} height={14} />}
iconDirection="left"
showOptions={showOptions}
>
<Typography variant="body3">Share</Typography>
</CustomTag>
{showOptions && (
<Options>
<Label>
<Typography variant="body3">Share Options</Typography>
</Label>
<ShareOption onClick={() => handleCopyClipBoard(url)}>
<CopyIcon width={14} height={14} />
<Typography variant="body2">
{copied ? 'Copied' : 'Copy link'}
</Typography>
</ShareOption>
<CustomLink href={`http://www.twitter.com/share?url=${url}`}>
<ShareOption>
<XIcon />
<Typography variant="body2">X</Typography>
</ShareOption>
</CustomLink>
</Options>
)}
</Container>
)
}
const HEIGHT = 24
const Container = styled.div`
position: relative;
`
const CustomTag = styled(Tag)<{ showOptions: boolean }>`
width: 69px;
height: ${HEIGHT}px;
padding: 0 8px;
border-bottom: ${(props) =>
props.showOptions
? '1px solid transparent'
: '1px solid rgb(var(--lsd-border-primary))'};
`
const Options = styled.div`
top: ${HEIGHT - 1}px;
left: 0;
width: 169px;
border: 1px solid rgb(var(--lsd-border-primary));
position: absolute;
background-color: rgb(var(--lsd-surface-primary));
padding-bottom: 8px;
z-index: 1;
`
const Label = styled.div`
padding: 12px;
`
const ShareOption = styled.div`
cursor: pointer;
padding: 6px 12px 6px 14px;
display: flex;
gap: 14px;
align-items: center;
&:hover {
text-decoration: underline;
}
`
const CustomLink = styled(Link)`
text-decoration: none;
display: flex;
align-items: center;
gap: 14px;
&:hover {
text-decoration: underline;
}
`

View File

@ -0,0 +1 @@
export { default as ShareButton } from './ShareButton'

View File

@ -0,0 +1,34 @@
import styled from '@emotion/styled'
import { ShareButton } from '../ShareButton'
import { Tags } from '../Tags'
export type TagsProps = {
tags: string[]
className?: string
}
const TagsAndSocial: React.FC<TagsProps> = ({ tags, className }) => {
const currentUrl = typeof window !== 'undefined' ? window.location.href : ''
return (
<Container>
{tags && <Tags tags={tags} className={className} />}
<VerticalLine />
<ShareButton url={currentUrl} />
</Container>
)
}
const Container = styled.div`
display: flex;
align-items: center;
gap: 16px;
width: fit-content;
`
const VerticalLine = styled.div`
height: 12px;
border-left: 1px solid rgb(var(--lsd-border-primary));
`
export default TagsAndSocial

View File

@ -0,0 +1 @@
export { default as TagsAndSocial } from './TagsAndSocial'