mp-design-system 1.2.52 → 1.2.54

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mp-design-system",
3
- "version": "1.2.52",
3
+ "version": "1.2.54",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "dev": "npm-run-all --parallel bundle:*",
package/src/_headers CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- Content-Security-Policy: default-src 'self'; base-uri 'self'; block-all-mixed-content; font-src 'self' https://fonts.gstatic.com; form-action 'self'; frame-src 'self' https://brand.malvernpanalytical.com https://www.youtube.com https://challenges.cloudflare.com https://newassets.hcaptcha.com; frame-ancestors 'self' https://brand.malvernpanalytical.com; img-src 'self' data: https://p3.aprimocdn.net https://img.youtube.com; object-src 'none'; picture-in-picture 'self'; sandbox allow-forms allow-same-origin allow-scripts allow-downloads; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://polyfill.io https://eu.altcha.org https://challenges.cloudflare.com https://js.hcaptcha.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; upgrade-insecure-requests;
2
+ Content-Security-Policy: default-src 'self'; base-uri 'self'; block-all-mixed-content; font-src 'self' https://fonts.gstatic.com; form-action 'self'; frame-src 'self' https://brand.malvernpanalytical.com https://www.youtube.com https://challenges.cloudflare.com https://newassets.hcaptcha.com; frame-ancestors 'self' https://brand.malvernpanalytical.com; img-src 'self' data: https://dam.malvernpanalytical.com https://p3.aprimocdn.net https://img.youtube.com; object-src 'none'; picture-in-picture 'self'; sandbox allow-forms allow-same-origin allow-scripts allow-downloads; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://polyfill.io https://eu.altcha.org https://challenges.cloudflare.com https://js.hcaptcha.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; upgrade-insecure-requests;
3
3
  X-Content-Type-Options: nosniff
4
4
  X-Frame-Options: SAMEORIGIN
5
5
  X-XSS-Protection: 1; mode=block
@@ -0,0 +1,55 @@
1
+ module.exports = {
2
+ title: 'Hotspot image',
3
+ component: {
4
+ name: 'hotspot-image',
5
+ },
6
+ context: {
7
+ image: {
8
+ src: 'https://dam.malvernpanalytical.com/3f407d1c-a153-4806-ab9e-b1bf00d41bc5/2524009%20MALV%20Infographic%20Analycial%20process_WITHOUT_TEXT_ModAW_Original%20file.jpg',
9
+ alt: 'Description of the image',
10
+ },
11
+ heading: {
12
+ position: 'top: 2.75%; left: 2.75%;',
13
+ content: 'All the elements of an integrated analytical workflow',
14
+ },
15
+ hotspots: [
16
+ {
17
+ position: 'top: 46%; left: 29%;',
18
+ button: {
19
+ label: 'Preparing your sample',
20
+ },
21
+ tooltip: {
22
+ content:
23
+ '<ul class="o-grid o-grid--of-two"><li class="u-bg-white u-pad-2xs">Sample preparation methods & advice</li><li class="u-bg-white u-pad-2xs">Labware and accessories</li><li class="u-bg-white u-pad-2xs">Instruments for flux dosing and fusion</li><li class="u-bg-white u-pad-2xs">Methods and advice</li></ul>',
24
+ },
25
+ },
26
+ {
27
+ position: 'top: 28.75%; left: 70%;',
28
+ button: {
29
+ label: 'Analysis with XRF',
30
+ },
31
+ tooltip: {
32
+ content:
33
+ '<ul class="o-grid o-grid--of-two"><span class="u-margin-0"></span><li class="o-grid o-grid--of-two u-align-items-start u-margin-0" style="flex-basis: 100%;"><span class="u-bg-white u-pad-2xs">XRF application methods</span><ul class="u-flow--2xs"><li class="u-bg-petrol u-petrol-step-3 u-pad-2xs">Templates in i.e., Wroxi</li><li class="u-bg-petrol u-petrol-step-3 u-pad-2xs">Application Support</li></ul></li><span class="u-margin-0"></span><li class="o-grid o-grid--of-two u-align-items-start u-margin-0" style="flex-basis: 100%;"><span class="u-bg-white u-pad-2xs">Certified reference materials</span><ul><li class="u-bg-petrol u-petrol-step-3 u-pad-2xs">Off-the-shelf and customized</li></ul></li><li class="u-bg-white u-pad-2xs">Expertise support</li><li class="u-bg-white u-pad-2xs">Pre-calibration</li><li class="u-bg-white u-pad-2xs">XRF instruments and maintenance</li></ul>',
34
+ },
35
+ },
36
+ {
37
+ position: 'top: 67.75%; left: 76%;',
38
+ button: {
39
+ label: 'Reporting results',
40
+ },
41
+ tooltip: {
42
+ content:
43
+ '<ul class="o-grid o-grid--of-two"><li class="u-bg-white u-pad-2xs">Seamless connection to LIMS</li><li class="u-bg-white u-pad-2xs">Training Instrument operation training</li><li class="u-bg-white u-pad-2xs">Data interpretation</li><li class="u-bg-white u-pad-2xs">XRF Application training</li><li class="u-bg-white u-pad-2xs">Sample preparation training</li></ul>',
44
+ },
45
+ },
46
+ {
47
+ position: 'top: 85%; left: 48.5%;',
48
+ button: {
49
+ label: 'Training',
50
+ },
51
+ },
52
+ ],
53
+ },
54
+ variants: [],
55
+ };
@@ -0,0 +1,41 @@
1
+ {% set classNames = "mp c-hotspot-image" %}
2
+
3
+ <div class="{{ classNames }}" role="img" aria-label="Interactive image with hotspots">
4
+ {% if params.image %}
5
+ <img src="{{ params.image.src }}" alt="{{ params.image.alt }}" role="presentation">
6
+ {% endif %}
7
+
8
+ {% if params.heading %}
9
+ <p class="{{ classNames }}__heading" style="{{ params.heading.position }}" aria-labelledby="image-heading">
10
+ {{ params.heading.content }}
11
+ </p>
12
+ {% endif %}
13
+
14
+ {% if params.hotspots | length %}
15
+ {% for hotspot in params.hotspots %}
16
+ <div class="{{ classNames }}__hotspot" style="{{ hotspot.position }}" aria-live="polite">
17
+ {% if hotspot.button and hotspot.tooltip %}
18
+ <button class="{{ classNames }}__button"
19
+ role="button"
20
+ aria-expanded="false"
21
+ aria-controls="tooltip-{{ loop.index }}"
22
+ aria-label="{{ hotspot.button.label }}">
23
+ {{ hotspot.button.label }}
24
+ </button>
25
+ <div id="tooltip-{{ loop.index }}"
26
+ class="c-hotspot-image__tooltip"
27
+ role="tooltip"
28
+ aria-hidden="true">
29
+ {{ hotspot.tooltip.content | safe }}
30
+ </div>
31
+ {% elseif hotspot.button %}
32
+ <span class="{{ classNames }}__button c-hotspot-image__button--no-tooltip"
33
+ role="button"
34
+ aria-label="{{ hotspot.button.label }}">
35
+ {{ hotspot.button.label }}
36
+ </span>
37
+ {% endif %}
38
+ </div>
39
+ {% endfor %}
40
+ {% endif %}
41
+ </div>
@@ -0,0 +1,103 @@
1
+ .c-hotspot-image {
2
+ position: relative;
3
+ counter-reset: hotspot-counter;
4
+
5
+ &__heading,
6
+ &__hotspot {
7
+ position: absolute;
8
+ }
9
+
10
+ &__heading {
11
+ background: color('petrol', 'step--1');
12
+ color: color('petrol', 'step-3');
13
+ @include padding('s', 'm');
14
+ border-radius: 1em;
15
+ font-size: var(--step-1);
16
+ }
17
+
18
+ &__hotspot {
19
+ isolation: isolate;
20
+
21
+ &:has([aria-expanded='true']) {
22
+ z-index: 1;
23
+ }
24
+ }
25
+
26
+ &__button {
27
+ position: relative;
28
+ background: color('petrol');
29
+ color: color('petrol', 'step-3');
30
+ @include padding('2xs');
31
+ display: flex;
32
+ gap: var(--space-2xs);
33
+ align-items: center;
34
+ border: none;
35
+ border-radius: 1em;
36
+ font-size: var(--step--1);
37
+
38
+ &:not(&--no-tooltip) {
39
+ cursor: pointer;
40
+ transition: 300ms background-color;
41
+
42
+ &:where(:hover, :focus) {
43
+ background: color('petrol', 'step--1');
44
+ }
45
+ }
46
+
47
+ &::before,
48
+ &::after {
49
+ --number-size: calc(var(--step-1) * 1.5);
50
+ height: var(--number-size);
51
+ width: var(--number-size);
52
+ display: flex;
53
+ justify-content: center;
54
+ align-items: center;
55
+ border-radius: 2em;
56
+ font-size: var(--step-1);
57
+ font-weight: 600;
58
+ }
59
+
60
+ &::before {
61
+ counter-increment: hotspot-counter;
62
+ content: counter(hotspot-counter);
63
+ background: color('red');
64
+ color: color('white');
65
+ }
66
+
67
+ &::after {
68
+ content: '+';
69
+ background: color('petrol', 'step--1');
70
+ color: color('white');
71
+ @include padding('3xs');
72
+ }
73
+
74
+ &--no-tooltip::after {
75
+ display: none;
76
+ }
77
+ }
78
+
79
+ &__tooltip {
80
+ --gutter: var(--space-2xs);
81
+ display: none;
82
+ position: absolute;
83
+ background: color('petrol', 'step-1');
84
+ margin-top: -1em;
85
+ padding-top: calc(var(--space-2xs) + 1em);
86
+ @include padding-right('2xs');
87
+ @include padding-bottom('2xs');
88
+ @include padding-left('2xs');
89
+ border-bottom-right-radius: 1em;
90
+ border-bottom-left-radius: 1em;
91
+ z-index: -1;
92
+ font-size: var(--step--2);
93
+
94
+ .u-bg-white,
95
+ .u-bg-petrol {
96
+ border-radius: calc(1em / 2);
97
+ }
98
+
99
+ &--open {
100
+ display: block;
101
+ }
102
+ }
103
+ }
@@ -0,0 +1,5 @@
1
+ {%- from "components/component/component.njk" import c -%}
2
+
3
+ {%- macro hotspotImage(params) -%}
4
+ {{ c({ name: 'hotspot-image' }, params) }}
5
+ {%- endmacro -%}
@@ -6,6 +6,7 @@ import Facet from './imports/facet';
6
6
  import Gallery from './imports/gallery';
7
7
  import HeroPattern from './imports/hero-pattern';
8
8
  import HeroVideo from './imports/hero-video';
9
+ import HotspotImage from './imports/hotspot-image';
9
10
  import InternalNav from './imports/internal-nav';
10
11
  import OffCanvas from './imports/off-canvas';
11
12
  import ResponsiveTable from './imports/responsive-table';
@@ -14,13 +15,13 @@ import ScrollSpy from './imports/scroll-spy';
14
15
  import Tabs from './imports/tabs';
15
16
 
16
17
  (() => {
17
- if(window.NodeList && !NodeList.prototype.forEach) {
18
+ if (window.NodeList && !NodeList.prototype.forEach) {
18
19
  NodeList.prototype.forEach = Array.prototype.forEach;
19
20
  }
20
- if(window.HTMLCollection && !HTMLCollection.prototype.forEach) {
21
+ if (window.HTMLCollection && !HTMLCollection.prototype.forEach) {
21
22
  HTMLCollection.prototype.forEach = Array.prototype.forEach;
22
23
  }
23
-
24
+
24
25
  Accordion();
25
26
  Carousel();
26
27
  ClearForm();
@@ -29,10 +30,11 @@ import Tabs from './imports/tabs';
29
30
  Gallery();
30
31
  HeroPattern();
31
32
  HeroVideo();
33
+ HotspotImage();
32
34
  InternalNav();
33
35
  OffCanvas();
34
36
  ResponsiveTable();
35
37
  ScrollbarWidth();
36
38
  ScrollSpy();
37
39
  Tabs();
38
- })();
40
+ })();
@@ -0,0 +1,91 @@
1
+ // Function to initialize tooltip behavior
2
+ function HotspotImage() {
3
+ // Add delay for Tridion JavaScript created hotspot images
4
+ setTimeout(function () {
5
+ // Select all elements that trigger tooltips
6
+ const tooltips = document.querySelectorAll('.c-hotspot-image__button');
7
+
8
+ // Add event listeners for each tooltip button
9
+ tooltips.forEach((button) => {
10
+ button.addEventListener('click', handleTooltipToggle);
11
+ });
12
+
13
+ // Add event listener for Escape key press
14
+ document.addEventListener('keydown', handleKeyDown);
15
+
16
+ // Add event listener for click outside tooltip
17
+ document.addEventListener('click', handleClickOutside);
18
+ }, 2000);
19
+ }
20
+
21
+ // Function to handle the tooltip toggle
22
+ function handleTooltipToggle(event) {
23
+ // Prevent default action if needed
24
+ event.preventDefault();
25
+
26
+ const button = event.currentTarget;
27
+ const tooltipId = button.getAttribute('aria-controls');
28
+ const tooltip = document.getElementById(tooltipId);
29
+
30
+ if (tooltip.classList.contains('c-hotspot-image__tooltip--open')) {
31
+ closeTooltip(button, tooltip);
32
+ } else {
33
+ openTooltip(button, tooltip);
34
+ }
35
+ }
36
+
37
+ // Function to open a tooltip
38
+ function openTooltip(button, tooltip) {
39
+ // Add active class and make tooltip visible
40
+ tooltip.classList.add('c-hotspot-image__tooltip--open');
41
+ tooltip.setAttribute('aria-hidden', 'false');
42
+ button.setAttribute('aria-expanded', 'true');
43
+
44
+ // Add event listener for click outside
45
+ document.addEventListener('click', handleClickOutside);
46
+ }
47
+
48
+ // Function to close a tooltip
49
+ function closeTooltip(button, tooltip) {
50
+ // Remove active class and hide tooltip
51
+ tooltip.classList.remove('c-hotspot-image__tooltip--open');
52
+ tooltip.setAttribute('aria-hidden', 'true');
53
+ button.setAttribute('aria-expanded', 'false');
54
+
55
+ // Remove event listener for click outside
56
+ document.removeEventListener('click', handleClickOutside);
57
+ }
58
+
59
+ // Function to handle Escape key press
60
+ function handleKeyDown(event) {
61
+ if (event.key === 'Escape') {
62
+ const activeTooltip = document.querySelector(
63
+ '.c-hotspot-image__tooltip--open'
64
+ );
65
+ if (activeTooltip) {
66
+ const button = document.querySelector(
67
+ `[aria-controls="${activeTooltip.id}"]`
68
+ );
69
+ closeTooltip(button, activeTooltip);
70
+ }
71
+ }
72
+ }
73
+
74
+ // Function to handle click outside the tooltip
75
+ function handleClickOutside(event) {
76
+ const activeTooltip = document.querySelector(
77
+ '.c-hotspot-image__tooltip--open'
78
+ );
79
+ if (
80
+ activeTooltip &&
81
+ !activeTooltip.contains(event.target) &&
82
+ !event.target.closest('.c-hotspot-image__button')
83
+ ) {
84
+ const button = document.querySelector(
85
+ `[aria-controls="${activeTooltip.id}"]`
86
+ );
87
+ closeTooltip(button, activeTooltip);
88
+ }
89
+ }
90
+
91
+ export default HotspotImage;
@@ -188,6 +188,12 @@
188
188
  @include margin(0);
189
189
  }
190
190
  }
191
+
192
+ & > .o-grid,
193
+ & > .o-grid > * {
194
+ @include margin(0);
195
+ @include padding(0);
196
+ }
191
197
  }
192
198
 
193
199
  &__section + .c-form__section:not(.c-form__section--submit) {
@@ -21,6 +21,7 @@
21
21
  @import '~comp/gallery/gallery.scss';
22
22
  @import '~comp/header/header.scss';
23
23
  @import '~comp/hero/hero.scss';
24
+ @import '~comp/hotspot-image/hotspot-image.scss';
24
25
  @import '~comp/icon/icon.scss';
25
26
  @import '~comp/input/input.scss';
26
27
  @import '~comp/input/radio.scss';
@@ -10,6 +10,10 @@
10
10
  align-items: center;
11
11
  }
12
12
 
13
+ .u-align-items-start {
14
+ align-items: flex-start;
15
+ }
16
+
13
17
  .u-justify-center {
14
18
  justify-content: center;
15
19
  }
@@ -87,6 +87,9 @@
87
87
  .u-pad-3xs {
88
88
  @include padding('3xs');
89
89
  }
90
+ .u-pad-2xs {
91
+ @include padding('2xs');
92
+ }
90
93
  .u-pad-s {
91
94
  @include padding('s');
92
95
  }
@@ -173,7 +176,7 @@
173
176
  margin-top: auto;
174
177
  }
175
178
  .u-margin-top-negative-2xl {
176
- margin-top: calc(-1 * #{var(--space-2xl)})
179
+ margin-top: calc(-1 * #{var(--space-2xl)});
177
180
  }
178
181
  .u-margin-top-2xs {
179
182
  @include margin-top('2xs');
@@ -3,25 +3,31 @@ title: Boilerplate
3
3
  layout: content-page
4
4
  sidebar: content
5
5
  status: 'Ready'
6
- version: 1.0.2
6
+ version: 1.0.3
7
7
  tags: content
8
8
  date: 2020-01-03
9
9
  ---
10
10
 
11
- {% alert %}
12
- This is our **boilerplate**: the default text we use to describe ourselves in press releases and other publications.
13
- {% endalert %}
11
+ <div class="u-pad-l u-bg-petrol-step-3 o-prose u-flow--prose">
14
12
 
15
13
  ### About Malvern Panalytical
16
14
 
17
- We draw on the power of our analytical instruments and services to make the invisible visible and the impossible possible.
15
+ Malvern Panalytical is a global leader in the analytics of material and life sciences. We unleash the power of small things to make big things happen for our customers.
18
16
 
19
- Through the chemical, physical and structural analysis of materials, our high precision analytical systems and top-notch services support our customers in creating a better world. We help them improve everything from the energies that power us and the materials we build with, to the medicines that cure us and the foods we enjoy.
17
+ Our vision is to make the world cleaner, healthier, and more productive.
20
18
 
21
- We partner with many of the world’s biggest companies, universities and research organizations. They value us not only for the power of our solutions, but also for the depth of our expertise, collaboration and integrity.
19
+ We partner with our customers to make their solutions possible through the power of precision measurements, our expertise, trusted data, and insights.
22
20
 
23
- We are committed to Net Zero in our own operations by 2030 and in our total value chain by 2040. This is woven into the fabric of our business, and we help our employees and customers think about their part in creating a healthier, cleaner, and more productive world.
21
+ Our people are partners in discovery. We collaborate with our customers and with each other to discover new possibilities and achieve breakthroughs.
24
22
 
25
- With over 2300 employees, we serve the world, and we are part of Spectris plc, the world-leading precision measurement group.
23
+ Our culture is a healthy, high-performance culture shaped by our values: Own it, Aim High and Be True.
26
24
 
27
- **Malvern Panalytical. We’re BIG on small.™**
25
+ We’re committed to Net Zero in our own operations by 2030 and in our total value chain by 2040.
26
+
27
+ With over 2300 employees across the globe, we are part of Spectris plc, the world-leading precision measurement group.
28
+
29
+ **Malvern Panalytical. We’re BIG on small.™**
30
+
31
+ </div>
32
+
33
+ This is our **boilerplate**: the default text we use to describe ourselves in press releases and other publications.
@@ -1,21 +1,26 @@
1
1
  ---
2
- title: We're BIG on small
2
+ title: Elevator pitch
3
3
  layout: content-page
4
4
  sidebar: content
5
5
  tags: content
6
+ version: 1.0.3
7
+ status: 'Ready'
6
8
  date: 2020-01-02
7
9
  ---
8
10
 
9
- **We are Malvern Panalytical.** We are here to unleash the
10
- power of very small things, to make big things happen.
11
+ <div class="u-pad-l u-bg-petrol-step-3 o-prose u-flow--prose">
11
12
 
12
- **Our technologies enable our customers to create a better world.** Improving everything from the energies that power us and the materials we build with, to the medicines that cure us and the foods we enjoy.
13
+ Malvern Panalytical is a global leader in the analytics of material and life sciences. We exist to unleash the power of small things to make big things happen for our customers (we’re big on small).
13
14
 
14
- **We partner with many of the world’s biggest companies, universities and research organizations.** They value us not only for the power of our solutions, but also for the depth of our expertise, collaboration and integrity.
15
+ Every day we work in pursuit of a clear vision: to make the world cleaner, healthier, and more productive. To achieve our vision, we partner with our customers to make their solutions possible through the power of precision measurements, our expertise, trusted data, and insights.
15
16
 
16
- **We are a globally diverse mix of visionary thinkers, creative problem-solvers, and detail-loving geeks.** United by knowing that when you can make the invisible visible, you make the impossible possible.
17
+ Customers are at the heart of our company and core to our success: acting as partners in discovery, we collaborate every day with our customers and with each other to discover new possibilities and achieve breakthroughs.
17
18
 
18
- {% alert %}
19
+ Supported by a healthy, high-performance culture shaped by our values we collaborate to improve how we work together, how we create value, and how we remain relevant as an organization in the future.
20
+
21
+ **Malvern Panalytical. We’re BIG on small.™**
22
+
23
+ </div>
19
24
 
20
25
  ### This is our official ‘elevator pitch’.
21
26
 
@@ -26,5 +31,3 @@ We use it as the starting point whenever we’re talking about ourselves. (You
26
31
  Use it whenever you need to describe Malvern Panalytical.
27
32
 
28
33
  (Note that ‘We're BIG on small’ is trademarked.)
29
-
30
- {% endalert %}
@@ -0,0 +1,16 @@
1
+ ---
2
+ title: Spline 3D test
3
+ ---
4
+
5
+ {% extends "page.njk" %}
6
+
7
+ {% block content %}
8
+
9
+ <main class="u-wrap u-pad-m">
10
+ <p>Proof-of-concept test for interactive 3D product widget. Click on the lid or the touchscreen, or drag to view the model in 360.</p>
11
+ </main>
12
+
13
+ <script type="module" src="https://unpkg.com/@splinetool/viewer@1.9.0/build/spline-viewer.js" async></script>
14
+ <spline-viewer loading-anim-type="spinner-small-light" url="https://prod.spline.design/i8gXyHDuPT7GpT0x/scene.splinecode"><img src="data:image/png;base64,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" alt="Spline preview" style="width: 100%; height: 100%;"/></spline-viewer>
15
+
16
+ {% endblock %}