├── .circleci ├── config.yml └── frontools │ └── config │ └── themes.json ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .sass-lint.yml ├── .stylelintrc ├── CHANGELOG.md ├── LICENSE ├── README.md ├── components ├── 01-globals │ ├── _base │ │ └── _base.scss │ ├── _components.scss │ ├── _container │ │ └── _container.scss │ ├── _focus │ │ └── _focus.scss │ ├── _fonts │ │ ├── _fonts.scss │ │ ├── fonts.config.js │ │ ├── fonts.hbs │ │ ├── montserrat-black.svg │ │ ├── montserrat-black.woff │ │ ├── montserrat-black.woff2 │ │ ├── montserrat-bold.svg │ │ ├── montserrat-bold.woff │ │ ├── montserrat-bold.woff2 │ │ ├── montserrat-regular.svg │ │ ├── montserrat-regular.woff │ │ └── montserrat-regular.woff2 │ ├── grid │ │ ├── _grid.scss │ │ ├── grid.config.js │ │ └── grid.hbs │ ├── icon │ │ ├── _icon.scss │ │ ├── icon.config.js │ │ └── icon.hbs │ ├── icons │ │ ├── README.md │ │ ├── files │ │ │ ├── account-mini.svg │ │ │ ├── account.svg │ │ │ ├── angle-down.svg │ │ │ ├── angle-left.svg │ │ │ ├── angle-right.svg │ │ │ ├── angle-up.svg │ │ │ ├── arrow-down.svg │ │ │ ├── arrow-left.svg │ │ │ ├── arrow-right.svg │ │ │ ├── arrow-up.svg │ │ │ ├── check.svg │ │ │ ├── checked.svg │ │ │ ├── close.svg │ │ │ ├── compare.svg │ │ │ ├── curved-arrows.svg │ │ │ ├── delivery-truck.svg │ │ │ ├── edit.svg │ │ │ ├── envelope.svg │ │ │ ├── error.svg │ │ │ ├── facebook.svg │ │ │ ├── google-plus.svg │ │ │ ├── grid.svg │ │ │ ├── heart.svg │ │ │ ├── instagram.svg │ │ │ ├── linkedin.svg │ │ │ ├── list.svg │ │ │ ├── loader.svg │ │ │ ├── minus.svg │ │ │ ├── mobile-menu.svg │ │ │ ├── phone.svg │ │ │ ├── plus.svg │ │ │ ├── question-mark.svg │ │ │ ├── remove.svg │ │ │ ├── search.svg │ │ │ ├── settings.svg │ │ │ ├── shield.svg │ │ │ ├── shipping-time-truck.svg │ │ │ ├── shopping-cart.svg │ │ │ ├── signin.svg │ │ │ ├── star-border.svg │ │ │ ├── star.svg │ │ │ ├── twitter.svg │ │ │ ├── user.svg │ │ │ ├── warning.svg │ │ │ └── youtube.svg │ │ ├── icons.config.js │ │ └── icons.hbs │ ├── layouts │ │ └── _layouts.scss │ ├── libs │ │ ├── _choices.scss │ │ ├── _normalize.scss │ │ ├── _nouislider.scss │ │ ├── choices.js │ │ ├── choices.js.map │ │ ├── debounce.js │ │ ├── lazysizes.js │ │ ├── libs.hbs │ │ ├── lory.js │ │ ├── nouislider.min.js │ │ └── svg4everybody.js │ ├── mixins │ │ ├── _clearfix.scss │ │ ├── _focus.scss │ │ ├── _isIE.scss │ │ ├── _mq.scss │ │ ├── _svg-uri.scss │ │ └── _visually-hidden.scss │ ├── recaptcha │ │ └── _recaptcha.scss │ ├── typography │ │ ├── README.md │ │ ├── blockquote │ │ │ ├── _blockquote.scss │ │ │ └── blockquote.hbs │ │ ├── error │ │ │ └── _error.scss │ │ ├── heading │ │ │ ├── _heading.scss │ │ │ ├── heading.config.js │ │ │ └── heading.hbs │ │ ├── label │ │ │ ├── _label.scss │ │ │ └── label.hbs │ │ ├── link │ │ │ ├── _link.scss │ │ │ ├── link.config.js │ │ │ └── link.hbs │ │ ├── paragraph │ │ │ ├── _paragraph.scss │ │ │ ├── paragraph.config.js │ │ │ └── paragraph.hbs │ │ └── preformatted │ │ │ ├── _preformatted.scss │ │ │ └── preformatted.hbs │ └── variables │ │ ├── _variables.scss │ │ ├── variables.config.js │ │ └── variables.hbs ├── 02-elements │ ├── _components.scss │ ├── action │ │ ├── _action.scss │ │ ├── action.config.js │ │ └── action.hbs │ ├── badge │ │ ├── _badge.scss │ │ ├── badge.config.js │ │ └── badge.hbs │ ├── banner │ │ ├── _banner.scss │ │ ├── banner.config.js │ │ └── banner.hbs │ ├── breadcrumbs │ │ ├── _breadcrumbs.scss │ │ ├── breadcrumbs.config.js │ │ └── breadcrumbs.hbs │ ├── button │ │ ├── README.md │ │ ├── _button.scss │ │ ├── button.config.js │ │ └── button.hbs │ ├── cookie-message │ │ ├── README.md │ │ ├── _cookie-message.scss │ │ ├── cookie-message.config.js │ │ ├── cookie-message.hbs │ │ └── cookie-message.js │ ├── divider │ │ ├── _divider.scss │ │ └── divider.hbs │ ├── dropdown-list │ │ ├── README.md │ │ ├── _dropdown-list.scss │ │ ├── dropdown-list.config.js │ │ ├── dropdown-list.hbs │ │ └── dropdown-list.js │ ├── form │ │ ├── checkbox │ │ │ ├── _checkbox.scss │ │ │ ├── checkbox--link.hbs │ │ │ ├── checkbox.config.js │ │ │ └── checkbox.hbs │ │ ├── fieldset │ │ │ ├── _fieldset.scss │ │ │ ├── fieldset.config.js │ │ │ └── fieldset.hbs │ │ ├── file-upload │ │ │ ├── _file-upload.scss │ │ │ ├── file-upload.config.js │ │ │ ├── file-upload.hbs │ │ │ └── file-upload.js │ │ ├── input │ │ │ ├── _input.scss │ │ │ ├── input--textarea.hbs │ │ │ ├── input.config.js │ │ │ └── input.hbs │ │ ├── radio │ │ │ ├── _radio.scss │ │ │ ├── radio.config.js │ │ │ └── radio.hbs │ │ └── select │ │ │ ├── _select.scss │ │ │ ├── select.config.js │ │ │ ├── select.hbs │ │ │ └── select.js │ ├── image │ │ ├── _image.scss │ │ ├── image--picture.hbs │ │ ├── image.config.js │ │ └── image.hbs │ ├── information │ │ ├── _information.scss │ │ ├── information.config.js │ │ └── information.hbs │ ├── list │ │ ├── README.md │ │ ├── _list.scss │ │ ├── list--description.hbs │ │ ├── list--icon.hbs │ │ ├── list--image.hbs │ │ ├── list--link-content.hbs │ │ ├── list--link.hbs │ │ ├── list.config.js │ │ └── list.hbs │ ├── loader │ │ ├── _loader.scss │ │ └── loader.hbs │ ├── logo │ │ ├── _logo.scss │ │ ├── logo.config.js │ │ └── logo.hbs │ ├── marketing-bar │ │ ├── _marketing-bar.scss │ │ ├── marketing-bar.config.js │ │ ├── marketing-bar.hbs │ │ └── marketing-bar.js │ ├── message │ │ ├── _message.scss │ │ ├── message.config.js │ │ └── message.hbs │ ├── modal-trigger │ │ ├── modal-trigger.config.js │ │ └── modal-trigger.hbs │ ├── pager │ │ ├── README.md │ │ ├── _pager.scss │ │ ├── pager.config.js │ │ └── pager.hbs │ ├── password-strength │ │ ├── _password-strength.scss │ │ ├── password-strength.config.js │ │ └── password-strength.hbs │ ├── price │ │ ├── _price.scss │ │ ├── price--between.hbs │ │ ├── price--with-special-price.hbs │ │ ├── price.config.js │ │ └── price.hbs │ ├── rating │ │ ├── README.md │ │ ├── _rating.scss │ │ ├── rating--rate.hbs │ │ ├── rating-rate.js │ │ ├── rating.config.js │ │ └── rating.hbs │ ├── skip-nav │ │ ├── _skip-nav.scss │ │ ├── skip-nav--list.hbs │ │ ├── skip-nav.config.js │ │ ├── skip-nav.hbs │ │ └── skip-nav.js │ ├── swatch │ │ ├── README.md │ │ ├── _swatch.scss │ │ ├── swatch.config.js │ │ ├── swatch.hbs │ │ └── swatch.js │ ├── tab │ │ ├── README.md │ │ ├── _tab.scss │ │ ├── tab.config.js │ │ ├── tab.hbs │ │ └── tab.js │ └── table │ │ ├── README.md │ │ ├── _table.scss │ │ ├── table.config.js │ │ └── table.hbs ├── 03-modules │ ├── _components.scss │ ├── active-filters │ │ ├── _active-filters.scss │ │ ├── active-filters.config.js │ │ └── active-filters.hbs │ ├── additional-content │ │ ├── _additional-content.scss │ │ ├── additional-content.config.js │ │ └── additional-content.hbs │ ├── brief-info │ │ ├── _brief-info.scss │ │ ├── brief-info.config.js │ │ └── brief-info.hbs │ ├── bundle-option │ │ ├── _bundle-option.scss │ │ ├── bundle-option--checkbox.hbs │ │ ├── bundle-option--select.hbs │ │ ├── bundle-option.config.js │ │ └── bundle-option.hbs │ ├── cart-list-item │ │ ├── _cart-list-item.scss │ │ ├── cart-list-item.config.js │ │ └── cart-list-item.hbs │ ├── catalog-grid-item │ │ ├── _catalog-grid-item.scss │ │ ├── catalog-grid-item.config.js │ │ └── catalog-grid-item.hbs │ ├── catalog-list-item │ │ ├── _catalog-list-item.scss │ │ ├── catalog-list-item.config.js │ │ └── catalog-list-item.hbs │ ├── dashboard │ │ ├── actions-toolbar │ │ │ ├── _actions-toolbar.scss │ │ │ ├── actions-toolbar.config.js │ │ │ └── actions-toolbar.hbs │ │ ├── form │ │ │ ├── _form.scss │ │ │ ├── form.config.js │ │ │ ├── form.hbs │ │ │ └── form.js │ │ ├── items │ │ │ ├── _items.scss │ │ │ ├── items.config.js │ │ │ └── items.hbs │ │ ├── nav │ │ │ ├── _nav.scss │ │ │ ├── nav.config.js │ │ │ ├── nav.hbs │ │ │ └── nav.js │ │ └── table │ │ │ ├── _table.scss │ │ │ ├── table.config.js │ │ │ └── table.hbs │ ├── filter │ │ ├── _filter.scss │ │ ├── filter--category.hbs │ │ ├── filter--color.hbs │ │ ├── filter--range.hbs │ │ ├── filter--swatch.hbs │ │ ├── filter.config.js │ │ └── filter.hbs │ ├── filters │ │ ├── _filters.scss │ │ ├── filters.config.js │ │ ├── filters.hbs │ │ └── filters.js │ ├── footer │ │ ├── _footer.scss │ │ ├── footer.config.js │ │ ├── footer.hbs │ │ └── footer.js │ ├── gallery │ │ ├── _gallery.scss │ │ ├── gallery.config.js │ │ └── gallery.hbs │ ├── header │ │ ├── _button.scss │ │ ├── _featured-info.scss │ │ ├── _header.scss │ │ ├── _search-form.scss │ │ ├── _top-bar.scss │ │ ├── header.config.js │ │ └── header.hbs │ ├── mega-menu │ │ ├── _mega-menu.scss │ │ ├── mega-menu.config.js │ │ ├── mega-menu.hbs │ │ └── mega-menu.js │ ├── minicart-content │ │ ├── _minicart-content.scss │ │ ├── minicart-content.config.js │ │ └── minicart-content.hbs │ ├── minicart-product │ │ ├── _minicart-product.scss │ │ ├── minicart-product.config.js │ │ └── minicart-product.hbs │ ├── modal │ │ ├── README.md │ │ ├── _modal.scss │ │ ├── modal.config.js │ │ ├── modal.hbs │ │ └── modal.js │ ├── newsletter │ │ ├── _newsletter.scss │ │ ├── newsletter.config.js │ │ └── newsletter.hbs │ ├── popup │ │ ├── _popup.scss │ │ ├── popup.config.js │ │ ├── popup.hbs │ │ └── popup.js │ ├── product-view │ │ └── product-review │ │ │ ├── _product-review.scss │ │ │ ├── product-review.config.js │ │ │ └── product-review.hbs │ ├── quantity-update │ │ ├── _quantity-update.scss │ │ ├── quantity-update.config.js │ │ ├── quantity-update.hbs │ │ └── quantity-update.js │ ├── quicksearch │ │ ├── _quicksearch.scss │ │ ├── quicksearch.config.js │ │ └── quicksearch.hbs │ ├── range │ │ ├── _range.scss │ │ ├── range.config.js │ │ ├── range.hbs │ │ └── range.js │ ├── review │ │ ├── _review.scss │ │ ├── review--add.hbs │ │ ├── review--summary.hbs │ │ ├── review.config.js │ │ └── review.hbs │ ├── side-menu │ │ ├── _side-menu.scss │ │ ├── side-menu.config.js │ │ ├── side-menu.hbs │ │ └── side-menu.js │ ├── sidebar-block │ │ ├── _sidebar-block.scss │ │ ├── sidebar-block--recently-ordered.hbs │ │ ├── sidebar-block--wishlist.hbs │ │ ├── sidebar-block.config.js │ │ └── sidebar-block.hbs │ ├── slider │ │ ├── README.md │ │ ├── _slider.scss │ │ ├── slider.config.js │ │ ├── slider.hbs │ │ └── slider.js │ ├── title-wrapper │ │ ├── _title-wrapper.scss │ │ ├── title-wrapper.config.js │ │ └── title-wrapper.hbs │ └── toolbar │ │ ├── _toolbar.scss │ │ ├── toolbar.config.js │ │ └── toolbar.hbs ├── 04-views │ ├── _components.scss │ ├── b2b │ │ └── quickorder │ │ │ ├── _quickorder.scss │ │ │ ├── quickorder.config.js │ │ │ └── quickorder.hbs │ ├── cart │ │ ├── _actions.scss │ │ ├── _discount.scss │ │ ├── _main.scss │ │ ├── _summary.scss │ │ ├── _totals.scss │ │ ├── cart.config.js │ │ └── cart.hbs │ ├── catalog │ │ ├── grid │ │ │ ├── _grid.scss │ │ │ ├── grid.config.js │ │ │ └── grid.hbs │ │ └── list │ │ │ ├── _list.scss │ │ │ ├── list.config.js │ │ │ └── list.hbs │ ├── compare │ │ ├── _compare.scss │ │ ├── compare.config.js │ │ └── compare.hbs │ ├── confirmation-link │ │ ├── _confirmation-link.scss │ │ ├── confirmation-link.config.js │ │ └── confirmation-link.hbs │ ├── dashboard │ │ ├── account-info │ │ │ ├── account-info.config.js │ │ │ └── account-info.hbs │ │ ├── address-book │ │ │ ├── address-book--edit.hbs │ │ │ ├── address-book.config.js │ │ │ └── address-book.hbs │ │ ├── company-profile │ │ │ ├── company-profile--edit.hbs │ │ │ ├── company-profile.config.js │ │ │ └── company-profile.hbs │ │ ├── company-structure │ │ │ ├── _company-structure.scss │ │ │ ├── company-structure.config.js │ │ │ └── company-structure.hbs │ │ ├── company-users │ │ │ ├── _company-users.scss │ │ │ ├── company-users.config.js │ │ │ └── company-users.hbs │ │ ├── default │ │ │ ├── _dashboard.scss │ │ │ ├── dashboard.config.js │ │ │ └── dashboard.hbs │ │ ├── downloadable-product │ │ │ ├── downloadable-product.config.js │ │ │ └── downloadable-product.hbs │ │ ├── empty │ │ │ ├── empty.config.js │ │ │ └── empty.hbs │ │ ├── gift-card │ │ │ ├── gift-card.config.js │ │ │ └── gift-card.hbs │ │ ├── gift-registry │ │ │ ├── gift-registry--form.hbs │ │ │ ├── gift-registry--form.js │ │ │ ├── gift-registry--general-information.hbs │ │ │ ├── gift-registry.config.js │ │ │ └── gift-registry.hbs │ │ ├── invitation │ │ │ ├── invitation--form.hbs │ │ │ ├── invitation.config.js │ │ │ └── invitation.hbs │ │ ├── my-orders │ │ │ ├── my-orders--details.hbs │ │ │ ├── my-orders--return.hbs │ │ │ ├── my-orders.config.js │ │ │ └── my-orders.hbs │ │ ├── my-quotes │ │ │ ├── _my-quotes.scss │ │ │ ├── my-quotes.config.js │ │ │ └── my-quotes.hbs │ │ ├── newsletter-sub │ │ │ ├── newsletter-sub.config.js │ │ │ └── newsletter-sub.hbs │ │ ├── order-by-sku │ │ │ ├── order-by-sku.config.js │ │ │ └── order-by-sku.hbs │ │ ├── product-reviews │ │ │ ├── _product-reviews.scss │ │ │ ├── product-reviews--details.hbs │ │ │ ├── product-reviews.config.js │ │ │ └── product-reviews.hbs │ │ ├── requisition-lists │ │ │ ├── _requisition-lists--view.scss │ │ │ ├── requisition-lists--view.hbs │ │ │ ├── requisition-lists.config.js │ │ │ └── requisition-lists.hbs │ │ ├── returns │ │ │ ├── returns--details.hbs │ │ │ ├── returns.config.js │ │ │ └── returns.hbs │ │ ├── reward-points │ │ │ ├── reward-points.config.js │ │ │ └── reward-points.hbs │ │ ├── roles-and-permissions │ │ │ ├── _roles-and-permissions.scss │ │ │ ├── roles-and-permissions--edit.hbs │ │ │ ├── roles-and-permissions.config.js │ │ │ └── roles-and-permissions.hbs │ │ ├── store-credit │ │ │ └── store-credit.hbs │ │ └── wishlist │ │ │ ├── _wishlist.scss │ │ │ ├── wishlist.config.js │ │ │ └── wishlist.hbs │ ├── email-to-friend │ │ ├── _email-to-friend.scss │ │ ├── email-to-friend.config.js │ │ └── email-to-friend.hbs │ ├── forgot-password │ │ ├── _forgot-password.scss │ │ ├── forgot-password.config.js │ │ └── forgot-password.hbs │ ├── home │ │ ├── _home.scss │ │ ├── home.config.js │ │ └── home.hbs │ ├── login │ │ ├── _login.scss │ │ ├── login.config.js │ │ └── login.hbs │ ├── product-view │ │ ├── _product-view.scss │ │ ├── product-view--bundle.hbs │ │ ├── product-view--grouped.hbs │ │ ├── product-view.config.js │ │ └── product-view.hbs │ └── registration │ │ ├── _registration.scss │ │ ├── registration.config.js │ │ └── registration.hbs ├── _a11y-tests.hbs ├── _docs-only-styles.hbs ├── _preview.hbs └── _styles.scss ├── composer.json ├── docs └── styles │ ├── _fractal.scss │ ├── a11y-tests │ └── _a11y-tests.scss │ ├── docs-only-styles │ ├── _button.scss │ ├── _filter.scss │ ├── _grid.scss │ ├── _icons.scss │ ├── _list.scss │ ├── _minicart-product.scss │ ├── _newsletter.scss │ ├── _product.scss │ └── _search.scss │ └── styles.scss ├── gulpfile.js ├── now.json ├── package.json ├── public ├── images │ ├── banner │ │ ├── banner-1024_416.jpg │ │ ├── banner-1170_300.png │ │ ├── banner-1920_512.jpg │ │ ├── banner-320_176.jpg │ │ ├── banner-480_480.png │ │ ├── banner-768_402.png │ │ ├── banner-768_416.jpg │ │ └── banner-992_254.png │ ├── catalog-grid-item │ │ ├── product-1_320_312.jpg │ │ ├── product-2_320_312.jpg │ │ ├── product-3_320_312.jpg │ │ └── product-color-swatch-image-1-32_40.jpg │ ├── gallery │ │ ├── product-img-384-384.jpg │ │ ├── product-img-496-496.jpg │ │ └── product-img-80-80.jpg │ ├── home │ │ ├── banners │ │ │ ├── banner-medium-discover_304-176.jpg │ │ │ ├── banner-medium-discover_464-256.jpg │ │ │ ├── banner-medium-discover_656-360.jpg │ │ │ ├── banner-medium-discover_752-360.jpg │ │ │ ├── banner-medium-new_304-176.jpg │ │ │ ├── banner-medium-new_464-256.jpg │ │ │ ├── banner-medium-new_656-360.jpg │ │ │ ├── banner-medium-new_752-360.jpg │ │ │ ├── banner-small-gear_304-184.jpg │ │ │ ├── banner-small-gear_432-248.jpg │ │ │ ├── banner-small-men_304-184.jpg │ │ │ ├── banner-small-men_432-248.jpg │ │ │ ├── banner-small-women_304-184.jpg │ │ │ └── banner-small-women_432-248.jpg │ │ └── brand-example_112-112.png │ ├── icons │ │ └── arrow-down.svg │ ├── login │ │ ├── banner-304-144.jpg │ │ ├── banner-304-144@2x.jpg │ │ ├── banner-304-144@3x.jpg │ │ ├── banner-464-360@2x.jpg │ │ └── banner-656-360.jpg │ ├── logo │ │ └── logo.svg │ ├── product-view │ │ ├── banner.jpg │ │ └── slider-image.jpg │ ├── product │ │ ├── cart-product-160_160.jpg │ │ ├── minicart-product-72_72.png │ │ ├── product-base.jpg │ │ ├── product-img-230_180.png │ │ ├── product-img-70_46.png │ │ └── product-second.jpg │ ├── slider │ │ ├── slider-1500_500.png │ │ ├── slider-1920_500.png │ │ ├── slider-480_510.png │ │ ├── slider-768_500.png │ │ └── slider-992_646.png │ └── swatch │ │ ├── swatch-green.jpg │ │ ├── swatch-orange.jpg │ │ ├── swatch-red.jpg │ │ └── swatch-white.jpg └── tests │ ├── a11y-test.js │ └── libs │ └── accessibilityjs.js ├── static.json └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | build: 3 | docker: 4 | - image: circleci/php:7.2-stretch-node 5 | environment: 6 | - THEME_PATH: "vendor/snowdog/module-alpaca-components" 7 | - CONFIG_PATH: "vendor/snowdog/module-alpaca-components/.circleci/frontools/config" 8 | steps: 9 | - checkout 10 | - run: mkdir -p $THEME_PATH 11 | - run: rsync -r --delete . $THEME_PATH 12 | - run: cp "$THEME_PATH/composer.json" . 13 | - run: composer require snowdog/frontools --no-interaction --prefer-dist 14 | - run: mkdir -p dev/tools/frontools 15 | - run: cp -r $CONFIG_PATH dev/tools/frontools 16 | - run: cd vendor/snowdog/frontools && yarn && yarn setup 17 | - run: cd tools && yarn inheritance 18 | - run: cd tools && yarn sasslint --ci 19 | - run: cd tools && yarn styles --ci --pipeline 20 | - run: cd tools && yarn csslint --ci 21 | -------------------------------------------------------------------------------- /.circleci/frontools/config/themes.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpaca": { 3 | "src": "vendor/snowdog/module-alpaca-components", 4 | "dest": "pub/static/frontend/Snowdog/alpaca-components", 5 | "locale": ["en_US"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | charset = utf-8 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | 7 | [*.{css,scss,html,hbs}] 8 | indent_style = space 9 | indent_size = 4 10 | 11 | [*.{js,json}] 12 | indent_style = space 13 | indent_size = 2 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | components/01-globals/libs/*.js 2 | build/components/01-globals/libs/*.js 3 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | extends: 2 | - eslint:recommended 3 | - idiomatic 4 | env: 5 | browser: true 6 | es6: true 7 | amd: true 8 | jquery: true 9 | globals: 10 | module: true 11 | rules: 12 | no-multi-spaces: 0 13 | space-in-parens: 0 14 | array-bracket-spacing: 0 15 | computed-property-spacing: 0 16 | key-spacing: 0 17 | no-var: 2 18 | indent: 19 | - 2 20 | - 2 21 | - 22 | VariableDeclarator: 23 | var: 2 24 | let: 2 25 | const: 3 26 | brace-style: 27 | - 2 28 | - 'stroustrup' 29 | - 30 | allowSingleLine: false 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Jetbrains IDE 2 | .idea 3 | 4 | # Env 5 | .DS_Store 6 | 7 | # Dependencies 8 | node_modules 9 | 10 | # Build 11 | build 12 | dest 13 | public/css 14 | public/images/icons-sprite.svg 15 | 16 | # Libs 17 | vendor 18 | -------------------------------------------------------------------------------- /.sass-lint.yml: -------------------------------------------------------------------------------- 1 | # Linter Options 2 | options: 3 | merge-default-rules: false 4 | 5 | # Rule Configuration 6 | rules: 7 | brace-style: 8 | - 2 9 | - 10 | style: 'stroustrup' 11 | clean-import-paths: 2 12 | extends-before-declarations: 2 13 | extends-before-mixins: 2 14 | final-newline: 2 15 | indentation: 16 | - 2 17 | - 18 | size: 4 19 | leading-zero: 20 | - 2 21 | - 22 | include: true 23 | no-css-comments: 2 24 | no-debug: 1 25 | no-empty-rulesets: 2 26 | no-ids: 1 27 | no-important: 1 28 | no-invalid-hex: 2 29 | no-misspelled-properties: 30 | - 2 31 | - 32 | extra-properties: 33 | - 'touch-callout' 34 | - 'overflow-scrolling' 35 | no-vendor-prefixes: 1 36 | no-warn: 1 37 | one-declaration-per-line: 2 38 | single-line-per-selector: 2 39 | space-after-colon: 2 40 | space-after-comma: 2 41 | space-around-operator: 2 42 | space-before-bang: 2 43 | space-before-brace: 2 44 | trailing-semicolon: 2 45 | zero-unit: 2 46 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | extends: stylelint-config-standard 2 | rules: 3 | at-rule-empty-line-before: null 4 | block-closing-brace-newline-before: null 5 | indentation: null 6 | rule-empty-line-before: null 7 | selector-list-comma-newline-after: null 8 | selector-pseudo-element-colon-notation: null 9 | selector-descendant-combinator-no-non-space: null 10 | shorthand-property-no-redundant-values: null 11 | declaration-block-no-shorthand-property-overrides: null 12 | declaration-block-no-duplicate-properties: null 13 | comment-empty-line-before: null 14 | color-hex-length: null 15 | no-descending-specificity: null 16 | font-family-no-missing-generic-family-keyword: null 17 | no-duplicate-selectors: null 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Snowdog Apps 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /components/01-globals/_base/_base.scss: -------------------------------------------------------------------------------- 1 | *, 2 | *::after, 3 | *::before { 4 | box-sizing: border-box; 5 | } 6 | 7 | html, 8 | body { 9 | height: 100%; 10 | min-width: 320px; 11 | font-family: $font-family-base; 12 | font-weight: $font-weight-base; 13 | font-size: $font-size-base; 14 | color: $font-color-base; 15 | } 16 | 17 | body { 18 | display: flex; 19 | flex-direction: column; 20 | } 21 | 22 | .page-wrapper { 23 | flex: 1 0 auto; 24 | } 25 | 26 | p { 27 | margin: 0; 28 | padding: 0; 29 | } 30 | 31 | dl, 32 | dt, 33 | dd { 34 | margin: 0; 35 | } 36 | -------------------------------------------------------------------------------- /components/01-globals/_components.scss: -------------------------------------------------------------------------------- 1 | // ----- 2 | // Globals 3 | // ----- 4 | 5 | // Libs 6 | @import 'libs/normalize'; 7 | @import 'libs/choices'; 8 | @import 'libs/nouislider'; 9 | 10 | // Mixins 11 | @import 'mixins/clearfix'; 12 | @import 'mixins/focus'; 13 | @import 'mixins/isIE'; 14 | @import 'mixins/mq'; 15 | @import 'mixins/svg-uri'; 16 | @import 'mixins/visually-hidden'; 17 | 18 | // Base 19 | @import '_base/base'; 20 | @import '_container/container'; 21 | @import '_focus/focus'; 22 | @import 'grid/grid'; 23 | @import 'icon/icon'; 24 | @import 'layouts/layouts'; 25 | @import 'recaptcha/recaptcha'; 26 | 27 | // Typography 28 | @import '_fonts/fonts'; 29 | @import 'typography/blockquote/blockquote'; 30 | @import 'typography/error/error'; 31 | @import 'typography/heading/heading'; 32 | @import 'typography/label/label'; 33 | @import 'typography/link/link'; 34 | @import 'typography/paragraph/paragraph'; 35 | @import 'typography/preformatted/preformatted'; 36 | -------------------------------------------------------------------------------- /components/01-globals/_container/_container.scss: -------------------------------------------------------------------------------- 1 | $container__max-width: $max-content-width !default; 2 | $container__margin : 8px !default; 3 | 4 | .container { 5 | max-width: $container__max-width; 6 | margin: 0 $container__margin; 7 | @include mq($container__max-width + 2 * $container__margin) { 8 | margin: 0 auto; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /components/01-globals/_focus/_focus.scss: -------------------------------------------------------------------------------- 1 | .js-focus-visible :focus:not(.focus-visible) { 2 | outline: $outline-base; 3 | } 4 | 5 | .js-focus-visible .focus-visible { 6 | @include focus(); 7 | } 8 | -------------------------------------------------------------------------------- /components/01-globals/_fonts/_fonts.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Montserrat'; 3 | src: 4 | url('/components/raw/fonts/montserrat-regular.woff2') format('woff2'), 5 | url('/components/raw/fonts/montserrat-regular.woff') format('woff'), 6 | url('/components/raw/fonts/montserrat-regular.svg') format('svg'); 7 | font-weight: normal; 8 | font-style: normal; 9 | } 10 | @font-face { 11 | font-family: 'Montserrat'; 12 | src: 13 | url('/components/raw/fonts/montserrat-bold.woff2') format('woff2'), 14 | url('/components/raw/fonts/montserrat-bold.woff') format('woff'), 15 | url('/components/raw/fonts/montserrat-bold.svg') format('svg'); 16 | font-weight: 700; 17 | font-style: normal; 18 | } 19 | @font-face { 20 | font-family: 'Montserrat'; 21 | src: 22 | url('/components/raw/fonts/montserrat-black.woff2') format('woff2'), 23 | url('/components/raw/fonts/montserrat-black.woff') format('woff'), 24 | url('/components/raw/fonts/montserrat-black.svg') format('svg'); 25 | font-weight: 900; 26 | font-style: normal; 27 | } 28 | -------------------------------------------------------------------------------- /components/01-globals/_fonts/fonts.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'Fonts' 3 | }; 4 | -------------------------------------------------------------------------------- /components/01-globals/_fonts/fonts.hbs: -------------------------------------------------------------------------------- 1 | Fonts 2 | -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-black.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-black.woff -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-black.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-black.woff2 -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-bold.woff -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-bold.woff2 -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-regular.woff -------------------------------------------------------------------------------- /components/01-globals/_fonts/montserrat-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/components/01-globals/_fonts/montserrat-regular.woff2 -------------------------------------------------------------------------------- /components/01-globals/grid/grid.hbs: -------------------------------------------------------------------------------- 1 |

{{ title }}

2 |
3 | {{#each grids as |grid|}} 4 |
5 | {{#each grid}} 6 |
7 |
8 | {{ @index }} 9 |
10 |
11 | {{/each}} 12 |
13 | {{/each}} 14 |
15 | -------------------------------------------------------------------------------- /components/01-globals/icon/_icon.scss: -------------------------------------------------------------------------------- 1 | $icon__size : 24px !default; 2 | $icon__padding : 2px !default; 3 | 4 | .icon { 5 | display: block; 6 | width: $icon__size; 7 | height: $icon__size; 8 | padding: $icon__padding; 9 | } 10 | -------------------------------------------------------------------------------- /components/01-globals/icon/icon.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | id: 'angle-down', 4 | title: 'Angle down icon' 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /components/01-globals/icon/icon.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{#if title }} 3 | {{ title }} 4 | {{/if}} 5 | 6 | 7 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/account-mini.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/account.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/angle-down.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/angle-left.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/angle-right.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/angle-up.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/arrow-left.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/arrow-right.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/arrow-up.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/check.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/checked.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/close.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/compare.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/curved-arrows.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/edit.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/envelope.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/error.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/facebook.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/google-plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/grid.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/heart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/instagram.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/linkedin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/list.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/minus.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/mobile-menu.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/phone.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/plus.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/question-mark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/remove.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/search.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/shield.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/shopping-cart.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/signin.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/star-border.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/star.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/twitter.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/user.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /components/01-globals/icons/files/warning.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /components/01-globals/icons/icons.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#each icons}} 3 |
4 | {{ render '@icon' this }} 5 | 6 | {{ this.id }} 7 | 8 |
9 | {{/each}} 10 |
11 | -------------------------------------------------------------------------------- /components/01-globals/layouts/_layouts.scss: -------------------------------------------------------------------------------- 1 | $layout-sidebar-width: 25% !default; 2 | $layout-content-width: calc(100% - #{$layout-sidebar-width}) !default; 3 | 4 | .page-layout-2columns-left, 5 | .page-layout-2columns-right { 6 | .columns { 7 | display: flex; 8 | flex-direction: column; 9 | 10 | @include mq($screen-m) { 11 | flex-direction: row; 12 | } 13 | } 14 | 15 | .main { 16 | @include mq($screen-m) { 17 | order: 1; 18 | flex: 1 0 $layout-content-width; 19 | max-width: $layout-content-width; 20 | } 21 | } 22 | 23 | .sidebar { 24 | @include mq($screen-m) { 25 | flex: 1 0 $layout-sidebar-width; 26 | max-width: $layout-sidebar-width; 27 | } 28 | } 29 | } 30 | 31 | .page-layout-2columns-right { 32 | .main { 33 | @include mq($screen-m) { 34 | order: 0; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /components/01-globals/libs/debounce.js: -------------------------------------------------------------------------------- 1 | function debounce(callback, wait, context = this) { 2 | let timeout = null, 3 | callbackArgs = null; 4 | 5 | const later = () => callback.apply(context, callbackArgs); 6 | 7 | return function() { 8 | callbackArgs = arguments; 9 | clearTimeout(timeout); 10 | timeout = setTimeout(later, wait); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /components/01-globals/libs/libs.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /components/01-globals/mixins/_clearfix.scss: -------------------------------------------------------------------------------- 1 | @mixin clearfix { 2 | &::after { 3 | display: table; 4 | clear: both; 5 | content: ""; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /components/01-globals/mixins/_focus.scss: -------------------------------------------------------------------------------- 1 | @mixin focus($mode: '') { 2 | outline-offset: -1px; 3 | z-index: 1; 4 | @if $mode == 'dark' { 5 | outline: $border-focus-dark; 6 | } 7 | @else { 8 | outline: $border-focus; 9 | } 10 | } 11 | 12 | @mixin focus-inline($mode: '') { 13 | outline: $outline-focus-inline; 14 | text-decoration: $text-decoration-focus-inline; 15 | @if $mode == 'dark' { 16 | color: $color-focus-inline-dark; 17 | background-color: $bg-focus-inline-dark; 18 | } 19 | @else { 20 | color: $color-focus-inline; 21 | background-color: $bg-focus-inline; 22 | } 23 | } 24 | 25 | @mixin focus-input($mode: '') { 26 | outline: $outline-base; 27 | @if $mode == 'dark' { 28 | box-shadow: none; 29 | border: 2px solid $color-primary; 30 | } 31 | @else { 32 | border-color: $form-elements-border-color-focus; 33 | box-shadow: $form-input-box-shadow-focus; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /components/01-globals/mixins/_isIE.scss: -------------------------------------------------------------------------------- 1 | //sass-lint:disable no-vendor-prefixes 2 | 3 | @mixin isIE() { 4 | @media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { 5 | @content; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /components/01-globals/mixins/_mq.scss: -------------------------------------------------------------------------------- 1 | @mixin mq($min-screen: false, $max-screen: false) { 2 | 3 | @if ($min-screen and $max-screen) { 4 | @media all and (min-width: $min-screen) and (max-width: $max-screen) { 5 | @content; 6 | } 7 | } 8 | @else if ($max-screen and not $min-screen) { 9 | @media all and (max-width: $max-screen) { 10 | @content; 11 | } 12 | } 13 | @else { 14 | @media all and (min-width: $min-screen) { 15 | @content; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/01-globals/mixins/_visually-hidden.scss: -------------------------------------------------------------------------------- 1 | @mixin visually-hidden($usePseudo: '') { 2 | position: absolute; 3 | clip: rect(0 0 0 0); 4 | width: 1px; 5 | height: 1px; 6 | margin: -1px; 7 | padding: 0; 8 | overflow: hidden; 9 | border: 0; 10 | @if $usePseudo != '' { 11 | &.focus-visible, 12 | &:active { 13 | clip: auto; 14 | height: auto; 15 | margin: 0; 16 | overflow: visible; 17 | position: static; 18 | width: auto; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/01-globals/recaptcha/_recaptcha.scss: -------------------------------------------------------------------------------- 1 | $recaptcha__badge-z-index: 100 !default; 2 | 3 | .grecaptcha-badge { 4 | z-index: $recaptcha__badge-z-index; 5 | } 6 | -------------------------------------------------------------------------------- /components/01-globals/typography/README.md: -------------------------------------------------------------------------------- 1 | # Accessibility in typography 2 | 3 | * please use apropriate HTML5 semantic tag for inline elements 4 | [HTML semantics cheat sheet - text](https://learn-the-web.algonquindesign.ca/topics/html-semantics-cheat-sheet/#text) 5 | * add `title` attribute to link - it is only for desktop mode but it shows on hover and still some people use desktop view to search the WEB ;) 6 | * Headings on the page should keep logical order h1 -> h6, use only one h1 on the top of page (not necessary the first element but it should appear on top, at the latest at the top of `main` content) 7 | * For `blockquote` element, you at least `cite` element with a link to source inside. 8 | [HTML5 Doctor - cite and blockquote](http://html5doctor.com/cite-and-blockquote-reloaded/) 9 | * Use label for EVERY form field! if design point it should be unvisible, use `visually-hidden()` sass mixin fot styling 10 | -------------------------------------------------------------------------------- /components/01-globals/typography/blockquote/_blockquote.scss: -------------------------------------------------------------------------------- 1 | $blockquote__margin : 10px 0 !default; 2 | $blockquote__padding : 10px 10px 10px 20px !default; 3 | $blockquote__border-left: 5px solid $gray-light !default; 4 | 5 | .blockquote { 6 | margin: $blockquote__margin; 7 | padding: $blockquote__padding; 8 | border-left: $blockquote__border-left; 9 | } 10 | 11 | blockquote { 12 | @extend .blockquote; 13 | } 14 | -------------------------------------------------------------------------------- /components/01-globals/typography/blockquote/blockquote.hbs: -------------------------------------------------------------------------------- 1 |
2 | Blockquote 3 | 4 | 5 | Quotation source 6 | 7 | 8 |
9 | -------------------------------------------------------------------------------- /components/01-globals/typography/error/_error.scss: -------------------------------------------------------------------------------- 1 | $input__error-color : $color-danger !default; 2 | $input__error-margin-top: $spacer !default; 3 | 4 | div { 5 | &.mage-error { 6 | margin-top: $input__error-margin-top; 7 | color: $input__error-color; 8 | } 9 | 10 | &.required { 11 | label { 12 | &:after { 13 | content: '*'; 14 | color: $input__error-color; 15 | } 16 | } 17 | } 18 | } 19 | 20 | input, 21 | textarea, 22 | select { 23 | &.mage-error { 24 | border-color: $input__error-color; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /components/01-globals/typography/heading/heading.hbs: -------------------------------------------------------------------------------- 1 | <{{{ tag }}} class="{{ class }}" {{{ attributes }}}> 2 | {{ text }} 3 | 4 | -------------------------------------------------------------------------------- /components/01-globals/typography/label/_label.scss: -------------------------------------------------------------------------------- 1 | $label-margin : 0 0 $spacer !default; 2 | $label-margin--inline: 0 $spacer 0 0 !default; 3 | $label-font-size : $font-size-base !default; 4 | $label-color : $color-secondary !default; 5 | $label-font-family : $font-family-base !default; 6 | $label-font-weight : $font-weight-normal !default; 7 | $label-line-height : $font-line-height !default; 8 | $label-transition : none !default; 9 | 10 | .label { 11 | display: block; 12 | margin: $label-margin; 13 | font-size: $label-font-size; 14 | color : $label-color; 15 | font-family: $label-font-family; 16 | font-weight: $label-font-weight; 17 | line-height: $label-line-height; 18 | transition: $label-transition; 19 | &--inline { 20 | margin: $label-margin--inline; 21 | } 22 | 23 | &--hidden { 24 | @include visually-hidden(); 25 | } 26 | } 27 | 28 | label { 29 | @extend .label; 30 | } 31 | -------------------------------------------------------------------------------- /components/01-globals/typography/label/label.hbs: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /components/01-globals/typography/link/link.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | href: '#', 4 | title: 'Title', 5 | text: 'Link' 6 | }, 7 | variants: [ 8 | { 9 | name: 'Invert', 10 | context: { 11 | class: 'link--invert' 12 | } 13 | }, 14 | { 15 | name: 'Secondary', 16 | context: { 17 | class: 'link--secondary' 18 | } 19 | } 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /components/01-globals/typography/link/link.hbs: -------------------------------------------------------------------------------- 1 | 10 | {{ text }} 11 | 12 | -------------------------------------------------------------------------------- /components/01-globals/typography/paragraph/_paragraph.scss: -------------------------------------------------------------------------------- 1 | $paragraph-color : $color-secondary !default; 2 | $paragraph-font-family: $font-family-base !default; 3 | $paragraph-font-weight: $font-weight-normal !default; 4 | $paragraph-line-height: $font-line-height !default; 5 | $paragraph-font-size : $font-size-base !default; 6 | $paragraph-margin : 0 0 $spacer--medium 0 !default; 7 | $paragraph-transition : none !default; 8 | 9 | .paragraph { 10 | color: $paragraph-color; 11 | font-family: $paragraph-font-family; 12 | font-weight: $paragraph-font-weight; 13 | line-height: $paragraph-line-height; 14 | font-size: $paragraph-font-size; 15 | margin: $paragraph-margin; 16 | transition: $paragraph-transition; 17 | } 18 | 19 | p { 20 | @extend .paragraph; 21 | } 22 | -------------------------------------------------------------------------------- /components/01-globals/typography/paragraph/paragraph.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name:'Paragraph', 3 | context: { 4 | basicText: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris' 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /components/01-globals/typography/paragraph/paragraph.hbs: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{basicText}} 4 | 5 | 6 | {{basicText}} 7 | 8 |

9 | 10 | 11 | {{basicText}} 12 | 13 | 14 |
{{basicText}}
15 | 16 |
17 | {{basicText}} 18 |
19 |
20 | -------------------------------------------------------------------------------- /components/01-globals/typography/preformatted/_preformatted.scss: -------------------------------------------------------------------------------- 1 | $preformatted__padding : 20px !default; 2 | $preformatted__background : $gray-lightest !default; 3 | $preformatted__overflow : scroll !default; 4 | $preformatted__font-family: $font-family-monospace !default; 5 | 6 | .preformatted { 7 | padding: $preformatted__padding; 8 | background: $preformatted__background; 9 | overflow: $preformatted__overflow; 10 | font-family: $preformatted__font-family; 11 | } 12 | 13 | pre { 14 | @extend .preformatted; 15 | } 16 | -------------------------------------------------------------------------------- /components/01-globals/typography/preformatted/preformatted.hbs: -------------------------------------------------------------------------------- 1 |
2 |     Preformatted text
3 | 
4 | -------------------------------------------------------------------------------- /components/01-globals/variables/variables.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | status: 'wip' 3 | } 4 | -------------------------------------------------------------------------------- /components/01-globals/variables/variables.hbs: -------------------------------------------------------------------------------- 1 | Variables 2 | -------------------------------------------------------------------------------- /components/02-elements/_components.scss: -------------------------------------------------------------------------------- 1 | // ----- 2 | // Elements 3 | // ----- 4 | 5 | @import 'action/action'; 6 | @import 'badge/badge'; 7 | @import 'banner/banner'; 8 | @import 'breadcrumbs/breadcrumbs'; 9 | @import 'button/button'; 10 | @import 'cookie-message/cookie-message'; 11 | @import 'divider/divider'; 12 | @import 'dropdown-list/dropdown-list'; 13 | @import 'form/checkbox/checkbox'; 14 | @import 'form/fieldset/fieldset'; 15 | @import 'form/file-upload/file-upload'; 16 | @import 'form/input/input'; 17 | @import 'form/radio/radio'; 18 | @import 'form/select/select'; 19 | @import 'image/image'; 20 | @import 'information/information'; 21 | @import 'list/list'; 22 | @import 'loader/loader'; 23 | @import 'logo/logo'; 24 | @import 'marketing-bar/marketing-bar'; 25 | @import 'message/message'; 26 | @import 'pager/pager'; 27 | @import 'password-strength/password-strength'; 28 | @import 'price/price'; 29 | @import 'rating/rating'; 30 | @import 'skip-nav/skip-nav'; 31 | @import 'swatch/swatch'; 32 | @import 'tab/tab'; 33 | @import 'table/table'; 34 | -------------------------------------------------------------------------------- /components/02-elements/action/_action.scss: -------------------------------------------------------------------------------- 1 | $action-margin : 15px !default; 2 | $action-padding: 15px !default; 3 | 4 | .action { 5 | display: flex; 6 | flex-flow: row wrap; 7 | justify-content: space-between; 8 | align-items: center; 9 | width: 100%; 10 | 11 | &__handler { 12 | flex-basis: 100%; 13 | margin-bottom: $action-margin; 14 | 15 | @include mq($screen-m) { 16 | flex-basis: auto; 17 | margin-bottom: 0; 18 | } 19 | } 20 | 21 | &__button { 22 | margin-right: $action-margin; 23 | height: 30px; 24 | padding: 0 20px; 25 | font-size: 14px; 26 | width: 100%; 27 | margin-bottom: $action-margin; 28 | 29 | @include mq($screen-m) { 30 | width: auto; 31 | margin-bottom: auto; 32 | } 33 | 34 | &:last-child { 35 | margin-right: 0; 36 | } 37 | } 38 | 39 | &__link { 40 | padding: $action-padding 0; 41 | margin-right: 15px; 42 | background-clip: content-box; 43 | 44 | &.focus-visible { 45 | @include focus-inline(); 46 | } 47 | 48 | &:last-child { 49 | margin-right: 0; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /components/02-elements/action/action.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | sides: [ 4 | { 5 | action: [ 6 | { 7 | button: true, 8 | title: 'Example button' 9 | } 10 | ] 11 | }, 12 | { 13 | action: [ 14 | { 15 | title: 'Link this title' 16 | } 17 | ] 18 | } 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/02-elements/action/action.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#each sides }} 3 |
4 | {{#each action }} 5 | {{#if button }} 6 | 11 | {{else}} 12 | 16 | {{ title }} 17 | 18 | {{/if}} 19 | {{/each }} 20 |
21 | {{/each}} 22 |
23 | -------------------------------------------------------------------------------- /components/02-elements/badge/badge.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collated: true, 3 | context : { 4 | text: 'Default' 5 | }, 6 | variants: [ 7 | { 8 | name: 'new', 9 | context: { 10 | text: 'new', 11 | class: 'badge--new' 12 | } 13 | }, 14 | { 15 | name: 'discount', 16 | context: { 17 | text: 'discount', 18 | class: 'badge--discount' 19 | } 20 | } 21 | ] 22 | }; 23 | -------------------------------------------------------------------------------- /components/02-elements/badge/badge.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ text }} 3 |
4 | -------------------------------------------------------------------------------- /components/02-elements/banner/_banner.scss: -------------------------------------------------------------------------------- 1 | .banner { 2 | display: block; 3 | position: relative; 4 | width: 100%; 5 | 6 | &:hover { 7 | text-decoration: none; 8 | } 9 | 10 | &__image { 11 | width: 100%; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/02-elements/banner/banner.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | link: '#', 4 | attributes: 'aria-label="descriptive text about banner action and / or image"', 5 | image: { 6 | defaultSrc: '/images/banner/banner-320_176.jpg', 7 | sources: [ 8 | { 9 | src: '/images/banner/banner-320_176.jpg', 10 | mediaQuery: '(max-width: 480px)' 11 | }, 12 | { 13 | src: '/images/banner/banner-768_416.jpg', 14 | mediaQuery: '(max-width: 960px)' 15 | }, 16 | { 17 | src: '/images/banner/banner-1024_416.jpg', 18 | mediaQuery: '(max-width: 1328px)' 19 | }, 20 | { 21 | src: '/images/banner/banner-1920_512.jpg', 22 | mediaQuery: '' 23 | } 24 | ], 25 | alt: 'banner-image' 26 | } 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /components/02-elements/banner/banner.hbs: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /components/02-elements/breadcrumbs/breadcrumbs.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | ariaLabel: 'Breadcrumbs', 4 | categories: [ 5 | { 6 | name: 'Home', 7 | href: '#', 8 | linkClass: 'breadcrumbs__link link--invert' 9 | }, 10 | { 11 | name: 'category2', 12 | href: '#', 13 | linkClass: 'breadcrumbs__link link--invert' 14 | }, 15 | { 16 | name: 'category3', 17 | href: '#', 18 | linkClass: 'breadcrumbs__link link--invert' 19 | }, 20 | { 21 | name: 'category4', 22 | href: '#', 23 | linkClass: 'breadcrumbs__link link--invert' 24 | }, 25 | { 26 | name: 'category5', 27 | href: '#', 28 | linkClass: 'breadcrumbs__link link--invert' 29 | }, 30 | { 31 | name: 'category6', 32 | href: '#', 33 | } 34 | ] 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /components/02-elements/breadcrumbs/breadcrumbs.hbs: -------------------------------------------------------------------------------- 1 | 30 | 31 | -------------------------------------------------------------------------------- /components/02-elements/button/README.md: -------------------------------------------------------------------------------- 1 | # Accessibility notice for buttons 2 | 3 | IMPORTANT! All buttons that don't have text inside (labels) and have only graphic representation, usage or `aria-label` or `aria-labelledby` is mandatory! Text inside aria label should be informative and should explain what the button is for. 4 | -------------------------------------------------------------------------------- /components/02-elements/button/button.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preview: '@docs-only-styles', 3 | collated: true, 4 | context: { 5 | tag: 'button', 6 | class: '', 7 | attributes: 'type="button"', 8 | text: 'I am a button' 9 | }, 10 | variants: [ 11 | { 12 | name: 'icon', 13 | context: { 14 | text: '', 15 | class: 'button--icon', 16 | icon: { 17 | id: 'arrow-left', 18 | title: 'Arrow left', 19 | class: 'button__icon', 20 | }, 21 | attributes: 'type="button" aria-label="click to do something"' 22 | } 23 | }, 24 | { 25 | name: 'secondary', 26 | context: { 27 | class: 'button--secondary', 28 | text: 'I am button secondary' 29 | } 30 | }, 31 | { 32 | name: 'link', 33 | context: { 34 | tag: 'a', 35 | class: 'button--link', 36 | attributes: 'href="#" title="I am a link button"', 37 | text: 'I am a link button' 38 | } 39 | }, 40 | { 41 | name: 'fluid', 42 | context: { 43 | class: 'button--fluid' 44 | } 45 | }, 46 | 47 | ] 48 | }; 49 | -------------------------------------------------------------------------------- /components/02-elements/button/button.hbs: -------------------------------------------------------------------------------- 1 | <{{{ tag }}} class="button {{ class }}" {{{ attributes }}}> 2 | {{{ text }}} 3 | {{#if icon }} 4 | {{ render '@icon' icon }} 5 | {{/if}} 6 | 7 | -------------------------------------------------------------------------------- /components/02-elements/cookie-message/README.md: -------------------------------------------------------------------------------- 1 | # Cookie message accessibility 2 | 3 | 1. Implementing cookie message we have to remember about focus management. After closing bar, focus should be set on some visible element on the page. In this component it's set to move focus on the first focusable elements on the website. 4 | 2. Aria labels on buttons should be set, icon can be hidden (aria-hidden="true") 5 | -------------------------------------------------------------------------------- /components/02-elements/cookie-message/cookie-message.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Message', 3 | context: { 4 | linkAnchor: 'Action\'s details', 5 | ariaLabel: 'Cookie policy message', 6 | closeIcon: 'close', 7 | closeLabel: false, 8 | closeAriaLabel: 'Close cookie message', 9 | text: 'Example link Find out more about their purpose and settings in your browser. By browsing the site you are agreeing to use cookies according to your browser settings.', 10 | class: 'cookie-message', 11 | dataType: 'cookie' 12 | }, 13 | variants: [ 14 | { 15 | name: 'With button', 16 | context: { 17 | linkAnchor: 'Details', 18 | ariaLabel: 'Cookie policy message', 19 | closeIcon: 'close', 20 | closeLabel: 'Close', 21 | closeAriaLabel: false, 22 | text: 'This site uses cookies. Example link Find out more about their purpose and settings in your browser. By browsing the site you are agreeing to use cookies according to your browser settings.', 23 | class: 'cookie-message--with-button', 24 | dataType: 'cookie1' 25 | } 26 | } 27 | ] 28 | }; 29 | -------------------------------------------------------------------------------- /components/02-elements/cookie-message/cookie-message.hbs: -------------------------------------------------------------------------------- 1 | 30 | 31 | -------------------------------------------------------------------------------- /components/02-elements/divider/_divider.scss: -------------------------------------------------------------------------------- 1 | $divider__height : 8px !default; 2 | $divider__height--before : 100% !default; 3 | $divider__width--before : 30% !default; 4 | $divider__background-color : $gray-lighter !default; 5 | $divider__background-color--before: $color-primary !default; 6 | 7 | .divider { 8 | display: flex; 9 | height: $divider__height; 10 | background-color: $divider__background-color; 11 | 12 | &::before { 13 | content: ''; 14 | width: $divider__width--before; 15 | height: $divider__height--before; 16 | background-color: $divider__background-color--before; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/02-elements/divider/divider.hbs: -------------------------------------------------------------------------------- 1 |
2 | -------------------------------------------------------------------------------- /components/02-elements/dropdown-list/README.md: -------------------------------------------------------------------------------- 1 | # Dropdown list 2 | 3 | ## Accessibility: 4 | * Buttons (reactive elements, which open dropdown) should have following aria attributes: 5 | * `aria-expanded` - set to `true` if dropdown field is open, to `false` when it's closed 6 | * `aria-controls` where value it's an `id` of content dropdown element 7 | * Dropdown content should have `aria-hidden` attribute set to `true` of it's closed and to `false` when it's open. 8 | * focus management and keyboard support should be implemented 9 | 10 | -------------------------------------------------------------------------------- /components/02-elements/form/checkbox/checkbox--link.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {{ label.text }} 7 | 8 | 9 | -------------------------------------------------------------------------------- /components/02-elements/form/checkbox/checkbox.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collated: true, 3 | context: { 4 | id: 'checkbox', 5 | name: 'checkbox-name', 6 | label: { 7 | text: 'Checkbox field', 8 | class: '' 9 | }, 10 | icon: { 11 | class: '' 12 | }, 13 | input: { 14 | class: '' 15 | } 16 | }, 17 | variants: [ 18 | { 19 | name: 'long-label', 20 | context: { 21 | id: 'checkbox-long-label', 22 | label: { 23 | text: 'I hereby agree for processing my personal data, included in my job offer, for the purpose of recruitment (as defined in the Act of August 29, 1997 on the Protection of Personal Data (Journal of Laws No. 133, item 883).' 24 | }, 25 | } 26 | }, 27 | { 28 | name: 'link', 29 | context: { 30 | class: '', 31 | href: '#', 32 | label: { 33 | text: 'Checkbox link' 34 | }, 35 | } 36 | } 37 | ] 38 | }; 39 | -------------------------------------------------------------------------------- /components/02-elements/form/checkbox/checkbox.hbs: -------------------------------------------------------------------------------- 1 |
2 | 7 | 8 | 9 | 10 | 13 |
14 | -------------------------------------------------------------------------------- /components/02-elements/form/fieldset/_fieldset.scss: -------------------------------------------------------------------------------- 1 | $fieldset__border : none !default; 2 | $fieldset__margin : 0 !default; 3 | $fieldset__padding : 0 !default; 4 | $fieldset__legend-margin : 0 0 25px !default; 5 | $fieldset__legend-font-size : $font-size-large !default; 6 | $fieldset__legend-line-height: 1.2 !default; 7 | 8 | .fieldset { 9 | border: $fieldset__border; 10 | padding: $fieldset__padding; 11 | margin: $fieldset__margin; 12 | 13 | &__legend { 14 | padding: 0; 15 | margin: $fieldset__legend-margin; 16 | font-size: $fieldset__legend-font-size; 17 | line-height: $fieldset__legend-line-height; 18 | } 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /components/02-elements/form/fieldset/fieldset.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | class: '', 4 | legend: { 5 | text: 'Legend', 6 | class: '' 7 | } 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /components/02-elements/form/fieldset/fieldset.hbs: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{ legend.text }} 4 | 5 |
6 | -------------------------------------------------------------------------------- /components/02-elements/form/file-upload/file-upload.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | labelText: 'Your file (pdf, doc, max 1 MB)', 4 | fileName: 'File not choosen', 5 | id: 'file', 6 | input: { 7 | name: 'file', 8 | formats: '.pdf,.doc,.png', 9 | size: '1024' 10 | }, 11 | button: { 12 | tag: 'span', 13 | class: 'file-upload__button', 14 | attributes: 'role="button" tabindex="0" aria-controls="file"', 15 | text: 'Upload a file' 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/02-elements/form/file-upload/file-upload.hbs: -------------------------------------------------------------------------------- 1 |
2 | 9 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /components/02-elements/form/file-upload/file-upload.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function FileUpload() { 4 | const components = [...document.querySelectorAll('.file-upload')]; 5 | 6 | components.forEach(component => { 7 | const input = component.querySelector('.file-upload__input'), 8 | name = component.querySelector('.file-upload__name'), 9 | button = component.querySelector('span[role="button"]'); 10 | 11 | input.addEventListener('change', file => { 12 | const filePath = file.target.value, 13 | fileName = filePath.split('\\').pop(); 14 | 15 | if (fileName) { 16 | name.textContent = fileName; 17 | } 18 | else { 19 | name.textContent = name.dataset.defaultText; 20 | } 21 | name.focus(); 22 | }); 23 | 24 | button.addEventListener('keypress', event => { 25 | if (event.which === 32 || event.which === 13) { 26 | input.click(); 27 | } 28 | }); 29 | }); 30 | })(); 31 | -------------------------------------------------------------------------------- /components/02-elements/form/input/input--textarea.hbs: -------------------------------------------------------------------------------- 1 |
2 | 8 | 9 | 15 |
16 | -------------------------------------------------------------------------------- /components/02-elements/form/input/input.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | attributes: '', 4 | class: '', 5 | label: { 6 | attributes: '', 7 | text: 'Label text', 8 | hidden: false 9 | }, 10 | field: { 11 | attributes: '', 12 | class: '', 13 | id: 'field-id', 14 | name: 'field-name', 15 | placeholder: 'First and last name', 16 | type: 'text' 17 | } 18 | }, 19 | variants: [ 20 | { 21 | name: 'inline', 22 | context: { 23 | class: 'input--inline' 24 | } 25 | } 26 | ] 27 | }; 28 | -------------------------------------------------------------------------------- /components/02-elements/form/input/input.hbs: -------------------------------------------------------------------------------- 1 |
2 | 15 | 23 |
24 | -------------------------------------------------------------------------------- /components/02-elements/form/radio/radio.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | name: 'radio1', 4 | legend: 'Choose option', 5 | legendId: 'legend-id', 6 | options: [ 7 | { 8 | id: 'id1', 9 | label: 'Option one' 10 | }, 11 | { 12 | id: 'id2', 13 | label: 'Option two' 14 | }, 15 | { 16 | id: 'id3', 17 | label: 'Options three' 18 | } 19 | ] 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /components/02-elements/form/radio/radio.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{#if legend }} 4 | 5 | {{ legend }} 6 | 7 | {{/if }} 8 | {{#each options}} 9 |
10 | 16 | 23 |
24 | {{/each}} 25 |
26 |
27 | -------------------------------------------------------------------------------- /components/02-elements/form/select/select.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | label: { 4 | attributes: '', 5 | text: 'Label text', 6 | class: 'select__label' 7 | }, 8 | field: { 9 | id: 'field-id', 10 | name: 'field-name', 11 | class: '', 12 | attributes: '' 13 | }, 14 | options: [ 15 | { 16 | value: 'option1', 17 | text: 'Option 1' 18 | }, 19 | { 20 | value: 'option2', 21 | text: 'Option 2' 22 | }, 23 | { 24 | value: 'option3', 25 | text: 'Option 3', 26 | attributes: 'disabled' 27 | } 28 | ] 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /components/02-elements/form/select/select.hbs: -------------------------------------------------------------------------------- 1 |
2 | 9 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /components/02-elements/form/select/select.js: -------------------------------------------------------------------------------- 1 | /* global Choices */ 2 | 3 | (function() { // eslint-disable-line 4 | 'use strict' 5 | 6 | const selects = [...document.querySelectorAll('.select__field')]; 7 | 8 | selects.forEach(select => { 9 | new Choices(select, { 10 | searchEnabled: false, 11 | classNames: { 12 | containerInner: 'select__field', 13 | list: 'select__field-list', 14 | input: 'select__field-input', 15 | item: 'select__field-item', 16 | listSingle: 'select__field-list--single', 17 | }, 18 | itemSelectText: '' 19 | }); 20 | }); 21 | }()); 22 | -------------------------------------------------------------------------------- /components/02-elements/image/_image.scss: -------------------------------------------------------------------------------- 1 | $image__width : 100% !default; 2 | $image__transition : $transition-fade !default; 3 | $image__wrapper-background-color: $white !default; 4 | 5 | .image { 6 | display: block; 7 | width: $image__width; 8 | max-width: $image__width; 9 | transition: $image__transition; 10 | 11 | &.lazyload, 12 | &.lazyloading { 13 | opacity: 0; 14 | } 15 | 16 | &.lazyloaded { 17 | opacity: 1; 18 | } 19 | } 20 | 21 | img, 22 | picture { 23 | @extend .image; 24 | } 25 | 26 | .lazyload-wrapper { 27 | position: relative; 28 | background-color: $image__wrapper-background-color; 29 | } 30 | -------------------------------------------------------------------------------- /components/02-elements/image/image--picture.hbs: -------------------------------------------------------------------------------- 1 | 2 | {{#each sources}} 3 | 4 | {{/each}} 5 | 6 | {{ alt }} 12 | 13 | -------------------------------------------------------------------------------- /components/02-elements/image/image.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | src: 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==', 4 | dataSrc: '/images/banner/banner-480_480.png', 5 | alt: 'image alt text' 6 | }, 7 | variants: [ 8 | { 9 | name: 'picture', 10 | context: { 11 | defaultSrc: '/images/banner/banner-480_480.png', 12 | sources: [ 13 | { 14 | src: '/images/banner/banner-480_480.png', 15 | mediaQuery: '(max-width: 480px)' 16 | }, 17 | { 18 | src: '/images/banner/banner-768_402.png', 19 | mediaQuery: '(max-width: 768px)' 20 | }, 21 | { 22 | src: '/images/banner/banner-992_254.png', 23 | mediaQuery: '(max-width: 992px)' 24 | }, 25 | { 26 | src: '/images/banner/banner-1170_300.png', 27 | mediaQuery: '' 28 | } 29 | ], 30 | alt: 'image alt text' 31 | } 32 | } 33 | ] 34 | }; 35 | -------------------------------------------------------------------------------- /components/02-elements/image/image.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ alt }} 9 |
10 | -------------------------------------------------------------------------------- /components/02-elements/information/_information.scss: -------------------------------------------------------------------------------- 1 | $information-margin: 15px !default; 2 | 3 | .information { 4 | margin-bottom: $information-margin * 2; 5 | 6 | &__title { 7 | margin-bottom: $information-margin; 8 | } 9 | 10 | &__text { 11 | margin-bottom: 0; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/02-elements/information/information.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | informations: [ 4 | { 5 | title: 'Balance', 6 | text: 'Your balance is: $0.00', 7 | headingTag: 'h5' 8 | }, 9 | { 10 | title: 'Redeem Gift Card', 11 | text: 'Have a gift card? Click here to redeem it.', 12 | headingTag: 'h5' 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /components/02-elements/information/information.hbs: -------------------------------------------------------------------------------- 1 | {{#each informations }} 2 |
3 | <{{headingTag}} class="heading heading--fifth-level information__title"> 4 | {{ title }} 5 | 6 | 7 |

8 | {{ text }} 9 |

10 |
11 | {{/each}} 12 | -------------------------------------------------------------------------------- /components/02-elements/list/README.md: -------------------------------------------------------------------------------- 1 | # Improve a11y on the lists 2 | 3 | If the list is preceded by the title (in heading or some other element), it's recommended to add an `aria-labelledby` attribute on the list and bind there the list title: 4 | 5 | ```html 6 |

List title

7 | 24 | ``` 25 | -------------------------------------------------------------------------------- /components/02-elements/list/list--description.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{# each elements }} 3 |
{{ label }}
4 |
{{ value }}
5 | {{/ each }} 6 |
7 | -------------------------------------------------------------------------------- /components/02-elements/list/list--icon.hbs: -------------------------------------------------------------------------------- 1 | <{{{ listTag }}} class="list {{ class }}" {{{ attributes }}}> 2 | {{# each elements }} 3 | <{{{ ../elementTag }}} class="list__item {{ this.class }}"> 4 | 5 | {{ render '@icon' this.icon }} 6 | 7 | 8 | {{/ each }} 9 | 10 | -------------------------------------------------------------------------------- /components/02-elements/list/list--image.hbs: -------------------------------------------------------------------------------- 1 | <{{{ listTag }}} class="list {{ class }}" {{{ attributes }}}> 2 | {{# each elements }} 3 | <{{{ ../elementTag }}} class="list__item"> 4 |
5 | {{ render '@image' }} 6 |
7 |
8 | {{ text }} 9 |
10 | 11 | {{/ each }} 12 | 13 | -------------------------------------------------------------------------------- /components/02-elements/list/list--link-content.hbs: -------------------------------------------------------------------------------- 1 | <{{{ listTag }}} class="list {{ class }}" {{{ attributes }}}> 2 | {{# each elements }} 3 | <{{{ ../elementTag }}} class="list__item {{ this.class }}"> 4 | 5 | {{ render (component content) contentContext }} 6 | 7 | 8 | {{/ each }} 9 | 10 | -------------------------------------------------------------------------------- /components/02-elements/list/list--link.hbs: -------------------------------------------------------------------------------- 1 | <{{{ listTag }}} class="list {{ class }}" {{{ attributes }}}> 2 | {{# each elements }} 3 | <{{{ ../elementTag }}} class="list__item {{ this.class }}"> 4 | 5 | {{ text }} 6 | 7 | 8 | {{/ each }} 9 | 10 | -------------------------------------------------------------------------------- /components/02-elements/list/list.hbs: -------------------------------------------------------------------------------- 1 | <{{{ listTag }}} class="list {{ class }}" {{{ attributes }}}> 2 | {{# each elements }} 3 | <{{{ ../elementTag }}} class="list__item {{ this.class }}"> 4 | {{{ text }}} 5 | 6 | {{/ each }} 7 | 8 | -------------------------------------------------------------------------------- /components/02-elements/loader/_loader.scss: -------------------------------------------------------------------------------- 1 | $loader__size : 100% !default; 2 | $loader__circle-size : 80px !default; 3 | $loader__circle-border : $spacer solid $gray-lightest !default; 4 | $loader__circle-border-top : $spacer solid $color-primary !default; 5 | $loader__circle-border-radius: 50% !default; 6 | $loader__circle-animation : rotate 1s infinite linear !default; 7 | 8 | @keyframes rotate { 9 | 0% {transform: rotate(0deg);} 10 | 100% {transform: rotate(360deg);} 11 | } 12 | 13 | .loader { 14 | position: absolute; 15 | top: 0; 16 | left: 0; 17 | display: none; 18 | width: $loader__size; 19 | height: $loader__size; 20 | background-color: inherit; 21 | 22 | &--visible { 23 | display: block; 24 | } 25 | 26 | &__circle { 27 | position: absolute; 28 | top: 0; 29 | left: 0; 30 | right: 0; 31 | bottom: 0; 32 | width: $loader__circle-size; 33 | height: $loader__circle-size; 34 | margin: auto; 35 | border: $loader__circle-border; 36 | border-top: $loader__circle-border-top; 37 | border-radius: $loader__circle-border-radius; 38 | animation: $loader__circle-animation; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /components/02-elements/loader/loader.hbs: -------------------------------------------------------------------------------- 1 |
6 |
7 |
8 | -------------------------------------------------------------------------------- /components/02-elements/logo/_logo.scss: -------------------------------------------------------------------------------- 1 | $logo__max-width : 84px !default; 2 | $logo__max-width\@medium : 112px !default; 3 | $logo__image-height : 25px !default; 4 | $logo__image-height\@medium : 34px !default; 5 | 6 | .logo { 7 | display: flex; 8 | align-items: center; 9 | flex: 1 $logo__max-width; 10 | justify-content: center; 11 | max-width: $logo__max-width; 12 | 13 | @include mq($screen-m) { 14 | flex: 1 $logo__max-width\@medium; 15 | max-width: $logo__max-width\@medium; 16 | } 17 | 18 | &__image { 19 | height: $logo__image-height; 20 | 21 | @include mq($screen-m) { 22 | height: $logo__image-height\@medium; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /components/02-elements/logo/logo.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Logo', 3 | context: { 4 | class: '', 5 | ariaLabel: 'Homepage', 6 | imageAlt: 'Alpaca Logo', 7 | imageAttributes: '', 8 | imageClass: '', 9 | imageSrc: '/images/logo/logo.svg', 10 | href: '#' 11 | } 12 | }; 13 | -------------------------------------------------------------------------------- /components/02-elements/logo/logo.hbs: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /components/02-elements/marketing-bar/marketing-bar.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | closeIcon: 'close', 4 | text: 'Subscribe and get 10$ for Shopping!', 5 | class: 'marketing-bar--closed', 6 | attributes: 'data-type="marketing-bar"', 7 | closeButton: { 8 | tag: 'button', 9 | text: '', 10 | class: 'button--icon marketing-bar__close', 11 | icon: { 12 | id: 'close', 13 | title: 'Close', 14 | class: 'marketing-bar__close-icon' 15 | }, 16 | attributes: 'type="button" aria-label="Close marketing bar"', 17 | }, 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /components/02-elements/marketing-bar/marketing-bar.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{ text }} 5 |
6 | {{ render '@button--icon' closeButton }} 7 |
8 |
9 | 10 | -------------------------------------------------------------------------------- /components/02-elements/message/message.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collated: true, 3 | context: { 4 | class: '', 5 | attributes: 'role="alert" aria-live="polite"', 6 | text: 'You added Jacket to your shopping cart.' 7 | }, 8 | variants: [ 9 | { 10 | name: 'success', 11 | context: { 12 | class: 'message--success' 13 | } 14 | }, 15 | { 16 | name: 'error', 17 | context: { 18 | class: 'message--error', 19 | text: 'Please specify product\'s required options(s).' 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /components/02-elements/message/message.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ text }} 3 |
4 | -------------------------------------------------------------------------------- /components/02-elements/modal-trigger/modal-trigger.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | buttonModalTrigger: { 4 | tag: 'button', 5 | class: 'modal-trigger', 6 | text: 'Modal trigger button', 7 | attributes: 'data-modal-trigger="modal-1" type="button"' 8 | } 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /components/02-elements/modal-trigger/modal-trigger.hbs: -------------------------------------------------------------------------------- 1 | {{ render '@button' buttonModalTrigger }} 2 | -------------------------------------------------------------------------------- /components/02-elements/pager/README.md: -------------------------------------------------------------------------------- 1 | # Pager 2 | 3 | ## Accessibility 4 | * Add apropriate labels and `aria-labels` form page items 5 | * Structure pagination as a navigation and use a `nav` element 6 | * Use `aria-current="page"` to mark active/current page in pager 7 | * Use `disable` on buttons like previous or next which are not lead anywhere 8 | 9 | -------------------------------------------------------------------------------- /components/02-elements/password-strength/password-strength.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collated: true, 3 | context: { 4 | text: 'Password Strength:', 5 | strengthIndicatorClass: 'password-none', 6 | noPassword: 'No Password' 7 | }, 8 | variants: [ 9 | { 10 | name: 'Week', 11 | context: { 12 | strengthIndicatorClass: 'password-weak', 13 | noPassword: 'Weak' 14 | } 15 | }, 16 | { 17 | name: 'Medium', 18 | context: { 19 | strengthIndicatorClass: 'password-medium', 20 | noPassword: 'Medium' 21 | } 22 | }, 23 | { 24 | name: 'Strong', 25 | context: { 26 | strengthIndicatorClass: 'password-strong', 27 | noPassword: 'Strong' 28 | } 29 | }, 30 | { 31 | name: 'Very Strong', 32 | context: { 33 | strengthIndicatorClass: 'password-very-strong', 34 | noPassword: 'Very Strong' 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /components/02-elements/password-strength/password-strength.hbs: -------------------------------------------------------------------------------- 1 |
2 |
6 |
7 | {{ text }} 8 | 13 | {{ noPassword }} 14 | 15 |
16 | 17 |
18 | -------------------------------------------------------------------------------- /components/02-elements/price/_price.scss: -------------------------------------------------------------------------------- 1 | $price__spacing : $spacer !default; 2 | $price__color--special : $green !default; 3 | $price__font-weight : $font-weight-bold !default; 4 | $price__font-weight--old : $font-weight-normal !default; 5 | $price__font-weight--special: $font-weight-bold !default; 6 | 7 | .price { 8 | &__value { 9 | font-weight: $price__font-weight; 10 | 11 | &--old { 12 | text-decoration: line-through; 13 | font-weight: $price__font-weight--old; 14 | margin-right: $price__spacing; 15 | } 16 | 17 | &--special { 18 | color: $price__color--special; 19 | font-weight: $price__font-weight--special; 20 | 21 | & > ins { 22 | text-decoration: none; 23 | } 24 | } 25 | 26 | &--between { 27 | display: block; 28 | 29 | &:last-child { 30 | margin-top: $price__spacing; 31 | } 32 | } 33 | } 34 | 35 | &__text { 36 | font-weight: $price__font-weight--old; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /components/02-elements/price/price.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'price', 3 | context: { 4 | regularPrice: '1 400.00', 5 | specialPrice: '', 6 | prefix: { 7 | tag: '', 8 | text: '$' 9 | }, 10 | suffix: { 11 | tag: '', 12 | text: '' 13 | }, 14 | }, 15 | variants: [ 16 | { 17 | name: 'with-special-price', 18 | context: { 19 | oldPriceClass: '', 20 | prefix: { 21 | tag: '', 22 | closingTag: '', 23 | text: '$' 24 | }, 25 | regularPrice: '1 400.00', 26 | regularPriceClass: '', 27 | specialPrice: '1 299.99', 28 | specialPriceClass: '', 29 | suffix: { 30 | tag: '', 31 | closingTag: '', 32 | text: '' 33 | }, 34 | } 35 | }, 36 | { 37 | name: 'between', 38 | context: { 39 | priceClass: 'price__value--between', 40 | textBeforeFromPrice: 'From', 41 | textBeforeToPrice: 'To', 42 | fromPrice: '61.00', 43 | toPrice: '79.00', 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /components/02-elements/price/price.hbs: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{#if prefix.tag}} 4 | <{{tag}}> 5 | {{/if}} 6 | {{prefix.text}} 7 | {{#if prefix.tag}} 8 | 9 | {{/if}} 10 | {{regularPrice}} 11 | {{#if suffix.tag}} 12 | <{{suffix.tag}}> 13 | {{/if}} 14 | {{suffix.text}} 15 | {{#if suffix.tag}} 16 | 17 | {{/if}} 18 | 19 |
20 | -------------------------------------------------------------------------------- /components/02-elements/rating/README.md: -------------------------------------------------------------------------------- 1 | # Rating component 2 | 3 | ## Accessible rating 4 | * Rating component (which shows the average rate) should be focusable (`tabindex="0"`) and should have `aria-label` set with descriptive value and average rating value. 5 | * Rating--rate component has to be usable with keyboard. 6 | It acts like a small form with `input type="button"` behing the stars. moving focus we see that background changes and with space click we can set the field selected/star active. 7 | 8 | What should be done to keep it working for AT: 9 | * keep ratio inputs in `fieldset` and add `legend` to set some label 10 | * use `role="listbox"` `aria-required="true"` and `aria-labelledby=""` to make list of options with required rating field 11 | * use `role="option"` & `aria-selected` on the input radio wrapper 12 | * use `aria-label` for input radio `label` elements 13 | -------------------------------------------------------------------------------- /components/02-elements/rating/rating.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | ariaLabel: 'Average rating: 72%', 4 | title: 'Average rating: 72%', 5 | star: { 6 | attributes: 'style="width: 72%"' 7 | } 8 | }, 9 | variants: [ 10 | { 11 | name: 'rate', 12 | context: { 13 | script: true, 14 | star: { 15 | attributes: '' 16 | }, 17 | rateItems: [ 18 | { 19 | id: 'Rating_1', 20 | name: 'ratings[1]', 21 | labelText: 'Rate option, 1 of 5. Click to vote' 22 | }, 23 | { 24 | id: 'Rating_2', 25 | name: 'ratings[2]', 26 | labelText: 'Rate option, 2 of 5. Click to vote' 27 | }, 28 | { 29 | id: 'Rating_3', 30 | name: 'ratings[3]', 31 | labelText: 'Rate option, 3 of 5. Click to vote' 32 | }, 33 | { 34 | id: 'Rating_4', 35 | name: 'ratings[4]', 36 | labelText: 'Rate option, 4 of 5. Click to vote' 37 | }, 38 | { 39 | id: 'Rating_5', 40 | name: 'ratings[5]', 41 | labelText: 'Rate option, 5 of 5. Click to vote' 42 | } 43 | ] 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /components/02-elements/rating/rating.hbs: -------------------------------------------------------------------------------- 1 |
8 | 21 |
22 | -------------------------------------------------------------------------------- /components/02-elements/skip-nav/_skip-nav.scss: -------------------------------------------------------------------------------- 1 | .skip-nav { 2 | @include visually-hidden('focus'); 3 | padding: 12px $spacer--extra-large; 4 | top: 0; 5 | left: 0; 6 | 7 | &.focus-visible, 8 | &:hover { 9 | position: absolute; 10 | margin: $spacer; 11 | background-color: $color-primary; 12 | color: $black; 13 | } 14 | 15 | &--relative { 16 | &.focus-visible, 17 | &:hover { 18 | display: block; 19 | position: relative; 20 | margin: $spacer--medium; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /components/02-elements/skip-nav/skip-nav--list.hbs: -------------------------------------------------------------------------------- 1 | 13 | 14 | {{#if script}} 15 | 16 | {{/if}} 17 | -------------------------------------------------------------------------------- /components/02-elements/skip-nav/skip-nav.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | text: 'Skip to content', 4 | anchor: '#maincontent', 5 | script: true 6 | }, 7 | variants: [ 8 | { 9 | name: 'list', 10 | context: { 11 | anchor: [ 12 | { 13 | value: '#header', 14 | text: 'Go to top' 15 | }, 16 | { 17 | value: '#maincontent', 18 | text: 'Go to main content' 19 | } 20 | ] 21 | } 22 | } 23 | ] 24 | } 25 | -------------------------------------------------------------------------------- /components/02-elements/skip-nav/skip-nav.hbs: -------------------------------------------------------------------------------- 1 | 5 | {{ text }} 6 | 7 | {{#if script}} 8 | 9 | {{/if}} 10 | -------------------------------------------------------------------------------- /components/02-elements/skip-nav/skip-nav.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const skipNavLink = document.querySelector('.skip-nav'); 3 | 4 | function skipNavigation(skipElem) { 5 | skipElem.addEventListener('click', (e) => { 6 | let targetElem = document.querySelector(e.target.hash); 7 | if (targetElem) { 8 | targetElem.setAttribute('tabindex', -1) 9 | targetElem.focus(); 10 | targetElem.addEventListener('focusout', (e) => { 11 | e.target.removeAttribute('tabindex'); 12 | }) 13 | } 14 | }) 15 | } 16 | 17 | skipNavigation(skipNavLink); 18 | -------------------------------------------------------------------------------- /components/02-elements/swatch/README.md: -------------------------------------------------------------------------------- 1 | # Swatches accessibility 2 | 3 | Swatches require following aria structure to be accessible for assistive technology and keyboard: 4 | 5 | 1. Swatches wrapper `.swatch__wrapper` should have following aria attributes: 6 | * `role="listbox"` to easy list swatch's options 7 | * `aria-activedescendant` with value of selected swatch option 8 | * `tabindex="0"` to make element focusable 9 | * `aria-required` with value `true` or `false` depending if swatch option is required 10 | * `aria-invalid` with value `true` if required field is not filled (if none of options is selected) or with the value `false` if required field is field (option is selected) 11 | 12 | 2. Swatch option `.swatch__option` should have following aria attributes: 13 | * `role="option"` to show options of swatch 14 | * `tabindex="0"` to make element focusable 15 | * `aria-label` with value of the name/label of swatch option if the swatch option is not a text but graphic element - icon or image (color option - ex: "Green") 16 | * `aria-describedby` with value of the listbox label/heading if exist 17 | * `aria-selected` with value `true` if the option was selected 18 | -------------------------------------------------------------------------------- /components/02-elements/swatch/swatch.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if heading}} 3 | <{{{ heading.tag }}} 4 | id="{{ heading.id }}" 5 | class="swatch__title {{ heading.class }}" 6 | > 7 | {{ heading.text }} 8 | 9 | {{/if}} 10 | 11 |
15 | {{#each options }} 16 |
24 |
28 | {{ this.text }} 29 |
30 |
31 | {{/each }} 32 |
33 |
34 | 35 | {{#if script}} 36 | 37 | {{/if}} 38 | -------------------------------------------------------------------------------- /components/02-elements/swatch/swatch.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function() { // eslint-disable-line 4 | const swatchWrapper = document.querySelector('.swatch__wrapper'), 5 | swatchOptions = swatchWrapper.querySelectorAll('.swatch__option-container'); 6 | 7 | swatchOptions.forEach(option => { 8 | option.addEventListener('click', () => { 9 | swatchOptions.forEach(option => { 10 | option.classList.remove('selected'); 11 | option.setAttribute('aria-selected', 'false'); 12 | }) 13 | 14 | option.classList.add('selected'); 15 | swatchWrapper.setAttribute('aria-activedescendant', option.id); 16 | option.setAttribute('aria-selected', 'true'); 17 | }) 18 | }) 19 | })(); 20 | -------------------------------------------------------------------------------- /components/02-elements/table/README.md: -------------------------------------------------------------------------------- 1 | # Tables accessibility 2 | 3 | * Use table semantics elements: `table`, `tbody`, `tr`, `th`, `td` 4 | * Use `scope="col"` or `scope="row"` for table headings (`th` elements) 5 | * use `capion` element to describe what kind of data are presented in the table 6 | * To make mobile table accessible, please add apropriate aria roles: 7 | * `role="columnheader"` for `th` elements 8 | * `role="row"` for `row` elements 9 | * `role="gridcell"` for `td` elements 10 | 11 | In desktop mode (wide screens) HTML5 tags are sufficient to make HTML table accessible. However, we change display mode on small screen to set our table visible without horizontal scrolling, so we need to ad apropriate aria roles to make it focusable and well read by AT. 12 | -------------------------------------------------------------------------------- /components/03-modules/active-filters/active-filters.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | clear: { 4 | href: '#', 5 | text: 'Clear all', 6 | title: 'Clear all filters', 7 | }, 8 | filters: [ 9 | { 10 | label: 'Label', 11 | value: 'Value', 12 | ariaLabel: 'Disable filter: Label - Value', 13 | icon: { 14 | id: 'close', 15 | title: 'Close', 16 | class: 'active-filters__remove-icon' 17 | } 18 | }, 19 | { 20 | label: 'Label', 21 | value: 'Value', 22 | ariaLabel: 'Disable filter: Label - Value', 23 | icon: { 24 | id: 'close', 25 | title: 'Close', 26 | class: 'active-filters__remove-icon' 27 | } 28 | }, 29 | { 30 | label: 'Label', 31 | value: 'Value', 32 | ariaLabel: 'Disable filter: Label - Value', 33 | icon: { 34 | id: 'close', 35 | title: 'Close', 36 | class: 'active-filters__remove-icon' 37 | } 38 | } 39 | ] 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /components/03-modules/active-filters/active-filters.hbs: -------------------------------------------------------------------------------- 1 | 28 | -------------------------------------------------------------------------------- /components/03-modules/additional-content/_additional-content.scss: -------------------------------------------------------------------------------- 1 | $additional-content__image-margin : 0 0 41px !default; 2 | $additional-content__image-margin\@large : 0 0 32px !default; 3 | $additional-section-width : 48% !default; 4 | .additional-content { 5 | &__image { 6 | margin: $additional-content__image-margin; 7 | @include mq($screen-l) { 8 | margin: $additional-content__image-margin\@large; 9 | } 10 | } 11 | &__info { 12 | @include mq($screen-l) { 13 | display: flex; 14 | flex-flow: row nowrap; 15 | justify-content: space-between; 16 | } 17 | 18 | } 19 | &__section { 20 | @include mq($screen-l) { 21 | flex: 0 0 $additional-section-width; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/03-modules/additional-content/additional-content.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | class: '', 4 | contentInfo: { 5 | class: '' 6 | }, 7 | image: { 8 | class: 'additional-content__image', 9 | defaultSrc: '', 10 | sources: [ 11 | { 12 | src: '/images/product-view/banner.jpg', 13 | mediaQuery: '(min-width: 768px)' 14 | } 15 | ], 16 | alt: 'image alt text' 17 | }, 18 | firstSection: { 19 | class: '', 20 | html: '

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry\'s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.

' 21 | }, 22 | secondSection: { 23 | class: '', 24 | html: '

It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.

' 25 | } 26 | } 27 | }; 28 | -------------------------------------------------------------------------------- /components/03-modules/additional-content/additional-content.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@image--picture' image }} 3 | 11 |
12 | -------------------------------------------------------------------------------- /components/03-modules/brief-info/brief-info.hbs: -------------------------------------------------------------------------------- 1 |
2 | <{{heading.tag}} class="brief-info__heading {{heading.class}}"> 3 | {{heading.text}} 4 | 5 |
    6 | {{#each items as |item|}} 7 |
  • 8 | 12 | {{ render '@icon' item.icon }} 13 | 14 |
    15 | <{{ item.title.tag }} 16 | {{{ item.title.attributes }}} 17 | class="brief-info__title {{ item.title.class }}" 18 | > 19 | {{ item.title.text }} 20 | 21 |
    22 |
  • 23 | {{/each}} 24 |
25 |
26 | -------------------------------------------------------------------------------- /components/03-modules/bundle-option/bundle-option--checkbox.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if title}} 3 | <{{{title.tag}}} class="bundle-option__title"> 4 | {{ title.message }} 5 | 6 | {{/if}} 7 | 8 | {{#each checkboxes }} 9 | {{ render '@checkbox' this merge=true }} 10 | {{/each}} 11 | 12 | {{#if qty }} 13 | {{ render '@input' qty merge=true }} 14 | {{/if}} 15 |
16 | -------------------------------------------------------------------------------- /components/03-modules/bundle-option/bundle-option--select.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if title}} 3 | <{{{title.tag}}} class="bundle-option__title"> 4 | {{ title.message }} 5 | 6 | {{/if}} 7 | 8 | {{ render '@select' select merge=true }} 9 | 10 | {{#if qty }} 11 | {{ render '@input' qty merge=true }} 12 | {{/if}} 13 |
14 | -------------------------------------------------------------------------------- /components/03-modules/bundle-option/bundle-option.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if title}} 3 | <{{{title.tag}}} class="bundle-option__title"> 4 | {{ title.message }} 5 | 6 | {{/if}} 7 | 8 | {{ render '@radio' radio merge=true }} 9 | 10 | {{#if qty }} 11 | {{ render '@input' qty merge=true }} 12 | {{/if}} 13 |
14 | -------------------------------------------------------------------------------- /components/03-modules/cart-list-item/cart-list-item.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ render '@image' productImage }} 4 |
5 |
6 |
7 | 8 | {{ productName }} 9 | 10 |
11 |
12 | {{ render '@input' qtyInput }} 13 |
14 |
15 | {{ productPrice }} 16 |
17 |
18 | {{ render '@list--description' attributes }} 19 |
20 |
21 | {{ render '@button--icon' editIcon }} 22 | {{ render '@button--icon' removeIcon }} 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/actions-toolbar/_actions-toolbar.scss: -------------------------------------------------------------------------------- 1 | $dashboard-actions-toolbar__margin : 0 !default; 2 | $dashboard-actions-toolbar__item-margin : $spacer 0 0 0 !default; 3 | $dashboard-actions-toolbar__item-margin\@medium: 0 $spacer 0 0 !default; 4 | 5 | .dashboard-actions-toolbar { 6 | display: flex; 7 | flex-direction: column; 8 | margin: $dashboard-actions-toolbar__margin; 9 | 10 | @include mq($screen-m) { 11 | flex-direction: row; 12 | } 13 | 14 | &__item { 15 | margin: $dashboard-actions-toolbar__item-margin; 16 | 17 | @include mq($screen-m) { 18 | margin: $dashboard-actions-toolbar__item-margin\@medium; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/actions-toolbar/actions-toolbar.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | label: 'Actions toolbar', 3 | name: 'dashboard-actions-toolbar', 4 | context: { 5 | buttons: [ 6 | { 7 | tag: 'button', 8 | class: 'dashboard-actions-toolbar__item', 9 | attributes: 'type="button"', 10 | text: 'Action 1' 11 | }, 12 | { 13 | tag: 'button', 14 | class: 'dashboard-actions-toolbar__item', 15 | attributes: 'type="button"', 16 | text: 'Action 2' 17 | }, 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/actions-toolbar/actions-toolbar.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#each buttons }} 3 | {{ render '@button' this }} 4 | {{/each}} 5 |
6 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/form/_form.scss: -------------------------------------------------------------------------------- 1 | $dashborad-form-margin: 30px !default; 2 | 3 | .dashboard-form { 4 | &__title { 5 | margin-bottom: $dashborad-form-margin; 6 | padding-bottom: 10px; 7 | border-bottom: 1px solid $gray; 8 | } 9 | 10 | &__divider, 11 | &__select { 12 | margin-bottom: $dashborad-form-margin; 13 | } 14 | 15 | &--hidden { 16 | display: none; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/items/_items.scss: -------------------------------------------------------------------------------- 1 | $dashboard-items-padding : 15px !default; 2 | $dashboard-items-margin : 15px !default; 3 | $dashboard-items__item-max-width : calc(50% - #{$spacer--medium}) !default; 4 | $dashboard-items__item-margin : 15px $spacer--medium 15px 0 !default; 5 | 6 | .dashboard-items { 7 | &__title { 8 | margin-bottom: $dashboard-items-margin; 9 | padding-bottom: 10px; 10 | border-bottom: 1px solid $gray; 11 | } 12 | 13 | &__content { 14 | margin: 0; 15 | } 16 | 17 | &__address { 18 | margin-bottom: $dashboard-items-margin; 19 | } 20 | 21 | &__item { 22 | max-width: $dashboard-items__item-max-width; 23 | margin: $dashboard-items__item-margin; 24 | padding: $dashboard-items-padding 0; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/items/items.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | label: 'Items', 3 | name: 'dashboard-items', 4 | context: { 5 | title: 'Addresses', 6 | informations: [ 7 | { 8 | title: 'Contact information', 9 | class: 'col-sm-3', 10 | information: 'qweqwe qwe qwe@qwe.com', 11 | actions: { 12 | links: [ 13 | { 14 | title: 'Edit' 15 | }, 16 | { 17 | title: 'Change password' 18 | } 19 | ] 20 | } 21 | }, 22 | { 23 | title: 'Address second', 24 | class: 'col-sm-3', 25 | information: 'Second address qwe@qwe.com', 26 | actions: { 27 | links: [ 28 | { 29 | title: 'Edit' 30 | } 31 | ] 32 | } 33 | } 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/items/items.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if title }} 3 |

4 | {{ title }} 5 |

6 | {{/if}} 7 | {{#if informations }} 8 |
9 | {{#each informations }} 10 |
11 | {{#if this.title }} 12 |
13 | {{ this.title }} 14 |
15 | {{/if}} 16 | {{#if this.information }} 17 |
18 | {{ this.information }} 19 |
20 | {{/if}} 21 | {{#if actions }} 22 | {{> '@action' actions }} 23 | {{/if}} 24 |
25 | {{/each}} 26 |
27 | {{/if}} 28 |
29 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/nav/nav.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ actualPage }} 4 |
5 | 6 |
7 |

8 | {{ title }} 9 |

10 | 11 | {{> '@list--link' list }} 12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/nav/nav.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const content = document.querySelector('.dashboard-nav__content'), 4 | currentItem = content.querySelector('.dashboard-nav__item.current'), 5 | mobileNav = document.querySelector('.dashboard-nav__mobile'); 6 | 7 | mobileNav.innerHTML = currentItem.textContent; 8 | 9 | mobileNav.addEventListener('click', () => { 10 | mobileNav.classList.toggle('dashboard-nav__mobile--active'); 11 | content.classList.toggle('dashboard-nav__content--visible'); 12 | }); 13 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/table/_table.scss: -------------------------------------------------------------------------------- 1 | $dashboard-table-margin: $spacer--medium !default; 2 | 3 | .dashboard-table { 4 | overflow: hidden; 5 | 6 | &--tab { 7 | padding: 10px; 8 | margin-bottom: $dashboard-table-margin; 9 | border: 1px solid $gray; 10 | 11 | .dashboard-table__content { 12 | margin-bottom: 0; 13 | } 14 | } 15 | 16 | &__header { 17 | display: flex; 18 | flex-wrap: nowrap; 19 | align-items: flex-end; 20 | margin-bottom: $dashboard-table-margin; 21 | padding-bottom: 10px; 22 | border-bottom: 1px solid $gray; 23 | } 24 | 25 | &__content { 26 | margin-bottom: $dashboard-table-margin; 27 | overflow-x: auto; 28 | } 29 | 30 | &__table { 31 | margin: 0; 32 | } 33 | 34 | &__link { 35 | display: inline-flex; 36 | &.focus-visible { 37 | @include focus-inline(); 38 | } 39 | } 40 | 41 | &__spacer { 42 | margin-right: $spacer; 43 | } 44 | 45 | &__title { 46 | margin-bottom: 0; 47 | margin-right: $dashboard-table-margin; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /components/03-modules/dashboard/table/table.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{#if title }} 3 |
4 |
5 | {{ title }} 6 |
7 | 8 | {{ link }} 9 | 10 |
11 | {{/if }} 12 |
13 | {{ render '@table' table }} 14 |
15 |
16 | -------------------------------------------------------------------------------- /components/03-modules/filter/filter--category.hbs: -------------------------------------------------------------------------------- 1 | 20 | -------------------------------------------------------------------------------- /components/03-modules/filter/filter--range.hbs: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /components/03-modules/filter/filter--swatch.hbs: -------------------------------------------------------------------------------- 1 | 32 | -------------------------------------------------------------------------------- /components/03-modules/filter/filter.hbs: -------------------------------------------------------------------------------- 1 | 26 | -------------------------------------------------------------------------------- /components/03-modules/filters/filters.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Filters', 3 | context: { 4 | tag: 'div', 5 | activeFiltersHeading: 'Now Shopping by', 6 | skip: { 7 | tag: 'button', 8 | class: 'button button--secondary filters__skip-button', 9 | attributes: 'type="button"', 10 | text: 'Skip to products' 11 | }, 12 | allFiltersHeading: 'Shopping Options', 13 | switcherIcon: { 14 | id: 'angle-down', 15 | title: 'Arrow down', 16 | class: 'filters__switcher-icon' 17 | }, 18 | divider: { 19 | class: 'filters__divider' 20 | }, 21 | dropdownList: { 22 | class: 'dropdown-list--secondary' 23 | } 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /components/03-modules/filters/filters.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function Filters() { 4 | const filters = { 5 | init() { 6 | this.switcher = document.querySelector('.filters__switcher'); 7 | this.icon = document.querySelector('.filters__switcher-icon'); 8 | this.filters = document.querySelector('.filters__list'); 9 | this.switcher.addEventListener('click', this.toggle.bind(this)); 10 | }, 11 | toggle() { 12 | switch (this.switcher.dataset.stateCurrent) { 13 | case 'hidden': 14 | this.show(); 15 | break; 16 | case 'display': 17 | this.hide(); 18 | break 19 | } 20 | }, 21 | show() { 22 | this.filters.classList.remove('filters__list--mobile-hidden'); 23 | this.icon.classList.add('filters__switcher-icon--active'); 24 | this.switcher.dataset.stateCurrent = 'display' 25 | }, 26 | hide() { 27 | document.querySelector('.filters__list').classList.add('filters__list--mobile-hidden'); 28 | this.icon.classList.remove('filters__switcher-icon--active'); 29 | this.switcher.dataset.stateCurrent = 'hidden'; 30 | } 31 | }; 32 | filters.init(); 33 | }()); 34 | 35 | -------------------------------------------------------------------------------- /components/03-modules/footer/footer.hbs: -------------------------------------------------------------------------------- 1 |
2 | 11 | 25 | {{ render '@cookie-message' }} 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /components/03-modules/footer/footer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const scrollToTop = document.querySelector('.footer__scroll-top'); 4 | 5 | scrollToTop.addEventListener('click', () => { 6 | window.scrollTo(0, 0); 7 | }); 8 | -------------------------------------------------------------------------------- /components/03-modules/gallery/gallery.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Product grid item', 3 | context: { 4 | class: '', 5 | typeHorizontal: false, 6 | imageMain: { 7 | dataSrc: '/images/gallery/product-img-496-496.jpg' 8 | }, 9 | thumbs: [ 10 | { 11 | imageThumb: { 12 | dataSrc: '/images/gallery/product-img-80-80.jpg', 13 | active: true 14 | } 15 | }, 16 | { 17 | imageThumb: { 18 | dataSrc: '/images/gallery/product-img-80-80.jpg' 19 | } 20 | }, 21 | { 22 | imageThumb: { 23 | dataSrc: '/images/gallery/product-img-80-80.jpg' 24 | } 25 | }, 26 | { 27 | imageThumb: { 28 | dataSrc: '/images/gallery/product-img-80-80.jpg' 29 | } 30 | } 31 | ] 32 | }, 33 | variants: [ 34 | { 35 | name: 'horizontal', 36 | context: { 37 | typeHorizontal: true 38 | }, 39 | }, 40 | { 41 | name: 'with-label', 42 | context: { 43 | productLabel: { 44 | class: 'badge--new gallery__product-label', 45 | text: 'new' 46 | } 47 | } 48 | } 49 | ] 50 | }; 51 | -------------------------------------------------------------------------------- /components/03-modules/minicart-content/minicart-content.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | {{ counter}} 6 |
7 |
8 |
9 | {{ total }} 10 |
11 |
12 | {{ price }} 13 |
14 |
15 |
16 |
17 | {{ render '@button--secondary' checkoutButton }} 18 |
19 |
20 | {{#each products}} 21 | {{ render '@minicart-product' this merge=true }} 22 | {{/each}} 23 |
24 | 29 |
30 | -------------------------------------------------------------------------------- /components/03-modules/minicart-product/minicart-product.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ render '@image' productImage }} 4 |
5 |
6 |

7 | 8 | {{ productName }} 9 | 10 |

11 | {{#if configurable }} 12 | {{ render '@dropdown-list' attributes }} 13 | {{/if}} 14 |
15 | {{ productPrice }} 16 |
17 |
18 |
19 | {{ render '@input' productQty }} 20 | {{#if updateQty }} 21 | {{ render '@button' updateQty }} 22 | {{/if}} 23 |
24 |
25 | {{ render '@button--icon' editIcon }} 26 | {{ render '@button--icon' removeIcon }} 27 |
28 |
29 |
30 |
31 | -------------------------------------------------------------------------------- /components/03-modules/newsletter/newsletter.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collated: true, 3 | preview: '@docs-only-styles', 4 | context: { 5 | heading: { 6 | text: 'Sing up to our twisted newsletter' 7 | }, 8 | input: { 9 | class: 'newsletter__input', 10 | field: { 11 | placeholder: 'Enter your email address', 12 | id: 'newsletterEmail', 13 | name: 'newsletterEamil', 14 | class: 'newsletter__field' 15 | }, 16 | label: { 17 | class: 'newsletter__label', 18 | hidden: true, 19 | text: 'Email for newsletter subscription' 20 | } 21 | }, 22 | button: { 23 | tag: 'button', 24 | text: 'Submit', 25 | class: 'newsletter__button' 26 | }, 27 | checkbox: { 28 | class: 'newsletter__checkbox', 29 | id: 'newsletter', 30 | label: { 31 | text: 'I agree to Terms and conditions and I am happy to receive your newsletter with all your promotions.' 32 | } 33 | } 34 | } 35 | }; 36 | -------------------------------------------------------------------------------- /components/03-modules/newsletter/newsletter.hbs: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /components/03-modules/popup/popup.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | popupTrigger: true, 4 | buttonPopupTrigger: { 5 | class: 'popup-trigger', 6 | text: 'Popup trigger button', 7 | attributes: 'data-popuptrigger="popup-1" type="button"' 8 | }, 9 | class: '', 10 | popupId: 'popup-1', 11 | content: 'button', 12 | buttonClose: { 13 | tag: 'button', 14 | text: '', 15 | class: 'button--icon popup__close-button', 16 | icon: { 17 | id: 'close', 18 | title: 'Close', 19 | class: 'button__icon popup__close-button-icon' 20 | }, 21 | attributes: 'type="button" aria-label="close popup button, click to close the popup"' 22 | }, 23 | script: true 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /components/03-modules/popup/popup.hbs: -------------------------------------------------------------------------------- 1 | {{#if popupTrigger }} 2 | {{ render '@button' buttonPopupTrigger merge=true }} 3 | {{/if}} 4 | 5 | 13 | 14 | 15 | {{#if script }} 16 | 17 | {{/if}} 18 | -------------------------------------------------------------------------------- /components/03-modules/product-view/product-review/product-review.hbs: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{ title }} 4 |

5 |
6 | {{ render '@review--summary' summary merge=true }} 7 |
8 |
9 |
    10 | {{#each reviews }} 11 |
  • 12 | {{ render '@review--default' this }} 13 |
  • 14 | {{/each}} 15 |
16 |
17 | {{ render '@review--add' }} 18 |
19 | -------------------------------------------------------------------------------- /components/03-modules/quantity-update/quantity-update.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | input: { 4 | id: 'qty', 5 | min: '1', 6 | defaultValue: '1', 7 | ariaLabel: 'Change the quantity' 8 | }, 9 | minusQtyButton: { 10 | tag: 'button', 11 | class: 'button--icon quantity-update__button quantity-update__button--minus quantity-update__button--disabled', 12 | attributes: 'type="button" aria-label="Decrease the quantity"', 13 | icon: { 14 | id: 'minus', 15 | title: 'Minus mark', 16 | class: 'button__icon quantity-update__icon' 17 | } 18 | }, 19 | plusQtyButton: { 20 | tag: 'button', 21 | class: 'button--icon quantity-update__button quantity-update__button--plus', 22 | attributes: 'type="button" aria-label="Increase the quantity"', 23 | icon: { 24 | id: 'plus', 25 | title: 'Plus mark', 26 | class: 'button__icon quantity-update__icon' 27 | } 28 | }, 29 | script: true 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/03-modules/quantity-update/quantity-update.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{> '@button--icon' minusQtyButton }} 3 | 4 | 11 | 12 | {{> '@button--icon' plusQtyButton }} 13 |
14 | {{#if script}} 15 | 16 | {{/if}} 17 | -------------------------------------------------------------------------------- /components/03-modules/range/range.hbs: -------------------------------------------------------------------------------- 1 |
2 |
7 |
8 | {{ render '@input' rangeInputLower }} 9 | 10 | {{ filter.suffix.lowerText }} 11 | 12 | - 13 | {{ render '@input' rangeInputUpper }} 14 | 15 | {{ filter.suffix.upperText }} 16 | 17 |
18 |
19 | {{ render '@button--secondary' apply }} 20 | {{#if script}} 21 | 22 | {{/if}} 23 | -------------------------------------------------------------------------------- /components/03-modules/review/review--add.hbs: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{ addTitle }}: 4 | 5 | {{ productTitle }} 6 | 7 |

8 | {{ render '@rating--rate' rate merge=true }} 9 |
10 | {{ render '@input' nickname }} 11 | {{ render '@input' summary }} 12 | {{ render '@input--textarea' textReview }} 13 | {{ render '@button' submitReview merge=true }} 14 |

15 | * Required fields 16 |

17 |
18 |
19 | -------------------------------------------------------------------------------- /components/03-modules/review/review--summary.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 | {{ render '@rating' }} 4 | {{#if amountLink}} 5 | 6 | {{ reviewsQty }} 7 | 8 | {{else}} 9 | 10 | {{ reviewsQty }} 11 | 12 | {{/if}} 13 | 14 | Add your review 15 | 16 |
17 |
18 | -------------------------------------------------------------------------------- /components/03-modules/review/review.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | {{ author }} 5 |

6 |
7 | {{ date }} 8 |
9 | {{> '@rating' rating }} 10 |
11 |
12 |

13 | {{ title }} 14 |

15 | 16 |
17 |

{{ content }}

18 |
19 |
20 |
21 | -------------------------------------------------------------------------------- /components/03-modules/side-menu/side-menu.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'Header module', 3 | context: { 4 | sideMenuIconOpen: { 5 | id: 'mobile-menu', 6 | title: 'Mobile menu', 7 | class: 'side-menu__trigger-icon' 8 | }, 9 | sideMenuIconClose: { 10 | id: 'close', 11 | title: 'Close', 12 | class: 'side-menu__trigger-icon' 13 | }, 14 | dropdown: { 15 | id: 'dropdown-side-menu', 16 | class: 'side-menu__dropdown' 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /components/03-modules/side-menu/side-menu.hbs: -------------------------------------------------------------------------------- 1 |
2 | 12 |
13 |
14 | 24 |
25 | 26 | {{ render '@dropdown-list--with-nested' dropdown merge=true }} 27 |
28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /components/03-modules/side-menu/side-menu.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | class SideMenu { 4 | constructor() { 5 | this.sideMenuContainer = document.querySelector('.side-menu'); 6 | this.sideMenuOverlay = this.sideMenuContainer.querySelector('.side-menu__overlay'); 7 | this.menuTrigger = this.sideMenuContainer.querySelectorAll('.side-menu__trigger'); 8 | this.init(); 9 | } 10 | 11 | toggleSideMenu() { 12 | this.sideMenuContainer.classList.toggle('side-menu--is-open'); 13 | 14 | if (this.sideMenuContainer.classList.contains('side-menu--is-open')) { 15 | document.body.style.overflow = 'hidden'; 16 | } 17 | else { 18 | document.body.style.overflow = 'auto'; 19 | } 20 | } 21 | 22 | setListeners() { 23 | this.menuTrigger.forEach(el => { 24 | el.addEventListener('click', () => { 25 | this.toggleSideMenu(); 26 | }); 27 | }); 28 | 29 | this.sideMenuOverlay.addEventListener('click', () => { 30 | this.toggleSideMenu(); 31 | }); 32 | } 33 | 34 | init() { 35 | this.setListeners(); 36 | } 37 | } 38 | 39 | new SideMenu(); 40 | -------------------------------------------------------------------------------- /components/03-modules/sidebar-block/sidebar-block--recently-ordered.hbs: -------------------------------------------------------------------------------- 1 | 23 | -------------------------------------------------------------------------------- /components/03-modules/sidebar-block/sidebar-block.hbs: -------------------------------------------------------------------------------- 1 | 22 | -------------------------------------------------------------------------------- /components/03-modules/slider/slider.hbs: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | {{#each slides }} 5 |
9 | {{ render (component content) contentContext }} 10 |
11 | {{/each}} 12 |
13 |
14 | 15 | 20 | 21 | {{#if navigation }} 22 |
23 | {{/if}} 24 |
25 | 26 | {{#if script }} 27 | 28 | {{/if}} 29 | -------------------------------------------------------------------------------- /components/03-modules/title-wrapper/_title-wrapper.scss: -------------------------------------------------------------------------------- 1 | $title-wrapper__margin : 0 0 $spacer--medium 0 !default; 2 | 3 | .title-wrapper { 4 | margin: $title-wrapper__margin; 5 | flex-direction: column; 6 | 7 | @include mq($screen_m) { 8 | flex-direction: row; 9 | } 10 | 11 | &__actions { 12 | display: flex; 13 | justify-content: center; 14 | flex-direction: column; 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /components/03-modules/title-wrapper/title-wrapper.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | title: { 4 | text: 'main title', 5 | tag: 'h1', 6 | class: 'heading heading--page' 7 | }, 8 | button: { 9 | tag: 'button', 10 | class: 'button button--secondary', 11 | attributes: 'type="button"', 12 | text: 'I am a button' 13 | } 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /components/03-modules/title-wrapper/title-wrapper.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@heading' title }} 3 | {{#if button }} 4 |
5 | {{ render '@button--secondary' button }} 6 |
7 | {{/if }} 8 |
9 | -------------------------------------------------------------------------------- /components/04-views/_components.scss: -------------------------------------------------------------------------------- 1 | // ----- 2 | // Views 3 | // ----- 4 | 5 | @import 'b2b/quickorder/quickorder'; 6 | @import 'cart/actions'; 7 | @import 'cart/discount'; 8 | @import 'cart/main'; 9 | @import 'cart/summary'; 10 | @import 'cart/totals'; 11 | @import 'catalog/grid/grid'; 12 | @import 'catalog/list/list'; 13 | @import 'compare/compare'; 14 | @import 'confirmation-link/confirmation-link'; 15 | @import 'dashboard/default/dashboard'; 16 | @import 'dashboard/product-reviews/product-reviews'; 17 | @import 'dashboard/company-structure/company-structure'; 18 | @import 'dashboard/company-users/company-users'; 19 | @import 'dashboard/my-quotes/my-quotes'; 20 | @import 'dashboard/requisition-lists/requisition-lists--view'; 21 | @import 'dashboard/roles-and-permissions/roles-and-permissions'; 22 | @import 'dashboard/wishlist/wishlist'; 23 | @import 'email-to-friend/email-to-friend'; 24 | @import 'forgot-password/forgot-password'; 25 | @import 'home/home'; 26 | @import 'login/login'; 27 | @import 'product-view/product-view'; 28 | @import 'registration/registration'; 29 | -------------------------------------------------------------------------------- /components/04-views/cart/_actions.scss: -------------------------------------------------------------------------------- 1 | $cart-actions__margin : 15px !default; 2 | $cart-actions__padding: 10px !default; 3 | 4 | .cart-actions { 5 | display: flex; 6 | flex-wrap: wrap; 7 | margin-top: $cart-actions__margin; 8 | 9 | &__button { 10 | width: 100%; 11 | margin-bottom: $cart-actions__margin; 12 | @include mq($screen-m) { 13 | width: 190px; 14 | margin: 0 0 $cart-actions__margin $cart-actions__margin; 15 | padding: 0 $cart-actions__padding; 16 | } 17 | 18 | &--continue { 19 | @include mq($screen-m) { 20 | margin: 0 auto 0 0; 21 | } 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/04-views/cart/_main.scss: -------------------------------------------------------------------------------- 1 | $cart__margin : $spacer--large !default; 2 | $cart__border : 1px solid $gray-lighter !default; 3 | 4 | $cart__bottom-margin : 0 !default; 5 | $cart__bottom-padding : $spacer 0 0 0 !default; 6 | 7 | .cart { 8 | display: flex; 9 | margin-bottom: $cart__margin; 10 | 11 | &__bottom { 12 | display: flex; 13 | margin: $cart__bottom-margin; 14 | padding: $cart__bottom-padding; 15 | border-top: $cart__border; 16 | } 17 | 18 | &__products-list { 19 | margin: 0; 20 | border-top: $cart__border; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /components/04-views/cart/_totals.scss: -------------------------------------------------------------------------------- 1 | $cart-totals__padding : 15px !default; 2 | $cart-totals__margin : 15px !default; 3 | $cart-totals__border : 1px solid #d9d9d9 !default; 4 | $cart-totals__font-size : $font-size-base !default; 5 | $cart-totals__padding--summary : ($cart-totals__padding - 5) !default; 6 | $cart-totals__font-size--summary: $font-size-base !default; 7 | 8 | .cart-totals { 9 | padding-top: $cart-totals__padding; 10 | border-top: $cart-totals__border; 11 | 12 | &__row { 13 | padding-bottom: $cart-totals__margin; 14 | font-size: $cart-totals__font-size; 15 | 16 | &--summary { 17 | margin-bottom: $cart-totals__margin; 18 | padding-top: $cart-totals__padding--summary; 19 | border-top: $cart-totals__border; 20 | font-weight: 600; 21 | font-size: $cart-totals__font-size--summary; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/04-views/catalog/grid/_grid.scss: -------------------------------------------------------------------------------- 1 | $catalog-grid__gap : $spacer--medium !default; 2 | $catalog-grid__margin : 0 !default; 3 | $catalog-grid__padding: $spacer--medium 0 $spacer--large 0 !default; 4 | $catalog-grid__border : 1px solid $gray-light !default; 5 | 6 | .catalog-grid { 7 | display: grid; 8 | grid-template-columns: 1fr 1fr; 9 | grid-gap: $catalog-grid__gap; 10 | margin: $catalog-grid__margin; 11 | padding: $catalog-grid__padding; 12 | border-bottom: $catalog-grid__border; 13 | list-style: none; 14 | 15 | @include mq($screen-m) { 16 | grid-template-columns: 1fr 1fr 1fr; 17 | } 18 | 19 | @include isIE() { 20 | display: flex; 21 | flex-wrap: wrap; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /components/04-views/catalog/grid/grid.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'grid-view', 3 | context: { 4 | gridItem: { 5 | tag: 'li' 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /components/04-views/catalog/list/list.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | name: 'list-view' 3 | } 4 | -------------------------------------------------------------------------------- /components/04-views/confirmation-link/_confirmation-link.scss: -------------------------------------------------------------------------------- 1 | $confirmation-link__max-width : 600px !default; 2 | $confirmation-link__margin-bottom : $spacer--extra-large !default; 3 | $confirmation-link__link-margin-top: $spacer--medium !default; 4 | 5 | .confirmation-link { 6 | max-width: $confirmation-link__max-width; 7 | margin-bottom: $confirmation-link__margin-bottom; 8 | 9 | &__link { 10 | display: block; 11 | margin-top: $confirmation-link__link-margin-top; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /components/04-views/confirmation-link/confirmation-link.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | mainHeading: { 4 | tag: 'h1', 5 | class: 'heading heading--page', 6 | text: 'Send confirmation link' 7 | }, 8 | info: 'Please enter your email below and we will send you the confirmation link.', 9 | email: { 10 | label: { 11 | text: 'Email', 12 | hidden: false 13 | }, 14 | field: { 15 | id: 'email', 16 | name: 'email', 17 | type: 'email' 18 | } 19 | }, 20 | submit: { 21 | tag: 'button', 22 | attributes: 'type="submit"', 23 | text: 'Send confirmation link' 24 | }, 25 | back: { 26 | href: '#', 27 | class: 'confirmation-link__link', 28 | text: 'Back to Sign In' 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /components/04-views/confirmation-link/confirmation-link.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 | {{ render '@heading' mainHeading }} 6 | 14 |
15 |
16 | 17 | {{ render '@footer' }} 18 | -------------------------------------------------------------------------------- /components/04-views/dashboard/account-info/account-info.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | buttons: { 4 | class: 'dashboard__actions', 5 | sides: [ 6 | { 7 | action: [ 8 | { 9 | button: true, 10 | title: 'Save' 11 | } 12 | ] 13 | }, 14 | { 15 | action: [ 16 | { 17 | title: 'Go Back' 18 | } 19 | ] 20 | } 21 | ], 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /components/04-views/dashboard/account-info/account-info.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@dashboard-form' }} 10 | {{> '@action' buttons }} 11 |
12 |
13 |
14 |
15 | {{ render '@footer' }} 16 | -------------------------------------------------------------------------------- /components/04-views/dashboard/address-book/address-book--edit.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 |
12 | {{> '@dashboard-form' contactInfo }} 13 | 14 | {{> '@dashboard-form' address }} 15 |
16 | 17 | {{> '@action' buttons }} 18 |
19 |
20 |
21 |
22 | 23 | {{ render '@footer' }} 24 | -------------------------------------------------------------------------------- /components/04-views/dashboard/address-book/address-book.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-items' addresses }} 12 | 13 | {{> '@dashboard-items' additionalAddresses }} 14 | 15 | {{> '@action' buttons }} 16 |
17 |
18 |
19 |
20 | 21 | {{ render '@footer' }} 22 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-profile/company-profile--edit.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@heading' mainTitle }} 10 | {{> '@dashboard-form' form }} 11 | {{> '@action' buttons }} 12 |
13 |
14 |
15 |
16 | {{ render '@footer' }} 17 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-profile/company-profile.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{> '@dashboard-items' accountInformation }} 11 | {{> '@dashboard-items' legalAddress }} 12 | {{> '@dashboard-items' contacts }} 13 |
14 |
15 |
16 |
17 | {{ render '@footer' }} 18 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-structure/_company-structure.scss: -------------------------------------------------------------------------------- 1 | .company-structure { 2 | &__actions { 3 | margin-bottom: $spacer--medium; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-structure/company-structure.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{ render '@heading' businessStructureHeading }} 11 | {{ render '@dashboard-actions-toolbar' businessStructureActions }} 12 |
13 |
14 |
15 |
16 | {{ render '@footer' }} 17 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-users/_company-users.scss: -------------------------------------------------------------------------------- 1 | .company-users { 2 | &__filters { 3 | margin-bottom: $spacer--medium; 4 | } 5 | 6 | &__actions { 7 | margin: $spacer--medium 0; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /components/04-views/dashboard/company-users/company-users.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{ render '@dashboard-actions-toolbar' filtersActions }} 11 | {{> '@dashboard-table' users }} 12 | {{ render '@toolbar' toolbar merge=true }} 13 | {{ render '@dashboard-actions-toolbar' actions }} 14 |
15 |
16 |
17 |
18 | {{ render '@footer' }} 19 | -------------------------------------------------------------------------------- /components/04-views/dashboard/default/dashboard.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{ render '@dashboard-table' }} 12 | 13 | {{> '@dashboard-items' account }} 14 | 15 | {{> '@dashboard-items' addreses }} 16 |
17 |
18 |
19 |
20 | 21 | {{ render '@footer' }} 22 | -------------------------------------------------------------------------------- /components/04-views/dashboard/downloadable-product/downloadable-product.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-table' products }} 12 | 13 | {{> '@action' button }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/empty/empty.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | message: { 4 | text: 'You have no items in your wish list' 5 | }, 6 | action: { 7 | sides: [ 8 | { 9 | action: [ 10 | { 11 | title: 'Back' 12 | } 13 | ] 14 | } 15 | ] 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /components/04-views/dashboard/empty/empty.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@message' message }} 12 | 13 | {{> '@action' action }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-card/gift-card.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | form: { 4 | title: 'Gift Card', 5 | fields: [ 6 | { 7 | input: { 8 | class: 'dashboard-form__divider', 9 | field: { 10 | id: 'giftCardCode', 11 | name: 'giftCardCode', 12 | placeholder: 'Enter gitf card code' 13 | } 14 | } 15 | } 16 | ] 17 | }, 18 | buttons: { 19 | sides: [ 20 | { 21 | action: [ 22 | { 23 | button: true, 24 | title: 'Reedem Gift Card' 25 | } 26 | ] 27 | }, 28 | { 29 | action: [ 30 | { 31 | button: true, 32 | title: 'Check statuc and balance' 33 | } 34 | ] 35 | } 36 | ] 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-card/gift-card.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' form }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-registry/gift-registry--form.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' generalInformation }} 12 | 13 | {{> '@dashboard-form' eventInformation }} 14 | 15 | {{> '@dashboard-form' eventInformationSecondPart }} 16 | 17 | {{> '@dashboard-form' registrantInformation }} 18 | 19 | {{> '@action' addRegistrant }} 20 | 21 | {{> '@dashboard-form' shippingAddress }} 22 | 23 | {{> '@dashboard-form' hiddenNewAddressForm }} 24 | 25 | {{> '@action' buttons }} 26 |
27 |
28 |
29 |
30 | 31 | {{ render '@footer' }} 32 | 33 | 34 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-registry/gift-registry--form.js: -------------------------------------------------------------------------------- 1 | 'use static' 2 | 3 | const hiddenForm = document.querySelector('.dashboard__form'), 4 | select = document.querySelector('.dashboard__address select'); 5 | 6 | select.addEventListener('change', (event) => { 7 | if (event.detail.value === 'newAddress') { 8 | hiddenForm.classList.remove('dashboard__form--hidden'); 9 | } 10 | else { 11 | hiddenForm.classList.add('dashboard__form--hidden'); 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-registry/gift-registry--general-information.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' form }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/gift-registry/gift-registry.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-table' giftRegistry }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/invitation/invitation--form.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' form }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/invitation/invitation.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-table' invitations }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/my-orders/my-orders--return.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 |

12 | {{ title }} 13 |

14 | 15 |
16 | {{> '@information' info }} 17 |
18 | 19 | {{> '@input' contactEmailAddress }} 20 | 21 | {{> '@dashboard-form' form }} 22 | 23 | {{> '@action' addReturnItem }} 24 | 25 | {{> '@input--textarea' comments }} 26 | 27 | {{> '@action' action }} 28 |
29 |
30 |
31 |
32 | 33 | {{ render '@footer' }} 34 | -------------------------------------------------------------------------------- /components/04-views/dashboard/my-orders/my-orders.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@dashboard-table' }} 10 | {{ render '@toolbar--pager' toolbar merge=true }} 11 | {{> '@action' action }} 12 |
13 |
14 |
15 |
16 | {{ render '@footer' }} 17 | -------------------------------------------------------------------------------- /components/04-views/dashboard/my-quotes/_my-quotes.scss: -------------------------------------------------------------------------------- 1 | .my-quotes { 2 | &__filters { 3 | margin-bottom: $spacer--medium; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /components/04-views/dashboard/my-quotes/my-quotes.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{ render '@dashboard-actions-toolbar' filtersActions }} 11 | {{> '@dashboard-table' users }} 12 | {{ render '@toolbar' toolbar merge=true }} 13 |
14 |
15 |
16 |
17 | {{ render '@footer' }} 18 | -------------------------------------------------------------------------------- /components/04-views/dashboard/newsletter-sub/newsletter-sub.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | context: { 3 | form: { 4 | title: 'Subscription option', 5 | checkboxes: [ 6 | { 7 | checkbox: { 8 | class: 'dashboard-form__divider', 9 | id: 'subscription', 10 | label: { 11 | text: 'General Subscription' 12 | } 13 | } 14 | } 15 | ] 16 | }, 17 | buttons: { 18 | sides: [ 19 | { 20 | action: [ 21 | { 22 | button: true, 23 | title: 'Save' 24 | } 25 | ] 26 | }, 27 | { 28 | action: [ 29 | { 30 | title: 'Back' 31 | } 32 | ] 33 | } 34 | ] 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /components/04-views/dashboard/newsletter-sub/newsletter-sub.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' form }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/order-by-sku/order-by-sku.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-form' form }} 12 | 13 | {{> '@action' addRow }} 14 | 15 | {{> '@information' uploadInfo }} 16 | 17 | {{> '@file-upload' fileUpload }} 18 | 19 | {{> '@action' buttons }} 20 |
21 |
22 |
23 |
24 | 25 | {{ render '@footer' }} 26 | -------------------------------------------------------------------------------- /components/04-views/dashboard/product-reviews/_product-reviews.scss: -------------------------------------------------------------------------------- 1 | $product-reviews__image-margin : $spacer auto !default; 2 | $product-reviews__image-max-width : 300px !default; 3 | $product-reviews__details-margin-bottom: $spacer--medium !default; 4 | $product-reviews__product-name-margin : 0 !default; 5 | 6 | .product-reviews { 7 | &__image { 8 | display: block; 9 | margin: $product-reviews__image-margin; 10 | max-width: $product-reviews__image-max-width; 11 | } 12 | 13 | &__details { 14 | display: flex; 15 | justify-content: space-between; 16 | align-items: center; 17 | margin-bottom: $product-reviews__details-margin-bottom; 18 | } 19 | 20 | &__name { 21 | margin: $product-reviews__product-name-margin; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /components/04-views/dashboard/product-reviews/product-reviews--details.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{ render '@heading' title }} 12 | 13 | 18 | {{ render '@image' product.image }} 19 | 20 | 21 |
22 | 23 | {{ render '@heading' product.name }} 24 | 25 | {{ render '@review--add' }} 26 |
27 | 28 | {{ render '@heading' yourReview }} 29 | 30 | {{ render '@review' }} 31 |
32 |
33 |
34 |
35 | 36 | {{ render '@footer' }} 37 | -------------------------------------------------------------------------------- /components/04-views/dashboard/product-reviews/product-reviews.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-table' reviews }} 12 | 13 | {{> '@action' button }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/requisition-lists/_requisition-lists--view.scss: -------------------------------------------------------------------------------- 1 | $requisition-list-view__margin: 0 0 $spacer--medium 0 !default; 2 | 3 | .requisition-list-view { 4 | &__description { 5 | margin: $requisition-list-view__margin; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /components/04-views/dashboard/requisition-lists/requisition-lists--view.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 |
10 | {{ render '@title-wrapper' titleWrapper }} 11 |

12 | {{ description }} 13 |

14 |
15 | {{ render '@dashboard-actions-toolbar' }} 16 |
17 |
18 |
19 |
20 | {{ render '@footer' }} 21 | -------------------------------------------------------------------------------- /components/04-views/dashboard/requisition-lists/requisition-lists.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{> '@dashboard-table' itemsOrdered }} 11 | {{ render '@toolbar' toolbar merge=true }} 12 |
13 |
14 |
15 |
16 | {{ render '@footer' }} 17 | -------------------------------------------------------------------------------- /components/04-views/dashboard/returns/returns--details.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 |
12 |

13 | {{ returnNumer }} 14 |

15 | 16 | 17 | {{ returnStatus }} 18 | 19 |
20 | 21 | {{> '@dashboard-items' addresses }} 22 | 23 | {{> '@dashboard-table' returns }} 24 | 25 | {{> '@dashboard-form' comments }} 26 | 27 | {{> '@action' buttons }} 28 |
29 |
30 |
31 |
32 | 33 | {{ render '@footer' }} 34 | -------------------------------------------------------------------------------- /components/04-views/dashboard/returns/returns.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@dashboard-table' returns }} 12 | 13 | {{> '@action' buttons }} 14 |
15 |
16 |
17 |
18 | 19 | {{ render '@footer' }} 20 | -------------------------------------------------------------------------------- /components/04-views/dashboard/reward-points/reward-points.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{> '@information' info }} 12 | 13 | {{> '@dashboard-table' points }} 14 | 15 | {{> '@dashboard-form' form }} 16 | 17 | {{> '@action' buttons }} 18 |
19 |
20 |
21 |
22 | 23 | {{ render '@footer' }} 24 | -------------------------------------------------------------------------------- /components/04-views/dashboard/roles-and-permissions/_roles-and-permissions.scss: -------------------------------------------------------------------------------- 1 | $roles-and-permissions__margin: $spacer--medium 0 !default; 2 | 3 | .roles-and-permissions { 4 | &__actions { 5 | margin: $roles-and-permissions__margin; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /components/04-views/dashboard/roles-and-permissions/roles-and-permissions--edit.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@heading' mainTitle }} 10 | {{> '@dashboard-form' form }} 11 | {{> '@action' buttons }} 12 |
13 |
14 |
15 |
16 | {{ render '@footer' }} 17 | -------------------------------------------------------------------------------- /components/04-views/dashboard/roles-and-permissions/roles-and-permissions.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 |
4 |
5 |
6 | {{ render '@dashboard-nav' }} 7 |
8 |
9 | {{ render '@title-wrapper' titleWrapper }} 10 | {{> '@dashboard-table' itemsOrdered }} 11 | {{ render '@toolbar' toolbar merge=true }} 12 | {{ render '@dashboard-actions-toolbar' actions }} 13 |
14 |
15 |
16 |
17 | {{ render '@footer' }} 18 | -------------------------------------------------------------------------------- /components/04-views/dashboard/store-credit/store-credit.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 |
7 | {{ render '@dashboard-nav' }} 8 |
9 | 10 |
11 | {{ render '@information' }} 12 |
13 |
14 |
15 |
16 | 17 | {{ render '@footer' }} 18 | -------------------------------------------------------------------------------- /components/04-views/forgot-password/forgot-password.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 |
6 | {{ render '@heading' mainHeading }} 7 |

8 | {{ info }} 9 |

10 |
11 | {{ render '@input' email }} 12 | {{ render '@input' captcha.field }} 13 |
14 | {{ render '@image' captcha.image }} 15 | {{ render '@button' captcha.reload }} 16 |
17 | {{ render '@button' captcha.submit }} 18 |
19 |
20 |
21 |
22 | 23 | {{ render '@footer' }} 24 | -------------------------------------------------------------------------------- /components/04-views/home/home.hbs: -------------------------------------------------------------------------------- 1 |
2 | {{ render '@header' }} 3 | 4 |
5 | {{ render '@banner' }} 6 |
7 |
8 | {{ render '@banner' bannerSmall1 }} 9 | {{ render '@banner' bannerSmall2 }} 10 | {{ render '@banner' bannerSmall3 }} 11 |
12 |
13 | {{ render '@banner' bannerMedium1 }} 14 | {{ render '@banner' bannerMedium2 }} 15 |
16 |
17 | {{ render '@heading' brandBlockHeading }} 18 | {{ render '@list--link-content' brandsList }} 19 |
20 |
21 |
22 | {{{ cmsBlock }}} 23 |
24 |
25 |
26 |
27 |
28 | 29 | {{ render '@footer' }} 30 | -------------------------------------------------------------------------------- /components/_a11y-tests.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | 6 | 7 | {{> @libs }} 8 | 9 | 10 |
11 |

12 | There is no a11y erros! Well done! 13 |

14 |
15 | 16 | {{{ yield }}} 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /components/_docs-only-styles.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | 6 | 7 | {{> @libs }} 8 | 9 | 10 | {{{ yield }}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /components/_preview.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ title }} 5 | 6 | 7 | {{> @libs }} 8 | 9 | 10 | {{{ yield }}} 11 | 12 | 13 | -------------------------------------------------------------------------------- /components/_styles.scss: -------------------------------------------------------------------------------- 1 | @import '01-globals/components'; 2 | @import '02-elements/components'; 3 | @import '03-modules/components'; 4 | @import '04-views/components'; 5 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "snowdog/module-alpaca-components", 3 | "description": "Components of the Alpaca theme for Magento 2", 4 | "license": "MIT", 5 | "type": "magento2-module" 6 | } 7 | -------------------------------------------------------------------------------- /docs/styles/_fractal.scss: -------------------------------------------------------------------------------- 1 | // ----- 2 | // Documentation 3 | // ----- 4 | 5 | @import 'docs-only-styles/button'; 6 | @import 'docs-only-styles/filter'; 7 | @import 'docs-only-styles/grid'; 8 | @import 'docs-only-styles/icons'; 9 | @import 'docs-only-styles/list'; 10 | @import 'docs-only-styles/minicart-product'; 11 | @import 'docs-only-styles/newsletter'; 12 | @import 'docs-only-styles/product'; 13 | @import 'docs-only-styles/search'; 14 | 15 | 16 | // ----- 17 | // A11y test 18 | // ----- 19 | 20 | @import 'a11y-tests/a11y-tests'; 21 | -------------------------------------------------------------------------------- /docs/styles/a11y-tests/_a11y-tests.scss: -------------------------------------------------------------------------------- 1 | .a11y-test { 2 | padding: 15px; 3 | border-bottom: 10px solid #31e37d; 4 | &--error { 5 | border-color: red; 6 | .a11y-test__success-msg { 7 | display: none; 8 | } 9 | } 10 | &__success-msg { 11 | color: #31e37d; 12 | } 13 | &__error-msg { 14 | color: red; 15 | } 16 | &__error-element { 17 | outline: 5px solid red; 18 | } 19 | &__error-preview { 20 | max-width: 500px; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_button.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .button { 3 | margin-bottom: 5px; 4 | vertical-align: top; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_filter.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | @extend .dropdown-list--secondary; 3 | .filter { 4 | &__content { 5 | height: auto; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_grid.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .col-large .row__content { 3 | height: 8em; 4 | } 5 | .grid-container { 6 | padding: 0 $spacer--medium; 7 | } 8 | .row { 9 | &__content { 10 | margin-bottom: $spacer--medium; 11 | padding: $spacer; 12 | background: $gray-light; 13 | text-align: center; 14 | font-size: 16px; 15 | font-weight: bold; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_icons.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .icons { 3 | padding: 10px; 4 | display: flex; 5 | flex-wrap: wrap; 6 | &__item { 7 | width: 100px; 8 | margin: 20px; 9 | 10 | } 11 | &__single-icon { 12 | margin: 0 auto; 13 | } 14 | &__name { 15 | display: block; 16 | margin-top: 20px; 17 | text-align: center; 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_list.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .list { 3 | &--with-icon { 4 | .list__item { 5 | background-color: $gray-darker; 6 | } 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_minicart-product.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/docs/styles/docs-only-styles/_minicart-product.scss -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_newsletter.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .newsletter { 3 | background: $gray-darkest; 4 | @include mq($screen-l) { 5 | background: $gray-darker; 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_product.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .product { 3 | list-style-type: none; 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /docs/styles/docs-only-styles/_search.scss: -------------------------------------------------------------------------------- 1 | .docs-only-styles { 2 | .search { 3 | position: relative; 4 | top: 100px; 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /docs/styles/styles.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | @import '../../components/01-globals/variables/variables'; 3 | 4 | // Components 5 | @import '../../components/styles'; 6 | 7 | // Styles necessary only for Fractal purpoueses 8 | @import 'fractal'; 9 | -------------------------------------------------------------------------------- /now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "alias": "alpaca-components.now.sh", 4 | "builds": [ 5 | { "src": "package.json", "use": "@now/static-build", "config": { "distDir": "dest" } } 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpaca-components", 3 | "scripts": { 4 | "dev": "gulp dev", 5 | "build": "gulp", 6 | "now-build": "gulp --ci" 7 | }, 8 | "dependencies": { 9 | "@frctl/fractal": "~1.1.7", 10 | "autoprefixer": "~9.6.0", 11 | "eslint-config-idiomatic": "~4.0.0", 12 | "fs-extra": "~8.0.1", 13 | "globby": "~9.2.0", 14 | "gulp": "~4.0.1", 15 | "gulp-eslint": "~5.0.0", 16 | "gulp-if": "~2.0.2", 17 | "gulp-logger": "^0.0.2", 18 | "gulp-notify": "~3.2.0", 19 | "gulp-plumber": "~1.2.0", 20 | "gulp-postcss": "~8.0.0", 21 | "gulp-sass": "~4.0.2", 22 | "gulp-sass-error": "~1.0.5", 23 | "gulp-sass-lint": "~1.4.0", 24 | "gulp-sourcemaps": "~2.6.1", 25 | "gulp-svg-sprite": "~1.5.0", 26 | "gulp-util": "~3.0.8", 27 | "path": "~0.12.7", 28 | "postcss-reporter": "~6.0.1", 29 | "stylelint": "~10.1.0", 30 | "stylelint-config-standard": "~18.3.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /public/images/banner/banner-1024_416.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-1024_416.jpg -------------------------------------------------------------------------------- /public/images/banner/banner-1170_300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-1170_300.png -------------------------------------------------------------------------------- /public/images/banner/banner-1920_512.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-1920_512.jpg -------------------------------------------------------------------------------- /public/images/banner/banner-320_176.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-320_176.jpg -------------------------------------------------------------------------------- /public/images/banner/banner-480_480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-480_480.png -------------------------------------------------------------------------------- /public/images/banner/banner-768_402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-768_402.png -------------------------------------------------------------------------------- /public/images/banner/banner-768_416.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-768_416.jpg -------------------------------------------------------------------------------- /public/images/banner/banner-992_254.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/banner/banner-992_254.png -------------------------------------------------------------------------------- /public/images/catalog-grid-item/product-1_320_312.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/catalog-grid-item/product-1_320_312.jpg -------------------------------------------------------------------------------- /public/images/catalog-grid-item/product-2_320_312.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/catalog-grid-item/product-2_320_312.jpg -------------------------------------------------------------------------------- /public/images/catalog-grid-item/product-3_320_312.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/catalog-grid-item/product-3_320_312.jpg -------------------------------------------------------------------------------- /public/images/catalog-grid-item/product-color-swatch-image-1-32_40.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/catalog-grid-item/product-color-swatch-image-1-32_40.jpg -------------------------------------------------------------------------------- /public/images/gallery/product-img-384-384.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/gallery/product-img-384-384.jpg -------------------------------------------------------------------------------- /public/images/gallery/product-img-496-496.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/gallery/product-img-496-496.jpg -------------------------------------------------------------------------------- /public/images/gallery/product-img-80-80.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/gallery/product-img-80-80.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-discover_304-176.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-discover_304-176.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-discover_464-256.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-discover_464-256.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-discover_656-360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-discover_656-360.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-discover_752-360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-discover_752-360.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-new_304-176.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-new_304-176.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-new_464-256.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-new_464-256.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-new_656-360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-new_656-360.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-medium-new_752-360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-medium-new_752-360.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-gear_304-184.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-gear_304-184.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-gear_432-248.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-gear_432-248.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-men_304-184.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-men_304-184.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-men_432-248.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-men_432-248.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-women_304-184.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-women_304-184.jpg -------------------------------------------------------------------------------- /public/images/home/banners/banner-small-women_432-248.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/banners/banner-small-women_432-248.jpg -------------------------------------------------------------------------------- /public/images/home/brand-example_112-112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/home/brand-example_112-112.png -------------------------------------------------------------------------------- /public/images/icons/arrow-down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /public/images/login/banner-304-144.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/login/banner-304-144.jpg -------------------------------------------------------------------------------- /public/images/login/banner-304-144@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/login/banner-304-144@2x.jpg -------------------------------------------------------------------------------- /public/images/login/banner-304-144@3x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/login/banner-304-144@3x.jpg -------------------------------------------------------------------------------- /public/images/login/banner-464-360@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/login/banner-464-360@2x.jpg -------------------------------------------------------------------------------- /public/images/login/banner-656-360.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/login/banner-656-360.jpg -------------------------------------------------------------------------------- /public/images/product-view/banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product-view/banner.jpg -------------------------------------------------------------------------------- /public/images/product-view/slider-image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product-view/slider-image.jpg -------------------------------------------------------------------------------- /public/images/product/cart-product-160_160.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/cart-product-160_160.jpg -------------------------------------------------------------------------------- /public/images/product/minicart-product-72_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/minicart-product-72_72.png -------------------------------------------------------------------------------- /public/images/product/product-base.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/product-base.jpg -------------------------------------------------------------------------------- /public/images/product/product-img-230_180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/product-img-230_180.png -------------------------------------------------------------------------------- /public/images/product/product-img-70_46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/product-img-70_46.png -------------------------------------------------------------------------------- /public/images/product/product-second.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/product/product-second.jpg -------------------------------------------------------------------------------- /public/images/slider/slider-1500_500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/slider/slider-1500_500.png -------------------------------------------------------------------------------- /public/images/slider/slider-1920_500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/slider/slider-1920_500.png -------------------------------------------------------------------------------- /public/images/slider/slider-480_510.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/slider/slider-480_510.png -------------------------------------------------------------------------------- /public/images/slider/slider-768_500.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/slider/slider-768_500.png -------------------------------------------------------------------------------- /public/images/slider/slider-992_646.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/slider/slider-992_646.png -------------------------------------------------------------------------------- /public/images/swatch/swatch-green.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/swatch/swatch-green.jpg -------------------------------------------------------------------------------- /public/images/swatch/swatch-orange.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/swatch/swatch-orange.jpg -------------------------------------------------------------------------------- /public/images/swatch/swatch-red.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/swatch/swatch-red.jpg -------------------------------------------------------------------------------- /public/images/swatch/swatch-white.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SnowdogApps/magento2-alpaca-components/1a88626c3fe124052d2e8b2fa4c78ee6067af856/public/images/swatch/swatch-white.jpg -------------------------------------------------------------------------------- /public/tests/a11y-test.js: -------------------------------------------------------------------------------- 1 | 'use-strict' 2 | 3 | 4 | function logError(error) { 5 | const a11yWrap = document.getElementById('a11y-test'); 6 | const errorMsg = `

${error.name}

7 |
${error.message}

`; 8 | 9 | error.element.classList.add('a11y-test__error-element'); 10 | console.log(`%c ${error.name}\n\n${error.message}`, 'color: #ff5252'); 11 | a11yWrap.classList.add('a11y-test--error'); 12 | a11yWrap.innerHTML += errorMsg; 13 | } 14 | 15 | document.addEventListener('DOMContentLoaded', function() { 16 | accessibilityjs.scanForProblems(document, logError) 17 | }); 18 | -------------------------------------------------------------------------------- /static.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": "dest/" 3 | } 4 | --------------------------------------------------------------------------------