feat: add imageOverlay field to AlternateHero, WideCard, UspChecklist blocks
This commit is contained in:
parent
fb8b75ecaa
commit
e7df2e3cba
@ -3,6 +3,17 @@ import type { FDAlternateHeroBlock as Props, Media } from '@/payload-types'
|
||||
import { FDImage } from '@/components/FDImage'
|
||||
import { FDButton } from '@/components/FDButton'
|
||||
|
||||
const overlayMap: Record<string, string> = {
|
||||
none: '',
|
||||
navyLight: 'bg-fd-navy/20',
|
||||
navyMedium: 'bg-fd-navy/40',
|
||||
yellowLight: 'bg-fd-yellow/20',
|
||||
yellowMedium:'bg-fd-yellow/40',
|
||||
sepia: 'bg-[#8B7D3C]/30',
|
||||
blackLight: 'bg-black/20',
|
||||
blackMedium: 'bg-black/40',
|
||||
}
|
||||
|
||||
export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
heading,
|
||||
description,
|
||||
@ -12,9 +23,11 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
secondaryCtaLink = '#',
|
||||
image,
|
||||
imageCaption,
|
||||
imageOverlay = 'none',
|
||||
sectionBackground = 'white',
|
||||
anchorId,
|
||||
}) => {
|
||||
const overlay = overlayMap[imageOverlay || 'none']
|
||||
const media = image as Media | undefined
|
||||
const hasImage = media && typeof media === 'object' && media.url
|
||||
const isDark = sectionBackground === 'navy'
|
||||
@ -65,7 +78,7 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
{/* Full-width image — no border radius, bleeds edge to edge */}
|
||||
{hasImage && (
|
||||
<div className="w-full">
|
||||
<div className="relative w-full" style={{ maxHeight: '620px', height: '45vw', minHeight: '220px' }}>
|
||||
<div className="relative w-full overflow-hidden" style={{ maxHeight: '620px', height: '45vw', minHeight: '220px' }}>
|
||||
<FDImage
|
||||
media={media}
|
||||
size="hero"
|
||||
@ -75,6 +88,7 @@ export const FDAlternateHeroBlockComponent: React.FC<Props> = ({
|
||||
sizes="100vw"
|
||||
fallbackAlt={heading || ''}
|
||||
/>
|
||||
{overlay && <div className={`absolute inset-0 ${overlay}`} />}
|
||||
</div>
|
||||
{imageCaption && (
|
||||
<div className={`text-center py-3 font-joey text-fd-small opacity-60 ${bodyClass} ${bgClass}`}>
|
||||
|
||||
@ -68,6 +68,25 @@ export const FDAlternateHeroBlock: Block = {
|
||||
condition: (_, siblingData) => Boolean(siblingData?.image),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'imageOverlay',
|
||||
type: 'select',
|
||||
label: 'Bildöverlagring',
|
||||
defaultValue: 'none',
|
||||
options: [
|
||||
{ label: 'Ingen', value: 'none' },
|
||||
{ label: 'Navy (lätt)', value: 'navyLight' },
|
||||
{ label: 'Navy (medium)', value: 'navyMedium' },
|
||||
{ label: 'Gul (lätt)', value: 'yellowLight' },
|
||||
{ label: 'Gul (medium)', value: 'yellowMedium' },
|
||||
{ label: 'Sepia', value: 'sepia' },
|
||||
{ label: 'Svart (lätt)', value: 'blackLight' },
|
||||
{ label: 'Svart (medium)', value: 'blackMedium' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => Boolean(siblingData?.image),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'sectionBackground',
|
||||
type: 'select',
|
||||
|
||||
@ -18,6 +18,17 @@ const bodyMap: Record<string, string> = {
|
||||
white: 'text-white',
|
||||
}
|
||||
|
||||
const overlayMap: Record<string, string> = {
|
||||
none: '',
|
||||
navyLight: 'bg-fd-navy/20',
|
||||
navyMedium: 'bg-fd-navy/40',
|
||||
yellowLight: 'bg-fd-yellow/20',
|
||||
yellowMedium:'bg-fd-yellow/40',
|
||||
sepia: 'bg-[#8B7D3C]/30',
|
||||
blackLight: 'bg-black/20',
|
||||
blackMedium: 'bg-black/40',
|
||||
}
|
||||
|
||||
const checkColors: Record<string, { circle: string; check: string }> = {
|
||||
navy: { circle: 'fill-fd-navy dark:fill-white/20', check: 'fill-white dark:fill-fd-yellow' },
|
||||
yellow: { circle: 'fill-fd-yellow', check: 'fill-fd-navy' },
|
||||
@ -38,6 +49,7 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
||||
heading,
|
||||
items,
|
||||
image,
|
||||
imageOverlay = 'none',
|
||||
imagePosition = 'right',
|
||||
checkColor = 'navy',
|
||||
sectionBackground = 'white',
|
||||
@ -49,6 +61,7 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
||||
const bodyClr = bodyMap[textColor || 'navy']
|
||||
const media = image as Media | undefined
|
||||
const hasImage = Boolean(media?.url)
|
||||
const overlay = overlayMap[imageOverlay || 'none']
|
||||
|
||||
const textContent = (
|
||||
<div className="flex-1 flex flex-col gap-6 md:gap-8">
|
||||
@ -65,14 +78,15 @@ export const FDUspChecklistBlockComponent: React.FC<FDUspChecklistBlockProps> =
|
||||
)
|
||||
|
||||
const imageContent = hasImage ? (
|
||||
<div className="flex-1">
|
||||
<div className="flex-1 relative overflow-hidden rounded-[40px]">
|
||||
<FDImage
|
||||
media={media!}
|
||||
size="large"
|
||||
className="w-full h-auto rounded-[40px] object-cover"
|
||||
className="w-full h-auto object-cover"
|
||||
sizes="(max-width: 1024px) 100vw, 550px"
|
||||
fallbackAlt={heading || ''}
|
||||
/>
|
||||
{overlay && <div className={`absolute inset-0 ${overlay}`} />}
|
||||
</div>
|
||||
) : null
|
||||
|
||||
|
||||
@ -39,6 +39,25 @@ export const FDUspChecklistBlock: Block = {
|
||||
relationTo: 'media',
|
||||
label: 'Bild (valfri)',
|
||||
},
|
||||
{
|
||||
name: 'imageOverlay',
|
||||
type: 'select',
|
||||
label: 'Bildöverlagring',
|
||||
defaultValue: 'none',
|
||||
options: [
|
||||
{ label: 'Ingen', value: 'none' },
|
||||
{ label: 'Navy (lätt)', value: 'navyLight' },
|
||||
{ label: 'Navy (medium)', value: 'navyMedium' },
|
||||
{ label: 'Gul (lätt)', value: 'yellowLight' },
|
||||
{ label: 'Gul (medium)', value: 'yellowMedium' },
|
||||
{ label: 'Sepia', value: 'sepia' },
|
||||
{ label: 'Svart (lätt)', value: 'blackLight' },
|
||||
{ label: 'Svart (medium)', value: 'blackMedium' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => Boolean(siblingData?.image),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'imagePosition',
|
||||
type: 'select',
|
||||
|
||||
@ -24,12 +24,24 @@ const btnVariantMap: Record<string, { variant: 'primary' | 'outline' }> = {
|
||||
|
||||
const cardRadius = 'rounded-[32px] md:rounded-[50px] lg:rounded-[70px]'
|
||||
|
||||
const overlayMap: Record<string, string> = {
|
||||
none: '',
|
||||
navyLight: 'bg-fd-navy/20',
|
||||
navyMedium: 'bg-fd-navy/40',
|
||||
yellowLight: 'bg-fd-yellow/20',
|
||||
yellowMedium:'bg-fd-yellow/40',
|
||||
sepia: 'bg-[#8B7D3C]/30',
|
||||
blackLight: 'bg-black/20',
|
||||
blackMedium: 'bg-black/40',
|
||||
}
|
||||
|
||||
export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
||||
heading,
|
||||
body,
|
||||
ctaText,
|
||||
ctaLink,
|
||||
image,
|
||||
imageOverlay = 'none',
|
||||
cardBackground = 'navy',
|
||||
buttonColor = 'yellow',
|
||||
sectionBackground = 'white',
|
||||
@ -40,6 +52,7 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
||||
const { variant } = btnVariantMap[buttonColor || 'yellow']
|
||||
const media = image as Media | undefined
|
||||
const hasImage = media && typeof media === 'object' && media.url
|
||||
const overlay = overlayMap[imageOverlay || 'none']
|
||||
|
||||
return (
|
||||
<section id={anchorId || undefined} className={`w-full py-16 md:py-20 lg:py-[99px] ${sectionBg}`}>
|
||||
@ -65,13 +78,16 @@ export const FDWideCardBlockComponent: React.FC<FDWideCardBlockProps> = ({
|
||||
|
||||
{hasImage && (
|
||||
<div className="flex items-center justify-center w-full min-[820px]:w-[45%] lg:w-[480px] flex-shrink-0 p-6 md:p-10 lg:p-12">
|
||||
<FDImage
|
||||
media={media}
|
||||
size="large"
|
||||
className="w-full h-auto max-h-[320px] object-contain drop-shadow-xl"
|
||||
sizes="(max-width: 820px) 80vw, 400px"
|
||||
fallbackAlt={heading || ''}
|
||||
/>
|
||||
<div className="relative w-full">
|
||||
<FDImage
|
||||
media={media}
|
||||
size="large"
|
||||
className="w-full h-auto max-h-[320px] object-contain drop-shadow-xl"
|
||||
sizes="(max-width: 820px) 80vw, 400px"
|
||||
fallbackAlt={heading || ''}
|
||||
/>
|
||||
{overlay && <div className={`absolute inset-0 ${overlay}`} />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -42,6 +42,25 @@ export const FDWideCardBlock: Block = {
|
||||
relationTo: 'media',
|
||||
label: 'Bild (valfri)',
|
||||
},
|
||||
{
|
||||
name: 'imageOverlay',
|
||||
type: 'select',
|
||||
label: 'Bildöverlagring',
|
||||
defaultValue: 'none',
|
||||
options: [
|
||||
{ label: 'Ingen', value: 'none' },
|
||||
{ label: 'Navy (lätt)', value: 'navyLight' },
|
||||
{ label: 'Navy (medium)', value: 'navyMedium' },
|
||||
{ label: 'Gul (lätt)', value: 'yellowLight' },
|
||||
{ label: 'Gul (medium)', value: 'yellowMedium' },
|
||||
{ label: 'Sepia', value: 'sepia' },
|
||||
{ label: 'Svart (lätt)', value: 'blackLight' },
|
||||
{ label: 'Svart (medium)', value: 'blackMedium' },
|
||||
],
|
||||
admin: {
|
||||
condition: (_, siblingData) => Boolean(siblingData?.image),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'cardBackground',
|
||||
type: 'select',
|
||||
|
||||
38641
src/migrations/20260313_081702.json
Normal file
38641
src/migrations/20260313_081702.json
Normal file
File diff suppressed because it is too large
Load Diff
33
src/migrations/20260313_081702.ts
Normal file
33
src/migrations/20260313_081702.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { MigrateUpArgs, MigrateDownArgs, sql } from '@payloadcms/db-postgres'
|
||||
|
||||
export async function up({ db, payload, req }: MigrateUpArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
CREATE TYPE "public"."enum_pages_blocks_fd_usp_checklist_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
CREATE TYPE "public"."enum_pages_blocks_fd_wide_card_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
CREATE TYPE "public"."enum_pages_blocks_fd_alternate_hero_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
CREATE TYPE "public"."enum__pages_v_blocks_fd_usp_checklist_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
CREATE TYPE "public"."enum__pages_v_blocks_fd_wide_card_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
CREATE TYPE "public"."enum__pages_v_blocks_fd_alternate_hero_image_overlay" AS ENUM('none', 'navyLight', 'navyMedium', 'yellowLight', 'yellowMedium', 'sepia', 'blackLight', 'blackMedium');
|
||||
ALTER TABLE "pages_blocks_fd_usp_checklist" ADD COLUMN "image_overlay" "enum_pages_blocks_fd_usp_checklist_image_overlay" DEFAULT 'none';
|
||||
ALTER TABLE "pages_blocks_fd_wide_card" ADD COLUMN "image_overlay" "enum_pages_blocks_fd_wide_card_image_overlay" DEFAULT 'none';
|
||||
ALTER TABLE "pages_blocks_fd_alternate_hero" ADD COLUMN "image_overlay" "enum_pages_blocks_fd_alternate_hero_image_overlay" DEFAULT 'none';
|
||||
ALTER TABLE "_pages_v_blocks_fd_usp_checklist" ADD COLUMN "image_overlay" "enum__pages_v_blocks_fd_usp_checklist_image_overlay" DEFAULT 'none';
|
||||
ALTER TABLE "_pages_v_blocks_fd_wide_card" ADD COLUMN "image_overlay" "enum__pages_v_blocks_fd_wide_card_image_overlay" DEFAULT 'none';
|
||||
ALTER TABLE "_pages_v_blocks_fd_alternate_hero" ADD COLUMN "image_overlay" "enum__pages_v_blocks_fd_alternate_hero_image_overlay" DEFAULT 'none';`)
|
||||
}
|
||||
|
||||
export async function down({ db, payload, req }: MigrateDownArgs): Promise<void> {
|
||||
await db.execute(sql`
|
||||
ALTER TABLE "pages_blocks_fd_usp_checklist" DROP COLUMN "image_overlay";
|
||||
ALTER TABLE "pages_blocks_fd_wide_card" DROP COLUMN "image_overlay";
|
||||
ALTER TABLE "pages_blocks_fd_alternate_hero" DROP COLUMN "image_overlay";
|
||||
ALTER TABLE "_pages_v_blocks_fd_usp_checklist" DROP COLUMN "image_overlay";
|
||||
ALTER TABLE "_pages_v_blocks_fd_wide_card" DROP COLUMN "image_overlay";
|
||||
ALTER TABLE "_pages_v_blocks_fd_alternate_hero" DROP COLUMN "image_overlay";
|
||||
DROP TYPE "public"."enum_pages_blocks_fd_usp_checklist_image_overlay";
|
||||
DROP TYPE "public"."enum_pages_blocks_fd_wide_card_image_overlay";
|
||||
DROP TYPE "public"."enum_pages_blocks_fd_alternate_hero_image_overlay";
|
||||
DROP TYPE "public"."enum__pages_v_blocks_fd_usp_checklist_image_overlay";
|
||||
DROP TYPE "public"."enum__pages_v_blocks_fd_wide_card_image_overlay";
|
||||
DROP TYPE "public"."enum__pages_v_blocks_fd_alternate_hero_image_overlay";`)
|
||||
}
|
||||
@ -27,8 +27,8 @@ export const generateMeta = async (args: {
|
||||
const ogImage = getImageURL(doc?.meta?.image)
|
||||
|
||||
const title = doc?.meta?.title
|
||||
? doc?.meta?.title + ' | Payload Website Template'
|
||||
: 'Payload Website Template'
|
||||
? doc?.meta?.title + ' | Fiber Direkt'
|
||||
: 'Fiber Direkt'
|
||||
|
||||
return {
|
||||
description: doc?.meta?.description,
|
||||
|
||||
@ -3,14 +3,14 @@ import { getServerSideURL } from './getURL'
|
||||
|
||||
const defaultOpenGraph: Metadata['openGraph'] = {
|
||||
type: 'website',
|
||||
description: 'An open-source website built with Payload and Next.js.',
|
||||
description: 'Fiber Direkt – snabb och pålitlig fiber till ditt företag.',
|
||||
images: [
|
||||
{
|
||||
url: `${getServerSideURL()}/website-template-OG.webp`,
|
||||
},
|
||||
],
|
||||
siteName: 'Payload Website Template',
|
||||
title: 'Payload Website Template',
|
||||
siteName: 'Fiber Direkt',
|
||||
title: 'Fiber Direkt',
|
||||
}
|
||||
|
||||
export const mergeOpenGraph = (og?: Metadata['openGraph']): Metadata['openGraph'] => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user