├── .node-version ├── .prettierignore ├── src ├── css │ ├── generic │ │ ├── _reset.css │ │ └── _normalize.css │ ├── elements │ │ ├── _tables.css │ │ ├── _buttons.css │ │ ├── _typography.css │ │ └── _forms.css │ ├── objects │ │ ├── _containers-dnd.css │ │ └── _layout.css │ ├── utilities │ │ └── _helper.css │ ├── main.css │ ├── tools │ │ └── _macros.css │ ├── templates │ │ ├── blog.css │ │ └── system.css │ └── components │ │ └── _default-modules.css ├── images │ ├── email.png │ ├── phone.png │ ├── location.png │ ├── team-image.jpg │ ├── grayscale-mountain.png │ ├── template-previews │ │ ├── 404.png │ │ ├── 500.png │ │ ├── about.png │ │ ├── home.png │ │ ├── hubdb.png │ │ ├── contact.png │ │ ├── pricing.png │ │ ├── blog-index.png │ │ ├── blog-post.png │ │ ├── landing-page.png │ │ ├── membership-login.png │ │ ├── password-prompt.png │ │ ├── search-results.png │ │ ├── backup-unsubscribe.png │ │ ├── membership-register.png │ │ ├── membership-reset-password.png │ │ ├── subscription-preferences.png │ │ ├── subscriptions-confirmation.png │ │ └── membership-reset-password-request.png │ ├── large-placeholder-image.png │ ├── section-previews │ │ ├── cards.png │ │ ├── pricing.png │ │ ├── hero-banner.png │ │ ├── call-to-action.png │ │ ├── multi-row-content.png │ │ └── multi-column-content.png │ └── module-icons │ │ ├── blog.svg │ │ ├── cta.svg │ │ ├── table.svg │ │ ├── social.svg │ │ ├── info-circle-solid.svg │ │ ├── menu.svg │ │ └── ellipses.svg ├── modules │ ├── button.module │ │ ├── meta.json │ │ ├── module.html │ │ └── fields.json │ ├── card.module │ │ ├── meta.json │ │ ├── module.css │ │ ├── module.html │ │ └── fields.json │ ├── pricing-card.module │ │ ├── meta.json │ │ ├── module.css │ │ ├── fields.json │ │ └── module.html │ ├── menu.module │ │ ├── meta.json │ │ ├── fields.json │ │ ├── module.js │ │ ├── module.html │ │ └── module.css │ └── social-follow.module │ │ ├── meta.json │ │ ├── module.css │ │ ├── module.html │ │ └── fields.json ├── license.txt ├── templates │ ├── contact.html │ ├── pricing.html │ ├── system │ │ ├── subscription-preferences.html │ │ ├── backup-unsubscribe.html │ │ ├── subscriptions-confirmation.html │ │ ├── 500.html │ │ ├── password-prompt.html │ │ ├── 404.html │ │ ├── membership-reset-password.html │ │ ├── membership-reset-password-request.html │ │ ├── membership-register.html │ │ ├── membership-login.html │ │ └── search-results.html │ ├── partials │ │ ├── header-no-navigation.html │ │ ├── footer.html │ │ └── header.html │ ├── landing-page.html │ ├── about.html │ ├── blog-index.html │ ├── home.html │ ├── layouts │ │ └── base.html │ ├── blog-post.html │ └── hubdb.html ├── theme.json ├── sections │ ├── multi-row-content.html │ ├── hero-banner.html │ ├── call-to-action.html │ ├── cards.html │ ├── pricing.html │ └── multi-column-content.html └── js │ └── main.js ├── prettier.config.js ├── .github ├── workflows │ ├── lint.yml │ └── deploy.yml ├── pull_request_template.md └── ISSUE_TEMPLATE │ ├── feature-request.md │ └── bug-report.md ├── .vscode └── extensions.json ├── LICENSE ├── package.json ├── .gitignore ├── CONTRIBUTING.md ├── README.md └── .eslintrc.js /.node-version: -------------------------------------------------------------------------------- 1 | 14.17.0 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.css 3 | -------------------------------------------------------------------------------- /src/css/generic/_reset.css: -------------------------------------------------------------------------------- 1 | *, *:before, *:after { 2 | box-sizing: border-box; 3 | } 4 | -------------------------------------------------------------------------------- /src/images/email.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/email.png -------------------------------------------------------------------------------- /src/images/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/phone.png -------------------------------------------------------------------------------- /src/images/location.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/location.png -------------------------------------------------------------------------------- /src/images/team-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/team-image.jpg -------------------------------------------------------------------------------- /src/images/grayscale-mountain.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/grayscale-mountain.png -------------------------------------------------------------------------------- /src/images/template-previews/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/404.png -------------------------------------------------------------------------------- /src/images/template-previews/500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/500.png -------------------------------------------------------------------------------- /src/images/large-placeholder-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/large-placeholder-image.png -------------------------------------------------------------------------------- /src/images/section-previews/cards.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/cards.png -------------------------------------------------------------------------------- /src/images/section-previews/pricing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/pricing.png -------------------------------------------------------------------------------- /src/images/template-previews/about.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/about.png -------------------------------------------------------------------------------- /src/images/template-previews/home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/home.png -------------------------------------------------------------------------------- /src/images/template-previews/hubdb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/hubdb.png -------------------------------------------------------------------------------- /src/images/template-previews/contact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/contact.png -------------------------------------------------------------------------------- /src/images/template-previews/pricing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/pricing.png -------------------------------------------------------------------------------- /src/images/section-previews/hero-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/hero-banner.png -------------------------------------------------------------------------------- /src/images/template-previews/blog-index.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/blog-index.png -------------------------------------------------------------------------------- /src/images/template-previews/blog-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/blog-post.png -------------------------------------------------------------------------------- /src/images/section-previews/call-to-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/call-to-action.png -------------------------------------------------------------------------------- /src/images/template-previews/landing-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/landing-page.png -------------------------------------------------------------------------------- /src/images/section-previews/multi-row-content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/multi-row-content.png -------------------------------------------------------------------------------- /src/images/template-previews/membership-login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/membership-login.png -------------------------------------------------------------------------------- /src/images/template-previews/password-prompt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/password-prompt.png -------------------------------------------------------------------------------- /src/images/template-previews/search-results.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/search-results.png -------------------------------------------------------------------------------- /src/images/template-previews/backup-unsubscribe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/backup-unsubscribe.png -------------------------------------------------------------------------------- /src/images/section-previews/multi-column-content.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/section-previews/multi-column-content.png -------------------------------------------------------------------------------- /src/images/template-previews/membership-register.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/membership-register.png -------------------------------------------------------------------------------- /src/images/template-previews/membership-reset-password.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/membership-reset-password.png -------------------------------------------------------------------------------- /src/images/template-previews/subscription-preferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/subscription-preferences.png -------------------------------------------------------------------------------- /src/images/template-previews/subscriptions-confirmation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/subscriptions-confirmation.png -------------------------------------------------------------------------------- /src/images/template-previews/membership-reset-password-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HubSpot/cms-theme-boilerplate/main/src/images/template-previews/membership-reset-password-request.png -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: true, 3 | jsxBracketSameLine: false, 4 | printWidth: 80, 5 | proseWrap: 'never', 6 | semi: true, 7 | singleQuote: true, 8 | tabWidth: 2, 9 | trailingComma: 'es5', 10 | useTabs: false, 11 | }; 12 | -------------------------------------------------------------------------------- /src/images/module-icons/blog.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/css/elements/_tables.css: -------------------------------------------------------------------------------- 1 | /* Table */ 2 | 3 | table { 4 | border-collapse: collapse; 5 | margin-bottom: 1.4rem; 6 | overflow-wrap: break-word; 7 | } 8 | 9 | /* Table cells */ 10 | 11 | td, 12 | th { 13 | vertical-align: top; 14 | } 15 | 16 | /* Table header */ 17 | 18 | thead th { 19 | vertical-align: bottom; 20 | } 21 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | on: [push] 2 | 3 | jobs: 4 | lint: 5 | runs-on: ubuntu-latest 6 | 7 | steps: 8 | - uses: actions/checkout@v1 9 | - name: Use Node.js 10 | uses: actions/setup-node@v1 11 | with: 12 | node-version: 14.x 13 | - name: Install NPM deps 14 | run: | 15 | npm install 16 | - name: Lint 17 | run: | 18 | npm run eslint 19 | -------------------------------------------------------------------------------- /src/modules/button.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Button", 3 | "css_assets": [], 4 | "external_js": [], 5 | "global": false, 6 | "host_template_types": ["PAGE"], 7 | "icon": "../../images/module-icons/cta.svg", 8 | "js_assets": [], 9 | "other_assets": [], 10 | "smart_type": "NOT_SMART", 11 | "tags": [], 12 | "is_available_for_new_content": true, 13 | "categories": [ 14 | "forms_and_buttons" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/card.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Card", 3 | "css_assets": [], 4 | "external_js": [], 5 | "global": false, 6 | "host_template_types": ["PAGE"], 7 | "icon": "../../images/module-icons/info-circle-solid.svg", 8 | "js_assets": [], 9 | "other_assets": [], 10 | "smart_type": "NOT_SMART", 11 | "tags": [], 12 | "is_available_for_new_content": true, 13 | "categories": [ 14 | "body_content" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/pricing-card.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Pricing card", 3 | "css_assets": [], 4 | "external_js": [], 5 | "global": false, 6 | "host_template_types": ["PAGE"], 7 | "icon": "../../images/module-icons/table.svg", 8 | "js_assets": [], 9 | "other_assets": [], 10 | "smart_type": "NOT_SMART", 11 | "tags": [], 12 | "is_available_for_new_content": true, 13 | "categories": [ 14 | "commerce" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/css/objects/_containers-dnd.css: -------------------------------------------------------------------------------- 1 | .content-wrapper { 2 | margin: 0 auto; 3 | padding: 0 1rem; 4 | } 5 | 6 | @media screen and (min-width: 1380px) { 7 | .content-wrapper { 8 | padding: 0; 9 | } 10 | } 11 | 12 | .dnd-section > .row-fluid { 13 | margin: 0 auto; 14 | } 15 | 16 | .dnd-section .dnd-column { 17 | padding: 0 1rem; 18 | } 19 | 20 | @media (max-width: 767px) { 21 | .dnd-section .dnd-column { 22 | padding: 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/modules/menu.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Menu", 3 | "css_assets": [], 4 | "external_js": [], 5 | "global": false, 6 | "host_template_types": ["PAGE", "BLOG_POST", "BLOG_LISTING"], 7 | "icon": "../../images/module-icons/menu.svg", 8 | "js_assets": [], 9 | "other_assets": [], 10 | "smart_type": "NOT_SMART", 11 | "tags": [], 12 | "is_available_for_new_content": true, 13 | "categories": [ 14 | "functionality" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/modules/social-follow.module/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Social follow", 3 | "css_assets": [], 4 | "external_js": [], 5 | "global": false, 6 | "host_template_types": ["PAGE", "BLOG_POST", "BLOG_LISTING"], 7 | "icon": "../../images/module-icons/social.svg", 8 | "js_assets": [], 9 | "other_assets": [], 10 | "smart_type": "NOT_SMART", 11 | "tags": [], 12 | "is_available_for_new_content": true, 13 | "categories": [ 14 | "social" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /src/images/module-icons/cta.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/license.txt: -------------------------------------------------------------------------------- 1 | Add the license for your theme here. 2 | 3 | To add a license to your theme you can either use a valid SPDX identifier (https://spdx.org/licenses/) for the license property in your theme.json file or you can update this file with your license as the license property in theme.json is already using the relative path option to link to this license file. For more information on the license property please reference this article (https://developers.hubspot.com/docs/cms/building-blocks/themes#theme-json). -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations. 3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp 4 | 5 | // List of extensions which should be recommended for users of this workspace. 6 | "recommendations": [ 7 | "hubspot.hubl" 8 | ], 9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace. 10 | "unwantedRecommendations": [ 11 | 12 | ] 13 | } -------------------------------------------------------------------------------- /src/templates/contact.html: -------------------------------------------------------------------------------- 1 | 7 | {% extends "./layouts/base.html" %} 8 | 9 | {% block body %} 10 | {% dnd_area "dnd_area" 11 | label="Main section", 12 | class="body-container body-container--contact" 13 | %} 14 | 15 | {# Cards #} 16 | 17 | {% include_dnd_partial path="../sections/cards.html" %} 18 | 19 | {% end_dnd_area %} 20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /src/templates/pricing.html: -------------------------------------------------------------------------------- 1 | 7 | {% extends "./layouts/base.html" %} 8 | 9 | {% block body %} 10 | {% dnd_area "dnd_area" 11 | label="Main section", 12 | class="body-container body-container--pricing" 13 | %} 14 | 15 | {# Pricing #} 16 | 17 | {% include_dnd_partial path="../sections/pricing.html" %} 18 | 19 | {% end_dnd_area %} 20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | jobs: 6 | deploy: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: Checkout 10 | uses: actions/checkout@v2.3.3 11 | - name: HubSpot Deploy Action 12 | uses: HubSpot/hubspot-cms-deploy-action@v1.5 13 | with: 14 | src_dir: src 15 | dest_dir: cms-theme-boilerplate 16 | portal_id: ${{ secrets.hubspot_portal_id }} 17 | personal_access_key: ${{ secrets.hubspot_personal_access_key }} 18 | -------------------------------------------------------------------------------- /src/modules/card.module/module.css: -------------------------------------------------------------------------------- 1 | .cards { 2 | display: flex; 3 | flex-wrap: nowrap; 4 | justify-content: space-between; 5 | } 6 | 7 | .cards__card { 8 | align-items: center; 9 | align-self: flex-start; 10 | display: flex; 11 | flex-wrap: wrap; 12 | margin-bottom: 1.4rem; 13 | max-width: 100%; 14 | width: 300px; 15 | } 16 | 17 | .card__image { 18 | height: auto; 19 | margin: 0 auto; 20 | max-width: 100%; 21 | padding: 0.7rem; 22 | } 23 | 24 | .card__text { 25 | padding: 0 0.7rem; 26 | width: 100%; 27 | } 28 | -------------------------------------------------------------------------------- /src/images/module-icons/table.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/images/module-icons/social.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020 HubSpot, Inc. 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | -------------------------------------------------------------------------------- /src/images/module-icons/info-circle-solid.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/modules/social-follow.module/module.css: -------------------------------------------------------------------------------- 1 | .social-links { 2 | align-items: center; 3 | display: flex; 4 | flex-wrap: wrap; 5 | justify-content: center; 6 | } 7 | 8 | .social-links__icon { 9 | border-radius: 50%; 10 | display: inline-flex; 11 | height: 1.75rem; 12 | margin: 0 0.35rem; 13 | position: relative; 14 | width: 1.75rem; 15 | } 16 | 17 | .social-links__icon svg { 18 | fill: #FFF; 19 | height: 0.625rem; 20 | left: 50%; 21 | position: absolute; 22 | top: 50%; 23 | transform: translate(-50%, -50%); 24 | width: auto; 25 | } 26 | 27 | .social-links__icon:hover svg, 28 | .social-links__icon:focus svg, 29 | .social-links__icon:active svg { 30 | fill: #FFF; 31 | } 32 | -------------------------------------------------------------------------------- /src/images/module-icons/menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/css/utilities/_helper.css: -------------------------------------------------------------------------------- 1 | /* For content that needs to be visually hidden but stay visible for screenreaders */ 2 | 3 | .show-for-sr { 4 | border: 0 !important; 5 | clip: rect(0, 0, 0, 0) !important; 6 | height: 1px !important; 7 | overflow: hidden !important; 8 | padding: 0 !important; 9 | position: absolute !important; 10 | white-space: nowrap !important; 11 | width: 1px !important; 12 | } 13 | 14 | @media (max-width: 767px) { 15 | .show-for-sr--mobile { 16 | border: 0 !important; 17 | clip: rect(0, 0, 0, 0) !important; 18 | height: 1px !important; 19 | overflow: hidden !important; 20 | padding: 0 !important; 21 | position: absolute !important; 22 | white-space: nowrap !important; 23 | width: 1px !important; 24 | } 25 | } -------------------------------------------------------------------------------- /src/theme.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "CMS theme boilerplate", 3 | "author": { 4 | "name": "HubSpot", 5 | "email": "hs-content-assets@hubspot.com", 6 | "url": "https://www.hubspot.com/" 7 | }, 8 | "documentation_url": "https://developers.hubspot.com/docs/cms/building-blocks/themes/hubspot-cms-boilerplate", 9 | "example_url": "https://boilerplate.hubspotcms.com", 10 | "preview_path": "./templates/home.html", 11 | "screenshot_path": "./images/template-previews/home.png", 12 | "enable_domain_stylesheets": false, 13 | "license": "./license.txt", 14 | "responsive_breakpoints": [ 15 | { 16 | "name": "mobile", 17 | "mediaQuery": "@media (max-width: 767px)", 18 | "previewWidth": { 19 | "value": 477 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /src/templates/system/subscription-preferences.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "Subscription preferences" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "subscription_preferences" 16 | path="@hubspot/email_subscriptions" 17 | %} 18 |
19 |
20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /src/templates/system/backup-unsubscribe.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "Unsubscribe" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "backup_unsubscribe" 16 | extra_classes="backup-unsubscribe", 17 | path="@hubspot/email_simple_subscription" 18 | %} 19 |
20 |
21 | {% endblock body %} 22 | -------------------------------------------------------------------------------- /src/templates/system/subscriptions-confirmation.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "Confirm subscriptions" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "subscriptions_confirmation" 16 | path="@hubspot/email_subscriptions_confirmation" 17 | %} 18 |
19 |
20 | {% endblock body %} 21 | -------------------------------------------------------------------------------- /src/images/module-icons/ellipses.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /src/templates/system/500.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "Error 500 | Server error" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "content" 16 | path="@hubspot/rich_text", 17 | html="

Something isn\'t quite right

Sorry, an internal server error occurred. But have no fear, we\'re on the case!

" 18 | %} 19 |
20 |
21 | {% endblock body %} 22 | -------------------------------------------------------------------------------- /src/css/elements/_buttons.css: -------------------------------------------------------------------------------- 1 | button, 2 | .button, 3 | .hs-button { 4 | cursor: pointer; 5 | display: inline-block; 6 | text-align: center; 7 | transition: all 0.15s linear; 8 | white-space: normal; 9 | } 10 | 11 | button:disabled, 12 | .button:disabled, 13 | .hs-button:disabled { 14 | background-color: #D0D0D0; 15 | border-color: #D0D0D0; 16 | color: #E6E6E6; 17 | } 18 | 19 | /* No button */ 20 | 21 | .no-button, 22 | .no-button:hover, 23 | .no-button:focus, 24 | .no-button:active { 25 | background: none; 26 | border: none; 27 | border-radius: 0; 28 | color: initial; 29 | font-family: inherit; 30 | font-size: inherit; 31 | font-style: inherit; 32 | font-weight: inherit; 33 | letter-spacing: inherit; 34 | line-height: inherit; 35 | margin-bottom: 0; 36 | padding: 0; 37 | text-align: left; 38 | text-decoration: none; 39 | transition: none; 40 | } 41 | -------------------------------------------------------------------------------- /src/templates/partials/header-no-navigation.html: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 | {# Top header drag and drop area #} 8 | 9 | {% dnd_area "header-top" 10 | label="Top header", 11 | class="content-wrapper" 12 | %} 13 | {% end_dnd_area %} 14 | 15 | {# Main header #} 16 | 17 |
18 | 19 | {# Logo #} 20 | 21 | 29 | 30 |
31 | 32 | {# Bottom header drag and drop area #} 33 | 34 | {% dnd_area "header-bottom" 35 | label="Bottom header", 36 | class="content-wrapper" 37 | %} 38 | {% end_dnd_area %} 39 | 40 |
41 | -------------------------------------------------------------------------------- /src/templates/system/password-prompt.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "This page is private | Enter password" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "content" 16 | path="@hubspot/rich_text", 17 | html="

Password Required

Please enter the password required to view this page.

" 18 | %} 19 | {% module "password_prompt" 20 | extra_classes="password-prompt", 21 | path="@hubspot/password_prompt" 22 | %} 23 |
24 |
25 | {% endblock body %} 26 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | **Types of change** 2 | 3 | - [ ] Bug fix (change which fixes an issue) 4 | - [ ] Enhancement (change which improves upon an existing feature) 5 | - [ ] New feature (change which adds new functionality) 6 | 7 | **Description** 8 | 9 | A clear and concise description of what the pull request is solving. 10 | 11 | **Relevant links** 12 | 13 | Example page: 14 | GitHub issue: 15 | 16 | **Checklist** 17 | 18 | - [ ] I have read the [CONTRIBUTING](https://github.com/HubSpot/cms-theme-boilerplate/blob/master/CONTRIBUTING.md) document. 19 | - [ ] My code follows the [style guide requirements](https://github.com/HubSpot/cms-theme-boilerplate/blob/master/STYLEGUIDE.md). 20 | - [ ] I have thoroughly tested my change. 21 | 22 | **People to notify** 23 | 24 | -------------------------------------------------------------------------------- /src/css/objects/_layout.css: -------------------------------------------------------------------------------- 1 | {% set total_columns_count = 12 %} 2 | 3 | /* CSS variables */ 4 | 5 | :root { 6 | --column-gap: 2.13%; 7 | --column-width-multiplier: 8.333; 8 | } 9 | 10 | /* Mobile layout */ 11 | 12 | .row-fluid { 13 | display: flex; 14 | flex-wrap: wrap; 15 | width: 100%; 16 | } 17 | 18 | {% for span_num in range(1, total_columns_count + 1) %} 19 | {{ ".row-fluid .span" ~ span_num }}{{ loop.last ? null : "," }} 20 | {%- endfor -%} { 21 | min-height: 1px; 22 | width: 100%; 23 | } 24 | 25 | /* Desktop layout */ 26 | 27 | @media (min-width: 768px) { 28 | .row-fluid { 29 | flex-wrap: nowrap; 30 | justify-content: space-between; 31 | } 32 | 33 | {% for span_num in range(1, total_columns_count) %} 34 | {{ ".row-fluid .span" ~ span_num }} { 35 | width: calc(var(--column-width-multiplier) * 1% * {{ span_num }} - var(--column-gap) * ({{ total_columns_count - span_num }} * var(--column-width-multiplier) / 100)); 36 | } 37 | {% endfor %} 38 | } 39 | -------------------------------------------------------------------------------- /src/templates/system/404.html: -------------------------------------------------------------------------------- 1 | 7 | {% set template_css = "../../css/templates/system.css" %} 8 | {% extends "../layouts/base.html" %} 9 | {# pageTitle is used on system templates for setting a value for the title tag #} 10 | {% set pageTitle = "Error 404 | Page not found" %} 11 | 12 | {% block body %} 13 |
14 |
15 | {% module "content" 16 | path="@hubspot/rich_text", 17 | html="

Page not found.

" 18 | %} 19 | {% module "button" 20 | path="../../modules/button", 21 | button_text="Go Home" 22 | link={ 23 | "url": 24 | { 25 | "type": "EXTERNAL", 26 | "href": "/" 27 | }, 28 | "open_in_new_tab": false, 29 | "no_follow": false 30 | } 31 | %} 32 |
33 |
34 | {% endblock body %} 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@hubspot/cms-theme-boilerplate", 3 | "version": "3.14.2", 4 | "description": "Boilerplate project for building websites on the HubSpot CMS", 5 | "repository": { 6 | "type": "git", 7 | "url": "git@git.hubteam.com:HubSpot/cms-theme-boilerplate.git" 8 | }, 9 | "author": "", 10 | "license": "Apache-2.0", 11 | "devDependencies": { 12 | "autoprefixer": "^9.0.0", 13 | "eslint": "^v8.0.0", 14 | "js-yaml": "^3.14.0", 15 | "postcss-cli": "^7.0.0", 16 | "prettier": "^2.1.2" 17 | }, 18 | "scripts": { 19 | "autoprefixer": "postcss src/css/**/*.css src/modules/**/*.css !src/**/_layout.css !src/**/_normalize.css !src/**/_reset.css !src/**/_macros.css !src/**/main.css !src/**/theme-overrides.css --use autoprefixer --replace --no-map", 20 | "eslint": "eslint src", 21 | "lint": "eslint src && prettier --list-different 'src/**/*.js' 'src/**/*.json'", 22 | "prettier:write": "prettier --write 'src/**/*.js' 'src/**/*.json'" 23 | }, 24 | "browserslist": [ 25 | "defaults", 26 | "IE 11" 27 | ] 28 | } 29 | -------------------------------------------------------------------------------- /src/templates/landing-page.html: -------------------------------------------------------------------------------- 1 | 7 | {% extends "./layouts/base.html" %} 8 | 9 | {% block header %} 10 | {% global_partial path="./partials/header-no-navigation.html" %} 11 | {% endblock header %} 12 | 13 | {% block body %} 14 | {% dnd_area "dnd_area" 15 | label="Main section", 16 | class="body-container body-container--landing-page" 17 | %} 18 | 19 | {# Hero banner #} 20 | 21 | {% include_dnd_partial 22 | path="../sections/hero-banner.html" 23 | context={ 24 | "content": "

Download your free eBook

Use this space to tell everyone what your eBook is all about.

" 25 | } 26 | %} 27 | 28 | {# Three column image with text #} 29 | 30 | {% include_dnd_partial 31 | path="../sections/multi-column-content.html", 32 | context={ 33 | "background_color": "#FFFFFF" 34 | } 35 | %} 36 | 37 | {% end_dnd_area %} 38 | {% endblock body %} 39 | 40 | {% block footer %} 41 | {% endblock footer %} 42 | -------------------------------------------------------------------------------- /src/sections/multi-row-content.html: -------------------------------------------------------------------------------- 1 | 8 | {% dnd_section 9 | vertical_alignment="MIDDLE" 10 | %} 11 | {% dnd_module 12 | path="@hubspot/rich_text", 13 | html={{ context.content or "

Provide more details here.

Use text and images to tell your company’s story. Explain what makes your product or service extraordinary.

" }} 14 | offset=0, 15 | width=6 16 | %} 17 | 18 | {% end_dnd_module %} 19 | {% dnd_module path="@hubspot/linked_image", 20 | img={ 21 | "alt": context.image_alt or "Stock placeholder image with grayscale geometrical mountain landscape", 22 | "loading": context.image_loading or "disabled", 23 | "max_height": context.image_height or 451, 24 | "max_width": context.image_width or 605, 25 | "size_type": "auto_custom_max", 26 | "src": context.image or get_asset_url("../images/grayscale-mountain.png") 27 | }, 28 | offset=6, 29 | width=6 30 | %} 31 | {% end_dnd_module %} 32 | {% end_dnd_section %} 33 | -------------------------------------------------------------------------------- /src/css/main.css: -------------------------------------------------------------------------------- 1 | /* Theme base styles */ 2 | 3 | /* Tools 4 | Any animations, or functions used throughout the project. 5 | Note: _macros.css needs to be imported into each stylesheet where macros are used and not included here 6 | */ 7 | 8 | /* Generic 9 | This is where reset, normalize & box-sizing styles go. 10 | */ 11 | 12 | {% include './generic/_reset.css' %} 13 | {% include './generic/_normalize.css' %} 14 | 15 | /* Objects 16 | Non-cosmetic design patterns including grid and layout classes) 17 | */ 18 | 19 | {% include './objects/_layout.css' %} 20 | {% include './objects/_containers-dnd.css' %} 21 | 22 | /* Elements 23 | Base HTML elements are styled in this section (,

, ,

, 115 |

120 | {% endif %} 121 | {% endif %} 122 | 123 | {% endmacro %} 124 | 125 | {% for link in menu %} 126 | {{ render_link_item(link, 1) }} 127 | {% endfor %} 128 | 129 | {% endmacro %} 130 | 131 | {# Desktop menu #} 132 | 133 | 138 | 139 | {# Mobile menu #} 140 | 141 | 146 | -------------------------------------------------------------------------------- /src/css/generic/_normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /* Document 4 | ========================================================================== */ 5 | 6 | /** 7 | * 1. Correct the line height in all browsers. 8 | * 2. Prevent adjustments of font size after orientation changes in iOS. 9 | */ 10 | 11 | html { 12 | line-height: 1.15; /* 1 */ 13 | -webkit-text-size-adjust: 100%; /* 2 */ 14 | } 15 | 16 | /* Sections 17 | ========================================================================== */ 18 | 19 | /** 20 | * Remove the margin in all browsers. 21 | */ 22 | 23 | body { 24 | margin: 0; 25 | } 26 | 27 | /** 28 | * Correct the font size and margin on `h1` elements within `section` and 29 | * `article` contexts in Chrome, Firefox, and Safari. 30 | */ 31 | 32 | h1 { 33 | font-size: 2em; 34 | margin: 0.67em 0; 35 | } 36 | 37 | /* Grouping content 38 | ========================================================================== */ 39 | 40 | /** 41 | * Add the correct box sizing in Firefox. 42 | */ 43 | 44 | hr { 45 | box-sizing: content-box; 46 | height: 0; 47 | } 48 | 49 | /** 50 | * 1. Correct the inheritance and scaling of font size in all browsers. 51 | * 2. Correct the odd `em` font sizing in all browsers. 52 | */ 53 | 54 | pre { 55 | font-family: monospace, monospace; /* 1 */ 56 | font-size: 1em; /* 2 */ 57 | } 58 | 59 | /* Text-level semantics 60 | ========================================================================== */ 61 | 62 | /** 63 | * 1. Remove the bottom border in Chrome 57- 64 | * 2. Add the correct text decoration in Chrome, Edge, Opera, and Safari. 65 | */ 66 | 67 | abbr[title] { 68 | border-bottom: none; /* 1 */ 69 | text-decoration: underline; /* 2 */ 70 | text-decoration: underline dotted; /* 2 */ 71 | } 72 | 73 | /** 74 | * Add the correct font weight in Chrome, Edge, and Safari. 75 | */ 76 | 77 | b, 78 | strong { 79 | font-weight: bolder; 80 | } 81 | 82 | /** 83 | * 1. Correct the inheritance and scaling of font size in all browsers. 84 | * 2. Correct the odd `em` font sizing in all browsers. 85 | */ 86 | 87 | code, 88 | kbd, 89 | samp { 90 | font-family: monospace, monospace; /* 1 */ 91 | font-size: 1em; /* 2 */ 92 | } 93 | 94 | /** 95 | * Add the correct font size in all browsers. 96 | */ 97 | 98 | small { 99 | font-size: 80%; 100 | } 101 | 102 | /** 103 | * Prevent `sub` and `sup` elements from affecting the line height in 104 | * all browsers. 105 | */ 106 | 107 | sub, 108 | sup { 109 | font-size: 75%; 110 | line-height: 0; 111 | position: relative; 112 | vertical-align: baseline; 113 | } 114 | 115 | sub { 116 | bottom: -0.25em; 117 | } 118 | 119 | sup { 120 | top: -0.5em; 121 | } 122 | 123 | /* Forms 124 | ========================================================================== */ 125 | 126 | /** 127 | * 1. Change the font styles in all browsers. 128 | * 2. Remove the margin in Firefox and Safari. 129 | */ 130 | 131 | button, 132 | input, 133 | optgroup, 134 | select, 135 | textarea { 136 | font-family: inherit; /* 1 */ 137 | font-size: 100%; /* 1 */ 138 | line-height: 1.15; /* 1 */ 139 | margin: 0; /* 2 */ 140 | } 141 | 142 | /** 143 | * Remove the inheritance of text transform in Edge and Firefox. 144 | * 1. Remove the inheritance of text transform in Firefox. 145 | */ 146 | 147 | button, 148 | select { /* 1 */ 149 | text-transform: none; 150 | } 151 | 152 | /** 153 | * Correct the inability to style clickable types in iOS and Safari. 154 | */ 155 | 156 | button, 157 | [type="button"], 158 | [type="reset"], 159 | [type="submit"] { 160 | -webkit-appearance: button; 161 | } 162 | 163 | /** 164 | * Remove the inner border and padding in Firefox. 165 | */ 166 | 167 | button::-moz-focus-inner, 168 | [type="button"]::-moz-focus-inner, 169 | [type="reset"]::-moz-focus-inner, 170 | [type="submit"]::-moz-focus-inner { 171 | border-style: none; 172 | padding: 0; 173 | } 174 | 175 | /** 176 | * Restore the focus styles unset by the previous rule. 177 | */ 178 | 179 | button:-moz-focusring, 180 | [type="button"]:-moz-focusring, 181 | [type="reset"]:-moz-focusring, 182 | [type="submit"]:-moz-focusring { 183 | outline: 1px dotted ButtonText; 184 | } 185 | 186 | /** 187 | * Correct the padding in Firefox. 188 | */ 189 | 190 | fieldset { 191 | padding: 0.35em 0.75em 0.625em; 192 | } 193 | 194 | /** 195 | * Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers. 196 | */ 197 | 198 | legend { 199 | padding: 0; 200 | } 201 | 202 | /** 203 | * Add the correct vertical alignment in Chrome, Firefox, and Opera. 204 | */ 205 | 206 | progress { 207 | vertical-align: baseline; 208 | } 209 | 210 | /** 211 | * Correct the cursor style of increment and decrement buttons in Chrome. 212 | */ 213 | 214 | [type="number"]::-webkit-inner-spin-button, 215 | [type="number"]::-webkit-outer-spin-button { 216 | height: auto; 217 | } 218 | 219 | /** 220 | * 1. Correct the odd appearance in Chrome and Safari. 221 | * 2. Correct the outline style in Safari. 222 | */ 223 | 224 | [type="search"] { 225 | -webkit-appearance: textfield; /* 1 */ 226 | outline-offset: -2px; /* 2 */ 227 | } 228 | 229 | /** 230 | * Remove the inner padding in Chrome and Safari on macOS. 231 | */ 232 | 233 | [type="search"]::-webkit-search-decoration { 234 | -webkit-appearance: none; 235 | } 236 | 237 | /** 238 | * 1. Correct the inability to style clickable types in iOS and Safari. 239 | * 2. Change font properties to `inherit` in Safari. 240 | */ 241 | 242 | ::-webkit-file-upload-button { 243 | -webkit-appearance: button; /* 1 */ 244 | font: inherit; /* 2 */ 245 | } 246 | 247 | /* Interactive 248 | ========================================================================== */ 249 | 250 | /* 251 | * Add the correct display in Edge and Firefox. 252 | */ 253 | 254 | details { 255 | display: block; 256 | } 257 | 258 | /* 259 | * Add the correct display in all browsers. 260 | */ 261 | 262 | summary { 263 | display: list-item; 264 | } -------------------------------------------------------------------------------- /src/modules/card.module/fields.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "Card", 4 | "name": "card", 5 | "type": "group", 6 | "occurrence": { 7 | "default": 3, 8 | "min": 1, 9 | "sorting_label_field": "card.title" 10 | }, 11 | "children": [ 12 | { 13 | "label": "Image", 14 | "name": "image", 15 | "type": "image", 16 | "responsive": true, 17 | "resizable": true, 18 | "show_loading": true, 19 | "default": { 20 | "loading": "lazy" 21 | } 22 | }, 23 | { 24 | "label": "Content", 25 | "name": "text", 26 | "type": "richtext", 27 | "enabled_features": [ 28 | "advanced_emphasis", 29 | "alignment", 30 | "block", 31 | "emoji", 32 | "font_family", 33 | "font_size", 34 | "lists", 35 | "standard_emphasis" 36 | ], 37 | "default": "

This is a title

Contextual advertising can be profitable. It can either pay for your hosting and maintenance costs for you website or it can pay for a lot more.

" 38 | } 39 | ], 40 | "default": [ 41 | { 42 | "image": { 43 | "loading": "lazy" 44 | }, 45 | "text": "

This is a title

Contextual advertising can be profitable. It can either pay for your hosting and maintenance costs for you website or it can pay for a lot more.

" 46 | }, 47 | { 48 | "image": { 49 | "loading": "lazy" 50 | }, 51 | "text": "

This is a title

Contextual advertising can be profitable. It can either pay for your hosting and maintenance costs for you website or it can pay for a lot more.

" 52 | }, 53 | { 54 | "image": { 55 | "loading": "lazy" 56 | }, 57 | "text": "

This is a title

Contextual advertising can be profitable. It can either pay for your hosting and maintenance costs for you website or it can pay for a lot more.

" 58 | } 59 | ] 60 | }, 61 | { 62 | "label": "Styles", 63 | "name": "styles", 64 | "type": "group", 65 | "tab": "STYLE", 66 | "children": [ 67 | { 68 | "label": "Image", 69 | "name": "image", 70 | "type": "group", 71 | "children": [ 72 | { 73 | "label": "Corner", 74 | "name": "corner", 75 | "type": "group", 76 | "children": [ 77 | { 78 | "label": "Radius", 79 | "name": "radius", 80 | "type": "number", 81 | "display": "text", 82 | "max": 100, 83 | "step": 1, 84 | "suffix": "px" 85 | } 86 | ] 87 | } 88 | ] 89 | }, 90 | { 91 | "label": "Card", 92 | "name": "card", 93 | "type": "group", 94 | "children": [ 95 | { 96 | "label": "Background", 97 | "name": "background", 98 | "type": "group", 99 | "children": [ 100 | { 101 | "label": "Background type", 102 | "name": "background_type", 103 | "id": "styles.card.background.background_type", 104 | "type": "choice", 105 | "choices": [ 106 | ["none", "None"], 107 | ["color", "Color"], 108 | ["gradient", "Gradient"], 109 | ["image", "Image"] 110 | ], 111 | "display": "radio", 112 | "default": "none" 113 | }, 114 | { 115 | "label": "Color", 116 | "name": "color", 117 | "type": "color", 118 | "visibility": { 119 | "controlling_field": "styles.card.background.background_type", 120 | "controlling_value_regex": "color", 121 | "operator": "EQUAL" 122 | } 123 | }, 124 | { 125 | "label": "Gradient", 126 | "name": "gradient", 127 | "type": "gradient", 128 | "visibility": { 129 | "controlling_field": "styles.card.background.background_type", 130 | "controlling_value_regex": "gradient", 131 | "operator": "EQUAL" 132 | } 133 | }, 134 | { 135 | "label": "Image", 136 | "name": "image", 137 | "type": "backgroundimage", 138 | "visibility": { 139 | "controlling_field": "styles.card.background.background_type", 140 | "controlling_value_regex": "image", 141 | "operator": "EQUAL" 142 | } 143 | } 144 | ] 145 | }, 146 | { 147 | "label": "Border", 148 | "name": "border", 149 | "type": "group", 150 | "children": [ 151 | { 152 | "label": "Border", 153 | "name": "border", 154 | "type": "border" 155 | } 156 | ] 157 | }, 158 | { 159 | "label": "Corner", 160 | "name": "corner", 161 | "type": "group", 162 | "children": [ 163 | { 164 | "label": "Radius", 165 | "name": "radius", 166 | "type": "number", 167 | "display": "text", 168 | "max": 100, 169 | "step": 1, 170 | "suffix": "px" 171 | } 172 | ] 173 | }, 174 | { 175 | "label": "Spacing", 176 | "name": "spacing", 177 | "type": "group", 178 | "children": [ 179 | { 180 | "label": "Spacing", 181 | "name": "spacing", 182 | "type": "spacing" 183 | } 184 | ] 185 | } 186 | ] 187 | } 188 | ] 189 | } 190 | ] 191 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

HubSpot CMS Boilerplate

2 | 3 |

4 | A straight-forward starting point for building a great website on the HubSpot CMS. 5 |

6 | 7 |

8 | Documentation | 9 | Demo website | 10 | Contributing 11 |

12 | 13 | [![Current version](https://img.shields.io/github/v/release/HubSpot/cms-theme-boilerplate)](https://github.com/HubSpot/cms-theme-boilerplate/releases) 14 | [![Latest commit](https://img.shields.io/github/last-commit/HubSpot/cms-theme-boilerplate)](https://github.com/HubSpot/cms-theme-boilerplate/commits/main) 15 | [![Contributors](https://img.shields.io/github/contributors/HubSpot/cms-theme-boilerplate?logo=blue)](https://github.com/HubSpot/cms-theme-boilerplate/graphs/contributors) 16 | [![GitHub watchers](https://img.shields.io/github/watchers/HubSpot/cms-theme-boilerplate?style=social)](https://github.com/HubSpot/cms-theme-boilerplate/watchers) 17 | [![GitHub stars](https://img.shields.io/github/stars/HubSpot/cms-theme-boilerplate?style=social)](https://github.com/HubSpot/cms-theme-boilerplate/stargazers) 18 | [![GitHub forks](https://img.shields.io/github/forks/HubSpot/cms-theme-boilerplate?style=social)](https://github.com/HubSpot/cms-theme-boilerplate/network/members) 19 | [![HubSpot website grader score](https://img.shields.io/badge/HubSpot%20website%20grader%20score-97-brightgreen)](https://website.grader.com/tests/boilerplate.hubspotcms.com) 20 | [![Google Lighthouse desktop performance score](https://img.shields.io/badge/Google%20Lighthouse%20desktop%20performance%20score-98-brightgreen)](https://developers.google.com/web/tools/lighthouse) 21 | [![Google Lighthouse SEO score](https://img.shields.io/badge/Google%20Lighthouse%20SEO%20score-100-brightgreen)](https://developers.google.com/web/tools/lighthouse) 22 | [![Google Lighthouse accessibility score](https://img.shields.io/badge/Google%20Lighthouse%20accessibility%20score-100-brightgreen)](https://developers.google.com/web/tools/lighthouse) 23 | [![License](https://img.shields.io/badge/license-Apache%20Version%202.0-red)](https://github.com/HubSpot/cms-theme-boilerplate/blob/main/LICENSE) 24 | 25 | ## Purpose 26 | 27 | The [HubSpot CMS Boilerplate](https://designers.hubspot.com/docs/building-blocks/themes/hubspot-cms-boilerplate) is designed to offer developers a head start in the website building process. While the HubSpot CMS Boilerplate represents HubSpot's opinionated best practices, we intend to learn from similar projects and feedback. We hope it offers inspiration and utility for all website projects! 28 | 29 | ## Getting started 30 | 31 | ### To download the HubSpot CMS Boilerplate using the HubSpot CMS CLI: 32 | 33 | Before getting started, you will need to have [Node.js](https://nodejs.org) installed, the [HubSpot CMS CLI](https://developers.hubspot.com/docs/cms/guides/getting-started-with-local-development#install-dependencies) installed, and we strongly suggest that you set up a [HubSpot CMS Developer Sandbox](https://offers.hubspot.com/free-cms-developer-sandbox) for your QA/testing environment. 34 | 35 | 1. Navigate to the directory that you want to use for your project 36 | 2. Run `hs create website-theme ` to create a project from the HubSpot CMS Boilerplate 37 | 3. [Configure](https://developers.hubspot.com/docs/cms/guides/getting-started-with-local-development#configure-the-local-development-tools) the local development tools for the portal(s) you'd like to use for your project. 38 | 4. Run `hs watch --portal= src --initial-upload` to upload all the files in the project and [watch for changes](https://developers.hubspot.com/docs/cms/developer-reference/local-development-cms-cli#watch) to files in the `src` directory 39 | 40 | Please reference our _[Quick start guide to developing on the HubSpot CMS](https://developers.hubspot.com/docs/cms/guides/getting-started)_ and our _[Getting started with local development](https://designers.hubspot.com/tutorials/getting-started-with-local-development)_ articles for more information. 41 | 42 | ### To use version control in your project using GitHub and GitHub Actions: 43 | 44 | 1. [Fork](https://help.github.com/en/github/getting-started-with-github/fork-a-repo) the HubSpot CMS Boilerplate repository and [clone](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository) your forked repository to your computer 45 | 2. [Set up GitHub secrets in your forked repository to encrypt sensitive information from showing publically](https://help.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets) for `HUBSPOT_PORTAL_ID` and `HUBSPOT_PERSONAL_ACCESS_KEY` 46 | 3. Update the name of the directory that you'll be deploying to in your Design Manager in the `.github/workflows/deploy.yml` file (the current default `dest_dir` is `cms-theme-boilerplate`) 47 | 4. Deploy changes to your Design Manager by pushing to the `main` branch of your forked repository 48 | 49 | Please reference our [_HubSpot CMS deploy GitHub action page_](https://github.com/marketplace/actions/hubspot-cms-deploy) and _[Setting up continuous integration with a GitHub repository using GitHub Actions article](https://designers.hubspot.com/tutorials/github-integration)_ for more information. 50 | 51 | ## Style guide 52 | 53 | For details about the HubSpot CMS Boilerplate's recommended best practices and code formatting, please reference our [style guide](https://github.com/HubSpot/cms-theme-boilerplate/blob/master/STYLEGUIDE.md). 54 | 55 | ## Contributing 56 | 57 | If you’re interested in contributing to the HubSpot CMS Boilerplate, please read [CONTRIBUTING.md](https://github.com/HubSpot/cms-theme-boilerplate/blob/master/CONTRIBUTING.md) and [STYLEGUIDE.md](https://github.com/HubSpot/cms-theme-boilerplate/blob/master/STYLEGUIDE.md) to see how you can report an issue, make a feature request, or make a pull request. 58 | 59 | ## Versioning 60 | 61 | Previous releases and their documentation are available for [download](https://github.com/HubSpot/cms-theme-boilerplate/releases). To provide transparency into future releases, we create a project board that documents our planning in preparation for each [upcoming major and minor version](https://github.com/HubSpot/cms-theme-boilerplate/projects). 62 | 63 | ## Community 64 | 65 | You can stay up to date with HubSpot CMS Boilerplate updates and discussions in the #hs-cms-boilerplate channel in the [HubSpot Developer Slack](https://designers.hubspot.com/slack). 66 | 67 | ## License 68 | 69 | The code is available under the [Apache License, Version 2.0](https://github.com/HubSpot/cms-theme-boilerplate/blob/main/LICENSE) 70 | -------------------------------------------------------------------------------- /src/modules/social-follow.module/fields.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "Social links", 4 | "name": "social_links", 5 | "type": "group", 6 | "occurrence": { 7 | "default": 4, 8 | "min": 1 9 | }, 10 | "children": [ 11 | { 12 | "label": "Social account", 13 | "name": "social_account", 14 | "id": "social_account", 15 | "type": "choice", 16 | "choices": [ 17 | ["facebook-f", "Facebook"], 18 | ["x-twitter", "Twitter"], 19 | ["instagram", "Instagram"], 20 | ["linkedin-in", "LinkedIn"], 21 | ["youtube", "YouTube"], 22 | ["pinterest-p", "Pinterest"], 23 | ["envelope", "Email"], 24 | ["link", "Website"], 25 | ["whatsapp", "Whatsapp"], 26 | ["custom_icon", "Custom icon"] 27 | ], 28 | "display": "select", 29 | "required": true, 30 | "default": "facebook-f" 31 | }, 32 | { 33 | "label": "Custom icon", 34 | "name": "custom_icon", 35 | "type": "icon", 36 | "icon_set" : "fontawesome-6.4.2", 37 | "visibility": { 38 | "controlling_field": "social_account", 39 | "controlling_value_regex": "custom_icon", 40 | "operator": "EQUAL" 41 | }, 42 | "required": true, 43 | "default": { 44 | "name": "arrow-alt-circle-up", 45 | "type" : "SOLID", 46 | "unicode": "f35b" 47 | } 48 | }, 49 | { 50 | "label": "Social link", 51 | "name": "social_link", 52 | "type": "link", 53 | "required": true, 54 | "supported_types": ["EXTERNAL", "EMAIL_ADDRESS"], 55 | "default": { 56 | "no_follow": false, 57 | "open_in_new_tab": true, 58 | "url": { 59 | "content_id": null, 60 | "href": "https://www.facebook.com", 61 | "type": "EXTERNAL" 62 | } 63 | } 64 | }, 65 | { 66 | "label": "Accessibility options", 67 | "name": "accessibility", 68 | "type": "group", 69 | "children": [ 70 | { 71 | "label": "Title", 72 | "name": "title", 73 | "type": "text", 74 | "required": true, 75 | "default": "Follow us on Facebook" 76 | } 77 | ] 78 | } 79 | ], 80 | "default": [ 81 | { 82 | "social_account": "facebook-f", 83 | "social_link": { 84 | "no_follow": false, 85 | "open_in_new_tab": true, 86 | "url": { 87 | "content_id": null, 88 | "href": "https://www.facebook.com", 89 | "type": "EXTERNAL" 90 | } 91 | }, 92 | "accessibility": { 93 | "title": "Follow us on Facebook" 94 | } 95 | }, 96 | { 97 | "social_account": "linkedin-in", 98 | "social_link": { 99 | "no_follow": false, 100 | "open_in_new_tab": true, 101 | "url": { 102 | "content_id": null, 103 | "href": "https://www.linkedin.com", 104 | "type": "EXTERNAL" 105 | } 106 | }, 107 | "accessibility": { 108 | "title": "Follow us on LinkedIn" 109 | } 110 | }, 111 | { 112 | "social_account": "x-twitter", 113 | "social_link": { 114 | "no_follow": false, 115 | "open_in_new_tab": true, 116 | "url": { 117 | "content_id": null, 118 | "href": "https://www.twitter.com", 119 | "type": "EXTERNAL" 120 | } 121 | }, 122 | "accessibility": { 123 | "title": "Follow us on Twitter" 124 | } 125 | }, 126 | { 127 | "social_account": "instagram", 128 | "social_link": { 129 | "no_follow": false, 130 | "open_in_new_tab": true, 131 | "url": { 132 | "content_id": null, 133 | "href": "https://www.instagram.com", 134 | "type": "EXTERNAL" 135 | } 136 | }, 137 | "accessibility": { 138 | "title": "Follow us on Instagram" 139 | } 140 | } 141 | ] 142 | }, 143 | { 144 | "label": "Styles", 145 | "name": "styles", 146 | "type": "group", 147 | "tab": "STYLE", 148 | "children": [ 149 | { 150 | "label": "Fill", 151 | "name": "fill", 152 | "type": "group", 153 | "children": [ 154 | { 155 | "label": "Color", 156 | "name": "color", 157 | "type": "color", 158 | "visibility": { 159 | "hidden_subfields": { 160 | "opacity": true 161 | } 162 | } 163 | } 164 | ] 165 | }, 166 | { 167 | "label": "Size", 168 | "name": "size", 169 | "type": "group", 170 | "children": [ 171 | { 172 | "label": "Size", 173 | "name": "size", 174 | "type": "number", 175 | "display": "text", 176 | "max": 50, 177 | "min": 1, 178 | "step": 1, 179 | "suffix": "px" 180 | } 181 | ] 182 | }, 183 | { 184 | "label": "Background", 185 | "name": "background", 186 | "type": "group", 187 | "children": [ 188 | { 189 | "label": "Color", 190 | "name": "color", 191 | "type": "color" 192 | } 193 | ] 194 | }, 195 | { 196 | "label": "Corner", 197 | "name": "corner", 198 | "type": "group", 199 | "children": [ 200 | { 201 | "label": "Radius", 202 | "name": "radius", 203 | "type": "number", 204 | "display": "text", 205 | "max": 100, 206 | "step": 1, 207 | "suffix": "px" 208 | } 209 | ] 210 | }, 211 | { 212 | "label": "Spacing", 213 | "name": "spacing", 214 | "type": "group", 215 | "children": [ 216 | { 217 | "label": "Space between icons", 218 | "name": "space_between_icons", 219 | "type": "number", 220 | "display": "slider", 221 | "max": 50, 222 | "min": 0, 223 | "step": 5, 224 | "suffix": "px" 225 | }, 226 | { 227 | "label": "Spacing", 228 | "name": "spacing", 229 | "type": "spacing" 230 | } 231 | ] 232 | }, 233 | { 234 | "label": "Alignment", 235 | "name": "alignment", 236 | "type": "group", 237 | "children": [ 238 | { 239 | "label": "Alignment", 240 | "name": "alignment", 241 | "type": "alignment", 242 | "alignment_direction": "HORIZONTAL" 243 | } 244 | ] 245 | } 246 | ] 247 | } 248 | ] 249 | -------------------------------------------------------------------------------- /src/modules/menu.module/module.css: -------------------------------------------------------------------------------- 1 | /* Menu */ 2 | 3 | .menu--desktop { 4 | display: block; 5 | } 6 | 7 | .menu--mobile { 8 | display: none; 9 | } 10 | 11 | @media (max-width: 767px) { 12 | .menu--desktop { 13 | display: none; 14 | } 15 | 16 | .menu--mobile { 17 | display: block; 18 | } 19 | } 20 | 21 | /* Menu items */ 22 | 23 | .menu__item { 24 | position: relative; 25 | } 26 | 27 | .menu__link { 28 | font-size: 0.917rem; 29 | line-height: 1.667rem; 30 | text-decoration: none; 31 | } 32 | 33 | .menu__link:hover, 34 | .menu__link:focus, 35 | .menu__link:active { 36 | text-decoration: none; 37 | } 38 | 39 | .menu__link--active-link, 40 | .menu__link--active-branch { 41 | font-weight: bold; 42 | } 43 | 44 | @media (min-width: 768px) and (max-width: 1150px) { 45 | .menu__link { 46 | font-size: 0.833rem; 47 | } 48 | } 49 | 50 | @media (max-width: 767px) { 51 | .menu__item { 52 | display: block; 53 | width: 100%; 54 | } 55 | 56 | .menu__link { 57 | display: block; 58 | font-size: 1.083rem; 59 | } 60 | } 61 | 62 | /* Menu items - top level */ 63 | 64 | .menu__item--depth-1 { 65 | display: inline-block; 66 | padding: 0.7rem 0.875rem; 67 | text-transform: uppercase; 68 | } 69 | 70 | .menu__item--depth-1 > .menu__link--active-link:after { 71 | bottom: -3px; 72 | content: ''; 73 | height: 2px; 74 | left: 0; 75 | position: absolute; 76 | width: 100%; 77 | } 78 | 79 | @media (max-width: 767px) { 80 | .menu__item--depth-1 { 81 | border-top: 2px solid #CED4DB; 82 | padding: 0; 83 | } 84 | 85 | .menu__item--depth-1 > .menu__link { 86 | padding: 0.35rem 1.225rem; 87 | } 88 | 89 | .menu__item--depth-1 > .menu__link--active-link:after { 90 | content: none; 91 | } 92 | } 93 | 94 | /* Menu items - submenus */ 95 | 96 | .menu__submenu { 97 | box-shadow: 0 2px 9px 0 rgba(0, 0, 0, 0.2); 98 | border-radius: 3px; 99 | display: none; 100 | left: 0; 101 | position: absolute; 102 | text-align: left; 103 | text-transform: none; 104 | top: 100%; 105 | width: 270px; 106 | z-index: 99; 107 | } 108 | 109 | .menu__item--open > .menu__submenu { 110 | display: block; 111 | } 112 | 113 | .menu__submenu--level-2 { 114 | transform: translateX(-50%); 115 | } 116 | 117 | /* Keeps the first menu item's drop down menu aligned to the left of the top level menu item */ 118 | 119 | .menu__item--depth-1:first-child .menu__submenu--level-2 { 120 | transform: unset; 121 | } 122 | 123 | .menu__submenu .menu__item { 124 | border-bottom: 1px solid #D1D6DC; 125 | padding: 0; 126 | width: 100%; 127 | } 128 | 129 | .menu__submenu .menu__link { 130 | display: block; 131 | padding: 0.7rem 1.05rem; 132 | transition: background-color 0.3s; 133 | width: 100%; 134 | } 135 | 136 | .menu__submenu--level-3 { 137 | left: 100%; 138 | top: 0; 139 | } 140 | 141 | /* Flyouts for the last two top level menu items go left to keep page responsive */ 142 | 143 | .menu__item--depth-1:nth-last-child(-n+2) .menu__submenu--level-3 { 144 | left: auto; 145 | right: 100%; 146 | top: 0; 147 | } 148 | 149 | /* Accounts for child toggle */ 150 | 151 | .menu__submenu .menu__item--has-submenu > .menu__link { 152 | padding-right: 3rem; 153 | } 154 | 155 | /* Creates the triangle at the top of the submenu drop down */ 156 | 157 | @media (min-width: 768px) { 158 | .menu__submenu--level-2 > .menu__item:first-child:before { 159 | border-radius: 6px; 160 | box-shadow: 0 2px 9px 0 rgb(0 0 0 / 20%); 161 | content: ''; 162 | display: block; 163 | height: 30px; 164 | left: 125px; 165 | margin-left: 1rem; 166 | overflow: hidden; 167 | position: absolute; 168 | top: -12px; 169 | transform: rotate(45deg); 170 | transition: background-color .3s; 171 | width: 30px; 172 | z-index: 2; 173 | } 174 | 175 | /* Keeps triangle to the left for the first menu item's drop down menu */ 176 | 177 | .menu__item--depth-1:first-child > .menu__submenu--level-2 > .menu__item:first-child:before { 178 | left: 0; 179 | } 180 | 181 | .menu__submenu--level-2 > .menu__item:first-child > .menu__link { 182 | position: relative; 183 | z-index: 2; 184 | } 185 | } 186 | 187 | @media (max-width: 767px) { 188 | .menu__submenu { 189 | border: none; 190 | border-radius: 0; 191 | box-shadow: none; 192 | position: static; 193 | transform: unset; 194 | width: 100%; 195 | } 196 | 197 | .menu__submenu .menu__item { 198 | background-color: #FFF; 199 | border-bottom: none; 200 | border-top: 2px solid #EBEFF3; 201 | padding: 0; 202 | } 203 | 204 | .menu__submenu .menu__link { 205 | display: block; 206 | padding: 0.7rem 2rem; 207 | transition: none; 208 | width: 100%; 209 | } 210 | 211 | .menu__submenu .menu__item .menu__link:hover, 212 | .menu__submenu .menu__item .menu__link:focus { 213 | background-color: inherit; 214 | transition: none; 215 | } 216 | 217 | .menu__item--has-submenu > .menu__link { 218 | width: 70%; 219 | } 220 | 221 | .menu__submenu--level-3 .menu__item .menu__link { 222 | padding: 0.7rem 3rem; 223 | } 224 | } 225 | 226 | /* Menu icons */ 227 | 228 | @media(min-width: 768px) { 229 | .menu__submenu .menu__child-toggle { 230 | margin-left: auto; 231 | padding: 0 1.05rem; 232 | } 233 | 234 | .menu__child-toggle { 235 | position: absolute; 236 | right: 5px; 237 | top: 30px; 238 | z-index: 2; 239 | } 240 | 241 | .menu__item--depth-1 > .menu__child-toggle { 242 | position: static; 243 | right: 0; 244 | top: 0; 245 | vertical-align: middle; 246 | } 247 | 248 | .menu__child-toggle-icon { 249 | border-left: 5px solid transparent; 250 | border-right: 5px solid transparent; 251 | border-top-style: solid; 252 | border-top-width: 7px; 253 | display: block; 254 | height: 0; 255 | margin-left: 1px; 256 | width: 0; 257 | } 258 | } 259 | 260 | @media (max-width: 767px) { 261 | .menu__child-toggle { 262 | background-position: center right 30px; 263 | background-repeat: no-repeat; 264 | background-size: 20px; 265 | border: none; 266 | cursor: pointer; 267 | height: 55px; 268 | padding: 15px 0; 269 | position: absolute; 270 | right: 0; 271 | top: 0; 272 | width: 30%; 273 | } 274 | 275 | .menu__child-toggle-icon { 276 | background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTkiIGhlaWdodD0iMTkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgc3Ryb2tlPSIjOTc5ODlGIiBzdHJva2Utd2lkdGg9IjIuNCIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj48cmVjdCB4PSIxLjIiIHk9IjkuNiIgd2lkdGg9IjE2LjgiIGhlaWdodD0iMSIgcng9Ii41Ii8+PHJlY3QgdHJhbnNmb3JtPSJyb3RhdGUoOTAgOS42IDkuNikiIHg9IjEuMiIgeT0iOS42IiB3aWR0aD0iMTYuOCIgaGVpZ2h0PSIxIiByeD0iLjUiLz48L2c+PC9zdmc+); 277 | background-repeat: no-repeat; 278 | display: block; 279 | height: 20px; 280 | margin-left: auto; 281 | margin-right: 1.05rem; 282 | transition: transform 0.4s; 283 | width: 20px; 284 | } 285 | 286 | .menu__item--open > .menu__child-toggle .menu__child-toggle-icon { 287 | transform: rotate(45deg); 288 | transition: transform 0.4s; 289 | } 290 | } 291 | 292 | -------------------------------------------------------------------------------- /src/templates/partials/header.html: -------------------------------------------------------------------------------- 1 | 5 | 6 | {% macro add_lang_switcher() %} 7 | {% if get_asset_version('@hubspot/language_switcher') == 1 %} 8 | {% module "language-switcher" 9 | path="@hubspot/language_switcher", 10 | label="Language switcher", 11 | display_mode="localized" 12 | styles={ 13 | "group_button" : { 14 | "group_alignment" : { 15 | "alignment" : { 16 | "horizontal_align" : "RIGHT" 17 | } 18 | }, 19 | "group_background" : { 20 | "color" : { 21 | "color" : "#000000", 22 | "opacity" : 0 23 | } 24 | }, 25 | "group_border" : { 26 | "border" : { 27 | "bottom" : { 28 | "style" : "none" 29 | }, 30 | "left" : { 31 | "style" : "none" 32 | }, 33 | "right" : { 34 | "style" : "none" 35 | }, 36 | "top" : { 37 | "style" : "none" 38 | } 39 | } 40 | }, 41 | "group_chevron" : { 42 | "color" : { 43 | "color" : "#516d8d", 44 | "opacity" : 100 45 | }, 46 | "size" : 10, 47 | "spacing" : 10 48 | }, 49 | "group_corner" : { 50 | "radius" : 0 51 | }, 52 | "group_icon" : { 53 | "color" : { 54 | "color" : "#516d8d", 55 | "opacity" : 100 56 | }, 57 | "size" : 15, 58 | "spacing" : 10 59 | }, 60 | "group_spacing" : { 61 | "spacing" : { 62 | "padding" : { 63 | "bottom" : { 64 | "units" : "px", 65 | "value" : 7 66 | }, 67 | "left" : { 68 | "units" : "px", 69 | "value" : 15 70 | }, 71 | "right" : { 72 | "units" : "px", 73 | "value" : 15 74 | }, 75 | "top" : { 76 | "units" : "px", 77 | "value" : 7 78 | } 79 | } 80 | } 81 | }, 82 | "group_text" : { 83 | "font" : { 84 | "color" : "#516d8d", 85 | "size" : 18, 86 | "size_unit" : "px" 87 | } 88 | } 89 | }, 90 | "group_dropdown" : { 91 | "group_border" : { 92 | "border" : { 93 | "bottom" : { 94 | "color" : "#000000", 95 | "opacity" : 100, 96 | "style" : "none", 97 | "width" : { 98 | "units" : "px", 99 | "value" : 1 100 | } 101 | }, 102 | "left" : { 103 | "color" : "#000000", 104 | "opacity" : 100, 105 | "style" : "none", 106 | "width" : { 107 | "units" : "px", 108 | "value" : 1 109 | } 110 | }, 111 | "right" : { 112 | "color" : "#000000", 113 | "opacity" : 100, 114 | "style" : "none", 115 | "width" : { 116 | "units" : "px", 117 | "value" : 1 118 | } 119 | }, 120 | "top" : { 121 | "color" : "#000000", 122 | "opacity" : 100, 123 | "style" : "none", 124 | "width" : { 125 | "units" : "px", 126 | "value" : 1 127 | } 128 | } 129 | } 130 | }, 131 | "group_box_shadow" : { 132 | "add_box_shadow" : true 133 | }, 134 | "group_hover" : { 135 | "group_background" : { 136 | "color" : { 137 | "color" : "#f8fafc", 138 | "opacity" : 100 139 | } 140 | } 141 | }, 142 | "group_text" : { 143 | "font" : { 144 | "color" : "#516d8d", 145 | "size" : 16, 146 | "size_unit" : "px" 147 | } 148 | } 149 | } 150 | }, 151 | add_chevron_down=true, 152 | icon_options="icon" 153 | %} 154 | {% else %} 155 | {% module "language-switcher" 156 | path="@hubspot/language_switcher", 157 | label="Language switcher", 158 | display_mode="localized" 159 | %} 160 |
{{ locale_name(locale) }}
161 | {% endif %} 162 | {% endmacro %} 163 |
164 | 165 | {# The link below is used for a navigation skipper which allows users navigating the site with their keyboard to skip over the site navigation. More information on the navigation skipper can be found here: https://github.com/HubSpot/cms-theme-boilerplate/wiki/Accessibility #} 166 | 167 | Skip to content 168 | 169 | {# Top header drag and drop area #} 170 | 171 | {% dnd_area "header-top" 172 | label="Top header", 173 | class="content-wrapper" 174 | %} 175 | {% end_dnd_area %} 176 | 177 | {# Main header #} 178 | 179 |
180 | 181 | {# Header logo column #} 182 | 183 | 191 | 192 | {# Header navigation column #} 193 | 194 |
195 | 196 | {# Header navigation row one #} 197 | 198 | 199 | 200 |
201 | {% if content.translated_content.values()|selectattr("published")|length or is_listing_view and group.translations %} 202 |
203 |
204 | {{ add_lang_switcher() }} 205 |
206 |
207 | {% endif %} 208 | 216 |
217 | 218 | {# Header navigation row two #} 219 | 220 |
221 |
222 | {% if content.translated_content|length or is_listing_view and group.translations %} 223 |
224 | {% endif %} 225 |
226 |
227 |
228 | {% module "navigation-primary" 229 | path="../../modules/menu", 230 | label="Primary navigation" 231 | %} 232 |
233 |
234 | 235 |
236 | 237 |
238 | 239 | {# Bottom header drag and drop area #} 240 | 241 | {% dnd_area "header-bottom" 242 | label="Bottom header", 243 | class="content-wrapper" 244 | %} 245 | {% end_dnd_area %} 246 | 247 |
248 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true, 6 | }, 7 | rules: { 8 | 'accessor-pairs': 'off', 9 | 'array-bracket-newline': 'off', 10 | 'array-bracket-spacing': 'off', 11 | 'array-callback-return': 'off', 12 | 'array-element-newline': 'off', 13 | 'arrow-body-style': 'off', 14 | 'arrow-parens': 'off', 15 | 'arrow-spacing': 'off', 16 | 'block-scoped-var': 'off', 17 | 'block-spacing': 'off', 18 | 'brace-style': 'off', 19 | 'callback-return': 'off', 20 | camelcase: 'off', 21 | 'capitalized-comments': 'off', 22 | 'class-methods-use-this': 'off', 23 | 'comma-dangle': 'off', 24 | 'comma-spacing': 'off', 25 | 'comma-style': 'off', 26 | complexity: 'off', 27 | 'computed-property-spacing': 'off', 28 | 'consistent-return': 'off', 29 | 'consistent-this': 'off', 30 | 'constructor-super': 'error', 31 | curly: 'off', 32 | 'default-case': 'off', 33 | 'dot-location': 'off', 34 | 'dot-notation': 'off', 35 | 'eol-last': 'off', 36 | eqeqeq: 'off', 37 | 'for-direction': 'off', 38 | 'func-call-spacing': 'off', 39 | 'func-name-matching': 'off', 40 | 'func-names': 'off', 41 | 'func-style': 'off', 42 | 'function-paren-newline': 'off', 43 | 'generator-star': 'off', 44 | 'generator-star-spacing': 'off', 45 | 'getter-return': 'off', 46 | 'global-require': 'off', 47 | 'guard-for-in': 'off', 48 | 'handle-callback-err': 'off', 49 | 'id-blacklist': 'off', 50 | 'id-length': 'off', 51 | 'id-match': 'off', 52 | 'implicit-arrow-linebreak': 'off', 53 | indent: 'off', 54 | 'indent-legacy': 'off', 55 | 'init-declarations': 'off', 56 | 'jsx-quotes': 'off', 57 | 'key-spacing': 'off', 58 | 'keyword-spacing': 'off', 59 | 'line-comment-position': 'off', 60 | 'linebreak-style': 'off', 61 | 'lines-around-comment': 'off', 62 | 'lines-around-directive': 'off', 63 | 'lines-between-class-members': 'off', 64 | 'max-depth': 'off', 65 | 'max-len': 'off', 66 | 'max-len': 0, 67 | 'max-lines': 'off', 68 | 'max-nested-callbacks': 'off', 69 | 'max-params': 'off', 70 | 'max-statements': 'off', 71 | 'max-statements-per-line': 'off', 72 | 'multiline-comment-style': 'off', 73 | 'multiline-ternary': 'off', 74 | 'multiline-ternary': 'off', 75 | 'new-cap': 'off', 76 | 'new-parens': 'off', 77 | 'new-parens': 'off', 78 | 'newline-after-var': 'off', 79 | 'newline-before-return': 'off', 80 | 'newline-per-chained-call': 'off', 81 | 'newline-per-chained-call': 'off', 82 | 'no-alert': 'off', 83 | 'no-array-constructor': 'off', 84 | 'no-arrow-condition': 'off', 85 | 'no-await-in-loop': 'off', 86 | 'no-bitwise': 'off', 87 | 'no-buffer-constructor': 'off', 88 | 'no-caller': 'off', 89 | 'no-case-declarations': 'error', 90 | 'no-catch-shadow': 'off', 91 | 'no-class-assign': 'error', 92 | 'no-comma-dangle': 'off', 93 | 'no-compare-neg-zero': 'error', 94 | 'no-cond-assign': 'error', 95 | 'no-confusing-arrow': 'off', 96 | 'no-confusing-arrow': 0, 97 | 'no-console': 'error', 98 | 'no-const-assign': 'error', 99 | 'no-constant-condition': 'error', 100 | 'no-continue': 'off', 101 | 'no-control-regex': 'error', 102 | 'no-debugger': 'error', 103 | 'no-delete-var': 'error', 104 | 'no-div-regex': 'off', 105 | 'no-dupe-args': 'error', 106 | 'no-dupe-class-members': 'error', 107 | 'no-dupe-keys': 'error', 108 | 'no-duplicate-case': 'error', 109 | 'no-duplicate-imports': 'off', 110 | 'no-else-return': 'off', 111 | 'no-empty': 'error', 112 | 'no-empty-character-class': 'error', 113 | 'no-empty-function': 'off', 114 | 'no-empty-pattern': 'error', 115 | 'no-eq-null': 'off', 116 | 'no-eval': 'off', 117 | 'no-ex-assign': 'error', 118 | 'no-extend-native': 'off', 119 | 'no-extra-bind': 'off', 120 | 'no-extra-boolean-cast': 'error', 121 | 'no-extra-label': 'off', 122 | 'no-extra-parens': 'off', 123 | 'no-extra-parens': 'off', 124 | 'no-extra-semi': 'error', 125 | 'no-extra-semi': 'off', 126 | 'no-fallthrough': 'error', 127 | 'no-floating-decimal': 'off', 128 | 'no-floating-decimal': 'off', 129 | 'no-func-assign': 'error', 130 | 'no-global-assign': 'error', 131 | 'no-implicit-coercion': 'off', 132 | 'no-implicit-globals': 'off', 133 | 'no-implied-eval': 'off', 134 | 'no-inline-comments': 'off', 135 | 'no-inner-declarations': 'error', 136 | 'no-invalid-regexp': 'error', 137 | 'no-invalid-this': 'off', 138 | 'no-irregular-whitespace': 'error', 139 | 'no-iterator': 'off', 140 | 'no-label-var': 'off', 141 | 'no-labels': 'off', 142 | 'no-lone-blocks': 'off', 143 | 'no-lonely-if': 'off', 144 | 'no-loop-func': 'off', 145 | 'no-magic-numbers': 'off', 146 | 'no-mixed-operators': 'off', 147 | 'no-mixed-operators': 0, 148 | 'no-mixed-requires': 'off', 149 | 'no-mixed-spaces-and-tabs': 'error', 150 | 'no-mixed-spaces-and-tabs': 'off', 151 | 'no-multi-assign': 'off', 152 | 'no-multi-spaces': 'off', 153 | 'no-multi-spaces': 'off', 154 | 'no-multi-str': 'off', 155 | 'no-multiple-empty-lines': 'off', 156 | 'no-multiple-empty-lines': 'off', 157 | 'no-native-reassign': 'off', 158 | 'no-negated-condition': 'off', 159 | 'no-negated-in-lhs': 'off', 160 | 'no-nested-ternary': 'off', 161 | 'no-new': 'off', 162 | 'no-new-func': 'off', 163 | 'no-new-object': 'off', 164 | 'no-new-require': 'off', 165 | 'no-new-symbol': 'error', 166 | 'no-new-wrappers': 'off', 167 | 'no-obj-calls': 'error', 168 | 'no-octal': 'error', 169 | 'no-octal-escape': 'off', 170 | 'no-param-reassign': 'off', 171 | 'no-path-concat': 'off', 172 | 'no-plusplus': 'off', 173 | 'no-process-env': 'off', 174 | 'no-process-exit': 'off', 175 | 'no-proto': 'off', 176 | 'no-prototype-builtins': 'off', 177 | 'no-redeclare': 'error', 178 | 'no-regex-spaces': 'error', 179 | 'no-reserved-keys': 'off', 180 | 'no-restricted-globals': 'off', 181 | 'no-restricted-imports': 'off', 182 | 'no-restricted-modules': 'off', 183 | 'no-restricted-properties': 'off', 184 | 'no-restricted-syntax': 'off', 185 | 'no-return-assign': 'off', 186 | 'no-return-await': 'off', 187 | 'no-script-url': 'off', 188 | 'no-self-assign': 'error', 189 | 'no-self-compare': 'off', 190 | 'no-sequences': 'off', 191 | 'no-shadow': 'off', 192 | 'no-shadow-restricted-names': 'off', 193 | 'no-space-before-semi': 'off', 194 | 'no-spaced-func': 'off', 195 | 'no-sparse-arrays': 'error', 196 | 'no-sync': 'off', 197 | 'no-tabs': 'off', 198 | 'no-template-curly-in-string': 'off', 199 | 'no-ternary': 'off', 200 | 'no-this-before-super': 'error', 201 | 'no-throw-literal': 'off', 202 | 'no-trailing-spaces': 'off', 203 | 'no-undef': 'error', 204 | 'no-undef-init': 'off', 205 | 'no-undefined': 'off', 206 | 'no-underscore-dangle': 'off', 207 | 'no-unexpected-multiline': 'error', 208 | 'no-unexpected-multiline': 0, 209 | 'no-unmodified-loop-condition': 'off', 210 | 'no-unneeded-ternary': 'off', 211 | 'no-unreachable': 'error', 212 | 'no-unsafe-finally': 'error', 213 | 'no-unsafe-negation': 'error', 214 | 'no-unused-expressions': 'off', 215 | 'no-unused-labels': 'error', 216 | 'no-unused-vars': 'error', 217 | 'no-use-before-define': 'off', 218 | 'no-useless-call': 'off', 219 | 'no-useless-computed-key': 'off', 220 | 'no-useless-concat': 'off', 221 | 'no-useless-constructor': 'off', 222 | 'no-useless-escape': 'error', 223 | 'no-useless-rename': 'off', 224 | 'no-useless-return': 'off', 225 | 'no-var': 'off', 226 | 'no-void': 'off', 227 | 'no-warning-comments': 'off', 228 | 'no-whitespace-before-property': 'off', 229 | 'no-with': 'off', 230 | 'no-wrap-func': 'off', 231 | 'nonblock-statement-body-position': 'off', 232 | 'object-curly-newline': 'off', 233 | 'object-curly-spacing': 'off', 234 | 'object-property-newline': 'off', 235 | 'object-shorthand': 'off', 236 | 'one-var': 'off', 237 | 'one-var-declaration-per-line': 'off', 238 | 'operator-assignment': 'off', 239 | 'operator-linebreak': 'off', 240 | 'padded-blocks': 'off', 241 | 'padding-line-between-statements': 'off', 242 | 'prefer-arrow-callback': 'off', 243 | 'prefer-const': 'off', 244 | 'prefer-destructuring': 'off', 245 | 'prefer-numeric-literals': 'off', 246 | 'prefer-promise-reject-errors': 'off', 247 | 'prefer-reflect': 'off', 248 | 'prefer-rest-params': 'off', 249 | 'prefer-spread': 'off', 250 | 'prefer-template': 'off', 251 | 'quote-props': 'off', 252 | quotes: 'off', 253 | radix: 'off', 254 | 'require-await': 'off', 255 | 'require-jsdoc': 'off', 256 | 'require-yield': 'error', 257 | 'rest-spread-spacing': 'off', 258 | semi: 'off', 259 | 'semi-spacing': 'off', 260 | 'semi-style': 'off', 261 | 'sort-imports': 'off', 262 | 'sort-keys': 'off', 263 | 'sort-vars': 'off', 264 | 'space-after-function-name': 'off', 265 | 'space-after-keywords': 'off', 266 | 'space-before-blocks': 'off', 267 | 'space-before-function-paren': 'off', 268 | 'space-before-function-parentheses': 'off', 269 | 'space-before-keywords': 'off', 270 | 'space-in-brackets': 'off', 271 | 'space-in-parens': 'off', 272 | 'space-infix-ops': 'off', 273 | 'space-return-throw-case': 'off', 274 | 'space-unary-ops': 'off', 275 | 'space-unary-word-ops': 'off', 276 | 'spaced-comment': 'off', 277 | strict: 'off', 278 | 'switch-colon-spacing': 'off', 279 | 'symbol-description': 'off', 280 | 'template-curly-spacing': 'off', 281 | 'template-tag-spacing': 'off', 282 | 'unicode-bom': 'off', 283 | 'use-isnan': 'error', 284 | 'valid-jsdoc': 'off', 285 | 'valid-typeof': 'error', 286 | 'vars-on-top': 'off', 287 | 'wrap-iife': 'off', 288 | 'wrap-regex': 'off', 289 | 'yield-star-spacing': 'off', 290 | yoda: 'off', 291 | }, 292 | }; 293 | -------------------------------------------------------------------------------- /src/modules/pricing-card.module/fields.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "label": "Product tier", 4 | "name": "tier", 5 | "id": "tier", 6 | "type": "richtext", 7 | "enabled_features": [ 8 | "alignment", 9 | "block", 10 | "font_family", 11 | "font_size", 12 | "standard_emphasis" 13 | ], 14 | "default": "

Free

" 15 | }, 16 | { 17 | "label": "Product description", 18 | "name": "description", 19 | "type": "richtext", 20 | "enabled_features": [ 21 | "alignment", 22 | "block", 23 | "font_family", 24 | "font_size", 25 | "standard_emphasis" 26 | ], 27 | "default": "

For teams that need additional security, control, and support.

" 28 | }, 29 | { 30 | "label": "Features list icon", 31 | "name": "feature_icon", 32 | "type": "icon", 33 | "icon_set" : "fontawesome-6.4.2", 34 | "default": { 35 | "name": "check", 36 | "type": "SOLID", 37 | "unicode": "f00c" 38 | } 39 | }, 40 | { 41 | "label": "Features", 42 | "name": "features", 43 | "type": "text", 44 | "occurrence": { 45 | "default": 4, 46 | "max": 50, 47 | "min": 1 48 | }, 49 | "show_emoji_picker": true, 50 | "default": [ 51 | "10 users included", 52 | "2 GB of storage", 53 | "Email support", 54 | "Help center access" 55 | ] 56 | }, 57 | { 58 | "label": "Price", 59 | "name": "price", 60 | "type": "text", 61 | "default": "$0" 62 | }, 63 | { 64 | "label": "Price timeframe", 65 | "name": "timeframe", 66 | "type": "text", 67 | "default": "/ mo" 68 | }, 69 | { 70 | "label": "Button text", 71 | "name": "button_text", 72 | "type": "text", 73 | "default": "Sign up for free" 74 | }, 75 | { 76 | "label": "Button target", 77 | "name": "button_target", 78 | "id": "button_target", 79 | "type": "choice", 80 | "choices": [ 81 | ["payment_link", "Use a payment link"], 82 | ["custom_link", "Other"] 83 | ], 84 | "display": "radio", 85 | "default" : "payment_link" 86 | }, 87 | { 88 | "label": "Button link", 89 | "name": "button_link", 90 | "type": "link", 91 | "visibility": { 92 | "controlling_field": "button_target", 93 | "controlling_value_regex": "custom_link", 94 | "operator": "EQUAL" 95 | }, 96 | "supported_types": ["EXTERNAL", "CONTENT"], 97 | "default": { 98 | "url": { 99 | "content_id": null, 100 | "type": "EXTERNAL", 101 | "href": "" 102 | } 103 | } 104 | }, 105 | { 106 | "label": "Payment link", 107 | "name": "payment_link", 108 | "id": "payment_link", 109 | "type": "payment", 110 | "visibility": { 111 | "controlling_field": "button_target", 112 | "controlling_value_regex": "payment_link", 113 | "operator": "EQUAL" 114 | }, 115 | "required": true 116 | }, 117 | { 118 | "label": "Checkout behavior", 119 | "name": "checkout_behavior", 120 | "type": "choice", 121 | "visibility_rules": "ADVANCED", 122 | "advanced_visibility": { 123 | "boolean_operator": "AND", 124 | "criteria": [ 125 | { 126 | "controlling_field": "button_target", 127 | "controlling_value_regex": "payment_link", 128 | "operator": "EQUAL" 129 | }, 130 | { 131 | "controlling_field": "payment_link", 132 | "controlling_value_regex": "id\":\\d+", 133 | "operator": "MATCHES_REGEX" 134 | } 135 | ] 136 | }, 137 | "choices": [ 138 | ["new_tab", "Open in a new tab"], 139 | ["overlay", "Sliding overlay"] 140 | ], 141 | "display": "radio", 142 | "default": "overlay" 143 | }, 144 | { 145 | "label": "Styles", 146 | "name": "styles", 147 | "type": "group", 148 | "tab": "STYLE", 149 | "children": [ 150 | { 151 | "label": "Features", 152 | "name": "features", 153 | "type": "group", 154 | "children": [ 155 | { 156 | "label": "Icon", 157 | "name": "icon", 158 | "type": "group", 159 | "children": [ 160 | { 161 | "label": "Color", 162 | "name": "color", 163 | "type": "color", 164 | "visibility": { 165 | "hidden_subfields": { 166 | "opacity": true 167 | } 168 | } 169 | } 170 | ] 171 | }, 172 | { 173 | "label": "Text", 174 | "name": "text", 175 | "type": "group", 176 | "children": [ 177 | { 178 | "label": "Font", 179 | "name": "font", 180 | "type": "font" 181 | } 182 | ] 183 | }, 184 | { 185 | "label": "Border", 186 | "name": "border", 187 | "type": "group", 188 | "children": [ 189 | { 190 | "label": "Color", 191 | "name": "color", 192 | "type": "color" 193 | } 194 | ] 195 | }, 196 | { 197 | "label": "Alignment", 198 | "name": "alignment", 199 | "type": "group", 200 | "children": [ 201 | { 202 | "label": "Alignment", 203 | "name": "alignment", 204 | "type": "alignment", 205 | "alignment_direction": "HORIZONTAL" 206 | } 207 | ] 208 | } 209 | ] 210 | }, 211 | { 212 | "label": "Price", 213 | "name": "price", 214 | "type": "group", 215 | "children": [ 216 | { 217 | "label": "Text", 218 | "name": "text", 219 | "type": "group", 220 | "children": [ 221 | { 222 | "label": "Font", 223 | "name": "font", 224 | "type": "font" 225 | } 226 | ] 227 | }, 228 | { 229 | "label": "Alignment", 230 | "name": "alignment", 231 | "type": "group", 232 | "children": [ 233 | { 234 | "label": "Alignment", 235 | "name": "alignment", 236 | "type": "alignment", 237 | "alignment_direction": "HORIZONTAL" 238 | } 239 | ] 240 | } 241 | ] 242 | }, 243 | { 244 | "label": "Button", 245 | "name": "button", 246 | "type": "group", 247 | "children": [ 248 | { 249 | "label": "Text", 250 | "name": "text", 251 | "type": "group", 252 | "children": [ 253 | { 254 | "label": "Font", 255 | "name": "font", 256 | "type": "font" 257 | } 258 | ] 259 | }, 260 | { 261 | "label": "Background", 262 | "name": "background", 263 | "type": "group", 264 | "children": [ 265 | { 266 | "label": "Color", 267 | "name": "color", 268 | "type": "color" 269 | } 270 | ] 271 | }, 272 | { 273 | "label": "Border", 274 | "name": "border", 275 | "type": "group", 276 | "children": [ 277 | { 278 | "label" : "Border", 279 | "name" : "border", 280 | "type" : "border" 281 | } 282 | ] 283 | }, 284 | { 285 | "label": "Corner", 286 | "name": "corner", 287 | "type": "group", 288 | "children": [ 289 | { 290 | "label": "Radius", 291 | "name": "radius", 292 | "type": "number", 293 | "display": "text", 294 | "max": 100, 295 | "step": 1, 296 | "suffix": "px" 297 | } 298 | ] 299 | }, 300 | { 301 | "label": "Spacing", 302 | "name": "spacing", 303 | "type": "group", 304 | "children": [ 305 | { 306 | "label": "Spacing", 307 | "name": "spacing", 308 | "type": "spacing", 309 | "visibility": { 310 | "hidden_subfields": { 311 | "margin": true 312 | } 313 | } 314 | } 315 | ] 316 | }, 317 | { 318 | "label": "Alignment", 319 | "name": "alignment", 320 | "type": "group", 321 | "children": [ 322 | { 323 | "label": "Alignment", 324 | "name": "alignment", 325 | "type": "alignment", 326 | "alignment_direction": "HORIZONTAL" 327 | } 328 | ] 329 | } 330 | ] 331 | }, 332 | { 333 | "label": "Card", 334 | "name": "card", 335 | "type": "group", 336 | "children": [ 337 | { 338 | "label": "Background", 339 | "name": "background", 340 | "type": "group", 341 | "children": [ 342 | { 343 | "label": "Background type", 344 | "name": "background_type", 345 | "id": "styles.card.background.background_type", 346 | "type": "choice", 347 | "choices": [ 348 | ["none", "None"], 349 | ["color", "Background color"], 350 | ["gradient", "Background gradient"], 351 | ["image", "Background image"] 352 | ], 353 | "display": "radio", 354 | "default": "none" 355 | }, 356 | { 357 | "label": "Color", 358 | "name": "color", 359 | "type": "color", 360 | "visibility": { 361 | "controlling_field": "styles.card.background.background_type", 362 | "controlling_value_regex": "color", 363 | "operator": "EQUAL" 364 | } 365 | }, 366 | { 367 | "label": "Gradient", 368 | "name": "gradient", 369 | "type": "gradient", 370 | "visibility": { 371 | "controlling_field": "styles.card.background.background_type", 372 | "controlling_value_regex": "gradient", 373 | "operator": "EQUAL" 374 | } 375 | }, 376 | { 377 | "label": "Image", 378 | "name": "image", 379 | "type": "backgroundimage", 380 | "visibility": { 381 | "controlling_field": "styles.card.background.background_type", 382 | "controlling_value_regex": "image", 383 | "operator": "EQUAL" 384 | } 385 | } 386 | ] 387 | }, 388 | { 389 | "label": "Border", 390 | "name": "border", 391 | "type": "group", 392 | "children": [ 393 | { 394 | "label": "Border", 395 | "name": "border", 396 | "type": "border" 397 | } 398 | ] 399 | }, 400 | { 401 | "label": "Corner", 402 | "name": "corner", 403 | "type": "group", 404 | "children": [ 405 | { 406 | "label": "Radius", 407 | "name": "radius", 408 | "type": "number", 409 | "display": "text", 410 | "max": 100, 411 | "step": 1, 412 | "suffix": "px" 413 | } 414 | ] 415 | }, 416 | { 417 | "label": "Spacing", 418 | "name": "spacing", 419 | "type": "group", 420 | "children": [ 421 | { 422 | "label": "Spacing", 423 | "name": "spacing", 424 | "type": "spacing" 425 | } 426 | ] 427 | } 428 | ] 429 | } 430 | ] 431 | } 432 | ] 433 | -------------------------------------------------------------------------------- /src/modules/pricing-card.module/module.html: -------------------------------------------------------------------------------- 1 | {# Module variables #} 2 | 3 | {# Setting variable to true if the button_target field has payment_link selected (based on new field setup in comments for this PR #} 4 | 5 | {% set has_payment_link = module.button_target == "payment_link" %} 6 | 7 | {# Setting variable to true if the checkout_behavior is set to overlay #} 8 | 9 | {% set has_overlay = has_payment_link and module.checkout_behavior == "overlay" %} 10 | 11 | {# Sets attributes used for the link field #} 12 | 13 | {% if has_payment_link %} 14 | {% set href = module.payment_link.properties.checkoutUrl ~ "?referrer=CMS_MODULE_NEWTAB" %} 15 | {% set data_src = module.payment_link.properties.checkoutUrl ~ "?referrer=CMS_MODULE_OVERLAY&layout=full-page-overlay" %} 16 | {% do rel.append("nofollow") %} 17 | {% do rel.append("noopener") %} 18 | {% else %} 19 | {% set href = module.button_link.url.href %} 20 | {% if module.button_link.url.type is equalto "EMAIL_ADDRESS" %} 21 | {% set href = "mailto:" + href %} 22 | {% endif %} 23 | {% set rel = [] %} 24 | {% if module.button_link.no_follow %} 25 | {% do rel.append("nofollow") %} 26 | {% endif %} 27 | {% if module.button_link.open_in_new_tab %} 28 | {% do rel.append("noopener") %} 29 | {% endif %} 30 | {% endif %} 31 | 32 | {# Module styles #} 33 | 34 | {% require_css %} 35 | 122 | {% end_require_css %} 123 | 124 | {# Pricing card #} 125 | 126 |
127 | {% if module.tier and module.description %} 128 |
129 | {% if module.tier %} 130 | {{ module.tier|sanitize_html }} 131 | {% endif %} 132 | {% if module.description %} 133 | {{ module.description|sanitize_html }} 134 | {% endif %} 135 |
136 | {% endif %} 137 |
138 |
139 |
    140 | {% for feature in module.features %} 141 |
  • 142 | {% icon 143 | extra_classes="card__icon", 144 | name="{{ module.feature_icon.name }}", 145 | purpose="decorative", 146 | style="{{ module.feature_icon.type }}", 147 | unicode="{{ module.feature_icon.unicode }}" 148 | %}{{ feature|escape_html }} 149 |
  • 150 | {% endfor %} 151 |
152 |
153 |

{{ module.price|escape_html }}{{ module.timeframe|escape_html }}

154 | 170 |
171 |
172 | 173 | {% if has_overlay %} 174 | 175 | 194 | {% endif %} 195 | 196 | {# Module JS #} 197 | 198 | {% if has_overlay %} 199 | {% require_js %} 200 | 327 | {% end_require_js %} 328 | {% endif %} 329 | --------------------------------------------------------------------------------