mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-18 20:09:25 +00:00
feat: add illustration and content alignment options to hero section
This commit is contained in:
parent
1c02a2bc6c
commit
570d6d61bb
3 changed files with 195 additions and 27 deletions
|
|
@ -174,7 +174,9 @@ const OrgEditLanding = () => {
|
|||
color: '#666666',
|
||||
size: 'medium'
|
||||
},
|
||||
buttons: []
|
||||
buttons: [],
|
||||
illustration: undefined,
|
||||
contentAlign: 'center'
|
||||
}
|
||||
case 'text-and-image':
|
||||
return {
|
||||
|
|
@ -950,6 +952,135 @@ const HeroSectionEditor: React.FC<{
|
|||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Illustration */}
|
||||
<div className="space-y-4">
|
||||
<Label>Illustration</Label>
|
||||
<div className="border rounded-lg p-4 space-y-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Illustration Image</Label>
|
||||
<Input
|
||||
value={section.illustration?.image.url || ''}
|
||||
onChange={(e) => {
|
||||
if (e.target.value) {
|
||||
onChange({
|
||||
...section,
|
||||
illustration: {
|
||||
image: { url: e.target.value, alt: section.illustration?.image.alt || '' },
|
||||
position: 'left',
|
||||
verticalAlign: 'center',
|
||||
size: 'medium'
|
||||
}
|
||||
})
|
||||
}
|
||||
}}
|
||||
placeholder="Illustration URL"
|
||||
/>
|
||||
<Input
|
||||
value={section.illustration?.image.alt || ''}
|
||||
onChange={(e) => {
|
||||
if (section.illustration?.image.url) {
|
||||
onChange({
|
||||
...section,
|
||||
illustration: {
|
||||
...section.illustration,
|
||||
image: { ...section.illustration.image, alt: e.target.value }
|
||||
}
|
||||
})
|
||||
}
|
||||
}}
|
||||
placeholder="Alt text"
|
||||
/>
|
||||
<ImageUploader
|
||||
id="hero-illustration"
|
||||
onImageUploaded={(url) => onChange({
|
||||
...section,
|
||||
illustration: {
|
||||
image: { url, alt: section.illustration?.image.alt || '' },
|
||||
position: 'left',
|
||||
verticalAlign: 'center',
|
||||
size: 'medium'
|
||||
}
|
||||
})}
|
||||
buttonText="Upload Illustration"
|
||||
/>
|
||||
{section.illustration?.image.url && (
|
||||
<img
|
||||
src={section.illustration?.image.url}
|
||||
alt={section.illustration?.image.alt}
|
||||
className="h-12 object-contain"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label>Position</Label>
|
||||
<Select
|
||||
value={section.illustration?.position || 'left'}
|
||||
onValueChange={(value: 'left' | 'right') => onChange({
|
||||
...section,
|
||||
illustration: {
|
||||
...section.illustration,
|
||||
position: value,
|
||||
image: section.illustration?.image || { url: '', alt: '' },
|
||||
size: section.illustration?.size || 'medium',
|
||||
verticalAlign: section.illustration?.verticalAlign || 'center'
|
||||
}
|
||||
})}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select position" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="left">Left</SelectItem>
|
||||
<SelectItem value="right">Right</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label>Size</Label>
|
||||
<Select
|
||||
value={section.illustration?.size || 'medium'}
|
||||
onValueChange={(value: 'small' | 'medium' | 'large') => onChange({
|
||||
...section,
|
||||
illustration: {
|
||||
...section.illustration,
|
||||
size: value,
|
||||
image: section.illustration?.image || { url: '', alt: '' },
|
||||
position: (section.illustration?.position || 'left') as 'left' | 'right',
|
||||
verticalAlign: section.illustration?.verticalAlign || 'center'
|
||||
}
|
||||
})}
|
||||
>
|
||||
<SelectTrigger>
|
||||
<SelectValue placeholder="Select size" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="small">Small</SelectItem>
|
||||
<SelectItem value="medium">Medium</SelectItem>
|
||||
<SelectItem value="large">Large</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{section.illustration?.image.url && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={() => onChange({
|
||||
...section,
|
||||
illustration: undefined
|
||||
})}
|
||||
className="text-red-500 hover:text-red-600 hover:bg-red-50 w-full"
|
||||
>
|
||||
<Trash2 className="h-4 w-4 mr-2" />
|
||||
Remove Illustration
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -74,6 +74,13 @@ export interface LandingHeroSection {
|
|||
heading: LandingHeading;
|
||||
subheading: LandingHeading;
|
||||
buttons: LandingButton[];
|
||||
illustration?: {
|
||||
image: LandingImage;
|
||||
position: 'left' | 'right';
|
||||
verticalAlign: 'top' | 'center' | 'bottom';
|
||||
size: 'small' | 'medium' | 'large';
|
||||
};
|
||||
contentAlign?: 'left' | 'center' | 'right';
|
||||
}
|
||||
|
||||
export type LandingSection = LandingTextAndImageSection | LandingHeroSection | LandingLogos | LandingPeople | LandingFeaturedCourses;
|
||||
|
|
|
|||
|
|
@ -41,33 +41,63 @@ function LandingCustom({ landing, orgslug }: LandingCustomProps) {
|
|||
: `url(${section.background.image}) center/cover`
|
||||
}}
|
||||
>
|
||||
<div className="text-center w-full max-w-4xl mx-auto px-4 sm:px-6">
|
||||
<h1
|
||||
className="text-xl sm:text-2xl md:text-3xl font-bold mb-2 sm:mb-4"
|
||||
style={{ color: section.heading.color }}
|
||||
>
|
||||
{section.heading.text}
|
||||
</h1>
|
||||
<h2
|
||||
className="text-sm sm:text-base md:text-lg mb-4 sm:mb-6 md:mb-8 font-medium px-4 max-w-2xl mx-auto"
|
||||
style={{ color: section.subheading.color }}
|
||||
>
|
||||
{section.subheading.text}
|
||||
</h2>
|
||||
<div className="flex flex-col sm:flex-row gap-3 sm:gap-4 justify-center items-center">
|
||||
{section.buttons.map((button, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={button.link}
|
||||
className="w-full sm:w-auto px-6 py-2.5 rounded-lg text-sm font-extrabold shadow transition-transform hover:scale-105"
|
||||
style={{
|
||||
backgroundColor: button.background,
|
||||
color: button.color
|
||||
}}
|
||||
<div className={`w-full h-full flex flex-col sm:flex-row ${
|
||||
section.illustration?.position === 'right' ? 'sm:flex-row-reverse' : 'sm:flex-row'
|
||||
} items-stretch`}>
|
||||
{/* Logo */}
|
||||
{section.illustration?.image.url && (
|
||||
<div className={`flex items-${section.illustration.verticalAlign} p-6 w-full ${
|
||||
section.illustration.size === 'small' ? 'sm:w-1/4' :
|
||||
section.illustration.size === 'medium' ? 'sm:w-1/3' :
|
||||
'sm:w-2/5'
|
||||
}`}>
|
||||
<img
|
||||
src={section.illustration.image.url}
|
||||
alt={section.illustration.image.alt}
|
||||
className="w-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Content */}
|
||||
<div className={`flex-1 flex items-center ${
|
||||
section.contentAlign === 'left' ? 'justify-start text-left' :
|
||||
section.contentAlign === 'right' ? 'justify-end text-right' :
|
||||
'justify-center text-center'
|
||||
} p-6`}>
|
||||
<div className="max-w-2xl">
|
||||
<h1
|
||||
className="text-xl sm:text-2xl md:text-3xl font-bold mb-2 sm:mb-4"
|
||||
style={{ color: section.heading.color }}
|
||||
>
|
||||
{button.text}
|
||||
</a>
|
||||
))}
|
||||
{section.heading.text}
|
||||
</h1>
|
||||
<h2
|
||||
className="text-sm sm:text-base md:text-lg mb-4 sm:mb-6 md:mb-8 font-medium"
|
||||
style={{ color: section.subheading.color }}
|
||||
>
|
||||
{section.subheading.text}
|
||||
</h2>
|
||||
<div className={`flex flex-col sm:flex-row gap-3 sm:gap-4 ${
|
||||
section.contentAlign === 'left' ? 'justify-start' :
|
||||
section.contentAlign === 'right' ? 'justify-end' :
|
||||
'justify-center'
|
||||
} items-center`}>
|
||||
{section.buttons.map((button, index) => (
|
||||
<a
|
||||
key={index}
|
||||
href={button.link}
|
||||
className="w-full sm:w-auto px-6 py-2.5 rounded-lg text-sm font-extrabold shadow transition-transform hover:scale-105"
|
||||
style={{
|
||||
backgroundColor: button.background,
|
||||
color: button.color
|
||||
}}
|
||||
>
|
||||
{button.text}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue