diff --git a/demo/index.html b/demo/index.html index 1c1f03e..55f549f 100644 --- a/demo/index.html +++ b/demo/index.html @@ -10,17 +10,9 @@ defer data-position="left" data-icon="4" - data-button-text="Share this page" src="https://unpkg.com/@royalfig/share-button/dist/share-button.umd.js" > - - - + @@ -40,7 +32,7 @@
- +

A fully customizable button to make sharing your content as easy as possible. @@ -50,11 +42,32 @@

LinkedIn with the click of a button.

- By Ryan Feigenbaum + + + Ryan Feigenbaum -

Updated on

-

+

+ + + + +

+ + + + +

@@ -76,7 +89,7 @@

Installation

There are two ways to add your share button to the page.

1. Use the CDN

Add the following script tag to your head.

-
<script defer src="https://unpkg.com/@royalfig/share-button/dist/share-button.umd.js"></script>
+
<script defer src="https://unpkg.com/@royalfig/share-button/dist/share-button.umd.js"></script>

2. Install with NPM

npm install @royalfig/share-button
@@ -124,44 +137,144 @@

Customization

Description Default value + + color-backdrop + The backdrop color behind the dialog + + hsl(210deg 20% 98% / 50%) + + color-border Border color on share dialog - + #e5e7eb - color-surface - Share dialog background color - + color-button-text + Button text color + #f9fafb + + + color-button + Button background color + #111827 color-element Share dialog text and icon color - + #111827 - color-button - Button background color - + color-surface + Share dialog background color + #f9fafb - color-button-text - Button text color - + button-text + See button text options + "Share" - color-backdrop - The blurred dialog background color + dark-mode + + See dark mode customization for details + + true + + + icon + Custom icon - position - Where ... + position + Position of the button -

Dark Mode Customization

+

Button Text

+

+ To change the button text, add the button-text attribute + to the share-button element. +

+
<share-button button-text="Share this page"></share-button>
+

+ Use an empty string to omit button text altogether. Styles will update + to make the button a circle and an aria-label will be + added to the button indicating its text. +

+

Dark Mode Customization

+ +

+ By default, the share button includes default support for dark mode + based on the user's OS preference. That is, when the OS is set to dark + mode, the share button and dialog will be in dark mode and vice versa. +

+ +

+ However, it's possible to override this behavior by setting the + dark-mode attribute to false. Doing so + disables dark mode and preserves all custom colors. +

+ +

+ Add custom dark mode styles by defining values for custom variables as + a string. +

+ +
<share-button dark-mode="false" style="--color-backdrop: #000; --color-border: #fff; --color-button-text: #fff; --color-button: #000; --color-element: #fff; --color-surface: #000;"></share-button>
+ +

Icon

+

+ There are seven icon possibilities. Set the icon using the `icon` data + attribute followed by a number 1 - 7. See icons below for examples of + options. +

+ +
<share-button icon="1"></share-button>
+ +
+ + + + + + + +
+ +

+ To omit an icon altogether, set the icon attribute to + false +

+ + + +
<share-button icon="false"></share-button>
+ +

FAQs

+

+ + I want to add social meta platform x. (Not that X, + something else...) + +

+

+ The share button is designed to be as lightweight as possible. It + currently supports Twitter, Facebook, LinkedIn, and copying the URL to + the clipboard. If you'd like to add support for another platform, + please open an issue on GitHub. +

+

diff --git a/demo/package-lock.json b/demo/package-lock.json index 4987d15..09bec72 100644 --- a/demo/package-lock.json +++ b/demo/package-lock.json @@ -7,6 +7,9 @@ "": { "name": "demo", "version": "0.0.0", + "dependencies": { + "highlight.js": "^11.9.0" + }, "devDependencies": { "typescript": "^5.2.2", "vite": "^5.0.8" @@ -601,6 +604,14 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", diff --git a/demo/package.json b/demo/package.json index 3fbb04b..8adda29 100644 --- a/demo/package.json +++ b/demo/package.json @@ -11,5 +11,8 @@ "devDependencies": { "typescript": "^5.2.2", "vite": "^5.0.8" + }, + "dependencies": { + "highlight.js": "^11.9.0" } } diff --git a/demo/src/main.ts b/demo/src/main.ts index 23c2f40..42f1f54 100644 --- a/demo/src/main.ts +++ b/demo/src/main.ts @@ -1,4 +1,8 @@ import "./style.css"; +import "highlight.js/styles/tokyo-night-dark.css"; +import hljs from "highlight.js/lib/common"; + +hljs.highlightAll(); async function getLatestRelease() { const res = await fetch( @@ -15,7 +19,7 @@ async function getLatestRelease() { }); const updatedOn = document.getElementById("updated-on"); - const version = document.getElementById("version"); + const version = document.getElementById("version") as HTMLAnchorElement; if (!updatedOn || !version) { return; @@ -23,12 +27,10 @@ async function getLatestRelease() { updatedOn.textContent = date; - const a = document.createElement("a"); - a.href = html_url; - a.setAttribute("target", "_blank"); - a.textContent = tag_name; - - version.append(a); + version.href = html_url; + const svg = version.querySelector("svg"); + version.textContent = tag_name; + svg && version.prepend(svg); } getLatestRelease(); diff --git a/demo/src/style.css b/demo/src/style.css index 99223d8..2bf4a83 100644 --- a/demo/src/style.css +++ b/demo/src/style.css @@ -4,7 +4,25 @@ --font-small: max(15px, 0.85rem); --font-x-small: max(12px, 0.75rem); --br-small: max(3px, 0.25rem); - --color-border: #e0e0e0; + --color-border: hsl(221deg 39% 86%); + --color-border-hover: hsl(244deg 83% 51% / 80%); + --color-surface: #f9fafb; + --color-element: #111827; + --color-inline-code: #111827; + --color-code: var(--color-border); + --color-surface-1: hsl(220deg 13% 91%); +} + +@media (prefers-color-scheme: dark) { + :root { + --color-border: hsl(221deg 39% 26%); + --color-border-hover: hsl(244deg 83% 51% / 80%); + --color-element: #f9fafb; + --color-surface: hsl(221deg 39% 11%); + --color-inline-code: #f9fafb; + --color-code: hsl(221deg 39% 21%); + --color-surface-1: hsl(221deg 39% 16%); + } } *, @@ -21,7 +39,12 @@ html { font-size: 1rem; font-size: clamp(1rem, 0.95rem + 0.25vw, 1.25rem); line-height: 1.5; - background-color: #edede1; + color: var(--color-element); + background-color: var(--color-surface); +} + +a { + color: inherit; } code, @@ -32,16 +55,16 @@ pre { :not(pre, td) > code { padding: 0.15rem 0.25rem; - background-color: #f9fafb; + color: var(--color-inline-code); + background-color: var(--color-code); border-radius: var(--br-small); } .container { display: grid; grid-template-columns: - [gutter-start] var(--gutter) [content-wide-start] 1fr [content-start] var( - --content-width - ) + [gutter-start] var(--gutter) [content-wide-start] 1fr [content-start] + minmax(auto, var(--content-width)) [content-end] 1fr [content-wide-end] var(--gutter) [gutter-end]; margin-block-end: 3rem; } @@ -111,11 +134,10 @@ header > p { .meta { display: flex; - gap: 0.5rem; + gap: 1rem; align-items: center; justify-content: center; font-size: var(--font-x-small); - color: #666; } .meta a { @@ -123,9 +145,21 @@ header > p { text-decoration: none; } -.meta > *:not(:last-child)::after { - margin-inline-start: 0.5rem; - content: "•"; +.meta-button { + display: flex; + gap: 0.25rem; + align-items: center; + justify-content: center; + min-width: 160px; + padding: 0.25rem 0.5rem; + background-color: var(--color-surface-1); + border-radius: 9999px; +} + +.meta-button > svg { + width: 1.15em; + height: 1.15em; + fill: currentcolor; } .container > .feature-image { @@ -135,8 +169,16 @@ header > p { mix-blend-mode: multiply; } +@media (prefers-color-scheme: dark) { + .container > .feature-image { + filter: invert(1); + mix-blend-mode: screen; + } +} + .container > .content { grid-column: content; + overflow-x: auto; } .content > *:not(:last-child) { @@ -152,9 +194,32 @@ h6 { } table { + width: 100%; font-size: var(--font-small); + border-collapse: collapse; + background-color: var(--color-surface-1); + border-radius: var(--br-small); } table td { padding: 0.25rem 0.5rem; } + +table tr { + border-bottom: 1px solid var(--color-border); + transition: border-bottom-color 300ms ease-out; +} + +table tr:first-child { + font-size: var(--font-x-small); + font-weight: 700; + text-transform: uppercase; +} + +table tr:last-of-type { + border-bottom: none; +} + +table tr:not(:first-of-type):hover { + border-bottom-color: var(--color-border-hover); +} diff --git a/index.html b/index.html index 85068d1..74bb911 100644 --- a/index.html +++ b/index.html @@ -6,232 +6,16 @@ Deep Dive into Web Components + - - -
- -
-
-
- -

- A fully customizable button to make sharing your content as easy as - possible. -

-

- Add the ability to easily share your page to X (Twitter), Facebook, - LinkedIn with the click of a button. -

-
- By Ryan Feigenbaum -

Updated on

-

-
-
-
-
- -
-
-
-

- Amet magna pariatur Lorem est veniam ex Lorem. Minim reprehenderit - aliquip et sint in mollit minim nulla ea enim mollit non reprehenderit - excepteur. Aliqua pariatur veniam cupidatat aliquip. Pariatur culpa - voluptate nisi cupidatat consectetur aliquip tempor adipisicing labore - commodo. Nostrud elit ad duis ipsum excepteur aute excepteur. Proident - proident ad mollit commodo occaecat. Labore irure dolore labore quis - occaecat et mollit cupidatat consequat sint. -

-

Installation

-

There are two ways to add your share button to the page.

-

1. Use the CDN

-

Add the following script tag to your head.

-
<script type="module" src="https://unpkg.com/share-button/dist/main.js"></script>
-
-
- + diff --git a/src/dark-mode.ts b/src/dark-mode.ts index 1a1f15f..826b0b1 100644 --- a/src/dark-mode.ts +++ b/src/dark-mode.ts @@ -1,9 +1,7 @@ import darkModeStyles from "./dark-mode-styles.css?inline"; -export function createDarkModeStyles(el: HTMLElement, isInjection = false) { - const darkMode = el.getAttribute( - isInjection ? "data-dark-mode" : "dark-mode", - ); +export function createDarkModeStyles(el: HTMLElement) { + const darkMode = el.getAttribute("dark-mode"); if (darkMode === "false") { return ""; diff --git a/src/dialog.ts b/src/dialog.ts index 84f28f0..0a5c16d 100644 --- a/src/dialog.ts +++ b/src/dialog.ts @@ -9,7 +9,7 @@ export function createDialogEl({ }: Record) { return `
-

${shareText}

+

${shareText ? shareText : "Share"}

diff --git a/src/main.ts b/src/main.ts index d32dd75..4de1922 100644 --- a/src/main.ts +++ b/src/main.ts @@ -47,15 +47,20 @@ class ShareButton extends HTMLElement { const shadow = this.attachShadow({ mode: "open" }); // icon - const iconChoice = this.getAttribute("icon") || "1"; - const icon = icons[iconChoice as keyof typeof icons]; + const icon = this.createIcon(); // user styles const userStyles = createUserStyles(this); // button const button = document.createElement("button"); - const buttonText = this.getAttribute("button-text") || "Share"; + const buttonText = this.getAttribute("button-text") ?? "Share"; + + if (!buttonText) { + button.setAttribute("aria-label", "Share"); + button.setAttribute("style", "border-radius: 50%; padding: 0.5rem;"); + } + button.setAttribute("class", "share-button"); button.innerHTML = buttonText + icon; @@ -118,6 +123,22 @@ class ShareButton extends HTMLElement { styles.replaceSync(style + userStyles + darkModeStyles); shadow.adoptedStyleSheets = [styles]; } + + private createIcon() { + const iconChoice = this.getAttribute("icon") || "1"; + let icon; + if (iconChoice === "false") { + icon = ""; + } else if (!["1", "2", "3", "4", "5", "6", "7"].includes(iconChoice)) { + console.log( + '[Share Link] It looks like you did not specify a valid icon. Please add an icon attribute with a value of "1," "2," "3," "4," "5," "6," or "7"', + ); + icon = icons["1" as keyof typeof icons]; + } else { + icon = icons[iconChoice as keyof typeof icons]; + } + return icon; + } } ShareButton.init(); diff --git a/src/style.css b/src/style.css index 22b9a84..4b71b79 100644 --- a/src/style.css +++ b/src/style.css @@ -1,9 +1,9 @@ .wrapper { --color-border: #e5e7eb; --color-surface: #f9fafb; - --color-element: hsl(221deg 39% 11%); - --color-button: var(--color-element); - --color-button-text: var(--color-surface); + --color-element: #111827; + --color-button: #111827; + --color-button-text: #f9fafb; --color-backdrop: hsl(210deg 20% 98% / 50%); --color-hover: rgb(255 255 255 / 15%); --border-radius-lg: 8px; diff --git a/src/user-styles.ts b/src/user-styles.ts index 328d611..7c83387 100644 --- a/src/user-styles.ts +++ b/src/user-styles.ts @@ -39,18 +39,12 @@ function createCustomStyle(el: HTMLElement, variables: string[]) { } export const userCustomProps = [ - "color-button", - "color-button-dark", - "color-button-text", - "color-button-text-dark", "color-backdrop", - "color-backdrop-dark", "color-border", - "color-border-dark", - "color-surface", - "color-surface-dark", + "color-button-text", + "color-button", "color-element", - "color-element-dark", + "color-surface", "button-text", "dark-mode", "icon",