Components
53
Accordion Items Article Selection Author Info Basic Carousel Basic Hero Basic Map Blog Pull Out Carousel Carousel Contact Content Accordion Content Carousel Content Image Cta Cta Bar Cta Blocks Cta Collage Event Content Events Grid Example Find Firm Firm Search Firms By Town Gated Content Download Guides Carousel Hero History Homepage Hero Image Content Cta Image List Content Industries Job Content Job Listings Local Firm Carousel Our Firms Pages Carousel Partners Partners Slider People Listing Post Carousel Post Feed Pullquote Section Wrap Service List Split Content Stats Tax Guides Team Grid Title Logos Two Column Video Video Carousel Video Old

Service List

Field
Field Type
Field Name
Instructions
Heading
text
heading
Services
repeater
services
-- Service
text
service
-- Content
wysiwyg
content
-- Content Selection
select
content_selection
-- Service Links
repeater
service_links
---- Link
link
link
---- Lede
textarea
lede
---- Image Type
select
image_type
---- Icon
clone
icon
---- Image
image
image
-- Services
post_object
services
-- Allow featured images
true_false
allow_featured_images

				
 @import "../../resources/scss/util/variables";
@import "../../resources/scss/util/mixins";

.block-service-list {
  p {
    line-height: 1.5;
  }

  &__sidebar {
		@include section-sidebar;
	}

  &__tabs {
    margin: 0;
    position: sticky;
    top: 0;
    background-color: $white;
    z-index: 1;

    ul {
      @include list-unstyled;
      display: flex;
      flex-wrap: nowrap;
      align-items: center;
      overflow-x: auto;
      -ms-overflow-style: none;
      scrollbar-width: none;
      margin: 0;
      scroll-behavior: smooth;

      @include bp($lg) {
        padding: 0 80px 0 83px;
      }

      &::-webkit-scrollbar {
        display: none;
      }

      &:after {
        content: "";
        width: 100%;
        bottom: 0;
        right: 0;
        position: absolute;
        height: 1px;
        background-color: $border-grey;

        @include bp($lg) {
          width: calc(100% - 83px);
        }
      }
    }

    li {
      @include fluid-type(16, 18, 375, $max-container-size);
      flex-shrink: 0;
      padding: 20px 24px;
      white-space: nowrap;
      cursor: pointer;
      border-right: 1px solid $border-grey;

      &:not(.current):hover {
        background-color: #f2f2f2;
      }

      &.current {
        font-weight: 600;
        background-color: $primary-blue;
        color: $white;
      }
    }
  }

  &__content {
    & > section {
      display: none;
      padding-left: 16px;
      padding-right: 16px;
      grid-template-columns: repeat(12, 1fr);
      column-gap: $grid-gutter-width;

      @include bp($lg) {
        padding-left: 80px;
        padding-right: 80px;
      }

      &.current {
        display: grid;
      }

      & > div {
        &:nth-of-type(1) {
          grid-row: 1;
          grid-column: 1 / 13;
          padding: 25px 0 45px;

          @include bp($lg) {
            grid-column: 1 / 5;
            padding: 75px 0;
          }

          @include bp($xl) {
            grid-column: 2 / 6;
          }

          & > div {
            position: sticky;
            top: 105px;
          }
        }

        &:nth-of-type(2) {
          grid-row: 2;
          grid-column: 1 / 13;

          @include bp($lg) {
            grid-row: 1;
            grid-column: 6 / 13;
          }

          @include bp($xl) {
            grid-column: 7 / 13;
          }
        }
      }

      .h4 {
        font-weight: 400;

        & + p {
          margin-bottom: 28px;
        }
      }

      .btn {
        @include fluid-type(16, 18, 375, $max-container-size);
        border-color: $primary;

        &:before {
          border-top: 52px solid $primary;
        }
      }
    }
  }

  &__links {
    @include list-unstyled;
    margin: 0;
    display: flex;
    flex-direction: column;
    row-gap: 16px;

    @include bp($lg) {
      padding-top: 60px;
    }

    a {
      display: flex;
      align-items: flex-start;
      flex-direction: column;
      position: relative;
      border: 1px solid $border-grey;
      text-decoration: none;
      transition: background-color .3s;
      row-gap: 20px;
			min-height: 150px;

      @include bp($sm) {
        flex-direction: row;
				align-items: center;
      }

      &:hover {
        background-color: #f2f2f2;
      }

      & > span {
        height: 100%;
				padding: 0 24px 32px;

				@include bp($sm) {
					padding: 24px 24px 32px;
				}

				@include bp($lg) {
					padding: clamp(24px, 2vw, 35px);
				}
      }

      h5 {
        margin: 0 0 12px;
      }

      p {
        margin: 0;
      }
    }

		&-link--image {
			@include bp($sm) {
				padding-left: 150px;
			}
		}

		&-link-icon {
			padding: 24px 24px 0;

			@include bp($sm) {
				padding: 24px 24px 32px;
			}

			@include bp($lg) {
        padding: clamp(24px, 2vw, 35px);
      }

			svg {
				width: 80px;
				height: 80px;
				flex-shrink: 0;
			}
		}

		&-link-image {
			width: 100%;
			position: relative;
			height: 150px;

			@include bp($sm) {
				position: absolute;
				width: 150px;
				height: 100%;
			}
		}

  }
}
class ServiceList {
  constructor() {
    this.init();
  }

  init() {
    // Find all service-list blocks on the page
    this.blocks = document.querySelectorAll('.block-service-list');

    if (!this.blocks.length) return;

    // Set up tab click handlers
    this.setupTabClickHandlers();
  }

  setupTabClickHandlers() {
    this.blocks.forEach(block => {
      const tabs = block.querySelectorAll('.tab-link');
      const tabContents = block.querySelectorAll('.tab-content');

      tabs.forEach(tab => {
        tab.addEventListener('click', () => {
          // Remove current class from all tabs and contents
          tabs.forEach(t => t.classList.remove('current'));
          tabContents.forEach(c => c.classList.remove('current'));

          // Add current class to clicked tab
          tab.classList.add('current');

          // Scroll the selected tab into view (at the start of the container)
          const tabsContainer = block.querySelector('.block-service-list__tabs ul');
          if (tabsContainer) {
            tabsContainer.scrollLeft = tab.offsetLeft;
          }

          // Show the corresponding tab content
          const tabId = tab.getAttribute('data-tab');
          const tabContent = block.querySelector(`#${tabId}`);
          if (tabContent) {
            tabContent.classList.add('current');
          }
        });
      });
    });
  }
}

// Initialize the service list functionality when the DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
  new ServiceList();
});
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 2,
  "name": "strategiq/service-list",
  "title": "Service List",
  "description": "Example block to be used as a template",
  "category": "strategiq",
  "icon": "strategiq",
  "acf": {
      "mode": "preview",
      "renderTemplate": "block-service-list.php"
  },
  "supports": {
      "anchor": true,
      "align": false,
      "spacing": {
          "margin": [
              "top",
              "bottom"
          ],
          "padding": [
              "top",
              "bottom"
          ]
      }
  },
  "example": {
      "attributes": {
          "mode": "preview",
          "data": {
              "heading_type": "h2",
              "heading_text": "Example - Service List",
              "content": "This is some example content to represent what the content will look like"
          }
      }
  },
  "style": "file:../../assets/css/service-list/block-service-list.css",
  "viewScript": ["service-list"]
}
This component is not currently used on any pages.
There are is no readme file with this component.