React(19系)にVhakraUI(V3系)とMotion(旧 Framer-motion)を使って2番目のボタンにオレンジ掛かったボタンを設定してみます。
イメージ
ChakraUI(V3系)の変更点について
Chakra UI v3 系(特に 3.2x〜3.3x 系)では <Button> にbgGradientを直接指定しても効かない という仕様変更・制約があります。
理由は:
■Chakra v3 のButtonは theme tokens と variants による background 制御が優先されるため、
■bgGradient(内部的に backgroundImage)が上書きされてしまう。
対応策(3通りあります)
方法①:backgroundImage を明示的に指定する(最も簡単・確実)
<Button
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
_hover={{
backgroundImage: 'linear-gradient(to right, #ffa94d, #ff7800)',
}}
rounded="md"
px={6}
py={4}
>
<FaCrown />
お申し込み
</Button>
bgGradient の代わりに backgroundImage を使うと、Button の内部スタイルに確実に適用されます。
方法②:variant="unstyled" にして自分で完全にスタイル管理する
Button が内部で bg を強制的に設定するのを防ぐ方法です。
<Button
variant="unstyled"
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
_hover={{
backgroundImage: 'linear-gradient(to right, #ffa94d, #ff7800)',
transform: 'scale(1.05)',
}}
transition="all 0.3s"
rounded="md"
px={6}
py={3}
>
<FaCrown />
お申し込み
</Button>
variant="unstyled" にすると、内部のデフォルトテーマが無効化され、
純粋な <button> 要素のように扱えるため、backgroundImage が確実に効きます。
方法③:useStyleConfig で独自 variant を定義する(テーマ拡張方式)
もし他のページでもこの「グラデーションボタン」を使いたい場合は、
Chakra の extendTheme でカスタム variant を登録するのがベストです。
// theme/components/button.ts
export const Button = {
variants: {
gradient: {
bgGradient: 'linear(to-r, orange.400, orange.600)',
color: 'white',
_hover: {
bgGradient: 'linear(to-r, orange.500, orange.700)',
},
},
},
};
そして、呼び出し側で:
<Button variant="gradient" leftIcon={<FaCrown />}>
お申し込み
</Button>
ディレクトリ構造
└── ReactAppProjekuto/
└── src/
├── chakraComponents/
│ └── ui/
│ └── CardList.tsx
├── framerMotionComponents/
│ └── fadeinWithScroll.tsx
├── App.tsx
└── main.tsx
実装
今回は、前述の「方法①:backgroundImage を明示的に指定する」を採用しました。
import { Box, SimpleGrid, Heading, Text, Card, Button } from '@chakra-ui/react';
import { FadeIn, FadeInStagger } from '@/framerMotionComponents/fadeInWithScroll';
import { motion } from 'framer-motion';
import { FaCrown } from 'react-icons/fa';
const cards = [
{ title: 'Card 1', text: 'This is the first card.' },
{ title: 'Card 2', text: 'This is the second card.' },
{ title: 'Card 3', text: 'This is the third card.' },
{ title: 'Card 4', text: 'This is the fourth card.' },
];
export const CardList = () => {
return (
<Box p={6}>
<FadeInStagger>
<SimpleGrid columns={[1, 2, 2, 4]}>
{cards.map((card, i) => (
<FadeIn key={i}>
{/* motion.div でラップして、カーソルオーバー時の拡大アニメーション */}
<motion.div whileHover={{ scale: 1.1 }} transition={{ duration: 0.3 }}>
<Card.Root
boxShadow="md"
borderWidth="1px"
borderRadius="lg"
overflow="hidden"
mr="4"
>
<Card.Body>
<Heading size="md" mb={2}>
{card.title}
</Heading>
<Text>{card.text}</Text>
{/* ボタン部分 */}
<motion.div whileHover={{ scale: 1.05 }} transition={{ duration: 0.3 }}>
{i === 1 ? (
// 2番目のカード専用ボタン
<Button
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
rounded="md"
>
<FaCrown />
お申し込み
</Button>
) : (
<Button bg="black" color="white" _hover={{ bg: 'gray.700' }} rounded="md">
お申し込み
</Button>
)}
</motion.div>
</Card.Body>
</Card.Root>
</motion.div>
</FadeIn>
))}
</SimpleGrid>
</FadeInStagger>
</Box>
);
};
ポイント解説
1.i === 1
→ 2番目のカード(配列インデックス1)のときにだけ、特別なボタンスタイルを適用。
2.グラデーションボタン
<Button
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
rounded="md"
>
3.クラウンアイコンの追加
<Button
backgroundImage="linear-gradient(to right, #ff9a36, #ff6b00)"
color="white"
rounded="md"
>
<FaCrown />
お申し込み
</Button>
4.アニメーション部分
→ motion.div の whileHover で拡大アニメーションを適用(カードとボタンの両方に)。
サイト
