playpark
ホーム会社概要サービスソリューションブログお知らせ気軽に相談する
playpark

あらゆる仕事を楽しむ

会社概要サービスソリューション気軽に相談する特定商取引法に基づく表記

© 2019-2026 合同会社playpark All Rights Reserved.

  1. ホーム
  2. ブログ
  3. 実験レポート
  4. 【React】playpark Lab UI - 泡が出るビーカーを作った話(真面目に)
ブログ一覧に戻る
実験レポート

【React】playpark Lab UI - 泡が出るビーカーを作った話(真面目に)

「コーポレートサイト、堅すぎない?」から始まった実験。科学実験室をモチーフにした10種類のUIコンポーネントと、SSR対応アニメーションの設計パターンを公開します。

2026年4月9日16分で読める
ReactTypeScriptFramer MotionTailwind CSSフロントエンドデザインシステム
【React】playpark Lab UI - 泡が出るビーカーを作った話(真面目に)

「コーポレートサイト、ちゃんとしすぎてない?」

シンプルで洗練されたデザイン。確かに悪くない。でも、playpark = 遊び場という社名なのに、遊び心が足りない。そんなモヤモヤ、ありませんでしたか?

私たちはありました。というか、普通のカードUIに飽きたんです。正直に言うと。

「じゃあ、泡が出るビーカー作ろうか」

...冗談で言ったはずなのに、気づいたら本当に作ってました。本記事では、その暴走の記録を共有します。(いや、真面目にUI設計した話です)

コンセプト:「遊び場」から「実験室」への連想

playpark という社名には「遊び場」という意味が込められています。

でも、ただの遊び場じゃない。「自己責任で好きなように遊んでいい子供の遊び場」というニュアンスなんです。お客様の課題を解決する「実験」を、責任を持ちながら楽しむ場所。

遊び場 → 実験 → 実験室 → ビーカー → 泡

...という連想ゲームの結果、こうなりました。(論理的でしょ?)

従来のコーポレートサイト vs playpark Lab UI

要素従来のコーポレートサイトplaypark Lab UI
ボーダー実線(堅い)破線(実験ノートっぽい)
カラーモノトーン(無難)ビビッドカラー(化学反応っぽい)
アニメーションフェードイン(眠い)泡立ち、浮遊(うるさい?)
ホバー色が変わる(普通)傾いて光る(やりすぎ?)

「やりすぎ?」と社内から言われました。

そのまま通しました。

結果、意外と評判良かったです。(安心した)

作ったもの一覧:10種類のコンポーネント

装飾系(一番楽しかったやつ)

コンポーネント何これ
Beaker泡が出るビーカー。液体が波打つ。なぜ作った。
BubblesBackground背景に泡が浮遊。ビールサイトじゃないよ。
FloatingParticles謎のパーティクルが漂う。雰囲気重視。
CursorParticlesマウスドラッグでパーティクル発生。子供ウケする。

Beaker は完全に趣味です。でも、「なんか面白いサイトだな」と思ってもらえたら勝ちじゃないですか。(自己正当化)

デコレーション系(手書き風)

コンポーネント用途
ArrowDecoration手書き風矢印。「ここ見て!」的な。
CircleHighlight手書き風丸囲み。採点してる感。
StickyNote付箋。傾いてる。テープで貼ってある風。
LiquidSpillDivider液体こぼれセクション区切り。掃除したい。
ScribbleUnderline手書き風下線。赤ペン先生。

実験ノートの落書き感を出したかったんです。「ちゃんとしすぎ」の対極。

フォーム系(ちゃんと使えるやつ)

コンポーネント特徴
LabButton6種類のバリエーション。reactionが派手で好き。
LabCardホバーで傾く+光る。shadcn/uiのCardを魔改造。
LabInput破線ボーダー。フォーカスでグロー。かわいい。
LabTextarea同上。高さが自動で伸びる。

shadcn/ui をベースに魔改造しています。既存のデザインシステムと共存できるように。(ここは真面目)

あわせて読みたい

【Next.js 16】MDXブログを自作した話 - ISRと予約投稿で「ちょうどいい」を目指す
技術Tips16分

【Next.js 16】MDXブログを自作した話 - ISRと予約投稿で「ちょうどいい」を目指す

CMSを使えばいいのに、なぜかMDXでブログを作りたくなる病。ISR、予約投稿、関連記事スコアリングまで実装した記録です。

読む

技術的に頑張ったところ

「遊び心」と言いつつ、中身は真面目です。(ここ大事)

1. SSR対応のアニメーション

Next.js App Router で一番ハマったやつ。Math.random() を SSR で使うと、サーバーとクライアントで値が違ってハイドレーションエラー祭りになります。

この経験、ありませんか?

// ダメなやつ
const bubbles = Array.from({ length: 10 }, () => ({
  x: Math.random() * 100, // ← サーバーとクライアントで値が違う
}));

// 良いやつ:Seeded random
function seededRandom(seed: number): number {
  const x = Math.sin(seed * 9999) * 10000;
  return x - Math.floor(x);
}

解決策: SSR 時は決定的な値を使い、クライアントでのみランダム化。

地味だけど、これがないと本番で「なんか泡の位置が毎回違う」とか言われます。(言われました)

2. 「マウント済み」の安全な検出

useState で isMounted を管理すると警告が出る問題。React 18 以降で厳しくなったやつ。

// 警告出るやつ
const [isMounted, setIsMounted] = useState(false);
useEffect(() => setIsMounted(true), []);

// 警告出ないやつ
function useIsMounted() {
  return useSyncExternalStore(
    () => () => {},
    () => true, // Client
    () => false // Server
  );
}

useSyncExternalStore、こういう時に使うんだなと学びました。(React 18 の恩恵)

ちなみに、このパターンを知らないと「なんか警告出るけど動いてるからいいや」ってなりがち。後で痛い目見ます。(見ました)

3. SVG SMIL + CSS アニメーションの使い分け

Beaker コンポーネントで地味に悩んだやつ。

{
  /* 液体の波打ち → SVG SMIL(SVG内部の属性操作に強い) */
}
<rect fill={liquidColor}>
  <animate attributeName="y" values="..." dur="2s" />
</rect>;

{
  /* 泡の上昇 → CSS(DOMの位置操作に強い) */
}
<div className="animate-beaker-bubble" />;

「全部 Framer Motion でいいじゃん」と思いました?

SVG 内部のアニメーションは SMIL が軽いんです。Framer Motion で SVG の y 属性をアニメーションさせると、DOM 操作が重くなる。適材適所。

4. CSS変数でテーマ対応

カラーパレットは CSS 変数で管理。ダークモード対応もこれで楽になります。(まだやってないけど)

:root {
  --color-primary: oklch(0.65 0.24 260);
  --color-reaction-pink: oklch(0.75 0.18 0);
  --color-reaction-yellow: oklch(0.85 0.16 85);
  /* 化学反応っぽい色を揃えた(自己満足) */
}

OKLCH 色空間を使っているのは、彩度と明度の調整がしやすいから。「ビビッドだけど目に痛くない」バランスを取るのに便利です。

あわせて読みたい

【Next.js App Router】実案件でパフォーマンス85%改善した技術選定
技術Tips26分

【Next.js App Router】実案件でパフォーマンス85%改善した技術選定

複数の業務システム開発を通じて得られた、Next.js App Router選定とパフォーマンス最適化の知見。実際の改善事例とともに解説します。

読む

パフォーマンス、ちゃんと考えた

「遊び心」を言い訳に重いサイトを作るわけにはいきません。

モバイルでは無効化

CursorParticles は PC のみ。スマホでマウスストーキングしても意味ないし、バッテリー食うし。

useEffect(() => {
  const checkMobile = () => {
    setIsMobile(
      window.matchMedia('(pointer: coarse)').matches || window.innerWidth < 768
    );
  };
  // ...
}, []);

if (isMobile) return null; // さようなら

pointer: coarse でタッチデバイスを検出しています。window.innerWidth だけだとタブレットを見逃す。

パーティクル数の上限

無限に増えるとブラウザが死ぬので、上限30個。古いやつから消える。

if (updated.length > maxParticles) {
  return updated.slice(-maxParticles); // 老害は退場
}

30個という数字は「見た目がちょうどいい」と「パフォーマンス」のバランス。60fps を維持できる限界を探りました。(目視で)

イベントのスロットリング

マウス移動イベント、毎フレーム処理したら死ぬ。50ms でスロットリング。

throttleTimer = setTimeout(() => {
  createParticles(e.clientX, e.clientY);
  throttleTimer = null;
}, 50); // 50ms = 20fps、これで十分

アニメーション自体は 60fps で動くけど、パーティクル生成は 20fps で十分。人間の目には滑らかに見えます。(たぶん)

あわせてチェック

この技術の導入、お手伝いします

記事で紹介した技術やツールの導入でお悩みですか?具体的な課題をお聞かせください。

気軽に相談する

使用例:お問い合わせフォーム

実際にサイトで使ってるコード。こんな感じで組み合わせています。

import {
  BubblesBackground,
  LabButton,
  LabCard,
  LabCardContent,
  LabCardHeader,
  LabCardTitle,
  LabInput,
  LabTextarea,
} from '@/components/lab';

export function ContactForm() {
  return (
    <div className="relative">
      <BubblesBackground count={10} />
      <LabCard tilt={2} glowColor="blue">
        <LabCardHeader>
          <LabCardTitle>お問い合わせ</LabCardTitle>
        </LabCardHeader>
        <LabCardContent>
          <form className="space-y-4">
            <LabInput placeholder="お名前" glowColor="blue" />
            <LabInput type="email" placeholder="メール" glowColor="pink" />
            <LabTextarea placeholder="内容" glowColor="green" />
            <LabButton variant="reaction">送信する</LabButton>
          </form>
        </LabCardContent>
      </LabCard>
    </div>
  );
}

背景に泡が浮いてて、フォームが傾いてて、ボタンがグラデーション。

うるさい?

でも、普通のフォームより記憶に残りませんか。「あの泡が出るサイト」って覚えてもらえたら、それはもうブランディングです。(自己弁護)

まとめ:遊び心、意外と難しい

playpark Lab UI は、遊び心と技術的な堅牢性を両立させる実験でした。

  • 科学実験室モチーフ → 破線、泡、手書き風
  • SSR 対応 → Seeded random、useSyncExternalStore
  • パフォーマンス → モバイル無効化、スロットリング

「コーポレートサイトだから堅くする」という固定観念、捨ててみませんか?

「やりすぎ」と言われても、自分が良いと思ったらそのまま通す。それが playpark スタイルです。

...ただし、本当にやりすぎると社内から「目がチカチカする」と言われるので、ほどほどに。

あわせて読みたい

  • ブログ運用を完全自動化 — GitHubリポジトリから記事・サムネイル・SNS投稿まで — ブログ運用の自動化事例

→ 気軽に相談する

About playpark

「あらゆる仕事を楽しむ」をミッションに、業務自動化・AI活用を手がける合同会社です。このブログの運用自体も、自社開発のClaude Code Skillsで完全自動化しています。

会社概要サービス
気軽に相談する
ブログ一覧に戻る

関連記事

すべての記事
【Next.js 16】MDXブログを自作した話 - ISRと予約投稿で「ちょうどいい」を目指す
技術Tips
2026年4月6日16分で読める
【Next.js 16】MDXブログを自作した話 - ISRと予約投稿で「ちょうどいい」を目指す

CMSを使えばいいのに、なぜかMDXでブログを作りたくなる病。ISR、予約投稿、関連記事スコアリングまで実装した記録です。

Next.jsReactTypeScript+2
【Next.js App Router】実案件でパフォーマンス85%改善した技術選定
技術Tips
2026年1月15日26分で読める
【Next.js App Router】実案件でパフォーマンス85%改善した技術選定

複数の業務システム開発を通じて得られた、Next.js App Router選定とパフォーマンス最適化の知見。実際の改善事例とともに解説します。

Next.jsReactTypeScript+2

実験から生まれたソリューション

実験で培った技術力を、あなたのビジネスに。具体的なソリューションをご確認ください。

ソリューション一覧へ