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

add new services to share tools (v2) #154

Merged
merged 5 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ nuxt.d.ts
.nuxt-storybook
storybook-static
.vscode
coverage/
coverage/
.DS_Store
23 changes: 23 additions & 0 deletions v2/src/assets/icons/BlueskyIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<svg
role="img"
:aria-label="title"
class="o-icon o-bluesky-icon"
viewBox="0 0 24 24"
width="40px"
height="40px"
xmlns="http://www.w3.org/2000/svg"
><path fill="currentColor" d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565C.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479c.815 2.736 3.713 3.66 6.383 3.364q.204-.03.415-.056q-.207.033-.415.056c-3.912.58-7.387 2.005-2.83 7.078c5.013 5.19 6.87-1.113 7.823-4.308c.953 3.195 2.05 9.271 7.733 4.308c4.267-4.308 1.172-6.498-2.74-7.078a9 9 0 0 1-.415-.056q.21.026.415.056c2.67.297 5.568-.628 6.383-3.364c.246-.828.624-5.79.624-6.478c0-.69-.139-1.861-.902-2.206c-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8"/></svg>
</template>

<script>
export default {
name: 'BlueskyIcon',
props: {
title: {
type: String,
default: 'Bluesky'
}
}
}
</script>
23 changes: 23 additions & 0 deletions v2/src/assets/icons/LinkIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<svg
role="img"
:aria-label="title"
class="o-icon o-link-icon"
viewBox="0 0 24 24"
width="40px"
height="40px"
xmlns="http://www.w3.org/2000/svg"
><path fill="currentColor" fill-rule="evenodd" d="M12.415 4.84a4.775 4.775 0 0 1 6.752 6.752l-.013.013l-2.264 2.265a4.776 4.776 0 0 1-7.201-.516a1 1 0 0 1 1.601-1.198a2.774 2.774 0 0 0 4.185.3l2.259-2.259a2.776 2.776 0 0 0-3.925-3.923L12.516 7.56a1 1 0 0 1-1.41-1.418l1.298-1.291zM8.818 9.032a4.775 4.775 0 0 1 5.492 1.614a1 1 0 0 1-1.601 1.198a2.775 2.775 0 0 0-4.185-.3l-2.258 2.259a2.775 2.775 0 0 0 3.923 3.924l1.285-1.285a1 1 0 1 1 1.414 1.414l-1.291 1.291l-.012.013a4.775 4.775 0 0 1-6.752-6.752l.012-.013L7.11 10.13a4.8 4.8 0 0 1 1.708-1.098" clip-rule="evenodd"/></svg>
</template>

<script>
export default {
name: 'LinkIcon',
props: {
title: {
type: String,
default: 'Homepage'
}
}
}
</script>
23 changes: 23 additions & 0 deletions v2/src/assets/icons/MastodonIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<svg
role="img"
:aria-label="title"
class="o-icon o-mastodon-icon"
viewBox="0 0 24 24"
width="40px"
height="40px"
xmlns="http://www.w3.org/2000/svg"
><path fill="currentColor" d="M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127C.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611c.118 1.24.325 2.47.62 3.68c.55 2.237 2.777 4.098 4.96 4.857c2.336.792 4.849.923 7.256.38q.398-.092.786-.213c.585-.184 1.27-.39 1.774-.753a.06.06 0 0 0 .023-.043v-1.809a.05.05 0 0 0-.02-.041a.05.05 0 0 0-.046-.01a20.3 20.3 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.6 5.6 0 0 1-.319-1.433a.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546c.376 0 .75 0 1.125-.01c1.57-.044 3.224-.124 4.768-.422q.059-.011.11-.024c2.435-.464 4.753-1.92 4.989-5.604c.008-.145.03-1.52.03-1.67c.002-.512.167-3.63-.024-5.545m-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976c-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35c-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102q0-1.965 1.011-3.12c.696-.77 1.608-1.164 2.74-1.164c1.311 0 2.302.5 2.962 1.498l.638 1.06l.638-1.06c.66-.999 1.65-1.498 2.96-1.498c1.13 0 2.043.395 2.74 1.164q1.012 1.155 1.012 3.12z"/></svg>
</template>

<script>
export default {
name: 'MastodonIcon',
props: {
title: {
type: String,
default: 'Mastodon'
}
}
}
</script>
23 changes: 23 additions & 0 deletions v2/src/assets/icons/ThreadsIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<svg
role="img"
:aria-label="title"
class="o-icon o-threads-icon"
viewBox="0 0 24 24"
width="40px"
height="40px"
xmlns="http://www.w3.org/2000/svg"
><path fill="currentColor" d="M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098c1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015c-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164c1.43 1.783 3.631 2.698 6.54 2.717c2.623-.02 4.358-.631 5.8-2.045c1.647-1.613 1.618-3.593 1.09-4.798c-.31-.71-.873-1.3-1.634-1.75c-.192 1.352-.622 2.446-1.284 3.272c-.886 1.102-2.14 1.704-3.73 1.79c-1.202.065-2.361-.218-3.259-.801c-1.063-.689-1.685-1.74-1.752-2.964c-.065-1.19.408-2.285 1.33-3.082c.88-.76 2.119-1.207 3.583-1.291a14 14 0 0 1 3.02.142c-.126-.742-.375-1.332-.75-1.757c-.513-.586-1.308-.883-2.359-.89h-.029c-.844 0-1.992.232-2.721 1.32l-1.757-1.18c.98-1.454 2.568-2.256 4.478-2.256h.044c3.194.02 5.097 1.975 5.287 5.388q.163.07.321.142c1.49.7 2.58 1.761 3.154 3.07c.797 1.82.871 4.79-1.548 7.158c-1.85 1.81-4.094 2.628-7.277 2.65Zm1.003-11.69q-.362 0-.739.021c-1.836.103-2.98.946-2.916 2.143c.067 1.256 1.452 1.839 2.784 1.767c1.224-.065 2.818-.543 3.086-3.71a10.5 10.5 0 0 0-2.215-.221"/></svg>
</template>

<script>
export default {
name: 'ThreadsIcon',
props: {
title: {
type: String,
default: 'Threads'
}
}
}
</script>
23 changes: 23 additions & 0 deletions v2/src/assets/icons/TikTokIcon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<template>
<svg
role="img"
:aria-label="title"
class="o-icon o-tiktok-icon"
viewBox="0 0 24 24"
width="40px"
height="40px"
xmlns="http://www.w3.org/2000/svg"
><path fill="currentColor" d="M12.525.02c1.31-.02 2.61-.01 3.91-.02c.08 1.53.63 3.09 1.75 4.17c1.12 1.11 2.7 1.62 4.24 1.79v4.03c-1.44-.05-2.89-.35-4.2-.97c-.57-.26-1.1-.59-1.62-.93c-.01 2.92.01 5.84-.02 8.75c-.08 1.4-.54 2.79-1.35 3.94c-1.31 1.92-3.58 3.17-5.91 3.21c-1.43.08-2.86-.31-4.08-1.03c-2.02-1.19-3.44-3.37-3.65-5.71c-.02-.5-.03-1-.01-1.49c.18-1.9 1.12-3.72 2.58-4.96c1.66-1.44 3.98-2.13 6.15-1.72c.02 1.48-.04 2.96-.04 4.44c-.99-.32-2.15-.23-3.02.37c-.63.41-1.11 1.04-1.36 1.75c-.21.51-.15 1.07-.14 1.61c.24 1.64 1.82 3.02 3.5 2.87c1.12-.01 2.19-.66 2.77-1.61c.19-.33.4-.67.41-1.06c.1-1.79.06-3.57.07-5.36c.01-4.03-.01-8.05.02-12.07"/></svg>
</template>

<script>
export default {
name: 'TikTokIcon',
props: {
title: {
type: String,
default: 'TikTok'
}
}
}
</script>
53 changes: 36 additions & 17 deletions v2/src/components/VShareToolsItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@
import { computed } from 'vue'

import AudioIcon from '../assets/icons/AudioIcon.vue'
// eslint-disable-next-line import/no-duplicates
import EmailIcon from '../assets/icons/EmailIcon.vue'
import FacebookIcon from '../assets/icons/FacebookIcon.vue'
import InstagramIcon from '../assets/icons/InstagramIcon.vue'
import LinkedinIcon from '../assets/icons/LinkedinIcon.vue'
// eslint-disable-next-line import/no-duplicates
import NewsletterIcon from '../assets/icons/EmailIcon.vue'
import PhoneIcon from '../assets/icons/PhoneIcon.vue'
import RedditIcon from '../assets/icons/RedditIcon.vue'
import SiteIcon from '../assets/icons/SiteIcon.vue'
import SpotifyIcon from '../assets/icons/SpotifyIcon.vue'
import TwitterIcon from '../assets/icons/TwitterIcon.vue'
import YoutubeIcon from '../assets/icons/YoutubeIcon.vue'
import BlueskyIcon from '../assets/icons/BlueskyIcon.vue'
import ThreadsIcon from '../assets/icons/ThreadsIcon.vue'
import TikTokIcon from '../assets/icons/TikTokIcon.vue'
import MastodonIcon from '../assets/icons/MastodonIcon.vue'
import LinkIcon from '../assets/icons/LinkIcon.vue'

const props = defineProps({
action: {
Expand Down Expand Up @@ -65,9 +67,14 @@ const icons = {
twitter: TwitterIcon,
youtube: YoutubeIcon,
site: SiteIcon,
bluesky: BlueskyIcon,
tiktok: TikTokIcon,
threads: ThreadsIcon,
mastodon: MastodonIcon,
homepage: LinkIcon,
}

const URL_PLACEHOLDER_PATTERN = new RegExp('%URL%', 'g')
const URL_PLACEHOLDER_PATTERN = /%URL%/g
const SOCIAL_SERVICE_MAP = {
spotify: {
profileBase: 'https://open.spotify.com/playlist/',
Expand Down Expand Up @@ -105,30 +112,41 @@ const SOCIAL_SERVICE_MAP = {
shareBase: 'tel:',
omitUrl: true,
},
bluesky: {
profileBase: 'https://bsky.app/profile/',
shareBase: 'https://bsky.app/intent/compose',
urlKey: 'text',
},
threads: {
profileBase: 'https://threads.net/@',
shareBase: 'https://threads.net/intent/post',
urlKey: 'text',
},
tiktok: {
profileBase: 'https://www.tiktok.com/@',
},
}

const socialLink = computed(() => {
return SOCIAL_SERVICE_MAP[props.service]?.profileBase + props.username || ''
return props.link ??
SOCIAL_SERVICE_MAP[props.service]?.profileBase + props.username ??
''
})
const shareBase = computed(() => {
return SOCIAL_SERVICE_MAP[props.service]?.shareBase || ''
})
const shareUrl = computed(() => {
const utmParams = Object.entries(props.utmParameters).map(([key, value]) => {
return 'utm_' + key + '=' + encodeURIComponent(value)
return `utm_${key}=${encodeURIComponent(value)}`
})
let url = props.url
if (utmParams.length > 0) {
url = url + '?' + utmParams.join('&')
url = `${url}?${utmParams.join('&')}`
}

const shareParams = Object.entries(props.shareParameters).map(
([key, value]) => {
return (
key +
'=' +
encodeURIComponent(value.replace(URL_PLACEHOLDER_PATTERN, url))
)
return `${key}=${encodeURIComponent(value.replace(URL_PLACEHOLDER_PATTERN, url))}`
}
)

Expand All @@ -137,23 +155,24 @@ const shareUrl = computed(() => {
const shouldOmitUrl = SOCIAL_SERVICE_MAP[props.service]?.omitUrl
if (!shouldOmitUrl) {
const urlKey = SOCIAL_SERVICE_MAP[props.service]?.urlKey || 'url'
const urlParam = urlKey + '=' + encodeURIComponent(url)
const urlParam = `${urlKey}=${encodeURIComponent(url)}`
params = [urlParam, ...params]
}

return shareBase.value + '?' + params.join('&')
return `${shareBase.value}?${params.join('&')}`
})
const ariaLabel = computed(() => {
if (props.label) {
return props.label
} else if (props.action === 'follow') {
return 'Follow us on ' + props.service
return `Follow us on ${props.service}`
} else if (props.action === 'share') {
return 'Share on ' + props.service
return `Share on ${props.service}`
}
return ''
})

// create share popup
const share = () => {
if (!props.service) {
return
Expand All @@ -175,7 +194,7 @@ const share = () => {
const left = windowWidth / 2 - 600 / 2 + screenLeft
const top = windowheight / 2 - 600 / 2 + screenTop

return { left: left, top: top }
return { left, top }
}

// get the position of the window
Expand Down
7 changes: 7 additions & 0 deletions v2/stories/VShareTools.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ const Template = (args) => ({
<v-share-tools-item service="reddit" username="WNYC" />
<v-share-tools-item service="spotify" username="WNYC" />
<v-share-tools-item service="youtube" username="UCbysmY4hyViQAAYEzOR-uCQ" />
<v-share-tools-item service="bluesky" username="npr.org" />
<v-share-tools-item service="mastodon" link="https://mstdn.social/@NPR" />
<v-share-tools-item service="threads" username="npr" />
<v-share-tools-item service="tiktok" username="npr" />
<v-share-tools-item service="phone" link="tel:19731231234" />
<v-share-tools-item service="email" link="mailto:sample@gmail.com" />
<v-share-tools-item service="homepage" link="https://www.google.com" />
<v-share-tools-item service="site" link="https://www.google.com" />
<v-share-tools-item service="site" label="google.com" link="https://www.google.com" />
</v-share-tools>
Expand All @@ -48,6 +53,8 @@ const TemplateShare = (args) => ({
<v-share-tools v-bind="args">
<v-share-tools-item service="facebook" username="WNYC" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="twitter" username="WNYC" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="bluesky" username="WNYC" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="threads" username="WNYC" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="instagram" username="WNYC" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="youtube" username="UCbysmY4hyViQAAYEzOR-uCQ" action="share" url="https://www.gothamist.com" />
<v-share-tools-item service="email" :share-parameters="{ body: 'Title of artice' + ' - %URL%' }" action="share" url="https://www.gothamist.com" />
Expand Down