Tips & Tricks

Claude CodeでWeb Share APIを活用する方法【ネイティブ共有機能】

Claude Codeを使ってWeb Share APIによるネイティブ共有機能を実装する方法を解説。フォールバック、共有ターゲット、ファイル共有まで紹介します。

Web Share APIでネイティブの共有体験を提供

Web Share APIを使えば、OSネイティブの共有ダイアログを呼び出せます。モバイルではLINEやX(Twitter)など、インストール済みのアプリに直接共有でき、ユーザー体験が大幅に向上します。

基本的な共有ボタンの実装

> Web Share APIを使った共有ボタンを作成して。
> 非対応ブラウザにはSNSリンクのフォールバックを表示して。
// components/ShareButton.tsx
import { useState } from 'react';

interface ShareButtonProps {
  title: string;
  text: string;
  url: string;
}

export function ShareButton({ title, text, url }: ShareButtonProps) {
  const [showFallback, setShowFallback] = useState(false);
  const canShare = typeof navigator !== 'undefined' && !!navigator.share;

  const handleShare = async () => {
    if (canShare) {
      try {
        await navigator.share({ title, text, url });
      } catch (err) {
        if ((err as Error).name !== 'AbortError') {
          setShowFallback(true);
        }
      }
    } else {
      setShowFallback(true);
    }
  };

  return (
    <div className="relative">
      <button
        onClick={handleShare}
        className="flex items-center gap-2 rounded-lg bg-blue-600 px-4 py-2 text-white hover:bg-blue-700"
      >
        <ShareIcon />
        共有する
      </button>

      {showFallback && (
        <ShareFallback title={title} url={url} onClose={() => setShowFallback(false)} />
      )}
    </div>
  );
}

function ShareIcon() {
  return (
    <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M4 12v8a2 2 0 002 2h12a2 2 0 002-2v-8" />
      <polyline points="16 6 12 2 8 6" />
      <line x1="12" y1="2" x2="12" y2="15" />
    </svg>
  );
}

SNSフォールバックコンポーネント

// components/ShareFallback.tsx
interface ShareFallbackProps {
  title: string;
  url: string;
  onClose: () => void;
}

function ShareFallback({ title, url, onClose }: ShareFallbackProps) {
  const encodedUrl = encodeURIComponent(url);
  const encodedTitle = encodeURIComponent(title);

  const platforms = [
    {
      name: 'X (Twitter)',
      href: `https://twitter.com/intent/tweet?text=${encodedTitle}&url=${encodedUrl}`,
      color: 'bg-black',
    },
    {
      name: 'Facebook',
      href: `https://www.facebook.com/sharer/sharer.php?u=${encodedUrl}`,
      color: 'bg-blue-600',
    },
    {
      name: 'LINE',
      href: `https://social-plugins.line.me/lineit/share?url=${encodedUrl}`,
      color: 'bg-green-500',
    },
    {
      name: 'はてなブックマーク',
      href: `https://b.hatena.ne.jp/entry/${url}`,
      color: 'bg-blue-400',
    },
  ];

  return (
    <div className="absolute right-0 top-full mt-2 w-56 rounded-xl border bg-white p-3 shadow-lg dark:bg-gray-800">
      <div className="mb-2 flex items-center justify-between">
        <span className="text-sm font-medium">共有先を選択</span>
        <button onClick={onClose} className="text-gray-400 hover:text-gray-600">&times;</button>
      </div>
      <div className="space-y-1">
        {platforms.map(p => (
          <a
            key={p.name}
            href={p.href}
            target="_blank"
            rel="noopener noreferrer"
            className={`block rounded-lg ${p.color} px-3 py-2 text-sm text-white transition-opacity hover:opacity-80`}
          >
            {p.name}
          </a>
        ))}
      </div>
      <button
        onClick={() => { navigator.clipboard.writeText(url); onClose(); }}
        className="mt-2 w-full rounded-lg bg-gray-100 px-3 py-2 text-sm hover:bg-gray-200 dark:bg-gray-700"
      >
        URLをコピー
      </button>
    </div>
  );
}

ファイルの共有

// 画像やファイルの共有
async function shareFile(file: File, title: string): Promise<void> {
  if (!navigator.canShare?.({ files: [file] })) {
    console.log('ファイル共有は非対応です');
    return;
  }

  await navigator.share({
    title,
    files: [file],
  });
}

// Canvas画像の共有
async function shareCanvasImage(canvas: HTMLCanvasElement): Promise<void> {
  const blob = await new Promise<Blob | null>(resolve =>
    canvas.toBlob(resolve, 'image/png')
  );
  if (!blob) return;

  const file = new File([blob], 'image.png', { type: 'image/png' });
  await shareFile(file, '生成した画像');
}

Web Share Target API

PWAとして共有ターゲットに登録することで、他のアプリからの共有を受け取ることもできます。

{
  "share_target": {
    "action": "/share-receiver",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url",
      "files": [
        {
          "name": "media",
          "accept": ["image/*", "video/*"]
        }
      ]
    }
  }
}

まとめ

Web Share APIは、モバイルユーザーに特に効果的な共有機能を提供します。Claude Codeを使えば、クリップボードAPIと連携したフォールバック付きの実装を効率的に構築できます。PWAと組み合わせれば、共有ターゲットとしての機能も追加可能です。詳しい仕様はMDN Web Docs - Web Share APIを参照してください。

#Claude Code #Web Share API #SNS共有 #モバイル #PWA