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

donate button v3 that only supports crypto #141

Merged
merged 23 commits into from
Apr 20, 2021
Merged

Conversation

osdiab
Copy link
Contributor

@osdiab osdiab commented Apr 17, 2021

Also implements compiled CSS in JS for styles to replace CSS modules + the style injector (#77) , and starts on #73 with a fresh options format that matches our terminology and is simpler. Also removes the docs/dist/dist folder, which i'm pretty certain is unused.

@vercel
Copy link

vercel bot commented Apr 17, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/everydotorg/donate-button/CkLeQ8ZgaacjoccHwX8NGY1cw5ap
✅ Preview: https://donate-button-git-osdiab-donate-button-3-everydotorg.vercel.app

]
}
],
"@babel/preset-typescript"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly teh same as donate-button, but adds this line.

"xo": "^0.37.1"
},
"dependencies": {
"@compiled/react": "^0.6.10",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the new thing

Comment on lines 26 to 34
const {options: babelOptions, ...babelLoaderRule} = config.module.rules[0]; // Get the babel rule and options
config.module.rules[0] = {
...babelLoaderRule,
loader: undefined, // Disable the predefined babel-loader on the rule
use: [
{loader: 'babel-loader', options: babelOptions},
{loader: '@compiled/webpack-loader', options: {babelOptions}}
]
};
Copy link
Contributor Author

@osdiab osdiab Apr 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block adds webpack support for compiled CSS in JS; the rest is same as donate-button

import constructEveryUrl from 'src/helpers/construct-every-url';
import {EmbedButtonOptions} from 'src/helpers/options-types';

const buttonCss = css`
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CSS in JS!

Comment on lines 12 to 16
declare module 'preact' {
interface Attributes {
css?: CSSProps;
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how we get the CSS prop to work.

Comment on lines +3 to +20
export interface DonateButtonOptions {
/**
* Identifier for nonprofit on Every.org; you can get it by going to the
* nonprofit's profile on Every.org and looking at its URL
*
* @example
* If the URL is https://www.every.org/givedirectly, the slug is givedirectly
*/
readonly nonprofitSlug: string;
/**
* Whether or not to render Crypto donation flow instead of the normal
* donation flow
*
* @default false
* For now, only crypto is supported
*/
readonly crypto: boolean; // For now only this is supported
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nowhere near supporting the kinds of stuff we have in donate-button, but I wanted to keep it as minimal as possible since that one is huge. We can expand over time.

Also I cut out all the modal stuff, since for now the pressing concern is to get crypto donation embeds working, and this is the quickest way there.

readonly crypto: boolean; // For now only this is supported
}

export interface EmbedButtonOptions extends DonateButtonOptions {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed it from GenericButton since it's not a very descriptive name.

@@ -0,0 +1,40 @@
import {render} from 'preact';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just moved the logic for making the donate button into this file since it's so short.

everyDotOrgDonateButton?: GlobalExport;
};

window.everyDotOrgDonateButton = {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is renamed since we don't call it everyMonth anymore.

Comment on lines +19 to +25
window.addEventListener("load", function() {
everyDotOrgDonateButton.createButton({
selector: "#button-root",
nonprofitSlug: "everydotorg",
crypto: true
});
})
Copy link
Contributor Author

@osdiab osdiab Apr 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very basic example of what an embed would look like; the ultimate embed script would be slightly more than this:

    <div id="edo-donate-btn" />
    <script src="https://assets.every.org/dist/donate-button/0.3/index.js" class="edo-donate-btn-js"></script>
    <script>
      (() => {
        const edoScript = document.querySelector(".edo-donate-btn-js")
        if (!edoScript) return;
        edoScript.onload = () => {
          everyDotOrgDonateButton.createButton({
            selector: "#edo-donate-btn",
            nonprofitSlug: "everydotorg",
            crypto: true
          });
        })
      )();
    </script>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I think this is fine for getting something up and running quickly, but I also think we can learn from TikTok here is what they do

  <blockquote
    class="tiktok-embed"
    cite="https://www.tiktok.com/@kyliejenner/video/6951976455400099077"
    data-video-id="6951976455400099077"
    style="max-width: 605px; min-width: 325px"
  >
    <section>
      <a
        target="_blank"
        title="@kyliejenner"
        href="https://www.tiktok.com/@kyliejenner"
        >@kyliejenner</a
      >
      <p>time goes too fast 😥😥🤍</p>
      <a
        target="_blank"
        title="♬ original sound - sam aldridge"
        href="https://www.tiktok.com/music/original-sound-6750691377606216453"
        >♬ original sound - sam aldridge</a
      >
    </section>
  </blockquote>
  <script async src="https://www.tiktok.com/embed.js"></script>

Several nice things about this:

  • Script is async
  • Without Javascript, instantly has multiple links for PageRank - the video, the person, the music. In our case, would be great to instantly have href to the nonprofit's main page (not their donate crypto page) for pagerank purposes.
  • Devs instantly know how to adjust the width without reading any documentation
  • Metadata included entirely via html, makes it look a bit cleaner and more obvious what to if you have multiple embeds
  • If client does not have Javascript, at least they can still get to the persons profile. In our case, would be nice if they can still get to the /donate/crypto page (though admittedly that page would then fail, but perhaps someone would be willing to explicitly enable javascript for www.every.org and not less well-known domains)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah the way I wrote the code the script can be async, I just forgot. Re the richer content I'll change it to by default not take a selector for where to make the element but attach a handler directly to a donate crypto link. Don't think we can add a whole lot more metadata though since this is supposed to be a single button, not a whole tweet or Tiktok post or something.

Copy link
Contributor Author

@osdiab osdiab Apr 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made it so that the embed can be done like this:

    <div class="edo-donate-btn">
      <a href="https://www.every.org/givedirectly/donate/crypto">Donate Crypto</a>	
    </div>
    <script async src="https://assets.every.org/dist/donate-button/0.3/index.js" class="edo-donate-btn-js"></script>
    <script>
      document.querySelector(".edo-donate-btn-js").onload = function() {
        everyDotOrgDonateButton.initButtons();
      };
    </script>

It can be copied into the page multiple times without causing issues. We can also make the text in the link to be replaced with the button be anything - so if we want it to be Donate Crypto for GiveDirectly or something that works too (it will be replaced with the generic "Donate Crypto" as soon as the script runs; this behavior can be changed if we want)

This new initButtons() function just looks for all elements with the class edo-donate-btn, and then looks for an a element inside it; parses the href value to extract the options to throw into the createButton() function from before, replacing the original contents of the div with the newly created button. In the future it can be made to not just read the href field but also anything else like data- attributes if we want to add more configuration in the future.

The explicit version above still works, though, for programmers who want more control.

Copy link
Contributor Author

@osdiab osdiab Apr 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can trim down the copy paste code to remove needing to explicitly call initButtons() as well by automatically calling initButtons() in the downloaded script - im not in love with the automatic side effects, but it is simplest. that said if people just copy-paste this it's not that bad as is, and gives people an idea how this library can be used more flexibly, not just a magic script.

Copy link
Contributor Author

@osdiab osdiab Apr 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

styling will not be as direct as just styling the underlying elemetns though, since they're in a Shadow DOM to provide encapsulation from the parent page's JS/CSS context - but it's not any worse than tik tok or twitter, who load their stuff in iframes, which prevent meddling even more. But we can allow for width styling by setting the width of the parent div, and the createButton() function already allows for a great deal of customization, including changing the text and colors and border radius.

Copy link
Member

@markulrich markulrich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the bundle size for someone who wants to embed donate button on their site?

</svg>
)}
<span css={verticalCenterTextCss}>
{label ? label : `Donate${donateOptions.crypto ? ' Crypto' : ''}`}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What text will this use? Ideally we want our Basis Grotesque - I'm guessing much faster for users to give them a single "[swirl] Donate Crypto" image than to download the entire Basis Grotesque font

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses Basis Grotesque, and I just edited it so that the fallback fonts are used first before Basis is loaded, so users will see text immediately.

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

I'll check but it should be less than like 5-6 kb gzipped, preact is tiny and compiled CSS in JS compiles any runtime component out of the resulting bundle.

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

I replaced Compiled CSS in JS with cxs because I figured that extracing separate CSS files at all adds complexity to the build system, proper usage of the library, and doesn't really provide much value so long as the button doesn't get crazy complicated style-wise (it shouldn't). cxs is a dead simple and extremely tiny CSS in JS library (< .7KB), no compile phase and runs hella fast.

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

After replacing with cxs as expected gzipped full bundle size is 6kb - tiny. But it's also really basic for now so i expect this to grow as this beta version supports the full donate modal experience (though can code-split it to make things remain tiny)

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

getting late for me so i'll wrap testing this up and making the embed code for the main every.org site tomorrow

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

me refreshing with no cache, showing the font transition on webfont load

Screen.Recording.2021-04-19.at.23.10.24.mov

@osdiab
Copy link
Contributor Author

osdiab commented Apr 19, 2021

cc @martinbianchi that i've been doing this - we wanted to get a simple donate crypto button out, trying to leverage the existing infra we have for donate button and didn't want the crypto stuff to be separate from the rest of donate button codebase. I also wanted to tackle a number of tech debt issues while doing it - so switched out the CSS stuff to cxs, starting fresh with the options format to simplify it, and for now removed everything that isn't necessary for the donate crypto button.

if this turns out to be not a great approach - we can always hop over 0.3 and go straight to 0.4 :)

this can serve as a base for the new designs for the donate button once we're ready to implement them.

@osdiab osdiab changed the title WIP: donate button v3 that only supports crypto donate button v3 that only supports crypto Apr 20, 2021
@osdiab osdiab merged commit 239c05f into main Apr 20, 2021
@osdiab osdiab deleted the osdiab/donate-button-3 branch April 20, 2021 13:47
@martinbianchi
Copy link
Contributor

I've just seen this! Amazing work @osdiab. I'll start with the new widget from here. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants