shadcn/ui でダッシュボードをデザインするベストプラクティス
モダンな Web アプリケーション開発において、効率的で美しいダッシュボードの構築は重要な課題です。shadcn/ui を活用することで、この課題を優雅に解決できるでしょう。
本記事では、shadcn/ui を使用したダッシュボード開発のベストプラクティスをご紹介します。初心者の方でも段階的に理解できるよう、基礎から実践的な実装まで詳しく解説いたします。
背景
shadcn/ui の特徴と利点
shadcn/ui は、Radix UI と Tailwind CSS を基盤とした革新的な UI コンポーネントライブラリです。従来のライブラリとは異なり、コンポーネントをコピー&ペーストで利用できる独特なアプローチを採用しています。
以下の図は shadcn/ui の基本構造を示しています。
mermaidflowchart TB
shadcn[shadcn/ui] --> radix[Radix UI<br/>アクセシビリティ基盤]
shadcn --> tailwind[Tailwind CSS<br/>スタイリング]
shadcn --> typescript[TypeScript<br/>型安全性]
radix --> components[コンポーネント群]
tailwind --> components
typescript --> components
components --> dashboard[ダッシュボード<br/>アプリケーション]
shadcn/ui の主な利点は以下の通りです。
| 項目 | 特徴 | メリット |
|---|---|---|
| 1 | アクセシビリティ対応 | Radix UI ベースで WAI-ARIA 準拠 |
| 2 | カスタマイズ性 | ソースコードを直接編集可能 |
| 3 | 型安全性 | TypeScript で完全に記述 |
| 4 | 軽量性 | 必要なコンポーネントのみ導入 |
| 5 | デザインシステム | 一貫したデザイントークン |
ダッシュボード開発における課題
現代のダッシュボード開発では、複数の技術的課題に直面します。特に以下の点が重要な検討事項となるでしょう。
データ表示の複雑性 大量のデータを直感的に表示する必要があります。テーブル、チャート、カードなど様々な形式でのデータ可視化が求められます。
レスポンシブデザインの実装 デスクトップからモバイルまで、あらゆるデバイスで最適な表示を実現する必要があります。
ユーザビリティの確保 複雑な機能を持つダッシュボードでも、直感的な操作性を維持しなければなりません。
以下の図は、一般的なダッシュボードの構成要素を示します。
mermaidflowchart LR
header[ヘッダー<br/>ナビゲーション] --> sidebar[サイドバー<br/>メニュー]
header --> main[メインコンテンツ<br/>ダッシュボード本体]
main --> cards[カード群<br/>KPI表示]
main --> charts[チャート群<br/>データ可視化]
main --> tables[テーブル群<br/>詳細データ]
sidebar --> navigation[ページ遷移]
sidebar --> filters[フィルタ機能]
なぜ shadcn/ui が選ばれるのか
shadcn/ui がダッシュボード開発で選ばれる理由は明確です。
開発効率の向上 すぐに使える高品質なコンポーネントが豊富に用意されています。ボタン、フォーム、モーダルなど、ダッシュボードに必要な要素がすべて揃っています。
一貫性のあるデザイン 統一されたデザインシステムにより、アプリケーション全体で一貫した見た目を実現できます。
メンテナンス性の高さ コンポーネントのソースコードを直接管理できるため、プロジェクト固有の要件に柔軟に対応できます。
課題
従来の UI 開発での問題点
従来の UI ライブラリを使用したダッシュボード開発では、いくつかの課題がありました。
カスタマイズの困難さ 多くの UI ライブラリは、デザインのカスタマイズが制限されていました。特に企業のブランドカラーや独自のデザイン要件に対応するのが困難でした。
typescript// 従来のライブラリでのカスタマイズ例
// CSS オーバーライドが必要で複雑
const customButton = {
backgroundColor: '!important #007bff',
border: '!important 1px solid #0056b3',
'&:hover': {
backgroundColor: '!important #0056b3',
},
};
バンドルサイズの問題 使用しないコンポーネントも含めてライブラリ全体をインポートする必要があり、アプリケーションのサイズが肥大化していました。
アクセシビリティの不備 多くのライブラリでアクセシビリティ対応が不十分で、後から対応するのが困難でした。
ダッシュボード特有の設計課題
ダッシュボードアプリケーションには、一般的な Web サイトとは異なる固有の課題があります。
複雑なレイアウト管理 サイドバー、ヘッダー、メインコンテンツエリアなど、複数の領域を効率的に管理する必要があります。
以下の図は、複雑なダッシュボードレイアウトの課題を示しています。
mermaidstateDiagram-v2
[*] --> モバイル表示
[*] --> タブレット表示
[*] --> デスクトップ表示
モバイル表示 --> ハンバーガーメニュー
タブレット表示 --> 縮小サイドバー
デスクトップ表示 --> フルサイドバー
ハンバーガーメニュー --> コンテンツ全幅
縮小サイドバー --> コンテンツ調整
フルサイドバー --> コンテンツ最適化
データローディング状態の管理 大量のデータを扱うダッシュボードでは、ローディング状態やエラー状態の適切な表示が重要です。
リアルタイム更新への対応 データが頻繁に更新されるダッシュボードでは、UI の再描画パフォーマンスが重要な要素となります。
レスポンシブ対応の難しさ
ダッシュボードのレスポンシブ対応は、特に複雑な課題です。
画面サイズによる情報優先度の変化 デスクトップでは多くの情報を同時表示できますが、モバイルでは重要な情報に絞って表示する必要があります。
インタラクション方法の違い マウス操作とタッチ操作では、最適な UI パターンが異なります。
チャートやグラフの表示調整 データ可視化要素は、画面サイズに応じて表示方法を大幅に変更する必要があります。
解決策
shadcn/ui を活用したコンポーネント設計
shadcn/ui を使用することで、これらの課題を効率的に解決できます。
コンポーネントベースアーキテクチャ まずは、shadcn/ui の基本的なコンポーネントをプロジェクトに導入します。
bash# shadcn/ui の初期化
npx shadcn-ui@latest init
プロジェクト設定後、必要なコンポーネントを個別にインストールします。
bash# ダッシュボードに必要な基本コンポーネント
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add table
npx shadcn-ui@latest add sidebar
以下は基本的なコンポーネント構成の例です。
typescript// components/ui 配下にコンポーネントが配置される
import { Button } from '@/components/ui/button';
import {
Card,
CardHeader,
CardTitle,
CardContent,
} from '@/components/ui/card';
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
再利用可能なカスタムコンポーネント shadcn/ui のベースコンポーネントを拡張して、プロジェクト固有のコンポーネントを作成します。
typescript// components/dashboard/MetricCard.tsx
import {
Card,
CardHeader,
CardTitle,
CardContent,
} from '@/components/ui/card';
import { LucideIcon } from 'lucide-react';
interface MetricCardProps {
title: string;
value: string | number;
icon: LucideIcon;
trend?: 'up' | 'down' | 'neutral';
trendValue?: string;
}
export function MetricCard({
title,
value,
icon: Icon,
trend,
trendValue,
}: MetricCardProps) {
return (
<Card>
<CardHeader className='flex flex-row items-center justify-between space-y-0 pb-2'>
<CardTitle className='text-sm font-medium'>
{title}
</CardTitle>
<Icon className='h-4 w-4 text-muted-foreground' />
</CardHeader>
<CardContent>
<div className='text-2xl font-bold'>{value}</div>
{trend && trendValue && (
<p
className={`text-xs ${
trend === 'up'
? 'text-green-600'
: trend === 'down'
? 'text-red-600'
: 'text-muted-foreground'
}`}
>
{trendValue}
</p>
)}
</CardContent>
</Card>
);
}
レイアウトの最適化手法
効率的なダッシュボードレイアウトを実現するため、shadcn/ui の柔軟性を活用します。
グリッドベースレイアウト CSS Grid と Tailwind CSS を組み合わせて、レスポンシブなグリッドレイアウトを構築します。
typescript// components/dashboard/DashboardGrid.tsx
interface DashboardGridProps {
children: React.ReactNode;
}
export function DashboardGrid({
children,
}: DashboardGridProps) {
return (
<div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4 p-4'>
{children}
</div>
);
}
以下の図は、レスポンシブグリッドレイアウトの動作を示します。
mermaidflowchart TD
mobile[モバイル<br/>1列グリッド] --> tablet[タブレット<br/>2列グリッド]
tablet --> desktop[デスクトップ<br/>3列グリッド]
desktop --> wide[ワイドスクリーン<br/>4列グリッド]
mobile --> |768px以上| tablet
tablet --> |1024px以上| desktop
desktop --> |1280px以上| wide
フレキシブルサイドバー shadcn/ui のサイドバーコンポーネントを活用して、適応的なナビゲーションを実装します。
typescript// components/dashboard/Sidebar.tsx
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Sheet,
SheetContent,
SheetTrigger,
} from '@/components/ui/sheet';
import { Menu } from 'lucide-react';
export function Sidebar() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
{/* モバイル用ハンバーガーメニュー */}
<Sheet open={isOpen} onOpenChange={setIsOpen}>
<SheetTrigger asChild className='md:hidden'>
<Button variant='outline' size='icon'>
<Menu className='h-4 w-4' />
</Button>
</SheetTrigger>
<SheetContent side='left' className='w-64'>
<nav className='space-y-2'>
{/* ナビゲーションアイテム */}
</nav>
</SheetContent>
</Sheet>
{/* デスクトップ用固定サイドバー */}
<aside className='hidden md:flex w-64 flex-col border-r bg-background'>
<nav className='flex-1 space-y-2 p-4'>
{/* ナビゲーションアイテム */}
</nav>
</aside>
</>
);
}
状態管理との連携
shadcn/ui コンポーネントは、現代的な状態管理ライブラリとシームレスに連携します。
Zustand との組み合わせ 軽量な状態管理ライブラリ Zustand を使用した例です。
typescript// stores/dashboardStore.ts
import { create } from 'zustand';
interface DashboardState {
metrics: {
totalUsers: number;
totalRevenue: number;
conversionRate: number;
};
isLoading: boolean;
fetchMetrics: () => Promise<void>;
}
export const useDashboardStore = create<DashboardState>(
(set) => ({
metrics: {
totalUsers: 0,
totalRevenue: 0,
conversionRate: 0,
},
isLoading: false,
fetchMetrics: async () => {
set({ isLoading: true });
try {
// API コール
const response = await fetch('/api/metrics');
const data = await response.json();
set({ metrics: data, isLoading: false });
} catch (error) {
set({ isLoading: false });
}
},
})
);
React Query との統合 データフェッチングには React Query を活用します。
typescript// hooks/useMetrics.ts
import { useQuery } from '@tanstack/react-query';
export function useMetrics() {
return useQuery({
queryKey: ['metrics'],
queryFn: async () => {
const response = await fetch('/api/metrics');
if (!response.ok) {
throw new Error('メトリクスの取得に失敗しました');
}
return response.json();
},
refetchInterval: 30000, // 30秒ごとに自動更新
});
}
アクセシビリティ対応
shadcn/ui は Radix UI ベースのため、優れたアクセシビリティサポートを提供します。
キーボードナビゲーション すべてのインタラクティブ要素がキーボードで操作可能です。
typescript// components/dashboard/AccessibleButton.tsx
import { Button } from '@/components/ui/button';
export function AccessibleButton({
children,
onClick,
...props
}) {
return (
<Button
onClick={onClick}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
onClick();
}
}}
{...props}
>
{children}
</Button>
);
}
ARIA ラベルの適切な使用 スクリーンリーダー対応のため、適切な ARIA ラベルを設定します。
typescript// components/dashboard/MetricWithAria.tsx
export function MetricWithAria({
title,
value,
description,
}) {
return (
<div
role='region'
aria-labelledby='metric-title'
aria-describedby='metric-description'
>
<h3 id='metric-title'>{title}</h3>
<div aria-live='polite'>{value}</div>
<p id='metric-description' className='sr-only'>
{description}
</p>
</div>
);
}
具体例
基本的なダッシュボードレイアウト
実際のダッシュボード実装例をご紹介します。まずは基本的なレイアウト構造から始めましょう。
typescript// app/dashboard/page.tsx
import { Sidebar } from '@/components/dashboard/Sidebar';
import { Header } from '@/components/dashboard/Header';
import { MetricCard } from '@/components/dashboard/MetricCard';
import { DashboardGrid } from '@/components/dashboard/DashboardGrid';
export default function DashboardPage() {
return (
<div className='flex min-h-screen bg-background'>
<Sidebar />
<div className='flex-1 flex flex-col'>
<Header />
<main className='flex-1 p-6'>
<div className='space-y-6'>
<div>
<h1 className='text-3xl font-bold tracking-tight'>
ダッシュボード
</h1>
<p className='text-muted-foreground'>
プロジェクトの概要と主要指標をご確認ください
</p>
</div>
<DashboardGrid>
<MetricCard
title='総ユーザー数'
value='12,345'
icon={Users}
trend='up'
trendValue='+12.5% 前月比'
/>
{/* 他のメトリクス */}
</DashboardGrid>
</div>
</main>
</div>
</div>
);
}
以下の図は、基本的なダッシュボードレイアウトの構造を示します。
mermaidflowchart TB
subgraph dashboard [ダッシュボード全体]
subgraph sidebar [サイドバー]
nav[ナビゲーション]
menu[メニューアイテム]
end
subgraph main [メインエリア]
header[ヘッダー]
content[コンテンツエリア]
end
subgraph content [コンテンツエリア]
title[ページタイトル]
grid[メトリクスグリッド]
charts[チャート群]
end
end
データ表示コンポーネントの実装
shadcn/ui のテーブルコンポーネントを活用して、効率的なデータ表示を実現します。
typescript// components/dashboard/DataTable.tsx
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
import { Badge } from '@/components/ui/badge';
interface User {
id: string;
name: string;
email: string;
status: 'active' | 'inactive';
lastLogin: string;
}
interface DataTableProps {
data: User[];
}
export function DataTable({ data }: DataTableProps) {
return (
<div className='rounded-md border'>
<Table>
<TableHeader>
<TableRow>
<TableHead>名前</TableHead>
<TableHead>メールアドレス</TableHead>
<TableHead>ステータス</TableHead>
<TableHead>最終ログイン</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.map((user) => (
<TableRow key={user.id}>
<TableCell className='font-medium'>
{user.name}
</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>
<Badge
variant={
user.status === 'active'
? 'default'
: 'secondary'
}
>
{user.status === 'active'
? 'アクティブ'
: '非アクティブ'}
</Badge>
</TableCell>
<TableCell>{user.lastLogin}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
ソート機能付きテーブル より高度な機能として、ソート機能を追加します。
typescript// components/dashboard/SortableTable.tsx
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import {
ArrowUpDown,
ArrowUp,
ArrowDown,
} from 'lucide-react';
type SortDirection = 'asc' | 'desc' | null;
export function SortableTable({ data, columns }) {
const [sortColumn, setSortColumn] = useState<
string | null
>(null);
const [sortDirection, setSortDirection] =
useState<SortDirection>(null);
const handleSort = (columnKey: string) => {
if (sortColumn === columnKey) {
setSortDirection(
sortDirection === 'asc'
? 'desc'
: sortDirection === 'desc'
? null
: 'asc'
);
} else {
setSortColumn(columnKey);
setSortDirection('asc');
}
};
const getSortIcon = (columnKey: string) => {
if (sortColumn !== columnKey)
return <ArrowUpDown className='ml-2 h-4 w-4' />;
if (sortDirection === 'asc')
return <ArrowUp className='ml-2 h-4 w-4' />;
if (sortDirection === 'desc')
return <ArrowDown className='ml-2 h-4 w-4' />;
return <ArrowUpDown className='ml-2 h-4 w-4' />;
};
return (
<Table>
<TableHeader>
<TableRow>
{columns.map((column) => (
<TableHead key={column.key}>
<Button
variant='ghost'
onClick={() => handleSort(column.key)}
className='h-auto p-0 font-semibold'
>
{column.label}
{getSortIcon(column.key)}
</Button>
</TableHead>
))}
</TableRow>
</TableHeader>
{/* テーブルボディの実装 */}
</Table>
);
}
ナビゲーション設計
効果的なナビゲーション設計は、ダッシュボードのユーザビリティに大きく影響します。
typescript// components/dashboard/Navigation.tsx
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
Home,
BarChart3,
Users,
Settings,
FileText,
} from 'lucide-react';
const navigationItems = [
{
title: 'ダッシュボード',
href: '/dashboard',
icon: Home,
},
{
title: 'アナリティクス',
href: '/dashboard/analytics',
icon: BarChart3,
},
{
title: 'ユーザー管理',
href: '/dashboard/users',
icon: Users,
},
{
title: 'レポート',
href: '/dashboard/reports',
icon: FileText,
},
{
title: '設定',
href: '/dashboard/settings',
icon: Settings,
},
];
interface NavigationProps {
currentPath: string;
}
export function Navigation({
currentPath,
}: NavigationProps) {
return (
<nav className='space-y-2'>
{navigationItems.map((item) => {
const Icon = item.icon;
const isActive = currentPath === item.href;
return (
<Button
key={item.href}
variant={isActive ? 'secondary' : 'ghost'}
className={cn(
'w-full justify-start',
isActive && 'bg-secondary'
)}
asChild
>
<a href={item.href}>
<Icon className='mr-2 h-4 w-4' />
{item.title}
</a>
</Button>
);
})}
</nav>
);
}
以下の図は、ナビゲーション設計の考え方を示します。
mermaidflowchart LR
subgraph nav [ナビゲーション構造]
primary[プライマリメニュー]
secondary[セカンダリメニュー]
primary --> dashboard[ダッシュボード]
primary --> analytics[アナリティクス]
primary --> users[ユーザー管理]
secondary --> settings[設定]
secondary --> help[ヘルプ]
end
dashboard --> overview[概要]
dashboard --> metrics[メトリクス]
analytics --> reports[レポート]
analytics --> insights[インサイト]
チャート・グラフの組み込み
データ可視化には、Recharts ライブラリと shadcn/ui を組み合わせて使用します。
bash# Recharts のインストール
yarn add recharts
yarn add -D @types/recharts
基本的なチャートコンポーネントを作成します。
typescript// components/dashboard/AreaChart.tsx
import {
ResponsiveContainer,
AreaChart as RechartsAreaChart,
Area,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
} from 'recharts';
import {
Card,
CardHeader,
CardTitle,
CardContent,
} from '@/components/ui/card';
interface ChartDataPoint {
name: string;
value: number;
}
interface AreaChartProps {
title: string;
data: ChartDataPoint[];
}
export function AreaChart({ title, data }: AreaChartProps) {
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<ResponsiveContainer width='100%' height={300}>
<RechartsAreaChart data={data}>
<CartesianGrid strokeDasharray='3 3' />
<XAxis dataKey='name' />
<YAxis />
<Tooltip
contentStyle={{
backgroundColor: 'hsl(var(--background))',
border: '1px solid hsl(var(--border))',
borderRadius: '6px',
}}
/>
<Area
type='monotone'
dataKey='value'
stroke='hsl(var(--primary))'
fill='hsl(var(--primary))'
fillOpacity={0.2}
/>
</RechartsAreaChart>
</ResponsiveContainer>
</CardContent>
</Card>
);
}
複数系列のチャート 複数のデータ系列を表示するチャートも簡単に実装できます。
typescript// components/dashboard/MultiLineChart.tsx
import {
ResponsiveContainer,
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
} from 'recharts';
interface MultiLineChartProps {
title: string;
data: Array<{
name: string;
users: number;
revenue: number;
}>;
}
export function MultiLineChart({
title,
data,
}: MultiLineChartProps) {
return (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<ResponsiveContainer width='100%' height={300}>
<LineChart data={data}>
<CartesianGrid strokeDasharray='3 3' />
<XAxis dataKey='name' />
<YAxis />
<Tooltip />
<Legend />
<Line
type='monotone'
dataKey='users'
stroke='hsl(var(--primary))'
strokeWidth={2}
name='ユーザー数'
/>
<Line
type='monotone'
dataKey='revenue'
stroke='hsl(var(--destructive))'
strokeWidth={2}
name='売上'
/>
</LineChart>
</ResponsiveContainer>
</CardContent>
</Card>
);
}
図で理解できる要点
- チャートは shadcn/ui のカードコンポーネントで統一感を保つ
- Recharts のテーマは CSS カスタムプロパティで shadcn/ui と同期
- レスポンシブコンテナで画面サイズに自動対応
まとめ
shadcn/ui を活用したダッシュボード開発は、現代の Web アプリケーション開発において最適なアプローチの一つです。
主な利点の再確認
- 開発効率: 高品質なコンポーネントですぐに開発開始
- カスタマイズ性: プロジェクト要件に合わせた柔軟な調整
- アクセシビリティ: Radix UI ベースの優れたアクセシビリティサポート
- 保守性: TypeScript による型安全性とコードの可読性
実装のポイント 段階的なアプローチで実装を進めることが重要です。まずは基本的なレイアウトから始めて、徐々に高度な機能を追加していきましょう。
今後の発展 shadcn/ui のエコシステムは継続的に発展しており、新しいコンポーネントや機能が定期的に追加されています。公式ドキュメントをチェックして、最新の機能を活用していくことをおすすめします。
効率的で美しいダッシュボードの構築により、ユーザーエクスペリエンスの向上と開発チームの生産性向上の両方を実現できるでしょう。
関連リンク
articleshadcn/ui で Command Palette を実装:検索・履歴・キーボードショートカット対応
articleshadcn/ui の asChild/Slot を極める:継承可能な API 設計と責務分離
articleshadcn/ui カラートークン早見表:ブランドカラー最適化&明暗コントラスト基準
articleshadcn/ui を Monorepo(Turborepo/pnpm)に導入するベストプラクティス
articleshadcn/ui と Headless UI/Vanilla Radix を徹底比較:実装量・a11y・可読性の差
articleshadcn/ui の思想を徹底解剖:なぜ「コピーして使う」アプローチが拡張性に強いのか
articleGemini CLI のコスト監視ダッシュボード:呼び出し数・トークン・失敗率の可視化
articleGrok アカウント作成から初回設定まで:5 分で完了するスターターガイド
articleFFmpeg コーデック地図 2025:H.264/H.265/AV1/VP9/ProRes/DNxHR の使いどころ
articleESLint の内部構造を覗く:Parser・Scope・Rule・Fixer の連携を図解
articlegpt-oss の量子化別ベンチ比較:INT8/FP16/FP8 の速度・品質トレードオフ
articleDify で実現する RAG 以外の戦略:ツール実行・関数呼び出し・自律エージェントの全体像
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来