Add blinks to your web app

This section covers adding Blinks directly to your React dapp using our Blinks React SDK. The SDK is open-source and can be found in our Github.

Installation

# npm
npm i @dialectlabs/blinks

#yarn
yard add @dialectlabs/blinks

The following hooks are exported from @dialectlabs/blinks/react in order to simplify the integration.

  • useAction - overall hook: fetches the action, sets up an adapter, inits registry and refreshes it every 10 minutes

  • useActionsRegistry - fetches the registry and refreshes it

  • useActionSolanaWalletAdapter - sets up an adapter for Action using wallet provider

If you want to build your own hooks, use Action , ActionsRegistry and ActionConfig/ActionAdapter classes and interfaces.

If you are using the useActionSolanaWalletAdapter hook, then be sure to have<WalletProvider />and<WalletModalProvider /> above in the component tree.

Basic Usage:

import '@dialectlabs/blinks/index.css';
import { useState, useEffect } from 'react';
import { Action, Blink, ActionsRegistry, useAction } from "@dialectlabs/blinks";
import { useActionSolanaWalletAdapter } from "@dialectlabs/blinks/hooks/solana"

// needs to be wrapped with <WalletProvider /> and <WalletModalProvider />
const App = () => {
  const [action, setAction] = useState<Action | null>(null);
  const actionApiUrl = '...';
  // useAction initiates registry, adapter and fetches the action.
  const { adapter } = useActionSolanaWalletAdapter('<YOUR_RPC_URL_OR_CONNECTION>');
  const { action } = useAction({url: actionApiUrl, adapter});    

  return action ? <Blink action={action} websiteText={new URL(actionApiUrl).hostname} /> : null;
}

Advanced:

import '@dialectlabs/blinks/index.css';
import { useState, useEffect } from 'react';
import { Action, Blink, type ActionAdapter, useActionsRegistryInterval } from "@dialectlabs/blinks";
import { useActionSolanaWalletAdapter } from "@dialectlabs/blinks/hooks/solana";

// needs to be wrapped with <WalletProvider /> and <WalletModalProvider />
const App = () => {
  // SHOULD be the only instance running (since it's launching an interval)
  const { isRegistryLoaded } = useActionsRegistryInterval();
  const { adapter } = useActionSolanaWalletAdapter('<YOUR_RPC_URL_OR_CONNECTION>');
    
  return isRegistryLoaded ? <ManyActions adapter={adapter} /> : null;
}

const ManyActions = ({ adapter }: { adapter: ActionAdapter }) => {
  const apiUrls = useMemo(() => (['...', '...', '...']), []);
  const [actions, setActions] = useState<Action[]>([]);
    
  useEffect(() => {
    const fetchActions = async () => {
      const promises = apiUrls.map(url => Action.fetch(url).catch(() => null));
      const actions = await Promise.all(promises);
            
      setActions(actions.filter(Boolean) as Action[]);
    }
        
    fetchActions();
  }, [apiUrls]);
    
    // we need to update the adapter every time, since it's dependent on wallet and walletModal states
  useEffect(() => {
    actions.forEach((action) => action.setAdapter(adapter));
  }, [actions, adapter]);
    
  return actions.map(action => (
    <div key={action.url} className="flex gap-2">
      <Blink action={action} websiteText={new URL(action.url).hostname} />
    </div>
  ));
}

The URLs in ActionApiUrl and apiUrls must be direct action URLs and not interstitials or website urls with actions.json

Dialect's Blinks SDK supports customizable styles so you can render Blinks that match the style of your dApp or 3rd party site, such as Twitter.

To render a Blink with a preset pass stylePreset prop (defaults to default which is the dial.to theme) to <Blink /> component:

import { Blink } from '@dialectlabs/blinks';
...
return <Blink stylePreset="x-dark" ... />;

Style presets are mapped to classes the following way:

  • x-dark -> .x-dark

  • x-light -> .x-light

  • default -> .dial-light

  • custom -> .custom

To override a certain preset use the following CSS Variables:

/* 
    Use .x-dark, .x-light, .dial-light, or .custom classes 
    .custom - does not contain any colors, radii or shadow
*/
.blink.x-dark {
  --blink-bg-primary: #202327;
  --blink-button: #1d9bf0;
  --blink-button-disabled: #2f3336;
  --blink-button-hover: #3087da;
  --blink-button-success: #00ae661a;
  --blink-icon-error: #ff6565;
  --blink-icon-error-hover: #ff7a7a;
  --blink-icon-primary: #6e767d;
  --blink-icon-primary-hover: #949ca4;
  --blink-icon-warning: #ffb545;
  --blink-icon-warning-hover: #ffc875;
  --blink-input-bg: #202327;
  --blink-input-stroke: #3d4144;
  --blink-input-stroke-disabled: #2f3336;
  --blink-input-stroke-error: #ff6565;
  --blink-input-stroke-hover: #6e767d;
  --blink-input-stroke-selected: #1d9bf0;
  --blink-stroke-error: #ff6565;
  --blink-stroke-primary: #1d9bf0;
  --blink-stroke-secondary: #3d4144;
  --blink-stroke-warning: #ffb545;
  --blink-text-brand: #35aeff;
  --blink-text-button: #ffffff;
  --blink-text-button-disabled: #768088;
  --blink-text-button-success: #12dc88;
  --blink-text-error: #ff6565;
  --blink-text-error-hover: #ff7a7a;
  --blink-text-input: #ffffff;
  --blink-text-input-disabled: #566470;
  --blink-text-input-placeholder: #6e767d;
  --blink-text-link: #6e767d;
  --blink-text-link-hover: #949ca4;
  --blink-text-primary: #ffffff;
  --blink-text-secondary: #949ca4;
  --blink-text-success: #12dc88;
  --blink-text-warning: #ffb545;
  --blink-text-warning-hover: #ffc875;
  --blink-transparent-error: #aa00001a;
  --blink-transparent-grey: #6e767d1a;
  --blink-transparent-warning: #a966001a;
    
  --blink-border-radius-rounded-lg: 0.25rem;
  --blink-border-radius-rounded-xl: 0.5rem;
  --blink-border-radius-rounded-2xl: 1.125rem;
  --blink-border-radius-rounded-button: 624.9375rem;
  --blink-border-radius-rounded-input: 624.9375rem;
    
  /* box-shadow */
  --blink-shadow-container: 0px 2px 8px 0px rgba(59, 176, 255, 0.22), 0px 1px 48px 0px rgba(29, 155, 240, 0.24);
}

Be sure to override with CSS Specificity in mind or by import order

Using these CSS classes, you can customize the styles to fit the UI of your application.

Last updated