{% for class in radius_classes %}
{% include '@atoms/image/_image.twig' with {
- imageStyleName: 'thumbnail',
- class: 'm-2 rounded' ~ class,
+ image: border_radius_image,
+ image_classes: ['m-2 rounded' ~ class],
} %}
{% endfor %}
diff --git a/source/default/_patterns/00-protons/demo/index.js b/source/default/_patterns/00-protons/demo/index.js
index 7b1980d3fb..fc9e96a6d9 100644
--- a/source/default/_patterns/00-protons/demo/index.js
+++ b/source/default/_patterns/00-protons/demo/index.js
@@ -1,6 +1,7 @@
import borders from './borders.twig';
import breakpoints from './breakpoints.twig';
import colors from './colors.twig';
+import demoBlock from './demo-block.twig';
import spacing from './spacing.twig';
import tables from './tables.twig';
import type from './type.twig';
@@ -10,6 +11,7 @@ export default {
borders,
breakpoints,
colors,
+ demoBlock,
spacing,
tables,
type,
diff --git a/source/default/_patterns/00-protons/demo/welcome.twig b/source/default/_patterns/00-protons/demo/welcome.twig
index b23c7e67fe..87992e7434 100644
--- a/source/default/_patterns/00-protons/demo/welcome.twig
+++ b/source/default/_patterns/00-protons/demo/welcome.twig
@@ -10,13 +10,16 @@
-
Welcome to Particle
+ {% set welcome_image = {
+ variant: 'primary',
+ src: paths.assets ~ '/astrogoat.png',
+ alt: 'A friendly goat wearing a space helmet. The Astrogoat!',
+ } %}
+
{% include "@atoms/_image.twig" with {
- img: {
- src: paths.assets ~ '/astrogoat.png',
- },
+ image: welcome_image
} %}
Particle is a starterkit to help you make design systems
diff --git a/source/default/_patterns/01-atoms/branding/_branding.twig b/source/default/_patterns/01-atoms/branding/_branding.twig
index 03fd7119b3..b30d0ec7f7 100644
--- a/source/default/_patterns/01-atoms/branding/_branding.twig
+++ b/source/default/_patterns/01-atoms/branding/_branding.twig
@@ -16,16 +16,19 @@
{% if logo_svg_inline %}
- {% include '@atoms/image/_svg.twig' with {
- svgpath: logo_svg_inline,
- colorOriginal: true,
+ {% include '@atoms/_svg.twig' with {
+ svg: {
+ svgpath: logo_svg_inline,
+ colorOriginal: true,
+ }
} %}
{% elseif logo_img_src %}
{% include "@atoms/_image.twig" with {
- img: {
+ image: {
+ variant: 'primary',
src: logo_img_src,
alt: site_name ~ ' site logo',
- }
+ }
} %}
{% endif %}
diff --git a/source/default/_patterns/01-atoms/branding/demo/brandings.twig b/source/default/_patterns/01-atoms/branding/demo/brandings.twig
index 35c1bd2e0c..f12f624012 100644
--- a/source/default/_patterns/01-atoms/branding/demo/brandings.twig
+++ b/source/default/_patterns/01-atoms/branding/demo/brandings.twig
@@ -14,7 +14,7 @@
{% block column_1 %}
{% include "@atoms/_branding.twig" with {
url: '#',
- logo_svg_inline: '@atoms/image/logo.svg',
+ logo_svg_inline: '@atoms/branding/logo.svg',
site_name: 'Particle',
site_slogan: 'Site Slogan that Describes the Logo Above with Inline SVG'
} %}
diff --git a/source/default/_patterns/01-atoms/branding/index.js b/source/default/_patterns/01-atoms/branding/index.js
index 9d4adf9d0f..c962571bbe 100644
--- a/source/default/_patterns/01-atoms/branding/index.js
+++ b/source/default/_patterns/01-atoms/branding/index.js
@@ -6,6 +6,8 @@
import 'protons';
import 'atoms/image';
+import './logo.svg';
+
// Module template
import './_branding.twig';
diff --git a/source/default/_patterns/01-atoms/image/logo.svg b/source/default/_patterns/01-atoms/branding/logo.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/image/logo.svg
rename to source/default/_patterns/01-atoms/branding/logo.svg
diff --git a/source/default/_patterns/01-atoms/image/__tests__/image.test.js b/source/default/_patterns/01-atoms/image/__tests__/image.test.js
index 8f03711cf7..446c797525 100644
--- a/source/default/_patterns/01-atoms/image/__tests__/image.test.js
+++ b/source/default/_patterns/01-atoms/image/__tests__/image.test.js
@@ -3,5 +3,3 @@ import { name } from '..';
test('image component is registered', () => {
expect(name).toBe('image');
});
-
-// @TODO: Test switch of svg replacement logic here
diff --git a/source/default/_patterns/01-atoms/image/_image--bg.twig b/source/default/_patterns/01-atoms/image/_image--bg.twig
new file mode 100644
index 0000000000..dd9369c8cf
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/_image--bg.twig
@@ -0,0 +1,13 @@
+{#
+/**
+ * @file
+ * image--bg
+ * Implements background images.
+ *
+ * Available variables for image:
+ * - Inherit variables from @atoms/_image.twig
+ * - image.repeat [string]: Background repeat value for image.
+ */
+#}
+
+
diff --git a/source/default/_patterns/01-atoms/image/_image--picture.twig b/source/default/_patterns/01-atoms/image/_image--picture.twig
new file mode 100644
index 0000000000..b6b6461b68
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/_image--picture.twig
@@ -0,0 +1,25 @@
+{#
+/**
+ * @file
+ * image--picture
+ * Implements images with picture properties.
+ *
+ * Available variables for image:
+ * - Inherit variables from @atoms/_image.twig
+ * - image.srcset [array]: An array of image src to pull from (falls back to image.src)
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/picture
+ */
+#}
+
+{% set bp = scssBreakpoints|keys %}
+
+
+ {% for item in image.srcset %}
+ {% set key = bp[loop.index]|default('xl') %}
+
+ {% endfor %}
+ {% include '@atoms/_image--primary.twig' with {
+ image: image,
+ image_classes: image_classes
+ } %}
+
diff --git a/source/default/_patterns/01-atoms/image/_image--placeholder.twig b/source/default/_patterns/01-atoms/image/_image--placeholder.twig
new file mode 100644
index 0000000000..ddb55d291e
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/_image--placeholder.twig
@@ -0,0 +1,43 @@
+{#
+/**
+ * @file
+ * image--placeholder
+ * Implements holder.js for placeholder images.
+ *
+ * Available variables for image:
+ * - Inherit variables from @atoms/_image.twig
+ */
+#}
+
+{% set placeholderStyleName = image.style|default('medium') %}
+
+{# `imageStyles` defined in `_data/imageStyles.yaml` #}
+{% set placeholderStyle = imageStyles[placeholderStyleName] %}
+
+{% set placeholderText = placeholderStyle.width ~ 'x' ~ placeholderStyle.height %}
+
+{# if there's no height, let's randomly get one somewhere between .75 and 1.25 times the width, in increments of 10 #}
+{% if not placeholderStyle.height %}
+ {% set height = random(range(placeholderStyle.width * 0.75, placeholderStyle.width * 1.25, 10)) %}
+ {% set placeholderStyle = placeholderStyle|merge({height: height}) %}
+ {% set placeholderText = placeholderStyle.width ~ 'wide, height varies' %}
+{% endif %}
+
+{# holder.js options #}
+{% set options = {
+ theme: 'gray',
+ auto: 'yes',
+ size: '8',
+ lineWrap: '.9',
+ text: placeholderStyleName ~ ' \n (' ~ placeholderText ~ ')',
+} %}
+
+{% set imgSrc = 'holder.js/' ~ placeholderStyle.width ~ 'x' ~ placeholderStyle.height|round ~ '?' ~ options|url_encode %}
+
+{% if image.variant == 'primary'%}
+
+
+{% elseif image.variant == 'bg' %}
+
+
+{% endif %}
diff --git a/source/default/_patterns/01-atoms/image/_image--primary.twig b/source/default/_patterns/01-atoms/image/_image--primary.twig
new file mode 100644
index 0000000000..3d40cdf092
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/_image--primary.twig
@@ -0,0 +1,12 @@
+{#
+/**
+ * @file
+ * image--primary
+ * Implements images src and alt.
+ *
+ * Available variables for image:
+ * - Inherit variables from @atoms/_image.twig
+ */
+#}
+
+
diff --git a/source/default/_patterns/01-atoms/image/_image.scss b/source/default/_patterns/01-atoms/image/_image.scss
index 7f918ea3fe..04fee40e12 100644
--- a/source/default/_patterns/01-atoms/image/_image.scss
+++ b/source/default/_patterns/01-atoms/image/_image.scss
@@ -1,3 +1,8 @@
+// Custom styles for image
+
// The non-printing variables, functions, and mixins of 00-protons/variables
// are provided to this file via:
// webpack.particle.js: sass-loader.data|includePaths
+
+.image {
+}
diff --git a/source/default/_patterns/01-atoms/image/_image.twig b/source/default/_patterns/01-atoms/image/_image.twig
index b2d0129046..565e4ff174 100644
--- a/source/default/_patterns/01-atoms/image/_image.twig
+++ b/source/default/_patterns/01-atoms/image/_image.twig
@@ -1,43 +1,47 @@
-{# if we're in pattern lab and there's no specific `img`, let's do a placeholder image #}
-{% if BUILD_TARGET == 'pl' and not img %}
- {# default image style is `medium` #}
- {% set imageStyleName = imageStyleName|default('medium') %}
+{#
+/**
+ * @file
+ * image
+ *
+ * Available variables for image:
+ * - image.variant [string]: Indicates which image pattern to use.
+ * - image.src [string]: Specifies the URL of an image.
+ * - image.alt [string]: Specifies an alternate text for an image.
+ * - image.placeholder [bool]: Specifies image as placeholder (see _image--placeholder.twig).
+ * - image.style [string]: Specifies image size or style attribute.
+ */
+#}
- {# `imageStyles` defined in `_data/imageStyles.yaml` #}
- {% set imageStyle = imageStyles[imageStyleName] %}
- {% set imageText = imageStyle.width ~ 'x' ~ imageStyle.height %}
+{% set image_classes = image_classes|default([])|merge([
+ 'image',
+ 'img-fluid',
+ image.style ? 'image--' ~ image.style : '',
+ image.variant ? 'image--' ~ image.variant : '',
+]) | sort | join(' ') | trim %}
- {# if there's no height, let's randomly get one somewhere between .75 and 1.25 times the width, in increments of 10 #}
- {% if not imageStyle.height %}
- {% set height = random(range(imageStyle.width * 0.75, imageStyle.width * 1.25, 10)) %}
- {% set imageStyle = imageStyle|merge({height: height}) %}
- {% set imageText = imageStyle.width ~ 'wide, height varies' %}
- {% endif %}
+{% if image.placeholder %}
+ {% include '@atoms/_image--placeholder.twig' with {
+ image: image,
+ image_classes: image_classes
+ } %}
+
+{% elseif image.variant == 'primary' %}
+ {% include '@atoms/_image--primary.twig' with {
+ image: image,
+ image_classes: image_classes
+ } %}
- {# holder.js options #}
- {% set options = {
- theme: 'gray',
- auto: 'yes',
- size: '8',
- lineWrap: '.9',
- text: imageStyleName ~ ' \n (' ~ imageText ~ ')',
+{% elseif image.variant == 'bg' %}
+ {% include '@atoms/_image--bg.twig' with {
+ image: image,
+ image_classes: image_classes
} %}
- {% set imgSrc = 'holder.js/' ~ imageStyle.width ~ 'x' ~ imageStyle.height|round ~ '?' ~ options|url_encode %}
- {% if bg %}
-
- {% else %}
-
- {% endif %}
-{% else %}
- {# Is `img` an object or string? #}
- {% set imgSrc = img is iterable ? img.src : img %}
- {% set imgAlt = img is iterable ? img.alt : '' %}
+{% elseif image.variant == 'picture' %}
+ {% include '@atoms/_image--picture.twig' with {
+ image: image,
+ image_classes: image_classes
+ } %}
- {% if bg %}
-
- {% else %}
-
- {% endif %}
{% endif %}
diff --git a/source/default/_patterns/01-atoms/image/_svg.scss b/source/default/_patterns/01-atoms/image/_svg.scss
deleted file mode 100644
index b240b12c95..0000000000
--- a/source/default/_patterns/01-atoms/image/_svg.scss
+++ /dev/null
@@ -1,7 +0,0 @@
-.svg--colorable {
- // Set svg elements to current color.
- @include svg-elements() {
- color: currentColor;
- fill: currentColor;
- }
-}
diff --git a/source/default/_patterns/01-atoms/image/_svg.twig b/source/default/_patterns/01-atoms/image/_svg.twig
deleted file mode 100644
index cee06e674a..0000000000
--- a/source/default/_patterns/01-atoms/image/_svg.twig
+++ /dev/null
@@ -1,7 +0,0 @@
-{% if not colorOriginal %}
-
- {{ source(svgpath) }}
-
-{% else %}
- {{ source(svgpath) }}
-{% endif %}
diff --git a/source/default/_patterns/01-atoms/image/demo/_image-demo.scss b/source/default/_patterns/01-atoms/image/demo/_image-demo.scss
index 6d7eca443a..ea7cb10578 100644
--- a/source/default/_patterns/01-atoms/image/demo/_image-demo.scss
+++ b/source/default/_patterns/01-atoms/image/demo/_image-demo.scss
@@ -1,9 +1,4 @@
-// Demonstration of how references to images for bg images are transformed
-// during hot-reload and extracttext in webpack
-
-.demo-image--bg1 {
- background: url('../logo.svg') no-repeat;
-}
-.demo-image--bg2 {
- background: url('./astrogoat.png') no-repeat;
+.image--bg {
+ height: 500px;
+ background-position: center;
}
diff --git a/source/default/_patterns/01-atoms/image/demo/image-bg.twig b/source/default/_patterns/01-atoms/image/demo/image-bg.twig
deleted file mode 100644
index a630bcfb40..0000000000
--- a/source/default/_patterns/01-atoms/image/demo/image-bg.twig
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
Background image: svg
-
-
-
-
Background image: png
-
diff --git a/source/default/_patterns/01-atoms/image/demo/image-img.md b/source/default/_patterns/01-atoms/image/demo/image-img.md
deleted file mode 100644
index 7878757c56..0000000000
--- a/source/default/_patterns/01-atoms/image/demo/image-img.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# How to handle static assets!
-
-Please note how `@atoms/image/demo/logo.twig` contains this code:
-
-```
-{% include "@atoms/_image.twig" with {
- img: {
- src: paths.assets ~ '/logo.svg',
- }
-} %}
-```
-
-And also notice how `@atoms/image/index.js` contains this code:
-
-```
-import './logo.svg';
-```
-
-All static assets (images, fonts) **must** be referenced within the javascript dependency chain to be moved to `dist/assets/`. These assets will be available to PL after running `npm run compile:pl`.
diff --git a/source/default/_patterns/01-atoms/image/demo/image-img.twig b/source/default/_patterns/01-atoms/image/demo/image-img.twig
deleted file mode 100644
index abb8b7fa42..0000000000
--- a/source/default/_patterns/01-atoms/image/demo/image-img.twig
+++ /dev/null
@@ -1,25 +0,0 @@
-{#
-All paths reference distributed OUTPUT, not local. Static assets are only
-referencable post-build.
-#}
-
-{% extends '@atoms/_grid-2-up.twig' %}
- {% set container = true %}
-
- {% block column_1 %}
-
- {% for imageStyleName, imageStyleSetting in imageStyles %}
-
- {% include "@atoms/_image.twig" with {
- imageStyleName: imageStyleName
- } %}
-
- {% endfor %}
-
-{% endblock %}
diff --git a/source/default/_patterns/01-atoms/image/demo/images.md b/source/default/_patterns/01-atoms/image/demo/images.md
new file mode 100644
index 0000000000..addd387e62
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/demo/images.md
@@ -0,0 +1,28 @@
+# How to handle static assets!
+
+Please note that image implementations may contain this or similar code:
+
+```twig
+{% include "@atoms/_image.twig" with {
+ image: {
+ src: paths.assets ~ '/logo.svg',
+ }
+} %}
+```
+
+The logo is file is stored in `project/themes/particle/source/images`,
+where it is imported into our design system as a proton in:
+`project/themes/particle/source/default/_patterns/00-protons/index.js`
+
+Notice how this `index.js` contains this code:
+
+```javascript
+import '../../../images/logo.svg';
+```
+
+All static assets (images, fonts) **must** be referenced within the javascript
+dependency chain to be moved to `dist/assets/`.
+These assets will be available to PL after running `npm run compile:pl`.
+The example here provides *Pattern Lab* assets only, as protons assets are not
+exported. The individual implementation should include references to files as
+needed.
diff --git a/source/default/_patterns/01-atoms/image/demo/images.twig b/source/default/_patterns/01-atoms/image/demo/images.twig
new file mode 100644
index 0000000000..fd0799dbc0
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/demo/images.twig
@@ -0,0 +1,64 @@
+{% embed '@protons/demo/demo-block.twig' with {
+ demo: image_demo_block
+} %}
+
+ {% block content %}
+
+
+
Primary Image
+ {% for imageStyleName, imageStyleSetting in imageStyles %}
+ {% set image = {
+ variant: 'primary',
+ style: imageStyleName,
+ placeholder: true,
+ } %}
+
+ {% include "@atoms/_image.twig" with {
+ image: image,
+ image_classes: ['d-inline', 'm-1']
+ } %}
+ {% endfor %}
+
+
+
+
Picture with Multiple Source
+
+ {% include '@atoms/_image.twig' with {
+ image: image_picture_demo,
+ } %}
+
+
+
+
+
Background Images
+
+
+
SVG
+ {% set image_bg_logo_demo = {
+ variant: 'bg',
+ src: paths.assets ~ '/logo.svg',
+ alt: 'A friendly goat wearing a space helmet. The Astrogoat!',
+ } %}
+
+ {% include '@atoms/_image.twig' with {
+ image: image_bg_logo_demo
+ } %}
+
+
+
PNG
+ {% set image_bg_astrogoat_demo = {
+ variant: 'bg',
+ src: paths.assets ~ '/astrogoat.png',
+ alt: 'A friendly goat wearing a space helmet. The Astrogoat!',
+ } %}
+
+ {% include '@atoms/_image.twig' with {
+ image: image_bg_astrogoat_demo
+ } %}
+
+
+
+
+ {% endblock content %}
+
+{% endembed %}
diff --git a/source/default/_patterns/01-atoms/image/demo/images.yml b/source/default/_patterns/01-atoms/image/demo/images.yml
new file mode 100644
index 0000000000..17938a73e0
--- /dev/null
+++ b/source/default/_patterns/01-atoms/image/demo/images.yml
@@ -0,0 +1,20 @@
+image_primary_demo:
+ variant: 'primary'
+ src: ''
+ alt: ''
+ style: 'small'
+ placeholder: true # this turns the image to a graybox.
+
+image_picture_demo:
+ variant: 'picture'
+ src: 'https://via.placeholder.com/500'
+ alt: 'A graybox image'
+ style: ''
+ srcset: ['https://via.placeholder.com/100', 'https://via.placeholder.com/200', 'https://via.placeholder.com/400']
+ placeholder: false
+
+image_demo_block:
+ title: 'Image'
+ text:
+ lead: 'Image HTML patterns.'
+ summary: 'The image pattern includes variants to cover most image use cases, including background images and picture.'
diff --git a/source/default/_patterns/01-atoms/image/demo/index.js b/source/default/_patterns/01-atoms/image/demo/index.js
index af591bcb84..1a485dd4d5 100644
--- a/source/default/_patterns/01-atoms/image/demo/index.js
+++ b/source/default/_patterns/01-atoms/image/demo/index.js
@@ -1,26 +1,29 @@
/**
- * Demo of Image. Pull in image assets, but provide demo-only assets.
+ * Demo of image. Pulls in image assets, and provides demo-only assets.
+ *
+ * (This file is NOT imported by the design system, but is included as part of
+ * a Pattern Lab app.)
*/
-// Ensure all image pattern deps are present
+// Import component assets
import 'atoms/image';
// Demo-only styles
import './_image-demo.scss';
-// Demo-only asset: astrogoat.png
+// Holder JS for Demos Only.
+import 'holderjs';
+
+// Import demo only astrogoat.
import './astrogoat.png';
-import imageImgMarkdown from './image-img.md';
-import imageImgTwig from './image-img.twig';
-import imageInlineTwig from './image-inline.twig';
-import imageStylesTwig from './image-styles.twig';
-import imageBgTwig from './image-bg.twig';
+// Import demo assets
+import twig from './images.twig';
+import yaml from './images.yml';
+import markdown from './images.md';
export default {
- imageImgMarkdown,
- imageImgTwig,
- imageInlineTwig,
- imageStylesTwig,
- imageBgTwig,
+ twig,
+ yaml,
+ markdown,
};
diff --git a/source/default/_patterns/01-atoms/image/index.js b/source/default/_patterns/01-atoms/image/index.js
index 30a2c89d8c..1b8530c4ce 100644
--- a/source/default/_patterns/01-atoms/image/index.js
+++ b/source/default/_patterns/01-atoms/image/index.js
@@ -1,24 +1,53 @@
-// Import custom sass, includes Bootstrap sass
-import './_image.scss';
-import './_svg.scss';
+/**
+ * image
+ */
+
+import $ from 'jquery';
-// Pull in system-wide images
-import './logo.svg';
+// Module dependencies
+import 'protons';
-// Module templates
+// Module styles
+import './_image.scss';
+
+// Module template
import './_image.twig';
-import './_svg.twig';
export const name = 'image';
-export function disable() {}
+export const defaults = {
+ dummyClass: 'js-image-exists',
+};
+
+/**
+ * Components may need to run clean-up tasks if they are removed from DOM.
+ *
+ * @param {jQuery} $context - A piece of DOM
+ * @param {Object} settings - Pertinent settings
+ */
+// eslint-disable-next-line no-unused-vars
+export function disable($context, settings) {}
-export function enable($context, { enableHolder }) {
- // Holder is only provided to PL, not Drupal. Like jQuery it's an IIFE
- // We can only conditionally import libraries using `require()`
- if (enableHolder) {
- require('holderjs'); // eslint-disable-line global-require
+/**
+ * Each component has a chance to run when its enable function is called. It is
+ * given a piece of DOM ($context) and a settings object. We destructure our
+ * component key off the settings object and provide an empty object fallback.
+ * Incoming settings override default settings via Object.assign().
+ *
+ * @param {jQuery} $context - A piece of DOM
+ * @param {Object} settings - Settings object
+ */
+export function enable($context, { image = {} }) {
+ // Find our component within the DOM
+ const $image = $('.image', $context);
+ // Bail if component does not exist
+ if (!$image.length) {
+ return;
}
+ // Merge defaults with incoming settings
+ const settings = Object.assign(defaults, image);
+ // An example of what could be done with this component
+ $image.addClass(settings.dummyClass);
}
export default enable;
diff --git a/source/default/_patterns/01-atoms/svg/__tests__/svg.test.js b/source/default/_patterns/01-atoms/svg/__tests__/svg.test.js
new file mode 100644
index 0000000000..f288aa4ce0
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/__tests__/svg.test.js
@@ -0,0 +1,5 @@
+import { name } from '../index';
+
+test('svg component is registered', () => {
+ expect(name).toBe('svg');
+});
diff --git a/source/default/_patterns/01-atoms/svg/_svg--icon.twig b/source/default/_patterns/01-atoms/svg/_svg--icon.twig
new file mode 100644
index 0000000000..56cb22bc0e
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/_svg--icon.twig
@@ -0,0 +1,23 @@
+{#
+/**
+ * @file
+ * svg--icon
+ *
+ * Available variables for svgicon:
+ * - svgicon.svgname [string]: String filename of the SVG to use from svg/
+ * - svgicon.svgfill [string]: Pass in a theme-color to colorize the SVG.
+ * Otherwise it will default to black.
+ */
+#}
+
+{% set svg_classes = svg_classes|default([])|merge([
+ 'svg',
+ 'svg--icon',
+ svgicon.svgfill ? 'color-fill--' ~ svgicon.svgfill : '',
+]) | sort | join(' ') | trim %}
+
+
+
+
diff --git a/source/default/_patterns/01-atoms/svgicon/_svgicon.scss b/source/default/_patterns/01-atoms/svg/_svg.scss
similarity index 75%
rename from source/default/_patterns/01-atoms/svgicon/_svgicon.scss
rename to source/default/_patterns/01-atoms/svg/_svg.scss
index 7887c23313..1e3d7bb535 100644
--- a/source/default/_patterns/01-atoms/svgicon/_svgicon.scss
+++ b/source/default/_patterns/01-atoms/svg/_svg.scss
@@ -1,15 +1,20 @@
+// Custom styles for svg
+
// The non-printing variables, functions, and mixins of 00-protons/variables
// are provided to this file via:
// webpack.particle.js: sass-loader.data|includePaths
-// Note!
-// ./scss/_icons-generated is automatically made available because
-// 00-protons/variables is provided to every scss file and _icons-generated
-// is @import'd within 00-protons/variables
+.svg {
+ .svg--colorable {
+ // Set svg elements to current color.
+ @include svg-elements() {
+ color: currentColor;
+ fill: currentColor;
+ }
+ }
+}
-// Default styles to maintain inline-block functionality
-// since the SVG is wrapped in a div
-.svgicon-default {
+.svg--icon {
display: inline-block;
width: rem-calc(40px);
diff --git a/source/default/_patterns/01-atoms/svg/_svg.twig b/source/default/_patterns/01-atoms/svg/_svg.twig
new file mode 100644
index 0000000000..64813b8a3c
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/_svg.twig
@@ -0,0 +1,17 @@
+{#
+/**
+ * @file
+ * svg
+ *
+ * Available variables for svg:
+ * - svg.svgpath [string]: Generic element to define shape of svg.
+ * - svg.colorOriginal [bool]: Whether to display the color.
+ */
+#}
+
+{% set svg_classes = svg_classes|default([])|merge([
+ 'svg',
+ not svg.colorOriginal ? 'svg--colorable' : '',
+]) | sort | join(' ') | trim %}
+
+{{ source(svg.svgpath) }}
diff --git a/source/default/_patterns/01-atoms/svgicon/demo/_svgicon-demo.scss b/source/default/_patterns/01-atoms/svg/demo/_svg--icon-demo.scss
similarity index 74%
rename from source/default/_patterns/01-atoms/svgicon/demo/_svgicon-demo.scss
rename to source/default/_patterns/01-atoms/svg/demo/_svg--icon-demo.scss
index e0723603e7..938e943050 100644
--- a/source/default/_patterns/01-atoms/svgicon/demo/_svgicon-demo.scss
+++ b/source/default/_patterns/01-atoms/svg/demo/_svg--icon-demo.scss
@@ -2,13 +2,13 @@
// are provided to this file via:
// webpack.particle.js: sass-loader.data|includePaths
-.svgicon-demo--particle-mixin {
- @include sprite('person');
+.svgicon-demo--particle-mixin-chevron-right {
+ @include sprite('chevron-right');
height: rem-calc(40px);
width: rem-calc(40px);
}
-.svgicon-demo-1 {
+.svgicon-demo--particle-mixin-person {
@include sprite(
'person',
(
diff --git a/source/default/_patterns/01-atoms/svg/demo/index.js b/source/default/_patterns/01-atoms/svg/demo/index.js
new file mode 100644
index 0000000000..f58f1fc380
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/demo/index.js
@@ -0,0 +1,23 @@
+/**
+ * Demo of svg. Pulls in svg assets, and provides demo-only assets.
+ *
+ * (This file is NOT imported by the design system, but is included as part of
+ * a Pattern Lab app.)
+ */
+
+// Import component assets
+import 'atoms/svg';
+
+// Demo-only styles
+import './_svg--icon-demo.scss';
+
+// Import demo assets
+import twig from './svgs.twig';
+import yaml from './svgs.yml';
+import markdown from './svgs.md';
+
+export default {
+ twig,
+ yaml,
+ markdown,
+};
diff --git a/source/default/_patterns/01-atoms/svg/demo/svgs.md b/source/default/_patterns/01-atoms/svg/demo/svgs.md
new file mode 100644
index 0000000000..2cd0cd74e6
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/demo/svgs.md
@@ -0,0 +1,3 @@
+---
+title: svg
+---
diff --git a/source/default/_patterns/01-atoms/svgicon/demo/svgicons.twig b/source/default/_patterns/01-atoms/svg/demo/svgs.twig
similarity index 86%
rename from source/default/_patterns/01-atoms/svgicon/demo/svgicons.twig
rename to source/default/_patterns/01-atoms/svg/demo/svgs.twig
index 576ec654c0..4e7b6d8f6c 100644
--- a/source/default/_patterns/01-atoms/svgicon/demo/svgicons.twig
+++ b/source/default/_patterns/01-atoms/svg/demo/svgs.twig
@@ -1,14 +1,8 @@
-{% extends '@atoms/grid/_grid-1-up.twig' %}
- {% set container = true %}
- {% block column_1 %}
-
-
SVG Icons
-
Store your SVG files in the SVG subdirectory to have them
- made available via the _svgicon.twig partial or using a Sass
- mixin. SVGs are rendered utilizing their filename as a variable. FontAwesome
- icons can also be used through an HTML class or a Sass mixin.
-
Note: If you’ve exported from Illustrator or Sketch you should be good to use the svgs directly.
However if you’ve used Inkscape, there are some issues with the added markup from the application. Use the
following fiddle to clean extra markup:
@@ -36,23 +30,27 @@
Font Awesome Sass support is currently disabled in Particle to reduce the volume of generated CSS and font files. However, Font Awesome Sass can be easily included by following the Font Awesome Sass guide.
+ {% endblock %}
- {% endblock column_1 %}
+{% endembed %}
diff --git a/source/default/_patterns/01-atoms/svg/demo/svgs.yml b/source/default/_patterns/01-atoms/svg/demo/svgs.yml
new file mode 100644
index 0000000000..0fd856d4dc
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/demo/svgs.yml
@@ -0,0 +1,8 @@
+svg_demo_block:
+ title: 'SVG Component'
+ text:
+ lead: 'Implements our SVG and SVG Icons.'
+ summary: 'Store your SVG files in the SVG subdirectory to have them
+ made available via the _svg--icon.twig partial or using a Sass
+ mixin. SVGs are rendered utilizing their filename as a variable. FontAwesome
+ icons can also be used through an HTML class or a Sass mixin.'
diff --git a/source/default/_patterns/01-atoms/svgicon/fontawesome.js b/source/default/_patterns/01-atoms/svg/fontawesome.js
similarity index 91%
rename from source/default/_patterns/01-atoms/svgicon/fontawesome.js
rename to source/default/_patterns/01-atoms/svg/fontawesome.js
index 401ce56292..c20a9b761b 100644
--- a/source/default/_patterns/01-atoms/svgicon/fontawesome.js
+++ b/source/default/_patterns/01-atoms/svg/fontawesome.js
@@ -11,7 +11,7 @@ import {
faRocket,
faSpaceShuttle,
faUser,
-} from '@fortawesome/free-solid-svg-icons';
+} from '@fortawesome/free-solid-svg-icons/index';
// Add specific icons required
library.add(faUserAstronaut, faRocket, faSpaceShuttle, faUser);
diff --git a/source/default/_patterns/01-atoms/svg/index.js b/source/default/_patterns/01-atoms/svg/index.js
new file mode 100644
index 0000000000..f13997a203
--- /dev/null
+++ b/source/default/_patterns/01-atoms/svg/index.js
@@ -0,0 +1,63 @@
+/**
+ * svg
+ */
+
+import $ from 'jquery';
+import svg4everybody from 'svg4everybody';
+
+// Module dependencies
+import 'protons';
+import fontawesome from './fontawesome';
+
+// Module styles
+import './_svg.scss';
+
+// Module template
+import './_svg.twig';
+import './_svg--icon.twig';
+
+// Enable Fontawesome immediately
+fontawesome();
+
+export const name = 'svg';
+
+export const defaults = {
+ dummyClass: 'js-svg-exists',
+};
+
+/**
+ * Components may need to run clean-up tasks if they are removed from DOM.
+ *
+ * @param {jQuery} $context - A piece of DOM
+ * @param {Object} settings - Pertinent settings
+ */
+// eslint-disable-next-line no-unused-vars
+export function disable($context, settings) {}
+
+/**
+ * Each component has a chance to run when its enable function is called. It is
+ * given a piece of DOM ($context) and a settings object. We destructure our
+ * component key off the settings object and provide an empty object fallback.
+ * Incoming settings override default settings via Object.assign().
+ *
+ * @param {jQuery} $context - A piece of DOM
+ * @param {Object} settings - Settings object
+ */
+export function enable($context, { svg = {} }) {
+ // Find our component within the DOM
+ const $svg = $('.svg', $context);
+ // Bail if component does not exist
+ if (!$svg.length) {
+ return;
+ }
+
+ // Enable svg4everybody.
+ svg4everybody();
+
+ // Merge defaults with incoming settings
+ const settings = Object.assign(defaults, svg);
+ // An example of what could be done with this component
+ $svg.addClass(settings.dummyClass);
+}
+
+export default enable;
diff --git a/source/default/_patterns/01-atoms/svgicon/scss/.gitkeep b/source/default/_patterns/01-atoms/svg/scss/.gitkeep
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/scss/.gitkeep
rename to source/default/_patterns/01-atoms/svg/scss/.gitkeep
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/chevron-down.svg b/source/default/_patterns/01-atoms/svg/svg/chevron-down.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/chevron-down.svg
rename to source/default/_patterns/01-atoms/svg/svg/chevron-down.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/chevron-left.svg b/source/default/_patterns/01-atoms/svg/svg/chevron-left.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/chevron-left.svg
rename to source/default/_patterns/01-atoms/svg/svg/chevron-left.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/chevron-right.svg b/source/default/_patterns/01-atoms/svg/svg/chevron-right.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/chevron-right.svg
rename to source/default/_patterns/01-atoms/svg/svg/chevron-right.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/chevron-up.svg b/source/default/_patterns/01-atoms/svg/svg/chevron-up.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/chevron-up.svg
rename to source/default/_patterns/01-atoms/svg/svg/chevron-up.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/close.svg b/source/default/_patterns/01-atoms/svg/svg/close.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/close.svg
rename to source/default/_patterns/01-atoms/svg/svg/close.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/menu.svg b/source/default/_patterns/01-atoms/svg/svg/menu.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/menu.svg
rename to source/default/_patterns/01-atoms/svg/svg/menu.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/person.svg b/source/default/_patterns/01-atoms/svg/svg/person.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/person.svg
rename to source/default/_patterns/01-atoms/svg/svg/person.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/svg/search.svg b/source/default/_patterns/01-atoms/svg/svg/search.svg
similarity index 100%
rename from source/default/_patterns/01-atoms/svgicon/svg/search.svg
rename to source/default/_patterns/01-atoms/svg/svg/search.svg
diff --git a/source/default/_patterns/01-atoms/svgicon/__tests__/svgicon.test.js b/source/default/_patterns/01-atoms/svgicon/__tests__/svgicon.test.js
deleted file mode 100644
index 633325721e..0000000000
--- a/source/default/_patterns/01-atoms/svgicon/__tests__/svgicon.test.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { name } from '..';
-
-test('svgicon component is registered', () => {
- expect(name).toBe('svgicon');
-});
diff --git a/source/default/_patterns/01-atoms/svgicon/_svgicon.twig b/source/default/_patterns/01-atoms/svgicon/_svgicon.twig
deleted file mode 100644
index 4f3aa1b61c..0000000000
--- a/source/default/_patterns/01-atoms/svgicon/_svgicon.twig
+++ /dev/null
@@ -1,17 +0,0 @@
-{#
-/**
- * @file
- * svgicon
- *
- * Available variables for svgicon:
- * - svgicon.svgname [string]: String filename of the SVG to use from svg/
- * - svgicon.svgfill [string]: Pass in a theme-color to colorize the SVG.
- * Otherwise it will default to black.
- */
-#}
-
-
-
-
diff --git a/source/default/_patterns/01-atoms/svgicon/demo/index.js b/source/default/_patterns/01-atoms/svgicon/demo/index.js
deleted file mode 100644
index bb6cc4367c..0000000000
--- a/source/default/_patterns/01-atoms/svgicon/demo/index.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * Demo of svgicon. Pulls in svgicon assets, and provides demo-only assets.
- *
- * (This file is NOT imported by the design system, but is included as part of
- * a Pattern Lab app.)
- */
-
-// Import component assets
-import 'atoms/svgicon';
-
-// Demo-only styles
-import './_svgicon-demo.scss';
-
-// Import demo assets
-import twig from './svgicons.twig';
-import yaml from './svgicons.yml';
-import markdown from './svgicons.md';
-
-export default {
- twig,
- yaml,
- markdown,
-};
diff --git a/source/default/_patterns/01-atoms/svgicon/demo/svgicons.md b/source/default/_patterns/01-atoms/svgicon/demo/svgicons.md
deleted file mode 100644
index 9119a852cc..0000000000
--- a/source/default/_patterns/01-atoms/svgicon/demo/svgicons.md
+++ /dev/null
@@ -1,3 +0,0 @@
----
-title: svgicon
----
diff --git a/source/default/_patterns/01-atoms/svgicon/demo/svgicons.yml b/source/default/_patterns/01-atoms/svgicon/demo/svgicons.yml
deleted file mode 100644
index e69de29bb2..0000000000
diff --git a/source/default/_patterns/01-atoms/svgicon/index.js b/source/default/_patterns/01-atoms/svgicon/index.js
deleted file mode 100644
index a47da94f1b..0000000000
--- a/source/default/_patterns/01-atoms/svgicon/index.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/**
- * SVG icons
- */
-
-import svg4everybody from 'svg4everybody';
-
-// Module dependencies
-import 'protons';
-import fontawesome from './fontawesome';
-
-// Module styles
-import './_svgicon.scss';
-
-// Module template
-import './_svgicon.twig';
-
-// Enable Fontawesome immediately
-fontawesome();
-
-export const name = 'svgicon';
-
-export function disable() {}
-
-export function enable() {
- svg4everybody();
-}
-
-export default enable;
diff --git a/source/default/_patterns/02-molecules/pagination/index.js b/source/default/_patterns/02-molecules/pagination/index.js
index c80765895f..0ab3cabd58 100644
--- a/source/default/_patterns/02-molecules/pagination/index.js
+++ b/source/default/_patterns/02-molecules/pagination/index.js
@@ -4,7 +4,7 @@
// Module dependencies
import 'protons';
-import 'atoms/svgicon';
+import 'atoms/svg';
// Module template
import './_pagination.twig';
diff --git a/source/default/_patterns/03-organisms/article/_article.twig b/source/default/_patterns/03-organisms/article/_article.twig
index a208adb0e8..ba7190b962 100644
--- a/source/default/_patterns/03-organisms/article/_article.twig
+++ b/source/default/_patterns/03-organisms/article/_article.twig
@@ -14,11 +14,9 @@
{% set image_classes = [
'm-3',
- 'img',
- 'img-fluid',
'rounded-circle',
'float-right'
-] | sort | join(' ') | trim %}
+] | sort %}
diff --git a/source/default/_patterns/05-pages/demo/homepage.twig b/source/default/_patterns/05-pages/demo/homepage.twig
index f450d35aa3..0f56541919 100644
--- a/source/default/_patterns/05-pages/demo/homepage.twig
+++ b/source/default/_patterns/05-pages/demo/homepage.twig
@@ -10,7 +10,7 @@
{% block jumbotron_branding %}
{% include "@atoms/_branding.twig" with {
url: '#',
- logo_svg_inline: '@atoms/image/logo.svg',
+ logo_svg_inline: '@atoms/branding/logo.svg',
site_name: 'Particle',
site_slogan: 'An opinionated toolkit for building design systems.'
} %}
@@ -30,4 +30,4 @@
Ei sit choro voluptaria, mei sint tation interpretaris et. Rebum iusto pertinacia et vim, usu inermis suscipit molestiae ex. Cu usu persius nominati, te nominati perpetua sed. Eu laudem noster est, ea duis quas ius.
{% endblock %}
{% endembed %}
- {% endblock %}
\ No newline at end of file
+ {% endblock %}
diff --git a/source/default/webpack.config.js b/source/default/webpack.config.js
index 01b4f65d9c..dae2bc3c1b 100644
--- a/source/default/webpack.config.js
+++ b/source/default/webpack.config.js
@@ -39,12 +39,12 @@ module.exports = {
plugins: [
// Sprite system options
new SVGSpritemapPlugin(
- path.resolve(PATH_PATTERNS, '01-atoms/svgicon/svg/**/*.svg'),
+ path.resolve(PATH_PATTERNS, '01-atoms/svg/svg/**/*.svg'),
{
styles: {
filename: path.resolve(
PATH_PATTERNS,
- '01-atoms/svgicon/scss/_icons-generated.scss'
+ '01-atoms/svg/scss/_icons-generated.scss'
),
variables: {
sizes: 'svgicon-sizes', // Prevent collision with Bootstrap $sizes
diff --git a/tools/tests/vrt/backstop-example-reference.js b/tools/tests/vrt/backstop-example-reference.js
index 7023b9278e..4b20cf51d7 100644
--- a/tools/tests/vrt/backstop-example-reference.js
+++ b/tools/tests/vrt/backstop-example-reference.js
@@ -2,6 +2,7 @@
* A barebones Backstop reference using example settings.
*/
+// eslint-disable-next-line
const backstop = require('backstopjs');
const backstopConfig = require('./backstop-example-settings.js')();
diff --git a/tools/tests/vrt/backstop-example-test.js b/tools/tests/vrt/backstop-example-test.js
index 8b1d289fa8..ad3a55ece7 100644
--- a/tools/tests/vrt/backstop-example-test.js
+++ b/tools/tests/vrt/backstop-example-test.js
@@ -2,6 +2,7 @@
* A barebones Backstop test using example settings.
*/
+// eslint-disable-next-line
const backstop = require('backstopjs');
const backstopConfig = require('./backstop-example-settings.js')();