0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【気になるライブラリ研究】Tippy.js【kintone】

Posted at

Tippy.js

Webシステムのツールチップって重要ですよね。
ボタンがあったとき、ツールチップがあると、押すとどんなことが起こるのか、ユーザーに分かりやすく知らせることができます。
また表示されているデータにどんな意味があるのか、Tipsを表示するのにもよいですね。

今回は気になるライブラリ【Tippy.js】を教えてもらったので、試してみようという記事です。

想定する読者

ウェブシステムの開発者を想定しています。
Cybozu社のkintoneのカスタマイズ開発者向けにも、少しだけコードを紹介します。

CDNで簡単に試してみる

Tippy.jsには、CDNが公開されていますので、 HTMLファイル一枚で試すことができます。

<html>

<head>
  <title>TippyCDNExample</title>
  <script src="https://unpkg.com/@popperjs/core@2"></script>
  <script src="https://unpkg.com/tippy.js@6"></script>
</head>

<body>
  <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100vh; margin: auto;"
       id="root">
    <div>
      <p>
        これはCDN経由でTippy.jsを使用する例です。下のscriptタグで必要なライブラリを読み込み、<br/>
        `tippy()`関数を使ってツールチップを作成できます。
      </p>

      <button id="myButton">My button</button>
    </div>

    <hr>

    <div>
      <p>`tippy()`関数を利用する以外にも、data-tippy-content属性を利用することもできます。</p>
      <button data-tippy-content="My button with data attribute">My button with data attribute</button>
    </div>

    <hr>


    <script>
      // With the above scripts loaded, you can call `tippy()` with a CSS
      // selector and a `content` prop:
      tippy('#myButton', {
        content: 'My tooltip!',
      });

      tippy("button");

      const button = document.createElement('button');
      button.textContent = 'New Button';

      const root = document.querySelector('div#root');
      if (root) {
        root.appendChild(button);
      } else {
        console.warn('No root element found to append the button.');
      }
      tippy(button, {
        content: `
        <p>この例では、JavaScriptで新しいボタンを作成し、ツールチップを追加しています。</p>
        <p>ボタンにマウスオーバーすると、このツールチップが表示されます。</p>
        <p>ツールチップの内容はHTMLとして記述できます。</p>
        <p>このように、Tippy.jsを使うことで、動的にツールチップを追加することができます。</p>
        <p>さらに、ツールチップのスタイルや動作をカスタマイズすることも可能です。</p>
        `,
        allowHTML: true,
      });
    </script>
  </div>
</body>

</html>

実際に動かすとこのようになります。
image.png
ボタンに触れるとツールチップが表示されることがわかると思います。

<script src="https://unpkg.com/@popperjs/core@2"></script>
<script src="https://unpkg.com/tippy.js@6"></script>

CDNからの利用ではpopper.jsと一緒に利用されていますね。

data-tippy-contentのようなカスタム属性を利用することもでき、タグに表記することでマークアップとしての可読性を高めることができます。

モジュールバンドラでの利用

モジュールバンドラからTippy.jsを利用するためには、モジュールとCSSを別に読み込みます。

import tippy from 'tippy.js';
import 'tippy.js/dist/tippy.css';

tippy関数(コンストラクタ)の利用はCDNを利用するときとおなじような感じです。
今回はReactと一緒に使ってみます。

import React from 'react';
import ReactDOM from 'react-dom/client';
import Tippy from '@tippyjs/react';
import 'tippy.js/dist/tippy.css';
import 'tippy.js/themes/light.css';
import 'tippy.js/themes/material.css';
import 'tippy.js/themes/translucent.css';

const THEMES = ["default", "light", "translucent", "material"];
function TippyApp() {
    const [themeIdx, setThemeIdx] = React.useState(0);
    const theme = THEMES[themeIdx % THEMES.length];
    return (
        <div style={{
            display: 'flex',
            flexDirection: 'column',
            gap: '10px',
            padding: '20px',
            fontFamily: 'Arial, sans-serif'
        }}>
            <div>
                <p>かんたんに文字列を表示</p>
                <Tippy content="Hello" theme={theme}>
                    <button onClick={() => setThemeIdx(themeIdx + 1)}>Change Theme ({theme})</button>
                </Tippy>
            </div>

            <div>
                <p>JSX記法でHTML構造を作成する場合</p>
                <Tippy content={(
                    <div>
                        <p>Tooltip content</p>
                        <p>More content here</p>
                    </div>
                )} theme={theme}>
                    <button onClick={() => setThemeIdx(themeIdx + 1)}>Change Theme ({theme})</button>
                </Tippy>
            </div>
        </div>
    )
}


const rootElement = document.getElementById('root');
const root = ReactDOM.createRoot(rootElement);

root.render(
    <React.StrictMode>
        <TippyApp />
    </React.StrictMode>
)

Reactに乗せる場合は、@tippyjs/reactも一緒に導入しなければいけませんでした。
tippy関数をuseEffectで利用しようと思ったら、状態が変わるたびにツールチップが作成されてしまいました😅

kintoneカスタマイズでの利用

TypeScriptでいつものようにkintoneのカスタマイズをします。
今回は一覧画面のボタンに分かりやすいTipsを表示しています。

import tippy from "tippy.js";
import { KintoneRestAPIClient } from "@kintone/rest-api-client"
import "tippy.js/dist/tippy.css";
import 'tippy.js/themes/light.css';
import 'tippy.js/themes/material.css';
import 'tippy.js/themes/translucent.css';
import "./sample.css";

declare const kintone: any;
const client = new KintoneRestAPIClient();

kintone.events.on(["app.record.index.show"], async (event) => {

    const $$a = document.querySelector("a.recordlist-show-gaia")!;
    const $$edit = document.querySelector("button.recordlist-edit-gaia")!;
    const $$remove = document.querySelector("button.recordlist-remove-gaia")!;

    tippy($$a, {
        content: `
            <p>ドキュメントレコードの詳細を表示します。</p>
        `,
        allowHTML: true,
    });

    tippy($$edit, {
        content: `
            <p>ドキュメントレコードを編集します。</p>
        `,
        allowHTML: true,
    });
    tippy($$remove, {
        content: `
            <p>ドキュメントレコードを削除します。</p>
        `,
        theme: 'tomato',

        allowHTML: true,
    });
    return event;
});

image.png
こんな感じで、でっかく何が起こるかを表示します。削除ボタンはトマト色にしました。

つづきです。詳細画面でフィールドにタッチすると、フィールドの定義が見えるようにしてみました。


kintone.events.on(["app.record.detail.show"], async (event) => {

    //文字列一行フィールドにツールチップを出す。
    const $$p = document.createElement('p');
    $$p.innerHTML = 'これはテキストフィールドのツールチップ例です。<br/>文字列一行フィールドにだけ、ツールチップを出すことができます。';
    const $$menu = kintone.app.record.getHeaderMenuSpaceElement();
    $$menu.appendChild($$p);

    const form = await client.app.getFormFields({
        app: kintone.app.getId()
    });

    const fields = Object.values(form.properties).filter(field => field.type === 'SINGLE_LINE_TEXT');

    for (const field of fields) {
        const elem = kintone.app.record.getFieldElement(field.code);

        if (null == elem) continue;

        tippy(elem, {
            content: `
                    <p>                
                    フィールドコード: ${field.code}<br/>フィールド名: ${field.label}
                    </p>
                    <pre>${JSON.stringify(field, null, 2)}</pre>
                `,
            allowHTML: true,
        });

    }

    return event;
});

👆のような動きをします。

.tippy-box[data-theme~='tomato'] {
  background-color: tomato;
  color: greenyellow;
}

カラーテーマの作成はとっても簡単で、上記のようなCSSを作成して、呼び出します。

    tippy($$remove, {
        content: `
            <p>ドキュメントレコードを削除します。</p>
        `,
        theme: 'tomato',

        allowHTML: true,
    });

👆呼び出しているところ

まとめ

今回は気になるライブラリとして【Tippy.js】を試してみました。
簡単にツールチップが出ちゃうので、とても楽しかったです!
ハマりポイントかなと思う点は以下です。

  • HTMLで記述する場合は、allowHTML=trueを設定する
  • cssはデフォルトテーマ別に読み込んであげる必要がある(自分で定義するときはまとめてよい)
  • Reactでは@tippy.js/reactを利用する
  • いまのところ、reactのバージョンは19だとエラーになる

今回のソースコードは以下のリポジトリで公開しています。

kintoneのプラグインを作れたら楽しそうです。


この記事は以上です。ありがとうございました。

kintoneのプラグイン開発や研修などを行っています。
お仕事のお話はこちらまで。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?