はじめに
社内向けの管理画面や、数百行のテーブルとフィルターが並ぶ業務システム。こういった「データ密度が高い」画面をReactで一から組むと、ボタンひとつ、フォームひとつのスタイリングに地味に時間を取られます。かといって一般的なUIライブラリは、ランディングページ向けの華やかなコンポーネントが中心で、業務システムが欲しい「Select」「Table」「トースト通知」のような地味だけど実用的な部品が手薄なことも少なくありません。
Blueprintは、まさにそうした「データ密度の高いデスクトップアプリケーション向けインターフェース」に的を絞ったReact UIツールキットです。投資会社・政府機関向けの解析ソフトウェアを手がけるPalantir社が、自社の管理画面群で使うために開発し、OSSとして公開しています。
とはいえ、読むより触った方が早いと思います。BlueprintのButtonやFormGroupが実際にどう動くか、先に挙動を見たい方はこちらからどうぞ。
Blueprintとは
Blueprintは、Palantir社が開発・保守しているReactベースのUIツールキットです。公式READMEでは「複雑でデータ密度の高いデスクトップアプリケーション向けインターフェースの構築に最適化されている」と明言されており、モバイルファーストではなくデスクトップの大画面を前提に設計されています。管理画面・ダッシュボード・データ分析ツールのような「情報量の多い画面」を作る用途に向いています。
主な特徴
- パッケージがモノレポで分割されている - コアの
@blueprintjs/coreに加えて、アイコン専用の@blueprintjs/icons、検索可能なリストの@blueprintjs/select、スプレッドシート型の対話的テーブルを提供する@blueprintjs/table、日付操作用の@blueprintjs/datetimeなどが独立しており、必要な分だけ導入できます - ダークテーマが標準搭載 -
Classes.DARKというクラス名をラップ要素に付けるだけで、配下のコンポーネントが一括でダークテーマに切り替わります - Intentによる色分けが徹底されている -
ButtonやInputGroupなど多くのコンポーネントがintentプロパティ(primary/success/warning/danger)を持ち、状態に応じた色分けを一貫した書き方で表現できます - TypeScriptで書かれている - 型定義が同梱されており、Propsの補完がそのまま効きます
- CSS変数ベースのデザイントークン - v6ではテーマ色が
--bp-プレフィックスのCSSカスタムプロパティとして公開されており、CSSレベルでのカスタマイズもしやすくなっています
ライセンスはApache-2.0で、2026年8月時点の最新版は@blueprintjs/coreのv6.18.0です。GitHubリポジトリはアーカイブされておらず、開発は継続中です。
インストール
まずはコアパッケージとアイコンパッケージを導入します。
npm install @blueprintjs/core @blueprintjs/icons
検索可能なリストが必要なら@blueprintjs/select、日付選択なら@blueprintjs/datetime、対話的なテーブルなら@blueprintjs/tableを追加します。
npm install @blueprintjs/select @blueprintjs/datetime @blueprintjs/table
各パッケージはコンポーネントとは別にCSSファイルを持っているため、使うパッケージの分だけCSSもインポートする必要があります。
import "normalize.css";
import "@blueprintjs/icons/lib/css/blueprint-icons.css";
import "@blueprintjs/core/lib/css/blueprint.css";
Blueprintのサンプルを動かす
下のサンプルはBlueprintのButtonとSwitchを使い、intentプロパティによる色分けと、Classes.DARKによるダークテーマ切り替えを組み合わせたものです。「ダークテーマ」のスイッチを押すと、Card全体の背景・文字色・ボタンの見た目が一括で反転します。
要点だけを抜き出すと、こんな形になります。
import { Button, Switch, Classes, Intent } from '@blueprintjs/core'
function App() {
const [dark, setDark] = useState(false)
return (
<div className={dark ? Classes.DARK : ''}>
<Switch checked={dark} label="ダークテーマ" onChange={() => setDark(!dark)} />
<Button intent={Intent.PRIMARY}>Primary</Button>
<Button intent={Intent.DANGER}>Danger</Button>
</div>
)
}
実際に編集できるサンプルが下です。「ダークテーマ」を切り替えると、Blueprintのコンポーネントが持つダークテーマ対応の広さがわかるはずです。
Classes.DARK(実体はbp6-darkというクラス名)を親要素に付けるだけで、CardやSwitch、Buttonまで含めてテーマが一括で切り替わっているのがわかると思います。個別にダーク用のスタイルを書く必要がない点が、Blueprintの大きな利点です。
基本的な使い方
ボタンとIntent
import { Button, Intent } from '@blueprintjs/core';
function ButtonExample() {
return (
<>
<Button intent={Intent.NONE}>Default</Button>
<Button intent={Intent.PRIMARY}>Primary</Button>
<Button intent={Intent.SUCCESS} icon="tick">Success</Button>
<Button intent={Intent.WARNING} icon="warning-sign">Warning</Button>
<Button intent={Intent.DANGER} icon="trash" minimal>Danger</Button>
</>
);
}
intentはButtonに限らず、InputGroupやFormGroupなど多くのコンポーネントで共通して使えるプロパティです。一度覚えると色の指定に迷わなくなります。
カードとIcon
import { Card, Elevation, Icon, H5 } from '@blueprintjs/core';
function CardExample() {
return (
<Card interactive elevation={Elevation.TWO}>
<H5>
<Icon icon="folder-open" /> プロジェクト一覧
</H5>
<p>elevationプロパティで影の強さを段階的に変えられます。</p>
</Card>
);
}
interactiveを付けると、マウスホバー時にカード全体がクリック可能なUIとして反応するようになります。
フォーム部品
import { FormGroup, InputGroup } from '@blueprintjs/core';
function FormExample() {
return (
<FormGroup
label="メールアドレス"
labelInfo="(必須)"
helperText="通知の送信先になります"
>
<InputGroup placeholder="you@example.com" leftIcon="envelope" />
</FormGroup>
);
}
FormGroupがラベル・補足テキスト・エラー表示をまとめて面倒を見てくれるので、フォーム周りの見た目を毎回自作しなくて済みます。
実践的なユースケース
フォームバリデーション
FormGroupのintentとhelperText、InputGroupのintentを入力値と連動させると、リアルタイムバリデーションを素直に実装できます。
const isValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)
<FormGroup
label="メールアドレス"
intent={isValid ? Intent.NONE : Intent.DANGER}
helperText={isValid ? '通知の送信先になります' : '正しいメールアドレスを入力してください'}
>
<InputGroup
leftIcon="envelope"
value={email}
intent={isValid ? Intent.NONE : Intent.DANGER}
onChange={(e) => setEmail(e.target.value)}
/>
</FormGroup>
下のサンプルではメールアドレス欄から@を消してみてください。FormGroupのintentがdangerになって枠が赤くなり、helperTextがエラーメッセージに切り替わり、送信ボタンもdisabledになって押せなくなります。
検索可能なセレクトリスト
一覧から1件選ばせるだけならネイティブの<select>でも十分ですが、選択肢が多い・絞り込みたいという場面では@blueprintjs/selectのSelectが便利です。itemsに配列を渡し、itemPredicateで絞り込みロジックを、itemRendererで1行分の見た目を定義します。
import { Select } from '@blueprintjs/select'
import { MenuItem, Button } from '@blueprintjs/core'
const FRUITS = ['りんご', 'バナナ', 'みかん', 'ぶどう', 'メロン']
function FruitSelect() {
const [selected, setSelected] = useState(FRUITS[0])
return (
<Select
items={FRUITS}
itemPredicate={(query, item) => item.includes(query)}
itemRenderer={(item, { handleClick, modifiers }) => (
<MenuItem key={item} text={item} active={modifiers.active} onClick={handleClick} />
)}
onItemSelect={setSelected}
>
<Button text={selected} rightIcon="caret-down" />
</Select>
)
}
下のサンプルでは、Buttonをクリックしてポップオーバーを開き、テキストボックスに「み」と入力してみてください。itemPredicateによって「みかん」だけに絞り込まれます。選択するとButtonの表示ラベルが選んだ果物名に切り替わります。
トースト通知
保存完了やエラーをユーザーに知らせるときはOverlayToasterを使います。OverlayToaster.createAsync()でトースターのインスタンスを非同期に生成し、以降はtoaster.show()を呼ぶだけで画面上部にメッセージが積み上がっていきます。
import { OverlayToaster, Intent } from '@blueprintjs/core'
const toaster = await OverlayToaster.createAsync({ position: 'top' })
function notify() {
toaster.show({
message: '保存しました',
intent: Intent.SUCCESS,
icon: 'tick',
})
}
下のサンプルでは「保存する」と「エラーを表示」の2つのボタンがあります。押すたびに画面上部にトーストが追加され、数秒後に自動で消えます。連打すると複数のトーストが積み重なる様子も確認できます。
なお、対話的なテーブルが欲しい場合は@blueprintjs/tableが、日付・時刻の入力には@blueprintjs/datetimeが用意されています。どちらもコンセプトは共通で、CSSファイルを追加インポートしてコンポーネントを差し込むだけで使えます。
まとめ
Blueprintは、派手なランディングページ向けというより、社内ツールや管理画面のような「情報量が多く、長く使われる画面」のために設計されたUIツールキットです。Intentによる一貫した色分け、Classes.DARKだけで切り替わるダークテーマ、FormGroupやSelectのような実務で頻出する部品が最初から揃っている点は、業務システムを書く場面で特にありがたく感じるはずです。
パッケージがcore / icons / select / table / datetimeに分かれているので、まずはcoreとiconsから導入し、必要になったタイミングで他のパッケージを足していくのがおすすめです。今回のサンプルをベースに、ぜひ自分の管理画面に組み込んでみてください。