Components
41
Accordion Block Benifits Grid Block 404 Card Stack Careers Grid Case Study Carousel Case Study Hero Content Columns Content Image Content Image Accordion Content Video Cta Block Example Featured Blog Hero Featured Resource Hero Form Cta Form Hero Full Width Image Homepage Hero Hover List Image Hero Image Mask Image Testimonial Carousel Industry Insights Latest News List Columns Logo Scroller Map Block Post Feed Resource Grid Split Hero Split Text Statement Statistics Row Team Filter Team Grid Testimonial Carousel Testimonial Carousel Text Highlight Tools Grid Two Column List

Post Feed

View example
942 Blogs
There are no ACF fields assigned to this component.

				
@import "../../resources/scss/util/variables";
@import "../../resources/scss/util/mixins";
@import "../../resources/scss/vendor/bootstrap/vendor/rfs";

.block-post-feed{
    @include padding-top(rem-calc(60));
    @include padding-bottom(rem-calc(60));
    position: relative;

    &:before {
        content: '';
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        opacity: 0;
        background-color: $white;
        z-index: 10;
        transition: opacity 0.25s ease-in-out;
        pointer-events: none;
    }

    &__items{
        display: grid;
        gap: rem-calc(10);
        grid-template-columns: 1fr; 
        @include margin-bottom(rem-calc(40));

        @include bp($md) {
            grid-template-columns: 1fr 1fr;
            @include margin-bottom(rem-calc(60));
        }

        @include bp($lg) {
            grid-template-columns: 1fr 1fr 1fr;
        }

        @include bp($xl) {
            grid-template-columns: 1fr 1fr 1fr 1fr;
        }
    }

    .post-card{
        overflow: hidden;
        &:nth-child(2n){
            --post-card-bg: var(--tertiary);
        }

        &--featured{
            min-height: rem-calc(420);
            transition: 0.3s ease-in all;

            @include bp($md) {
                grid-column: 1 / span 2;
            }

            .post-card__tags {
                top: rem-calc(10);
                left: rem-calc(10);

                @include bp($md) {
                    top: rem-calc(16);
                    left: rem-calc(16);
                }
            }

            .image-wrapper{
                width: 100%;
                height: 100%;
                position: absolute !important;
                top: 0;
                left: 0;
            }

            @media (hover: hover) and (pointer: fine){
                &:hover{

                    box-shadow: 0px 16px 34px 0px rgba(0, 0, 0, 0.25);
                    transform: translateY(-5px);

                    .image-wrapper{
                        &::after{
                            opacity: 1;
                        }
                    }
                }
            }
        }

        .image-wrapper{
            opacity: 1;
            transition: 0.3s ease opacity;
            position: relative;
            overflow: hidden;

            &:after{
                content: "";
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                opacity: 0;
                background-color: rgba(0,0,0,0.6);
                transition: 0.3s all ease;
            }
        }

        .image-wrapper-hover{
            opacity: 0;
            transition: 0.3s ease opacity;
            position: absolute;
            width: 100%;
            height: 100%;
            top: 0;
            left: 0;

            &:after{
                content: "";
                position: absolute;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                opacity: 1;
                background-color: rgba(0,0,0,0.6);
                transition: 0.3s all ease;
            }
        }

        &__tags {
            top: rem-calc(24);
            left: rem-calc(24);
        }

        &--standard{

            .post-card__tags {
                top: 1.25rem;
                left: 1.25rem;
            }

            @media (hover: hover) and (pointer: fine){
                transition: 0.3s ease-in all;
                &:hover{
                    box-shadow: 0px 16px 34px 0px rgba(0, 0, 0, 0.25);
                    transform: translateY(-5px);
                }
            }
        }
    }

    &.loading {
        &:before {
            opacity: 0.75;
            pointer-events: all;
        }

        &:after {
            content: '';
            position: absolute;
            top: 20%;
            left: calc(50% - 50px);
            width: 100px;
            height: 100px;
            animation: spin 1s linear infinite;
            border: 8px solid;
            border-color: color-mix(in srgb, var(--primary) 10%, transparent);
            border-top-color: var(--primary);
            border-radius: 50%;
            z-index: 20;
        }
    }

    .sort-by-wrap{
        width: 100%;
    }

    select[data-sort-by],
    select[data-filter-by]{
        border-radius: 60px;
        border: 1px solid rgba(0,0,0,0.2);
        width: 100%;
        min-height: rem-calc(44);
        background-size: rem-calc(8);
        font-size: rem-calc(16);
        cursor: pointer;
        padding:rem-calc(10) rem-calc(40) rem-calc(10) rem-calc(20);

        @include bp($md){
            width: rem-calc(200);
        }

        @include bp($lg){
            font-size: rem-calc(18);
        }
    }

    .mobile-filter{
        @include bp($lg){
            display: none;
        }
    }

    .filter-wrapper{
        display: block;
        position: relative;
        border-radius: 60px;
        border: 1px solid rgba(0,0,0,0.2);
        display:none;

        @include bp($lg){
            max-width: 100%;
            overflow-x: auto;
            white-space: nowrap;
            padding: 0 1px;
            display:block;

            &::-webkit-scrollbar {
                height: 5px;
                margin-top: 4px;
            }

            &::-webkit-scrollbar-track {
                background: transparent;
                margin: 10px 20px 0;
            }

            &::-webkit-scrollbar-thumb {
                background: #bbb;
                border-radius: 10px;
            }

            &::-webkit-scrollbar-thumb:hover {
                background: #999;
            }
        }
    }

    .filter-container{
        display: none;
        @include bp($lg){

            display: inline-flex;
            gap: 8px;
            padding-right: 4px;

            .filter{
                border-radius: 60px;
                font-size: rem-calc(18px);
                line-height: 1.5;
                background-color: $white;
                @include padding(rem-calc(8 18));
                text-decoration: none;
                flex-shrink: 0;
                margin-top: 4px;
                margin-left: 4px;

                &.active{
                    background-color: $grey-primary;
                }
            }
        }
    }    
}

@keyframes spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}
class PostFeedBlock {
    /**
	 * Create and initialise objects of this class
	 * @param {HTMLElement} block
	 */

    constructor(block) {
        this.block = block;
        this.postsContainer = this.block.querySelector('.results');
        this.countElement = this.block.querySelector('.post-feed-count');
        this.sortBy = this.block.querySelector('select[data-sort-by]'); 
        this.postType = this.block.dataset.postType;
        this.featuredId = this.block.dataset.featured;
        this.perPage = parseInt(this.block.dataset.perPage);
        this.taxonomy = this.block.dataset.taxonomy;
        this.filterCategory = false;
        this.orderBy = this.block.dataset.orderby;
        this.sortOrder = this.block.dataset.order;
        this.currentPage = 1;
		this.init();
    }

    init() {
        this.setupPagination();
        this.setupSorting();
        this.setupFilters();
    }

    

    setupPagination() {
        const pagination = this.block.querySelector('.pagination');

        if (!pagination) {
            return;
        }

        const paginationLinks = pagination.querySelectorAll('a');
        paginationLinks.forEach(link => {
            link.addEventListener('click', (e) => {
                e.preventDefault();

                // Get page
                let page = link.innerText;
                if (link.dataset.page) {
                    page = link.dataset.page;
                }

                if (!page) {
                    return;
                }
                if (page && page !== this.currentPage) {
                    this.currentPage = page;
                    this.fetchResults();
                }                
            });
        });
    }

    setupFilters() {
        const filters = this.block.querySelectorAll('select[data-filter-by]');
        const filtersLinks = this.block.querySelectorAll('.filter');
        
        if (filters) {
            filters.forEach(filter => {
                filter.addEventListener('change', (e) => {
                    const filterValue = filter.value;

                    if (!filterValue || filterValue === 'all') {
                        this.filterCategory = false;
                    } else {
                        this.filterCategory = filterValue;
                    }

                    this.currentPage = 1;
                    this.fetchResults();
                });
            });
        }

        if (filtersLinks) {
            filtersLinks.forEach(filterItem => {
                filterItem.addEventListener('click', (e) => {
                    if(!filterItem.classList.contains('active')){
                        filtersLinks.forEach(fitem=>{
                            fitem.classList.remove('active');
                        });
                    }
                    
                    const filterValue = filterItem.dataset.value;
                    filterItem.classList.add('active');
                    if (!filterValue || filterValue === 'all') {
                        this.filterCategory = false;
                    } else {
                        this.filterCategory = filterValue;
                    }

                    this.currentPage = 1;
                    this.fetchResults();
                });
            });
        }
    }

    setupSorting() {
        const sortSelect = this.sortBy;
        if (!sortSelect) return;

        sortSelect.addEventListener('change', () => {
            const val = sortSelect.value;

            if (!val) {
                this.feedSorting = {};
            } else {
                const [orderby, order] = val.split('_');
                this.orderBy=orderby;
                this.sortOrder=order;
            }
            this.fetchResults();
        });
    }

    async fetchResults() {
        this.block.classList.add('loading');
        try {
			const formData = new FormData();
			formData.append('action', 'load_post_feeds');
			formData.append('nonce', postFeed.nonce);
			formData.append('post_type', this.postType);
			formData.append('posts_per_page', this.perPage);
			formData.append('paged', this.currentPage);
			formData.append('orderby', this.orderBy);
			formData.append('order', this.sortOrder);
			formData.append('origin',postFeed.baseURL);
            formData.append('featured',this.featuredId);
            
			// Add category filter if selected
			if (this.filterCategory) {
                formData.append('taxonomy', this.taxonomy);
				formData.append('category', this.filterCategory);
			}

			const response = await fetch(postFeed.ajaxurl, {
				method: 'POST',
				credentials: 'same-origin',
				body: formData,
			});

			const data = await response.json();

			if (data.success) {
				this.totalPages = data.data.total_pages;
				this.updateResults(data.data);
                this.updatePagination(data.data.pagination);
				this.updateCount(data.data.found_posts);
			} else {
                this.updatePagination(false);
				this.showError(data.data.message || 'Error loading posts');
			}

		} catch (error) {
			this.showError('Error loading posts. Please try again.');
		} finally {
            this.block.classList.remove('loading');
		}
    }

    updateResults(data){
        if (!this.postsContainer) return;
        this.postsContainer.innerHTML = data.results;        
    }

    updateCount(count){
        if (!this.countElement) return;
        const countText = count === 1 ? 'Resource' : 'Resources';
        this.countElement.textContent = `${count} ${countText}`;
    }

    updatePagination(pagination){
        const paginationElem = this.block.querySelector('.pagination');
        if (!paginationElem) {
            return;
        }

        // if no pagination, remove pagination
        if (!pagination) {
            paginationElem.innerHTML = '';
            return;
        }

        // replace pagination
        paginationElem.outerHTML = pagination;

        // Reregister events
        this.setupPagination();
    } 
    
    showError(message = 'Sorry, there was an error loading posts. Please try again.') {
		if (!this.postsContainer) return;
		this.postsContainer.innerHTML = `
			

${message}

`; } } document.addEventListener('DOMContentLoaded', () => { document.querySelectorAll('.block-post-feed').forEach(block => new PostFeedBlock(block)); });
{
    "$schema": "https://schemas.wp.org/trunk/block.json",
    "apiVersion": 2,
    "name": "strategiq/post-feed",
    "title": "Post Feed",
    "description": "Example block to be used as a template",
    "category": "strategiq",
    "icon": "strategiq",
    "acf": {
        "mode": "preview",
        "renderTemplate": "block-post-feed.php"
    },
    "supports": {
        "anchor": true,
        "align": false,
        "color": {
            "background": true,
            "text": false,
            "gradients": true
        },
        "spacing": {
            "padding": [
                "top",
                "bottom"
            ],
            "margin": [
                "top",
                "bottom"
            ]
        }
    },
    "style": ["file:../../assets/css/post-feed/block-post-feed.css", "base-blog"],
    "viewScript": ["post-feed"]
}
Page Title
Page Type
Page URL
There are is no readme file with this component.