- ID, $collection_url, $image_size ) ); ?>
+ ID, $image_permalink, $image_size ) );
+ ?>
@@ -211,16 +216,26 @@ protected static function render_collection( $collection, $attributes ) {
+
+
+
+
+
+
-
+
+
{
{ showCTAs && filteredCtas.length > 0 && (
) }
diff --git a/src/blocks/collections/styles/_ctas.scss b/src/blocks/collections/styles/_ctas.scss
index 28719fd810..4d02fe9ac7 100644
--- a/src/blocks/collections/styles/_ctas.scss
+++ b/src/blocks/collections/styles/_ctas.scss
@@ -4,6 +4,10 @@
display: flex;
flex-wrap: wrap;
gap: 8px;
+
+ a {
+ width: 100%;
+ }
}
// See all collections link.
diff --git a/src/blocks/collections/styles/_layout-grid.scss b/src/blocks/collections/styles/_layout-grid.scss
index 44b453c394..e4bf1cb654 100644
--- a/src/blocks/collections/styles/_layout-grid.scss
+++ b/src/blocks/collections/styles/_layout-grid.scss
@@ -56,6 +56,7 @@
.wp-block-newspack-collections__title {
margin: 24px 0 0;
+ font-size: var(--newspack-theme-font-size-base);
}
}
}
diff --git a/src/blocks/collections/styles/_layout-list.scss b/src/blocks/collections/styles/_layout-list.scss
index c6d44bd99b..ceb70ff03a 100644
--- a/src/blocks/collections/styles/_layout-list.scss
+++ b/src/blocks/collections/styles/_layout-list.scss
@@ -3,91 +3,169 @@
.wp-block-newspack-collections {
// Layout: List.
&.layout-list {
+ margin-bottom: 32px;
+
.wp-block-newspack-collections__item {
- display: flex;
+ display: grid;
+ grid-template-columns: 1fr;
+ gap: 16px;
margin-bottom: 2em;
align-items: flex-start;
&:last-child {
margin-bottom: 0;
}
- }
- &.image-left {
- .wp-block-newspack-collections__image {
- margin-right: 1.5em;
- flex-shrink: 0;
+ @media #{bp.$media-sm-up} {
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ }
+
+ @media #{bp.$media-lg-up} {
+ grid-template-columns: repeat(6, minmax(0, 1fr));
+ gap: 32px;
}
}
+ &.image-left,
&.image-right {
- .wp-block-newspack-collections__item {
- flex-direction: row-reverse;
+ // Small size (default).
+ &.image-size-small {
+ .wp-block-newspack-collections__image {
+ grid-column: span 1;
+ }
+
+ .wp-block-newspack-collections__content {
+ @media #{bp.$media-sm-up} {
+ grid-column: span 2;
+ }
+
+ @media #{bp.$media-lg-up} {
+ grid-column: span 5;
+ }
+ }
}
- .wp-block-newspack-collections__image {
- margin-left: 1.5em;
- flex-shrink: 0;
+ // Medium size - slightly larger image.
+ &.image-size-medium {
+ .wp-block-newspack-collections__image {
+ grid-column: span 1;
+
+ @media #{bp.$media-lg-up} {
+ grid-column: span 2;
+ }
+ }
+
+ .wp-block-newspack-collections__content {
+ @media #{bp.$media-sm-up} {
+ grid-column: span 2;
+ }
+
+ @media #{bp.$media-lg-up} {
+ grid-column: span 4;
+ }
+ }
+ }
+
+ // Large size - larger image.
+ &.image-size-large {
+ .wp-block-newspack-collections__image {
+ grid-column: span 1;
+
+ @media #{bp.$media-sm-up} {
+ grid-column: span 2;
+ }
+
+ @media #{bp.$media-lg-up} {
+ grid-column: span 3;
+ }
+ }
+
+ .wp-block-newspack-collections__content {
+ @media #{bp.$media-sm-up} {
+ grid-column: span 1;
+ }
+
+ @media #{bp.$media-lg-up} {
+ grid-column: span 3;
+ }
+ }
}
}
- // Image sizes for left and right alignments.
- &.image-left,
+ // For the right alignment, reorder the grid items.
&.image-right {
- @media #{bp.$media-sm-up} {
- &.image-size-small .wp-block-newspack-collections__image {
- width: 150px;
- }
- &.image-size-medium .wp-block-newspack-collections__image {
- width: 30%;
+ .wp-block-newspack-collections__item {
+ .wp-block-newspack-collections__image {
+ order: 2;
}
- &.image-size-large .wp-block-newspack-collections__image {
- width: 50%;
+ .wp-block-newspack-collections__content {
+ order: 1;
}
}
}
+ // For the top alignment, stack the grid items vertically.
&.image-top {
.wp-block-newspack-collections__item {
- flex-direction: column;
+ grid-template-columns: 1fr;
+ }
+
+ .wp-block-newspack-collections__image,
+ .wp-block-newspack-collections__content {
+ grid-column: span 1;
}
.wp-block-newspack-collections__image {
- margin-bottom: 1em;
+ max-width: 100%;
}
- // Image sizes for top alignment (sm+ only).
+ // Apply size constraints only on larger screens.
@media #{bp.$media-sm-up} {
&.image-size-small .wp-block-newspack-collections__image {
- width: 30%;
+ max-width: 30%;
}
&.image-size-medium .wp-block-newspack-collections__image {
- width: 50%;
+ max-width: 50%;
}
&.image-size-large .wp-block-newspack-collections__image {
- width: 70%;
+ max-width: 70%;
}
}
}
- // On extra-small screens, ignore image size presets; stack and use full width.
- @media #{bp.$media-xs-only} {
- // Ensure stacking wins over the more specific .image-right rule.
- &.image-right .wp-block-newspack-collections__item,
- .wp-block-newspack-collections__item {
- flex-direction: column;
+
+ .wp-block-newspack-collections__title {
+ font-size: var(--newspack-theme-font-size-lg);
+ margin: 0;
+
+ @media #{bp.$media-md-up} {
+ font-size: var(--newspack-theme-font-size-xl);
}
+ }
- &.image-left,
- &.image-right,
- &.image-top {
- .wp-block-newspack-collections__image {
- width: 100%;
- max-width: 100%;
- margin: 0 0 1em 0;
+ .wp-block-newspack-collections__content {
+ display: flex;
+ flex-direction: column;
+ gap: 0.5em;
+ }
+
+ .wp-block-newspack-collections__meta {
+ margin: 0;
+ p {
+ margin: 0;
+ }
+ }
+
+ .wp-block-newspack-collections__excerpt {
+ margin: 22px 0;
+ }
+
+ .wp-block-newspack-collections__ctas {
+ a {
+ @media #{bp.$media-md-up} {
+ width: auto;
}
}
}
}
}
-
diff --git a/src/blocks/collections/styles/_text.scss b/src/blocks/collections/styles/_text.scss
index 95699ac58b..db4e4f280d 100644
--- a/src/blocks/collections/styles/_text.scss
+++ b/src/blocks/collections/styles/_text.scss
@@ -1,4 +1,10 @@
.wp-block-newspack-collections {
+ // Collection heading.
+ .wp-block-newspack-collections__heading {
+ margin: 0;
+ text-transform: uppercase;
+ }
+
// Title.
.wp-block-newspack-collections__title {
margin: 0 0 24px;
@@ -12,7 +18,6 @@
.wp-block-newspack-collections__excerpt {
margin-bottom: 1em;
color: var(--wp--preset--font-size--small);
- line-height: 1.4;
}
// Meta information (Period, Volume, Number).
diff --git a/src/collections/frontend/_common.scss b/src/collections/frontend/_common.scss
index f6d30ef57f..603ab01fc3 100644
--- a/src/collections/frontend/_common.scss
+++ b/src/collections/frontend/_common.scss
@@ -41,17 +41,9 @@
}
}
-.collection-cta {
- width: 100%;
-
- &.cta--subscribe_link {
- a {
- background-color: var(--newspack-primary-color);
- color: var(--newspack-primary-contrast-color);
- }
- }
-
- @media #{breakpoints.$media-sm-up} {
- width: auto;
+.wp-block-newspack-collections__ctas {
+ a.cta--subscribe_link {
+ background-color: var(--newspack-primary-color);
+ color: var(--newspack-primary-contrast-color);
}
}
diff --git a/tests/unit-tests/collections/class-test-collections-block.php b/tests/unit-tests/collections/class-test-collections-block.php
index c131ae8059..6c33aa0db0 100644
--- a/tests/unit-tests/collections/class-test-collections-block.php
+++ b/tests/unit-tests/collections/class-test-collections-block.php
@@ -31,7 +31,7 @@ public function set_up() {
// Ensure the block is registered.
require_once NEWSPACK_ABSPATH . 'src/blocks/collections/index.php';
-
+
if ( ! \WP_Block_Type_Registry::get_instance()->is_registered( Collections_Block::BLOCK_NAME ) ) {
Collections_Block::register_block();
}
@@ -144,6 +144,47 @@ public function test_render_block_with_default_see_all_link() {
$this->assertStringContainsString( 'See all', $output, 'Should contain default see all text' );
}
+ /**
+ * Test numberOfCTAs attribute handles -1 correctly for showing all CTAs.
+ *
+ * @covers \Newspack\Blocks\Collections\Collections_Block::render_block
+ * @covers \Newspack\Blocks\Collections\Collections_Block::render_collection_ctas
+ * @covers \Newspack\Collections\Template_Helper::render_cta
+ */
+ public function test_render_block_with_all_ctas() {
+ $collection_id = $this->create_test_collection();
+
+ // Create multiple CTAs using a loop.
+ $ctas_data = [];
+ $total_ctas = 5;
+ for ( $i = 1; $i <= $total_ctas; $i++ ) {
+ $ctas_data[] = [
+ 'type' => 'link',
+ 'label' => "CTA $i",
+ 'url' => "https://example.com/$i",
+ ];
+ }
+ Collection_Meta::set( $collection_id, 'ctas', $ctas_data );
+
+ $attributes = [
+ 'selectedCollections' => [ $collection_id ],
+ 'numberOfCTAs' => -1,
+ 'showCTAs' => true,
+ 'showSeeAllLink' => false,
+ ];
+
+ $output = $this->render_collections_block( $attributes );
+
+ // When numberOfCTAs is -1, all CTAs should be displayed.
+ for ( $i = 1; $i <= $total_ctas; $i++ ) {
+ $this->assertStringContainsString( "CTA $i", $output );
+ }
+
+ // Count CTA elements to verify total count.
+ $cta_count = substr_count( $output, 'wp-block-button__link' );
+ $this->assertEquals( $total_ctas, $cta_count, "Should render all $total_ctas CTAs when numberOfCTAs is -1" );
+ }
+
/**
* Test get_block_classes method.
*
diff --git a/tests/unit-tests/collections/class-test-template-helper.php b/tests/unit-tests/collections/class-test-template-helper.php
index ed34c824ba..83f374dcd8 100644
--- a/tests/unit-tests/collections/class-test-template-helper.php
+++ b/tests/unit-tests/collections/class-test-template-helper.php
@@ -260,12 +260,6 @@ public function test_render_see_all_link() {
* @covers \Newspack\Collections\Template_Helper::load_template_part
*/
public function test_load_template_part() {
- ob_start();
- Template_Helper::load_template_part( Template_Helper::TEMPLATE_PARTS_DIR . 'newspack-collection-intro', null, [], [] );
- $output = ob_get_clean();
- $this->assertNotEmpty( $output, 'Collections template part should be processed.' );
- $this->assertStringContainsString( 'collection-intro', $output, 'Collections template part should contain "collection-intro".' );
-
// Test collections template part with name parameter.
ob_start();
Template_Helper::load_template_part( Template_Helper::TEMPLATE_PARTS_DIR . 'newspack-collection-intro', 'variant', [], [] );
@@ -369,4 +363,21 @@ public function test_normalize_post_list() {
$this->assertEquals( 'ids', $result['type'] );
$this->assertEquals( [ $post_id_1, 1 ], $result['items'] ); // 0 filtered out, -1 becomes 1.
}
+
+ /**
+ * Test render_collections_intro generates collections block HTML.
+ *
+ * @covers \Newspack\Collections\Template_Helper::render_collections_intro
+ */
+ public function test_render_collections_intro() {
+ $collection = get_post( $this->create_test_collection() );
+
+ // Test basic rendering.
+ $html = Template_Helper::render_collections_intro( $collection );
+ $this->assertIsString( $html, 'Intro HTML should be a string.' );
+
+ // Test with invalid collection.
+ $html = Template_Helper::render_collections_intro( null );
+ $this->assertEmpty( $html, 'Invalid collection should return empty string.' );
+ }
}