Heroブロック
Hero は、MUI 上に構築されたレスポンシブなマーケティングヒーローセクションで、見出しコピー、プライマリのコールトゥアクション、大画面では横並びの大きなヒーロー画像を備えています。
インストール
- npm
- yarn
- pnpm
- bun
npm install @nodeblocks/frontend-hero-block
yarn add @nodeblocks/frontend-hero-block
pnpm add @nodeblocks/frontend-hero-block
bun add @nodeblocks/frontend-hero-block
必要なもの
| 項目 | 用途 |
|---|---|
byline | 見出し |
buttonText | CTA のラベル |
onClickButton | CTA クリック時のハンドラー |
imageUrl | 画像のソース URL(2:1 のアスペクト比を想定) |
ページまたは CMS からコピーと画像を渡してください。任意の secondaryText と tertiaryText は byline の下、ボタンの下にレンダリングされます。大画面での画像の縦位置は imageAlignment(top、center、bottom)で調整できます。
コード例
ドキュメントのプレビューでは、ヒーローがライブエディターに収まるよう境界付きフレームと明示的な Hero.Img サイズを使います。アプリでは全幅レイアウトを使い、プレビュー専用のスタイルは省略してください。
- クイックスタート
- レイアウト
- 複合コンポーネント
- ブロックのオーバーライド
function Example() { const imageUrl = '/img/undraw_docusaurus_mountain.svg'; return ( <Hero byline="プラットフォームへようこそ" secondaryText="業務を効率化し、生産性を向上" tertiaryText="30日間無料トライアル • クレジットカード不要" buttonText="始める" imageUrl={imageUrl} onClickButton={() => {}} sx={{ '& .nbb-hero-content': { position: 'relative', zIndex: 1, maxWidth: '100%', }, '& .nbb-hero-content-byline, & .nbb-hero-content-secondary-text, & .nbb-hero-content-tertiary-text': { color: 'grey.900', textShadow: '0 0 8px rgba(255,255,255,1), 0 0 16px rgba(255,255,255,0.9), 0 1px 2px rgba(255,255,255,0.95)', }, '& .nbb-hero-content-tertiary-text': { color: 'primary.dark', }, }} /> ); }
imageAlignment を切り替えて、大画面の行レイアウトでヒーロー画像を上・中央・下に配置します。
function Example() { const [imageAlignment, setImageAlignment] = React.useState('center'); const imageUrl = '/img/undraw_docusaurus_react.svg'; const alignments = ['top', 'center', 'bottom']; return ( <Box sx={{ width: '100%', maxWidth: 720, mx: 'auto' }}> <Stack direction="row" spacing={1} sx={{ mb: 1.5, flexWrap: 'wrap' }}> {alignments.map((value) => ( <Button key={value} size="small" variant={imageAlignment === value ? 'contained' : 'outlined'} onClick={() => setImageAlignment(value)} > {value} </Button> ))} </Stack> <Box sx={{ border: '1px solid', borderColor: 'divider', borderRadius: 2, overflow: 'hidden', bgcolor: 'background.paper', }} > <Hero byline="次の仕事を見つける" secondaryText="エンジニア向けの求人検索" buttonText="求人を見る" imageUrl={imageUrl} imageAlignment={imageAlignment} onClickButton={() => {}} sx={{ '& .nbb-hero-content': { position: 'relative', zIndex: 1, maxWidth: '100%', }, '& .nbb-hero-content-byline, & .nbb-hero-content-secondary-text, & .nbb-hero-content-tertiary-text': { color: 'grey.900', textShadow: '0 0 8px rgba(255,255,255,1), 0 0 16px rgba(255,255,255,0.9), 0 1px 2px rgba(255,255,255,0.95)', }, '& .nbb-hero-content-tertiary-text': { color: 'primary.dark', }, }} /> </Box> </Box> ); }
imageAlignment は行レイアウトで有効imageAlignment は、ヒーローが横並びの行になっているとき(デフォルトは lg ブレークポイント)に Hero.Img の縦位置を調整します。プレビューでは行レイアウトを強制し、ライブエディターで top、center、bottom を比較できるよう Hero.Img の alignSelf で配置を反映します。
Hero.Content と Hero.Img を直接構成し、各ブロックを sx でスタイルします。
function Example() { const imageUrl = '/img/undraw_docusaurus_mountain.svg'; return ( <Box sx={{ width: '100%', maxWidth: 720, mx: 'auto', border: '1px solid', borderColor: 'divider', borderRadius: 2, overflow: 'hidden', bgcolor: 'background.paper', }} > <Hero byline="プラットフォームへようこそ" secondaryText="すぐ使えるブロックで高速に構築" buttonText="始める" imageUrl={imageUrl} tertiaryText="30日間無料トライアル • クレジットカード不要" onClickButton={() => {}} sx={{ '& .nbb-hero-content': { position: 'relative', zIndex: 1, }, '& .nbb-hero-content-byline, & .nbb-hero-content-secondary-text, & .nbb-hero-content-tertiary-text': { color: 'grey.900', textShadow: '0 0 8px rgba(255,255,255,1), 0 0 16px rgba(255,255,255,0.9), 0 1px 2px rgba(255,255,255,0.95)', }, '& .nbb-hero-content-tertiary-text': { color: 'primary.dark', }, }} > <Hero.Content spacing={{ xs: 2, sm: 2.5 }} sx={{ p: { xs: 2, sm: 2.5 }, maxWidth: '100%', }} > <Stack sx={{ alignItems: 'center', width: '100%' }}> <Hero.Content.Byline /> <Hero.Content.SecondaryText /> </Stack> <Stack spacing={1.5} sx={{ alignItems: 'center', width: '100%' }}> <Hero.Content.ActionButton sx={{ px: 4, borderRadius: 99 }} /> <Hero.Content.TertiaryText sx={{ textAlign: 'center' }} /> </Stack> </Hero.Content> <Hero.Img src={imageUrl} /> </Hero> </Box> ); }
defaultBlocks と defaultBlockOrder を使う関数の children で、ブロックの差し替えと順序の制御を行います。全幅 UI は content ブロック内に置き、テキスト列に収めてください。
function Example() { const imageUrl = '/img/undraw_docusaurus_mountain.svg'; return ( <Box sx={{ width: '100%', maxWidth: 720, mx: 'auto', border: '1px solid', borderColor: 'divider', borderRadius: 2, overflow: 'hidden', bgcolor: 'background.paper', }} > <Hero byline="プラットフォームへようこそ" secondaryText="業務を効率化し、生産性を向上" buttonText="始める" imageUrl={imageUrl} tertiaryText="30日間無料トライアル • クレジットカード不要" onClickButton={() => {}} sx={{ maxHeight: 'none', flexDirection: 'column', alignItems: 'center', gap: 2, py: 2, px: 1, '& .nbb-hero-content': { position: 'relative', zIndex: 1, }, '& .nbb-hero-content-byline, & .nbb-hero-content-secondary-text, & .nbb-hero-content-tertiary-text': { color: 'grey.900', textShadow: '0 0 8px rgba(255,255,255,1), 0 0 16px rgba(255,255,255,0.9), 0 1px 2px rgba(255,255,255,0.95)', }, '& .nbb-hero-content-tertiary-text': { color: 'primary.dark', }, }} > {({ defaultBlocks }) => ({ blocks: { ...defaultBlocks, content: ( <Hero.Content spacing={{ xs: 2, sm: 2.5 }} sx={{ p: { xs: 2, sm: 2.5 }, width: '100%' }}> <Alert severity="info" sx={{ width: '100%' }}> 期間限定: 新規チーム向けにトライアル期間を延長しています。 </Alert> <Stack sx={{ alignItems: 'center', width: '100%' }}> <Hero.Content.Byline /> <Hero.Content.SecondaryText sx={{ fontSize: { xs: 24, sm: 32 }, lineHeight: 1.2, textAlign: 'center', }} /> </Stack> <Stack spacing={1.5} sx={{ alignItems: 'center', width: '100%' }}> <Hero.Content.ActionButton /> <Hero.Content.TertiaryText /> </Stack> </Hero.Content> ), img: <Hero.Img src={imageUrl} />, }, blockOrder: ['content', 'img'], })} </Hero> </Box> ); }
ブロックのオーバーライドを使うタイミング
デフォルトの defaultBlockOrder は content、img、byline、secondaryText、actionButton、tertiaryText です。ルートのレンダリングでは content と img を使用します。byline、secondaryText、actionButton、tertiaryText はデフォルトで Hero.Content 内にネストされます。バナーやカスタムマークアップはルート行の兄弟ではなく、content ブロックをオーバーライドして前置してください。ルートの imageUrl をコンテキスト用に保持しつつカスタム画像スタイルが必要な場合は img を差し替えてください。
主要プロパティ
コアプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
byline | ReactNode | はい | — | Hero.Content.Byline でレンダリングされるメイン見出し |
buttonText | string | はい | — | Hero.Content.ActionButton のラベル |
onClickButton | () => void | はい | — | アクションボタンクリック時に呼び出される(Hero.Content.ActionButton に onClick がない場合も使用) |
imageUrl | string | はい | — | サブコンポーネントで src が未設定のとき Hero.Img に渡される画像ソース |
コンテンツプロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
secondaryText | ReactNode | いいえ | undefined | byline 下の大きな補助行(Hero.Content.SecondaryText) |
tertiaryText | ReactNode | いいえ | undefined | アクションボタン下の小さな行(Hero.Content.TertiaryText) |
imageAlignment | 'top' | 'center' | 'bottom' | いいえ | undefined | 大画面(lg ブレークポイント)での Hero.Img の縦位置 |
レイアウトと構成プロパティ
| プロパティ | 型 | 必須 | デフォルト | 説明 |
|---|---|---|---|---|
children | ReactNode | function | いいえ | undefined | 複合サブコンポーネント(Hero.Content、Hero.Img など)、またはレイアウトブロックの注入・並べ替え用の関数 ({ defaultBlocks, defaultBlockOrder }) => ({ blocks, blockOrder }) |
className | string | いいえ | undefined | ルートスタックのクラス名(nbb-hero) |
sx | SxProps | いいえ | undefined | ルートスタック用の MUI システムスタイル |
Hero は StackProps(children を除く)を継承します。デフォルトの defaultBlockOrder: content、img、byline、secondaryText、actionButton、tertiaryText。
サブコンポーネントのプロパティ
サブコンポーネントはコンテキストから読み取り、同じコンテンツキーをプロパティとして渡すとローカルで上書きできます。
| サブコンポーネント | 主要プロパティ | 継承 | ベース |
|---|---|---|---|
Hero.Content | children、spacing(デフォルト { xs: 3, lg: 4 })、className、sx | StackProps | Stack |
Hero.Img | src、alt(デフォルト hero image)、imageUrl、imageAlignment、component、className、sx | BoxProps | Box(component="img") |
Hero.Content.Byline | byline、children、variant(デフォルト h3)、className、sx | TypographyProps | Typography |
Hero.Content.SecondaryText | secondaryText、children、variant(デフォルト h2)、className、sx | TypographyProps | Typography |
Hero.Content.ActionButton | buttonText、onClickButton、onClick、children、variant(デフォルト contained)、className、sx | ButtonProps | Button |
Hero.Content.TertiaryText | tertiaryText、children、variant(デフォルト h6)、color(デフォルト primary)、className、sx | TypographyProps | Typography |
デフォルト UI ブロック
| ブロック | ベース | 備考 |
|---|---|---|
Hero(ルート) | Stack | lg では横並び、中央揃え、最大高さに上限(nbb-hero) |
content(Hero.Content) | Stack | byline グループと CTA グループを持つテキスト列(nbb-hero-content) |
img(Hero.Img) | Box | imageUrl をレンダリング。alt のデフォルトは hero image(nbb-hero-img) |
byline(Hero.Content.Byline) | Typography | コンテキストの byline からのレスポンシブ見出し |
secondaryText(Hero.Content.SecondaryText) | Typography | secondaryText が設定されているときの大きな中央揃え行 |
actionButton(Hero.Content.ActionButton) | Button | コンテキストの buttonText を使う contained CTA |
tertiaryText(Hero.Content.TertiaryText) | Typography | tertiaryText が設定されているときのプライマリカラー行 |
デフォルトのルートレンダリング順序: content → img。
TypeScript
import * as React from 'react';
import { Hero } from '@nodeblocks/frontend-hero-block';
import type { ReactNode } from 'react';
type HeroSectionProps = {
byline: ReactNode;
buttonText: string;
imageUrl: string;
onClickButton: () => void;
secondaryText?: ReactNode;
tertiaryText?: ReactNode;
imageAlignment?: 'top' | 'center' | 'bottom';
};
export function HeroSection({
byline,
buttonText,
imageUrl,
onClickButton,
secondaryText,
tertiaryText,
imageAlignment,
}: HeroSectionProps) {
return (
<Hero
byline={byline}
buttonText={buttonText}
imageUrl={imageUrl}
onClickButton={onClickButton}
secondaryText={secondaryText}
tertiaryText={tertiaryText}
imageAlignment={imageAlignment}
/>
);
}