$id, 'title' => $title, 'subtitle' => $subtitle, // The card and the popup both read this as a list of plain image URLs. 'images' => $photos, 'colors' => array( 'color' => '#fff', 'bgType' => 'solid', 'bg' => '#505a64d9', ), 'btnColors' => array( 'color' => '#fff', 'bgType' => 'solid', 'bg' => '#000a1480', ), ); } /** * One Polaroid frame. * * The Polaroid style does not read the album list at all — it reads * imagesData.images, a flat list of photographs, each its own frame on the * wall. Passing it albums leaves the wall empty. * * @param string $id Photo id. * @param string $url Photo URL. * @param string $title Caption written under the frame. * @param string $note Second line under the caption. * @param string $date Date shown under the caption. * @return array */ function bigb_pattern_polaroid( $id, $url, $title, $note, $date ) { return array( 'id' => $id, 'url' => $url, 'title' => $title, 'description' => $note, 'date' => $date, 'category' => '', // Not read by the Polaroid wall itself — the frame is sized by // styles.card — but the item settings panel expects the keys. 'width' => array( 'desktop' => 800, 'tablet' => 600, 'mobile' => 400 ), 'height' => array( 'desktop' => 800, 'tablet' => 600, 'mobile' => 400 ), ); } /** * Serialise the gallery block into block markup. * * The block renders from render.php and saves nothing between its delimiters. * * @param array $attrs Block attributes. * @return string */ function bigb_pattern_block( $attrs ) { return ''; } /** * A centred core heading. * * @param string $text Heading text. * @param int $level Heading level. * @return string */ function bigb_pattern_heading( $text, $level = 2 ) { $level = (int) $level; return '' . '' . esc_html( $text ) . '' . ''; } /** * A centred core paragraph. * * @param string $text Paragraph text. * @return string */ function bigb_pattern_paragraph( $text ) { return '' . '

' . esc_html( $text ) . '

' . ''; } /** * A vertical spacer. * * @param int $px Height in pixels. * @return string */ function bigb_pattern_spacer( $px = 32 ) { $px = (int) $px; return '' . '' . ''; } /** * Wrap blocks in a group. * * @param string $inner Inner block markup. * @param string $align full, wide or empty. * @return string */ function bigb_pattern_group( $inner, $align = '' ) { $attrs = $align ? '{"align":"' . $align . '","layout":{"type":"constrained"}}' : '{"layout":{"type":"constrained"}}'; $classes = $align ? 'wp-block-group align' . $align : 'wp-block-group'; return '' . '
' . $inner . '
' . ''; } /** * Register the pattern category and the patterns themselves. * * @return void */ function bigb_register_patterns() { if ( ! function_exists( 'register_block_pattern' ) ) { return; } $category = 'image-gallery'; register_block_pattern_category( $category, array( 'label' => __( 'Image Galleries', 'image-gallery' ) ) ); // A small stock of placeholder photographs, warm to cool. $dawn = bigb_pattern_photo( '#f2c894', '#f0876a', '#7d5a63', '#a97d78' ); $noon = bigb_pattern_photo( '#8ec9e8', '#fff2cc', '#3f7a5a', '#6ba377' ); $dusk = bigb_pattern_photo( '#5b6b9e', '#f6b6a0', '#2b3355', '#3f4a75' ); $night = bigb_pattern_photo( '#1a2138', '#c7d4f0', '#0d1220', '#161d33' ); $forest = bigb_pattern_photo( '#cfe3d2', '#f7f2d8', '#2f5741', '#4b7a5c' ); $sand = bigb_pattern_photo( '#f0e0c4', '#e8b04f', '#9b7a4f', '#c19a66' ); $patterns = array(); /* Album grid ---------------------------------------------------------- */ $patterns['album-grid'] = array( 'title' => __( 'Photo album grid', 'image-gallery' ), 'description' => __( 'Three albums in a row, each opening into its own set of photographs. The classic layout for a photography or travel page.', 'image-gallery' ), 'keywords' => array( 'album', 'grid', 'photography', 'travel' ), 'content' => bigb_pattern_group( bigb_pattern_heading( __( 'Recent work', 'image-gallery' ) ) . bigb_pattern_paragraph( __( 'Three collections from the past year. Open any album to see the full set.', 'image-gallery' ) ) . bigb_pattern_spacer( 24 ) . bigb_pattern_block( array( 'styleSl' => 'styleDefault', 'gallery' => array( bigb_pattern_album( 1, __( 'Coastline', 'image-gallery' ), __( '18 photographs · Spring', 'image-gallery' ), array( $dawn, $noon, $dusk ) ), bigb_pattern_album( 2, __( 'Highlands', 'image-gallery' ), __( '24 photographs · Summer', 'image-gallery' ), array( $forest, $noon, $sand ) ), bigb_pattern_album( 3, __( 'After dark', 'image-gallery' ), __( '11 photographs · Autumn', 'image-gallery' ), array( $night, $dusk, $dawn ) ), ), 'columns' => array( 'desktop' => 3, 'tablet' => 2, 'mobile' => 1 ), 'itemHeight' => '420px', 'columnGap' => '24px', 'rowGap' => '32px', 'background' => array( 'type' => 'solid', 'color' => 'transparent' ), 'align' => 'wide', ) ), 'wide' ), ); /* Polaroid wall -------------------------------------------------------- */ $patterns['polaroid-wall'] = array( 'title' => __( 'Polaroid photo wall', 'image-gallery' ), 'description' => __( 'Six tilted Polaroid frames on a wall, each with a caption and a date, for a personal, scrapbook or team page.', 'image-gallery' ), 'keywords' => array( 'polaroid', 'wall', 'scrapbook', 'team', 'personal' ), 'content' => bigb_pattern_group( bigb_pattern_heading( __( 'A year on the wall', 'image-gallery' ) ) . bigb_pattern_paragraph( __( 'Six frames from the last twelve months. Click any one to open it full size.', 'image-gallery' ) ) . bigb_pattern_spacer( 24 ) . bigb_pattern_block( array( 'styleSl' => 'styleOne', // The Polaroid wall renders imagesData.images, not the // album list the default style uses. 'imagesData' => array( 'id' => 'polaroid', 'name' => __( 'Polaroid Style', 'image-gallery' ), 'showDate' => true, 'images' => array( bigb_pattern_polaroid( 'p1', $night, __( 'Cold light', 'image-gallery' ), __( 'The river before sunrise', 'image-gallery' ), '2026-01-14' ), bigb_pattern_polaroid( 'p2', $dawn, __( 'First warm week', 'image-gallery' ), __( 'Walked out at six for this one', 'image-gallery' ), '2026-04-02' ), bigb_pattern_polaroid( 'p3', $forest, __( 'Under the pines', 'image-gallery' ), __( 'Two hours in, no phone signal', 'image-gallery' ), '2026-05-23' ), bigb_pattern_polaroid( 'p4', $noon, __( 'Too bright to shoot', 'image-gallery' ), __( 'Shot it anyway', 'image-gallery' ), '2026-07-08' ), bigb_pattern_polaroid( 'p5', $sand, __( 'Everything gold', 'image-gallery' ), __( 'The last warm afternoon', 'image-gallery' ), '2026-10-19' ), bigb_pattern_polaroid( 'p6', $dusk, __( 'Blue hour', 'image-gallery' ), __( 'Twenty minutes, then gone', 'image-gallery' ), '2026-11-30' ), ), ), /* * The Polaroid wall takes its layout from styles, not from * the top-level columns / gap attributes: with styles.columns * unset the grid gets repeat(undefined, ...) and collapses * into a single column. */ 'styles' => array( 'columns' => array( 'desktop' => 3, 'tablet' => 2, 'mobile' => 1 ), 'card' => array( 'width' => array( 'desktop' => '17rem', 'tablet' => '16rem', 'mobile' => '100%' ), 'height' => array( 'desktop' => '230px', 'tablet' => '210px', 'mobile' => '240px' ), 'gap' => array( 'desktop' => '2.5rem', 'tablet' => '2rem', 'mobile' => '1.5rem' ), ), // The frames are tilted, so the wall needs room at the // edges or the corners clip against the group. 'container' => array( 'padding' => array( 'desktop' => '32px 16px', 'tablet' => '28px 12px', 'mobile' => '24px 8px' ), ), 'shadow' => array( array( 'hOffset' => '0px', 'vOffset' => '10px', 'blur' => '24px', 'spreed' => '-8px', 'color' => 'rgba(0,0,0,0.22)', 'isInset' => false ), ), 'hoverShadow' => array( array( 'hOffset' => '0px', 'vOffset' => '18px', 'blur' => '38px', 'spreed' => '-10px', 'color' => 'rgba(0,0,0,0.30)', 'isInset' => false ), ), /* * The caption sits on the frame's white card, so its * colour cannot be left to the theme — on a dark theme * it would inherit white and disappear. */ 'title' => array( 'color' => '#16181a' ), 'description' => array( 'color' => '#5b6167' ), 'date' => array( 'color' => '#8a9096' ), ), 'align' => 'wide', ) ), 'wide' ), ); /* Portfolio ------------------------------------------------------------ */ $patterns['portfolio-showcase'] = array( 'title' => __( 'Portfolio showcase', 'image-gallery' ), 'description' => __( 'Two large cards for a studio or agency, where each project gets room to breathe.', 'image-gallery' ), 'keywords' => array( 'portfolio', 'studio', 'agency', 'projects', 'case study' ), 'content' => bigb_pattern_group( bigb_pattern_heading( __( 'Selected projects', 'image-gallery' ) ) . bigb_pattern_spacer( 24 ) . bigb_pattern_block( array( 'styleSl' => 'styleDefault', 'gallery' => array( bigb_pattern_album( 1, __( 'Northwind', 'image-gallery' ), __( 'Brand identity · 2026', 'image-gallery' ), array( $dusk, $night, $dawn ) ), bigb_pattern_album( 2, __( 'Meridian', 'image-gallery' ), __( 'Packaging · 2025', 'image-gallery' ), array( $sand, $forest, $noon ) ), ), 'columns' => array( 'desktop' => 2, 'tablet' => 1, 'mobile' => 1 ), 'itemHeight' => '520px', 'columnGap' => '32px', 'rowGap' => '32px', 'titleTypo' => array( 'fontSize' => array( 'desktop' => 40, 'tablet' => 34, 'mobile' => 28 ) ), 'subtitleTypo' => array( 'fontSize' => array( 'desktop' => 18, 'tablet' => 16, 'mobile' => 15 ) ), 'background' => array( 'type' => 'solid', 'color' => 'transparent' ), 'align' => 'wide', ) ), 'wide' ), ); /* Product lookbook ----------------------------------------------------- */ $patterns['product-lookbook'] = array( 'title' => __( 'Product lookbook', 'image-gallery' ), 'description' => __( 'A denser four-column set with smaller cards, for a shop lookbook or catalogue page.', 'image-gallery' ), 'keywords' => array( 'lookbook', 'shop', 'product', 'catalogue', 'ecommerce' ), 'content' => bigb_pattern_group( bigb_pattern_heading( __( 'Autumn lookbook', 'image-gallery' ) ) . bigb_pattern_paragraph( __( 'Four ranges, photographed on location. Tap a card for the full set.', 'image-gallery' ) ) . bigb_pattern_spacer( 24 ) . bigb_pattern_block( array( 'styleSl' => 'styleDefault', 'gallery' => array( bigb_pattern_album( 1, __( 'Outerwear', 'image-gallery' ), __( '9 pieces', 'image-gallery' ), array( $dusk, $night ) ), bigb_pattern_album( 2, __( 'Knitwear', 'image-gallery' ), __( '12 pieces', 'image-gallery' ), array( $sand, $dawn ) ), bigb_pattern_album( 3, __( 'Denim', 'image-gallery' ), __( '7 pieces', 'image-gallery' ), array( $noon, $forest ) ), bigb_pattern_album( 4, __( 'Accessories', 'image-gallery' ), __( '15 pieces', 'image-gallery' ), array( $forest, $sand ) ), ), 'columns' => array( 'desktop' => 4, 'tablet' => 2, 'mobile' => 1 ), 'itemHeight' => '300px', 'columnGap' => '16px', 'rowGap' => '20px', 'titleTypo' => array( 'fontSize' => array( 'desktop' => 26, 'tablet' => 22, 'mobile' => 20 ) ), 'subtitleTypo' => array( 'fontSize' => array( 'desktop' => 15, 'tablet' => 14, 'mobile' => 14 ) ), 'background' => array( 'type' => 'solid', 'color' => 'transparent' ), 'align' => 'wide', ) ), 'wide' ), ); /* * Pattern search matches title, description and keywords — not the category * label. Someone who has just read "Image Galleries" in the category list * and types it into the search box would otherwise get nothing back. */ $base_keywords = array( __( 'gallery', 'image-gallery' ), __( 'image gallery', 'image-gallery' ), __( 'image galleries', 'image-gallery' ), __( 'photo gallery', 'image-gallery' ), ); foreach ( $patterns as $slug => $pattern ) { register_block_pattern( 'image-gallery/' . $slug, array( 'title' => $pattern['title'], 'description' => $pattern['description'], 'categories' => array( $category ), 'keywords' => array_values( array_unique( array_merge( $base_keywords, $pattern['keywords'] ) ) ), 'content' => $pattern['content'], ) ); } } /** * Late on init: register_block_pattern() silently drops a pattern whose blocks * are not registered yet, and the block registers on init at the default * priority. */ add_action( 'init', 'bigb_register_patterns', 20 );