Skip to content

Commit 2b03db6

Browse files
committed
Adds SocialShare
1 parent bf62fed commit 2b03db6

16 files changed

Lines changed: 477 additions & 2 deletions

dist/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@smitch/fluid",
3-
"version": "3.0.40",
3+
"version": "3.0.41",
44
"description": "A Next/React ui-component libray.",
55
"main": "index.js",
66
"keywords": [

src/ui/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export { Tabs } from './tabs'
5151
export { SearchInput } from './searchinput'
5252
export { Select } from './select'
5353
export { Sidebar } from './sidebar'
54+
export { SocialShare } from './socialshare'
5455
export { StatBar } from './statbar'
5556
export { Switch } from './switch'
5657
export { TextInput } from './textinput'

src/ui/map/stories/Map.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Map, MapMarker, MapCircle, MapPolygon, MapLine, MapRectangle } from '..
66
import { States } from '@/data/states'
77

88
const meta: Meta<typeof Map> = {
9-
title: 'Fluid UI/Map',
9+
title: 'Fluid UI/Maps/Map',
1010
component: Map,
1111
parameters: {
1212
docs: {

src/ui/socialshare/SocialShare.tsx

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import React, { useMemo } from 'react'
2+
import { twMerge } from 'tailwind-merge'
3+
4+
import dynamic from 'next/dynamic'
5+
6+
const XButton = dynamic(() => import('./buttons/XButton'), { ssr: false })
7+
const FacebookButton = dynamic(() => import('./buttons/FacebookButton'), { ssr: false })
8+
const LinkedInButton = dynamic(() => import('./buttons/LinkedinButton'), { ssr: false })
9+
const SlackButton = dynamic(() => import('./buttons/SlackButton'), { ssr: false })
10+
const WhatsAppButton = dynamic(() => import('./buttons/WhatsappButton'), { ssr: false })
11+
const RedditButton = dynamic(() => import('./buttons/RedditButton'), { ssr: false })
12+
const PinterestButton = dynamic(() => import('./buttons/PinterestButton'), { ssr: false })
13+
const TelegramButton = dynamic(() => import('./buttons/TelegramButton'), { ssr: false })
14+
const EmailButton = dynamic(() => import('./buttons/EmailButton'), { ssr: false })
15+
16+
import { SocialShareProps } from './types'
17+
18+
const buttonComponents: Record<string, React.ComponentType<any>> = {
19+
X: XButton,
20+
Facebook: FacebookButton,
21+
LinkedIn: LinkedInButton,
22+
Slack: SlackButton,
23+
WhatsApp: WhatsAppButton,
24+
Reddit: RedditButton,
25+
Pinterest: PinterestButton,
26+
Telegram: TelegramButton,
27+
Email: EmailButton,
28+
}
29+
30+
const gapSpacing = {
31+
none: 'gap-0',
32+
sm: 'gap-1',
33+
md: 'gap-2',
34+
lg: 'gap-3',
35+
xl: 'gap-4',
36+
}
37+
38+
const layouts = {
39+
horizontal: 'flex-row',
40+
vertical: 'flex-col',
41+
}
42+
43+
const SocialShare = ({
44+
text,
45+
buttons,
46+
btnShape = 'rounded',
47+
size = 'md',
48+
gap = 'none',
49+
layout = 'horizontal',
50+
className = '',
51+
style,
52+
}: SocialShareProps) => {
53+
const gapClasses = useMemo(() => gapSpacing[gap], [gap])
54+
const layoutClasses = useMemo(() => layouts[layout], [layout])
55+
56+
return (
57+
<div
58+
className={twMerge(
59+
`social-share w-fit flex items-center ${layoutClasses} ${gapClasses}`,
60+
className
61+
)}
62+
style={style}
63+
>
64+
{buttons.map((btn) => {
65+
const BtnComponent = buttonComponents[btn]
66+
if (!BtnComponent) return null
67+
68+
const needsText = !['Facebook', 'LinkedIn'].includes(btn)
69+
const props = needsText ? { text } : {}
70+
71+
return (
72+
<BtnComponent
73+
key={btn}
74+
btnShape={btnShape}
75+
size={size}
76+
{...props}
77+
/>
78+
)
79+
})}
80+
</div>
81+
)
82+
}
83+
84+
export default SocialShare
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use client'
2+
3+
import { MdEmail } from 'react-icons/md'
4+
import { Button } from '../..'
5+
import { XButtonProps } from '../types'
6+
7+
const EmailButton = ({ text, btnShape, size }: XButtonProps) => {
8+
const handleShareClick = () => {
9+
const subject = encodeURIComponent(document.title)
10+
const body = encodeURIComponent(`${text}\n\n${window.location.href}`)
11+
const mailtoUrl = `mailto:?subject=${subject}&body=${body}`
12+
window.open(mailtoUrl, '_blank', 'noopener,noreferrer')
13+
}
14+
15+
return (
16+
<Button
17+
onClick={handleShareClick}
18+
btnBackground='info'
19+
btnColor='light'
20+
hoverScale
21+
layout={btnShape}
22+
size={size}
23+
title='Share via Email'
24+
className='focus:border-info focus-visible:outline-info bg-[#0072C6]'
25+
>
26+
<MdEmail />
27+
<span className='sr-only'>Share via Email</span>
28+
</Button>
29+
)
30+
}
31+
32+
export default EmailButton
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use client'
2+
3+
import { FaFacebook } from 'react-icons/fa'
4+
import { Button } from '../..'
5+
import { FacebookButtonProps } from '../types'
6+
7+
const FacebookButton = ({ btnShape, size }: FacebookButtonProps) => {
8+
const handleShareClick = () => {
9+
const baseUrl = 'https://www.facebook.com/sharer/sharer.php'
10+
const shareUrl = new URL(baseUrl)
11+
12+
shareUrl.searchParams.set('u', window.location.href)
13+
14+
window.open(shareUrl.toString(), '_blank', 'noopener,noreferrer')
15+
}
16+
17+
return (
18+
<Button
19+
onClick={handleShareClick}
20+
btnBackground='primary'
21+
btnColor='light'
22+
hoverScale
23+
layout={btnShape}
24+
size={size}
25+
title='Share on Facebook'
26+
className='focus:border-info focus-visible:outline-info bg-[#1877F2]'
27+
>
28+
<FaFacebook />
29+
<span className='sr-only'>Share on Facebook</span>
30+
</Button>
31+
)
32+
}
33+
34+
export default FacebookButton
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use client'
2+
3+
import { FaLinkedin } from 'react-icons/fa'
4+
import { Button } from '../..'
5+
import { LinkedInButtonProps } from '../types'
6+
7+
const LinkedInButton = ({ btnShape, size }: LinkedInButtonProps) => {
8+
const handleShareClick = () => {
9+
const baseUrl = 'https://www.linkedin.com/sharing/share-offsite/'
10+
const shareUrl = new URL(baseUrl)
11+
12+
shareUrl.searchParams.set('url', window.location.href)
13+
14+
window.open(shareUrl.toString(), '_blank', 'noopener,noreferrer')
15+
}
16+
17+
return (
18+
<Button
19+
onClick={handleShareClick}
20+
btnBackground='primary'
21+
btnColor='light'
22+
hoverScale
23+
layout={btnShape}
24+
size={size}
25+
title='Share on LinkedIn'
26+
className='focus:border-info focus-visible:outline-info bg-[#0077B5]'
27+
>
28+
<FaLinkedin />
29+
<span className='sr-only'>Share on LinkedIn</span>
30+
</Button>
31+
)
32+
}
33+
34+
export default LinkedInButton
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client'
2+
3+
import { FaPinterestP } from 'react-icons/fa'
4+
import { Button } from '../..'
5+
import { XButtonProps } from '../types'
6+
7+
const PinterestButton = ({ text, btnShape, size }: XButtonProps) => {
8+
const handleShareClick = () => {
9+
const baseUrl = 'https://pinterest.com/pin/create/button/'
10+
const params = new URLSearchParams({
11+
description: text.replace(/(\r\n|\n|\r)/g, ' '),
12+
url: window.location.href,
13+
})
14+
15+
const shareUrl = `${baseUrl}?${params.toString()}`
16+
window.open(shareUrl, '_blank', 'noopener,noreferrer')
17+
}
18+
19+
return (
20+
<Button
21+
onClick={handleShareClick}
22+
btnBackground='danger'
23+
btnColor='light'
24+
hoverScale
25+
layout={btnShape}
26+
size={size}
27+
title='Share on Pinterest'
28+
className='focus:border-danger focus-visible:outline-danger bg-[#E60023]'
29+
>
30+
<FaPinterestP />
31+
<span className='sr-only'>Share on Pinterest</span>
32+
</Button>
33+
)
34+
}
35+
36+
export default PinterestButton
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client'
2+
3+
import { FaRedditAlien } from 'react-icons/fa'
4+
import { Button } from '../..'
5+
import { XButtonProps } from '../types'
6+
7+
const RedditButton = ({ text, btnShape, size }: XButtonProps) => {
8+
const handleShareClick = () => {
9+
const baseUrl = 'https://www.reddit.com/submit'
10+
const params = new URLSearchParams({
11+
title: text.replace(/(\r\n|\n|\r)/g, ' '),
12+
url: window.location.href,
13+
})
14+
15+
const shareUrl = `${baseUrl}?${params.toString()}`
16+
window.open(shareUrl, '_blank', 'noopener,noreferrer')
17+
}
18+
19+
return (
20+
<Button
21+
onClick={handleShareClick}
22+
btnBackground='danger'
23+
btnColor='light'
24+
hoverScale
25+
layout={btnShape}
26+
size={size}
27+
title='Share on Reddit'
28+
className='focus:border-danger focus-visible:outline-danger bg-[#FF4500]'
29+
>
30+
<FaRedditAlien />
31+
<span className='sr-only'>Share on Reddit</span>
32+
</Button>
33+
)
34+
}
35+
36+
export default RedditButton
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
'use client'
2+
3+
import { FaSlack } from 'react-icons/fa'
4+
import { Button } from '../..'
5+
import { SlackButtonProps } from '../types'
6+
7+
const SlackButton = ({ text, btnShape, size }: SlackButtonProps) => {
8+
const handleShareClick = () => {
9+
const baseUrl = 'https://slack.com/share'
10+
const shareUrl = new URL(baseUrl)
11+
12+
shareUrl.searchParams.set('url', window.location.href)
13+
shareUrl.searchParams.set('text', text)
14+
15+
window.open(shareUrl.toString(), '_blank', 'noopener,noreferrer')
16+
}
17+
18+
return (
19+
<Button
20+
onClick={handleShareClick}
21+
btnBackground='primary'
22+
btnColor='light'
23+
hoverScale
24+
layout={btnShape}
25+
size={size}
26+
title='Share on Slack'
27+
className='focus:border-info focus-visible:outline-info bg-[#4A154B]'
28+
>
29+
<FaSlack />
30+
<span className='sr-only'>Share on Slack</span>
31+
</Button>
32+
)
33+
}
34+
35+
export default SlackButton

0 commit comments

Comments
 (0)