Repository: exadel-inc/esl
Pull request #1664 (2023-05-19 18:28:53)

🚩epic: release esl-share 1.0.0-beta -> 4.6.0 stable


Patch:
diff --git a/package.json b/package.json
index 2aec4b98b..febb8bf68 100644
--- a/package.json
+++ b/package.json
@@ -41,7 +41,9 @@
     "modules/lib.js",
     "src/modules/lib.ts",
     "modules/esl-media/providers/**/*.js",
+    "modules/esl-share/actions/**/*.js",
     "src/modules/esl-media/providers/**/*.ts",
+    "src/modules/esl-share/actions/**/*.ts",
     "modules/draft/esl-carousel/core/view/*.js",
     "src/modules/draft/esl-carousel/core/view/*.ts",
     "polyfills/**/*.js",
diff --git a/pages/src/esl-share/esl-share.less b/pages/src/esl-share/esl-share.less
new file mode 100644
index 000000000..f75af649f
--- /dev/null
+++ b/pages/src/esl-share/esl-share.less
@@ -0,0 +1,12 @@
+esl-share-list esl-share-button[unavailable] {
+  display: inline-block;
+  opacity: .3;
+  cursor: not-allowed;
+  filter: grayscale(1);
+}
+
+esl-share-button {
+  path, circle {
+    fill: #fff;
+  }
+}
diff --git a/pages/src/localdev.less b/pages/src/localdev.less
index ee41f6492..6b3b86a33 100644
--- a/pages/src/localdev.less
+++ b/pages/src/localdev.less
@@ -33,6 +33,7 @@
 
 @import "./collection-grid/collection-grid.less";
 @import "./esl-media-demo/test-media.less";
+@import "./esl-share/esl-share.less";
 
 @import "../../src/modules/all.less";
 @import "../../src/modules/draft/all.less";
diff --git a/pages/src/localdev.ts b/pages/src/localdev.ts
index abd431ab3..c58aeca07 100644
--- a/pages/src/localdev.ts
+++ b/pages/src/localdev.ts
@@ -32,6 +32,7 @@ import {
   ESLFootnotes,
   ESLTooltip,
   ESLAnimate,
+  ESLShare,
   ESLRelatedTarget
 } from '../../src/modules/all';
 
@@ -41,6 +42,12 @@ import '../../src/modules/esl-media/providers/html5/video-provider';
 import '../../src/modules/esl-media/providers/youtube-provider';
 import '../../src/modules/esl-media/providers/brightcove-provider';
 
+import '../../src/modules/esl-share/actions/copy-action';
+import '../../src/modules/esl-share/actions/external-action';
+import '../../src/modules/esl-share/actions/media-action';
+import '../../src/modules/esl-share/actions/native-action';
+import '../../src/modules/esl-share/actions/print-action';
+
 import {
   ESLCarousel,
   ESLCarouselPlugins
@@ -106,5 +113,8 @@ ESLCarouselPlugins.Link.register();
 ESLCarouselPlugins.Touch.register();
 ESLCarouselPlugins.Autoplay.register();
 
+ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
+ESLShare.register();
+
 // Register ESL Mixins
 ESLRelatedTarget.register();
diff --git a/pages/src/navigation/header/header.less b/pages/src/navigation/header/header.less
index 7395ac320..9b2f1cdc9 100644
--- a/pages/src/navigation/header/header.less
+++ b/pages/src/navigation/header/header.less
@@ -15,12 +15,6 @@
     height: @header-height-desktop;
   }
 
-  @media @md-xl {
-    .landing-layout & {
-      background-color: transparent;
-    }
-  }
-
   &-container {
     display: flex;
     align-items: center;
@@ -90,6 +84,17 @@
     }
   }
 
+  &-share-popup.esl-popup {
+    &, & > .esl-popup-arrow {
+      background: @landing-bg-color;
+      border-color: gray;
+    }
+    > .esl-share {
+      margin: .75rem;
+      gap: .25rem;
+    }
+  }
+
   &-utility {
     display: flex;
     align-items: center;
diff --git a/pages/src/navigation/sidebar/sidebar-primary-nav.less b/pages/src/navigation/sidebar/sidebar-primary-nav.less
index 87190e28e..78066a9a1 100644
--- a/pages/src/navigation/sidebar/sidebar-primary-nav.less
+++ b/pages/src/navigation/sidebar/sidebar-primary-nav.less
@@ -13,6 +13,28 @@ esl-d-sidebar {
     margin-bottom: 5px;
   }
 
+  // Share item
+  .sidebar-nav-item-share {
+    margin-top: 20px;
+    @media @md-xl {
+      display: none;
+    }
+
+    .esl-share-list {
+      gap: 15px;
+    }
+    .esl-share-button {
+      width: 30px;
+      height: 30px;
+    }
+    .sidebar-nav-item-heading {
+      gap: 15px;
+      @media @sm {
+        flex-direction: column;
+      }
+    }
+  }
+
   // Primary Heading
   .sidebar-nav-item-heading {
     position: relative;
diff --git a/pages/src/page/landing-layout.less b/pages/src/page/landing-layout.less
index 25c1af016..7cedce72a 100644
--- a/pages/src/page/landing-layout.less
+++ b/pages/src/page/landing-layout.less
@@ -33,7 +33,6 @@
     100% { background-position: 100vw 0; opacity: 1; }
   }
 
-
   .main-scroll {
     position: absolute;
     z-index: 5;
@@ -50,4 +49,10 @@
       background: #2e2f35;
     }
   }
+
+  @media @md-xl {
+    .header {
+      background-color: transparent;
+    }
+  }
 }
diff --git a/pages/static/assets/common/header-share.svg b/pages/static/assets/common/header-share.svg
new file mode 100644
index 000000000..3749a002b
--- /dev/null
+++ b/pages/static/assets/common/header-share.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
+  <path fill="none" stroke="#fff" stroke-width="2" d="M25,20a5,5,0,0,0-3.91,1.93l-9.28-4.64A5,5,0,0,0,12,16a5,5,0,0,0-.19-1.29l9.28-4.64A5,5,0,0,0,25,12a5,5,0,1,0-5-5,5,5,0,0,0,.19,1.29l-9.28,4.64A5,5,0,0,0,7,11,5,5,0,0,0,7,21a5,5,0,0,0,3.91-1.93l9.28,4.64A5,5,0,1,0,25,20ZM25,4a3,3,0,1,1-3,3A3,3,0,0,1,25,4ZM7,19a3,3,0,1,1,3-3A3,3,0,0,1,7,19Zm18,9a3,3,0,1,1,3-3A3,3,0,0,1,25,28Z"/>
+</svg>
diff --git a/pages/static/assets/examples/share.svg b/pages/static/assets/examples/share.svg
new file mode 100644
index 000000000..277e15c9a
--- /dev/null
+++ b/pages/static/assets/examples/share.svg
@@ -0,0 +1,10 @@
+<svg viewBox="0 0 483 483" fill="none" xmlns="http://www.w3.org/2000/svg">
+  <g fill="#add1fa">
+    <path d="M395.72,0c-48.204,0-87.281,39.078-87.281,87.281c0,2.036,0.164,4.03,0.309,6.029l-161.233,75.674
+      c-15.668-14.971-36.852-24.215-60.231-24.215c-48.204,0.001-87.282,39.079-87.282,87.282c0,48.204,39.078,87.281,87.281,87.281
+      c15.206,0,29.501-3.907,41.948-10.741l69.789,58.806c-3.056,8.896-4.789,18.396-4.789,28.322c0,48.204,39.078,87.281,87.281,87.281
+      c48.205,0,87.281-39.078,87.281-87.281s-39.077-87.281-87.281-87.281c-15.205,0-29.5,3.908-41.949,10.74l-69.788-58.805
+      c3.057-8.891,4.789-18.396,4.789-28.322c0-2.035-0.164-4.024-0.308-6.029l161.232-75.674c15.668,14.971,36.852,24.215,60.23,24.215
+      c48.203,0,87.281-39.078,87.281-87.281C482.999,39.079,443.923,0,395.72,0z"/>
+  </g>
+</svg>
diff --git a/pages/static/assets/share/config.json b/pages/static/assets/share/config.json
new file mode 100644
index 000000000..02bafb874
--- /dev/null
+++ b/pages/static/assets/share/config.json
@@ -0,0 +1,181 @@
+{
+  "buttons": [
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 27.99 28\"\u003e\u003cpath d\u003d\"M23 17.11l.55-4.24h-4.2v-2.71c0-1.23.34-2.06 2.1-2.06h2.25V4.29a31.62 31.62 0 00-3.28-.16c-3.24 0-5.46 2-5.46 5.61v3.13h-3.63v4.24H15V28h4.39V17.11z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#3c5996",
+      "link": "//www.facebook.com/sharer.php?u\u003d{u}",
+      "name": "facebook",
+      "title": "Facebook"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 27.99 27.99\"\u003e\u003cpath d\u003d\"M6.37 11.33h3.25v10.45H6.37zM8 6.13A1.88 1.88 0 116.12 8 1.88 1.88 0 018 6.13M11.65 11.33h3.12v1.43h.05a3.4 3.4 0 013.07-1.69c3.29 0 3.9 2.17 3.9 5v5.73h-3.25v-5.11c0-1.21 0-2.77-1.69-2.77s-1.94 1.32-1.94 2.69v5.17h-3.25V11.33z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#0b77b3",
+      "link": "//www.linkedin.com/sharing/share-offsite/?url\u003d{u}",
+      "name": "linkedin",
+      "title": "LinkedIn"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 27.99 27.99\"\u003e\u003cpath d\u003d\"M21.84 9.14a6.34 6.34 0 01-1.84.51 3.25 3.25 0 001.4-1.78 6.22 6.22 0 01-2 .78 3.22 3.22 0 00-5.57 2.2 2.92 2.92 0 00.09.73 9.11 9.11 0 01-6.67-3.36 3.16 3.16 0 00-.43 1.62 3.21 3.21 0 001.43 2.68 3.25 3.25 0 01-1.46-.41 3.23 3.23 0 002.58 3.16 3 3 0 01-.84.11 3 3 0 01-.61-.05 3.22 3.22 0 003 2.23 6.39 6.39 0 01-4 1.38 6.19 6.19 0 01-.76-.05 9.14 9.14 0 0014.08-7.71v-.41a6.36 6.36 0 001.6-1.63z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#26a1ef",
+      "link": "//twitter.com/intent/tweet?text\u003d{t}\u0026url\u003d{u}",
+      "name": "twitter",
+      "title": "Twitter"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M27 15.5a2.452 2.452 0 01-1.338 2.21c.098.38.147.777.147 1.19 0 1.283-.437 2.47-1.308 3.563-.872 1.092-2.06 1.955-3.567 2.588-1.506.634-3.143.95-4.91.95-1.768 0-3.403-.316-4.905-.95-1.502-.632-2.69-1.495-3.56-2.587-.872-1.092-1.308-2.28-1.308-3.562 0-.388.045-.777.135-1.166a2.47 2.47 0 01-1.006-.912c-.253-.4-.38-.842-.38-1.322 0-.678.237-1.26.712-1.744a2.334 2.334 0 011.73-.726c.697 0 1.29.26 1.78.782 1.785-1.258 3.893-1.928 6.324-2.01l1.424-6.467a.42.42 0 01.184-.26.4.4 0 01.32-.063l4.53 1.006c.147-.306.368-.553.662-.74a1.78 1.78 0 01.97-.278c.508 0 .94.18 1.302.54.36.36.54.796.54 1.31 0 .512-.18.95-.54 1.315-.36.364-.794.546-1.302.546-.507 0-.94-.18-1.295-.54a1.793 1.793 0 01-.533-1.308l-4.1-.92-1.277 5.86c2.455.074 4.58.736 6.37 1.985a2.315 2.315 0 011.757-.757c.68 0 1.256.242 1.73.726.476.484.713 1.066.713 1.744zm-16.868 2.47c0 .513.178.95.534 1.315.356.365.787.547 1.295.547.508 0 .942-.182 1.302-.547.36-.364.54-.802.54-1.315 0-.513-.18-.95-.54-1.31-.36-.36-.794-.54-1.3-.54-.5 0-.93.183-1.29.547a1.79 1.79 0 00-.54 1.303zm9.944 4.406c.09-.09.135-.2.135-.323a.444.444 0 00-.44-.447c-.124 0-.23.042-.32.124-.336.348-.83.605-1.486.77a7.99 7.99 0 01-1.964.248 7.99 7.99 0 01-1.964-.248c-.655-.165-1.15-.422-1.486-.77a.456.456 0 00-.32-.124.414.414 0 00-.306.124.41.41 0 00-.135.317.45.45 0 00.134.33c.352.355.837.636 1.455.843.617.207 1.118.33 1.503.366a11.6 11.6 0 001.117.056c.36 0 .733-.02 1.117-.056.385-.037.886-.16 1.504-.366.62-.207 1.104-.488 1.456-.844zm-.037-2.544c.507 0 .938-.182 1.294-.547.356-.364.534-.802.534-1.315 0-.505-.18-.94-.54-1.303a1.75 1.75 0 00-1.29-.546c-.506 0-.94.18-1.3.54-.36.36-.54.797-.54 1.31s.18.95.54 1.315c.36.365.794.547 1.3.547z\" fill-rule\u003d\"evenodd\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#ff5700",
+      "link": "//www.reddit.com/submit?url\u003d{u}\u0026title\u003d{t}",
+      "name": "reddit",
+      "title": "Reddit"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M19.996 11.757c1.905 0 3.45-1.513 3.45-3.38C23.445 6.513 21.9 5 19.995 5c-1.903 0-3.448 1.512-3.448 3.378s1.545 3.38 3.448 3.38zm4.995 5.233c-.09-2.574-2.242-4.638-4.893-4.638a4.934 4.934 0 00-3.24 1.206 3.62 3.62 0 00-3.318-2.133c-.944 0-1.8.356-2.443.935a2.596 2.596 0 00-2.494-1.82c-1.407 0-2.55 1.093-2.6 2.462H6v4.783h3.92v3.712h5.276V26H25v-9.01h-.01zm-11.526-6.006c1.405 0 2.545-1.116 2.545-2.492C16.01 7.115 14.87 6 13.463 6 12.06 6 10.92 7.114 10.92 8.49c0 1.376 1.14 2.492 2.544 2.492zm-4.914-.762c1.012 0 1.83-.803 1.83-1.794 0-.992-.818-1.795-1.83-1.795-1.01 0-1.83.804-1.83 1.795 0 .99.82 1.794 1.83 1.794z\" fill-rule\u003d\"evenodd\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#282828",
+      "link": "//myspace.com/post?u\u003d{u}",
+      "name": "myspace",
+      "title": "Myspace"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M26 6v11.077C26 18.123 25.105 19 24 19s-2-.877-2-1.923v-1a2 2 0 00-2-2 2 2 0 00-2 2v2.846c-.02 1.046-.915 1.923-2 1.923-1.12 0-2.013-.877-2-1.923V11.23a2.036 2.036 0 00-2-2c-1.062.024-1.922.822-2 1.847-.003.025-.003 4.275 0 12.75 0 1.045-.895 1.923-2 1.923s-2-.878-2-1.923V6h20z\" opacity\u003d\".8\"/\u003e\u003cpath d\u003d\"M6 6v10.77c2.135-.006 3.878-1.648 4-3.693V11.23a.702.702 0 010-.153c.078-1.025.938-1.823 2-1.846 1.092.024 1.986.902 2 2v7.693c-.013 1.046.88 1.923 2 1.923 1.085 0 1.98-.877 2-1.923v-5.23C17.98 9.458 21.502 6 25.846 6H6\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#eb4924",
+      "link": "//mix.com/add?url\u003d{u}",
+      "name": "mix",
+      "title": "MIX"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M14.722 19.784l-3.48-6.832-2.667 1.36 3.82 7.497.056-.03.313.61 10.608-5.404-.48-.944-3.65-7.165-2.667 1.36 3.48 6.83-1.332.68-3.48-6.832-2.666 1.358 3.48 6.832-1.332.68z\"/\u003e\u003cpath d\u003d\"M7.372 12.77c0-2.38 1.86-4.308 4.152-4.308h8.952c2.294 0 4.152 1.928 4.152 4.308v6.46c0 2.38-1.86 4.308-4.152 4.308h-8.952c-2.294 0-4.152-1.928-4.152-4.308v-6.46zM5 12.77v6.46C5 22.97 7.92 26 11.524 26h8.952C24.08 26 27 22.97 27 19.23v-6.46C27 9.03 24.08 6 20.476 6h-8.952C7.92 6 5 9.03 5 12.77z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#fb803f",
+      "link": "//www.wykop.pl/dodaj?url\u003d{u}\u0026title\u003d{t}",
+      "name": "wykop",
+      "title": "Wykop"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 24 24\"\u003e\u003cpath d\u003d\"M12.486 4.771c-4.23 0-6.363 3.033-6.363 5.562 0 1.533.581 2.894 1.823 3.401.205.084.387.004.446-.221l.182-.717c.061-.221.037-.3-.127-.495-.359-.422-.588-.972-.588-1.747 0-2.25 1.683-4.264 4.384-4.264 2.392 0 3.706 1.463 3.706 3.412 0 2.568-1.137 4.734-2.824 4.734-.932 0-1.629-.77-1.405-1.715.268-1.13.786-2.347.786-3.16 0-.729-.392-1.336-1.2-1.336-.952 0-1.718.984-1.718 2.304 0 .841.286 1.409.286 1.409L8.728 16.79c-.34 1.44-.051 3.206-.025 3.385.013.104.149.131.21.051.088-.115 1.223-1.517 1.607-2.915.111-.396.627-2.445.627-2.445.311.589 1.213 1.108 2.175 1.108 2.863 0 4.804-2.608 4.804-6.103-.003-2.64-2.24-5.1-5.64-5.1z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#e60023",
+      "link": "//www.pinterest.com/pin/create/button/?url\u003d{u}\u0026description\u003d{t}",
+      "name": "pinterest",
+      "title": "Pinterest"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 455.731 455.731\"\u003e\u003cpath d\u003d\"M358.844 100.6 54.091 219.359c-9.871 3.847-9.273 18.012.888 21.012l77.441 22.868 28.901 91.706c3.019 9.579 15.158 12.483 22.185 5.308l40.039-40.882 78.56 57.665c9.614 7.057 23.306 1.814 25.747-9.859l52.031-248.76c2.548-12.185-9.44-22.337-21.039-17.817zm-38.208 55.206L179.08 280.984c-1.411 1.248-2.309 2.975-2.519 4.847l-5.45 48.448c-.178 1.58-2.389 1.789-2.861.271l-22.423-72.253c-1.027-3.308.312-6.892 3.255-8.717l167.163-103.676c3.844-2.386 7.78 2.906 4.391 5.902z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#61a8de",
+      "link": "//t.me/share/url?url\u003d{u}\u0026text\u003d{t}",
+      "name": "telegram",
+      "title": "Telegram"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M19.864 21.38H11.84a1.712 1.712 0 010-3.425h8.024a1.712 1.712 0 010 3.425zm-7.542-11.27l4.012.063a1.712 1.712 0 01-.054 3.424l-4.012-.064a1.712 1.712 0 01.054-3.424zm13.4 9.404c-.007-.374-.008-.71-.01-1.014-.006-1.58-.012-2.83-1.016-3.803-.716-.694-1.565-.914-2.855-.962.176-.747.226-1.575.145-2.47-.02-2.973-2.234-5.18-5.304-5.264h-.043l-4.692.072c-1.844-.007-3.3.53-4.332 1.606-.638.666-1.362 1.83-1.45 3.72H6.16v.057a8.6 8.6 0 00-.006.393l-.12 7.125c-.008.143-.015.288-.016.437-.12 2.088.372 3.728 1.463 4.876 1.078 1.132 2.664 1.706 4.715 1.706h7.32c1.84-.017 3.393-.624 4.494-1.757 1.1-1.132 1.692-2.743 1.713-4.66v-.06z\" fill-rule\u003d\"evenodd\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#f57d00",
+      "link": "//blogger.com/blog-this.g?n\u003d{t}\u0026u\u003d{u}",
+      "name": "blogger",
+      "title": "Blogger"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M29.27 22.19V8.07l-12.06 6.85 3.84 2.33C15.72 24.14 5.9 29.31 0 31.96V32h19.64c3.68-4.86 7.03-11.46 7.03-11.46l2.6 1.65z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#0878ba",
+      "link": "//www.pusha.se/posta?url\u003d{u}\u0026title\u003d{t}",
+      "name": "pusha",
+      "title": "Pusha"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M20.826 6h-9.652C10.524 6 10 6.51 10 7.138v9.336c0 .63.525 1.14 1.174 1.14h4.45c-.03 1.11-.507 2.318-1.196 3.39-.775 1.207-2.426 2.543-2.44 2.555-.13.12-.226.26-.23.456 0 .15.08.263.167.385l3.104 3.395s.15.154.274.183c.14.033.3.037.41-.045 5.374-4.032 6.15-9.085 6.285-11.82V7.137C22 6.508 21.475 6 20.826 6\" fill-rule\u003d\"evenodd\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#fab900",
+      "link": "//story.kakao.com/share?url\u003d{u}",
+      "name": "kakao",
+      "title": "Kakao"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M27 14.927c0 1.97-.764 3.744-2.358 5.492-2.307 2.655-7.468 5.89-8.642 6.385-1.174.495-1-.315-.953-.593l.157-.94c.037-.282.075-.718-.035-.996-.125-.306-.612-.465-.97-.542-5.287-.7-9.2-4.395-9.2-8.807C5 10.005 9.935 6 16 6c6.066 0 11 4.005 11 8.927zm-13.235-2.38h-.772a.214.214 0 00-.214.215v4.793c0 .118.095.214.213.214h.772a.214.214 0 00.214-.215v-4.793a.214.214 0 00-.215-.214zm5.31 0h-.77a.214.214 0 00-.215.215v2.848l-2.197-2.967a.235.235 0 00-.017-.023l-.014-.013-.003-.004c-.005-.003-.01-.006-.013-.01-.002 0-.003-.002-.005-.004l-.01-.008a.262.262 0 00-.018-.01c-.004 0-.006-.003-.008-.004a.605.605 0 00-.013-.005l-.007-.002a.106.106 0 00-.02-.005.098.098 0 00-.012-.003h-.01c-.003-.002-.006-.002-.01-.003-.004 0-.007 0-.01-.002h-.78a.214.214 0 00-.214.214v4.793c0 .118.095.214.214.214h.77a.214.214 0 00.216-.215v-2.847l2.2 2.97c.014.022.033.04.053.053 0 .002.002.002.002.003l.014.008c0 .002.003.003.005.004l.01.005c.003 0 .007.002.01.004.003 0 .004 0 .007.002l.014.005s.002 0 .003.002a.206.206 0 00.054.007h.772a.214.214 0 00.214-.215v-4.793a.214.214 0 00-.214-.214zm-7.17 4.022H9.81V12.76a.214.214 0 00-.216-.214h-.77a.214.214 0 00-.216.214v4.793c0 .058.023.11.06.148l.003.003c.002 0 .003.002.005.003.038.036.09.06.147.06h3.083a.214.214 0 00.214-.215v-.772a.214.214 0 00-.215-.214zm11.432-2.822a.214.214 0 00.214-.214v-.77a.214.214 0 00-.213-.216h-3.082a.213.213 0 00-.15.06s0 .002-.002.003c0 .002-.003.003-.004.005a.214.214 0 00-.06.147v4.793c0 .057.023.11.06.148l.003.003.003.003c.04.036.09.06.148.06h3.083a.214.214 0 00.214-.215v-.772a.214.214 0 00-.213-.214H21.24v-.812h2.097a.214.214 0 00.214-.214v-.77a.214.214 0 00-.213-.216H21.24v-.81h2.097z\" fill-rule\u003d\"evenodd\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#00b900",
+      "link": "//social-plugins.line.me/lineit/share?url\u003d{u}",
+      "name": "line",
+      "title": "LINE"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M14.24 23.808c-3.64.367-6.785-1.307-7.022-3.734-.236-2.43 2.525-4.693 6.164-5.06 3.642-.367 6.786 1.307 7.02 3.734.24 2.43-2.522 4.696-6.16 5.06m7.28-8.063c-.31-.096-.523-.157-.362-.57.352-.898.39-1.672.006-2.227-.713-1.036-2.667-.98-4.907-.028 0 0-.705.312-.523-.253.343-1.125.29-2.065-.243-2.61-1.214-1.238-4.446.045-7.216 2.86C6.205 15.023 5 17.26 5 19.192c0 3.694 4.664 5.942 9.226 5.942 5.98 0 9.96-3.53 9.96-6.333.003-1.695-1.402-2.657-2.665-3.055m3.973-6.763a5.76 5.76 0 00-5.542-1.823.855.855 0 00-.646 1.015.84.84 0 001 .657c1.398-.303 2.912.138 3.938 1.295a4.254 4.254 0 01.865 4.113c-.144.45.1.93.542 1.076a.84.84 0 001.06-.55v-.002a5.973 5.973 0 00-1.218-5.78\"/\u003e\u003cpath d\u003d\"M23.276 11.018a2.8 2.8 0 00-2.698-.885.74.74 0 00-.56.876c.086.396.472.65.86.563.467-.102.977.046 1.32.432.343.388.437.915.29 1.378a.742.742 0 00.466.928.724.724 0 00.913-.474c.3-.947.113-2.026-.59-2.818M14.44 19.41c-.126.223-.408.328-.627.235-.218-.09-.285-.34-.16-.555.127-.215.397-.32.612-.234.22.08.298.33.176.555m-1.16 1.512c-.353.57-1.11.82-1.676.558-.56-.26-.726-.922-.374-1.48.35-.555 1.078-.802 1.642-.56.57.25.753.905.407 1.482m1.322-4.04c-1.733-.46-3.69.42-4.443 1.97-.77 1.583-.025 3.34 1.723 3.914 1.815.595 3.95-.318 4.695-2.023.734-1.67-.182-3.39-1.976-3.86\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#e6162d",
+      "link": "//service.weibo.com/share/share.php?url\u003d{u}\u0026title\u003d{t}",
+      "name": "sina-weibo",
+      "title": "Sina Weibo"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M16.087 5.36c-6.414 0-11.97 3.93-11.97 11.265 0 6.865 7.628 10.092 12.635 8.918v2.348S27.88 24.958 27.88 15.04c0-6.043-4.458-9.68-11.793-9.68zm6.768 14.63h-1.643v-5.634c0-.703-.506-1.565-1.566-1.565-.89 0-2.504.374-2.504 2.06v5.14H15.5v-5.202c0-1.57-.782-2.073-1.486-2.073-1.14 0-2.698.802-2.698 2.384v4.89H9.673v-8.92h1.643v1.02c.654-.538 1.548-1.02 2.698-1.02 1.21 0 2.07.428 2.58 1.27a4.444 4.444 0 013.052-1.19c1.947 0 3.21 1.772 3.21 3.172v5.667z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#cfab59",
+      "link": "//mixi.jp/share.pl?u\u003d{u}",
+      "name": "mixi",
+      "title": "Mixi"
+    },
+    {
+      "action": "media",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 32 32\"\u003e\u003cpath d\u003d\"M6.96 8.22h7.33c1.25 0 2.21.37 2.88 1.1s1 1.64 1 2.72c0 .91-.24 1.69-.72 2.34-.32.43-.78.77-1.4 1.02.93.27 1.61.72 2.05 1.37.44.65.66 1.46.66 2.43 0 .8-.16 1.51-.47 2.15-.31.64-.74 1.14-1.28 1.51-.34.23-.84.4-1.52.5-.9.14-1.5.21-1.79.21H6.96V8.22zm3.88 6.02h1.74c.62 0 1.06-.13 1.3-.38.24-.26.37-.62.37-1.1 0-.44-.12-.8-.37-1.05-.24-.25-.67-.38-1.27-.38h-1.77v2.91zm0 6.03h2.04c.69 0 1.18-.15 1.46-.43s.43-.68.43-1.17c0-.45-.14-.82-.42-1.09-.28-.28-.77-.41-1.47-.41h-2.03c-.01-.01-.01 3.1-.01 3.1zM21.21 8.41h3.58v9.58h-3.58z\"/\u003e\u003ccircle cx\u003d\"23\" cy\u003d\"21.53\" r\u003d\"2.04\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#08aed9",
+      "link": "//b.hatena.ne.jp/entry/panel/?url\u003d{u}\u0026btitle\u003d{t}",
+      "name": "hatena",
+      "title": "Hatena"
+    },
+    {
+      "action": "external",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 28 28\"\u003e\u003cpath d\u003d\"M4.63 6.94v14.1h18.8V6.94H4.63zm2.44 1.78h13.9l-6.93 5.67-6.93-5.67zm14.6 1.72v8.82H6.47v-8.79l7.59 6.21 7.63-6.24z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#ff1493",
+      "link": "mailto:?subject\u003d{title}\u0026body\u003d{url}",
+      "name": "mail",
+      "title": "Mail"
+    },
+    {
+      "action": "copy",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 28 28\"\u003e\u003cpath d\u003d\"M17 9.69l-7.43 7.43 1.18 1.18 7.43-7.43L17 9.69z\"/\u003e\u003cpath d\u003d\"M4.31 17.8c-.481.481-.48 1.29.00138 1.77l4.02 4.02c.481.481 1.29.483 1.77.00138l4.95-4.95c.481-.481.481-1.29-7e-7-1.78l-4.02-4.02c-.481-.481-1.29-.481-1.78 0l-4.95 4.95zm1.47.887l4.36-4.36 3.44 3.44-4.36 4.36-3.44-3.44zm7-9.37c-.481.481-.481 1.29 2.8e-7 1.78l4.02 4.02c.481.481 1.29.481 1.78 0l4.95-4.95c.481-.481.48-1.29-.00138-1.77l-4.02-4.02c-.481-.481-1.29-.483-1.77-.00138l-4.95 4.95zm1.47.889l4.36-4.36 3.44 3.44-4.36 4.36-3.44-3.44z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#a0522d",
+      "link": "",
+      "name": "copy",
+      "title": "Copy",
+      "additional": {
+        "alertText": "Copied to clipboard"
+      }
+    },
+    {
+      "action": "native",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 24 24\"\u003e\u003cpath d\u003d\"m21.7 10.2-6.6-6c-.5-.5-1.1 0-1.1.8v3c-4.7 0-8.7 2.9-10.6 6.8-.7 1.3-1.1 2.7-1.4 4.1-.2 1 1.3 1.5 1.9.6C6.1 16 9.8 13.7 14 13.7V17c0 .8.6 1.3 1.1.8l6.6-6c.4-.4.4-1.2 0-1.6z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#ff6347",
+      "link": "",
+      "name": "native-share",
+      "title": "Share page"
+    },
+    {
+      "action": "print",
+      "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 247.1 247.1\"\u003e\u003cpath d\u003d\"M75.4 175.5h97v6.5h-97zM75.4 194.9h97v6.5h-97z\"/\u003e\u003ccircle stroke-width\u003d\"2\" stroke-miterlimit\u003d\"10\" cx\u003d\"178.9\" cy\u003d\"117.3\" r\u003d\"6.5\"/\u003e\u003cpath d\u003d\"M198.3 84.9h-12.9V39.6c0-7.1-5.8-12.9-12.9-12.9h-97c-7.1 0-12.9 5.8-12.9 12.9v45.3H49.5c-11 0-19.4 8.4-19.4 19.4v58.2c0 11 8.4 19.4 19.4 19.4h12.9v25.9c0 7.1 5.8 12.9 12.9 12.9h97c7.1 0 12.9-5.8 12.9-12.9v-25.9h12.9c11 0 19.4-8.4 19.4-19.4v-58.2c.2-11-8.2-19.4-19.2-19.4zM68.9 39.6c0-3.2 2.6-6.5 6.5-6.5h97c3.2 0 6.5 2.6 6.5 6.5v45.3h-110V39.6zm110 168.2c0 3.2-2.6 6.5-6.5 6.5h-97c-3.2 0-6.5-2.6-6.5-6.5v-45.3h110v45.3zm32.3-45.3c0 7.1-5.8 12.9-12.9 12.9h-12.9V156h-123v19.4H49.5c-7.1 0-12.9-5.8-12.9-12.9v-58.2c0-7.1 5.8-12.9 12.9-12.9h148.8c7.1 0 12.9 5.8 12.9 12.9v58.2z\"/\u003e\u003c/svg\u003e",
+      "iconBackground": "#2f4f4f",
+      "link": "",
+      "name": "print",
+      "title": "Print page"
+    }
+  ],
+  "groups": [
+    {
+      "name": "site",
+      "list": "facebook twitter linkedin telegram copy"
+    },
+    {
+      "name": "demo",
+      "list": "facebook twitter linkedin wykop copy"
+    },
+    {
+      "name": "alternative",
+      "list": "kakao hatena mixi line mail"
+    }
+  ]
+}
diff --git a/pages/views/_includes/navigation/header.njk b/pages/views/_includes/navigation/header.njk
index 319c36ca7..f00e1b214 100644
--- a/pages/views/_includes/navigation/header.njk
+++ b/pages/views/_includes/navigation/header.njk
@@ -23,6 +23,20 @@
           {% include 'static/assets/common/header-search.svg' %}
         </esl-trigger>
       </li>
+      <li class="header-nav-item">
+        <esl-trigger target="::next" mode="toggle" track-click track-hover class="header-link icon-link">
+          {% include 'static/assets/common/header-share.svg' %}
+        </esl-trigger>
+        <esl-popup id="site-share-popup"
+                   class="header-share-popup"
+                   position="bottom"
+                   default-params="{hideDelay: 500}"
+                   close-on-esc
+                   close-on-outside-action>
+          <esl-share list="group:site"></esl-share>
+          <span class="esl-popup-arrow"></span>
+        </esl-popup>
+      </li>
     </ul>
     <div class="header-utility">
       <a class="header-btn btn btn-lg btn-sec-blue" href="{{ '/introduction' | url }}">Get started</a>
diff --git a/pages/views/_includes/navigation/sidebar.njk b/pages/views/_includes/navigation/sidebar.njk
index 58592562e..058ccf08a 100644
--- a/pages/views/_includes/navigation/sidebar.njk
+++ b/pages/views/_includes/navigation/sidebar.njk
@@ -42,6 +42,12 @@
             {{ navitem ('Drafts', 'draft', 'static/assets/common/flask.svg') }}
           </li>
         {% endif %}
+        <li class="sidebar-nav-item sidebar-nav-item-share">
+          <div class='sidebar-nav-item-heading'>
+            <span>Share us with:</span>
+            <esl-share list="group:site"></esl-share>
+          </div>
+        </li>
       </ul>
 
       <esl-scrollbar class="sidebar-scrollbar" target="::prev"></esl-scrollbar>
diff --git a/pages/views/components/esl-share.njk b/pages/views/components/esl-share.njk
new file mode 100644
index 000000000..eb8635a95
--- /dev/null
+++ b/pages/views/components/esl-share.njk
@@ -0,0 +1,17 @@
+---
+layout: content
+title: ESL Share
+seoTitle: ESL Share - custom element to trigger various share actions for page or url with metadata
+name: ESL Share
+tags: [components, beta]
+aside:
+  components:
+    - esl-popup
+    - esl-toggleable
+  examples:
+    - share
+    - popup
+    - toggleable
+---
+
+{% mdRender 'src/modules/esl-share/README.md', 'intro' %}
diff --git a/pages/views/examples/share.njk b/pages/views/examples/share.njk
new file mode 100644
index 000000000..11352f970
--- /dev/null
+++ b/pages/views/examples/share.njk
@@ -0,0 +1,81 @@
+---
+layout: content
+title: Share
+name: Share
+tags: [examples, beta]
+icon: examples/share.svg
+aside:
+  components:
+    - esl-share
+---
+{% import 'lorem.njk' as lorem %}
+
+<section>
+  <h2>Share example</h2>
+
+  <h3>Just a standalone share button</h3>
+  <esl-share-button action="media" link="//www.linkedin.com/sharing/share-offsite/?url={u}" name="linkedin" share-title="Standalone share button" share-url="/standalone.html" tabindex="0" role="button" title="LinkedIn">
+    <span title="Linkedin" class="esl-share-icon" style="background-color:#0b77b3;">
+      <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" role="presentation" viewBox="0 0 27.99 27.99"><path d="M6.37 11.33h3.25v10.45H6.37zM8 6.13A1.88 1.88 0 116.12 8 1.88 1.88 0 018 6.13M11.65 11.33h3.12v1.43h.05a3.4 3.4 0 013.07-1.69c3.29 0 3.9 2.17 3.9 5v5.73h-3.25v-5.11c0-1.21 0-2.77-1.69-2.77s-1.94 1.32-1.94 2.69v5.17h-3.25V11.33z"></path></svg>
+    </span>
+  </esl-share-button>
+  <hr>
+
+  <h3>Displays list of share buttons of group 'demo'</h3>
+  <p>Shows buttons from a specified group.</p>
+  <esl-share list="group:demo"></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons of group 'alternative'</h3>
+  <p>Shows buttons from a specified group.</p>
+  <esl-share list=" group:alternative  "></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons of the mix of Facebook, the group 'alternative', and Twitter button</h3>
+  <p>Shows a Facebook button, buttons from a specified group, and a Twitter button.</p>
+  <esl-share list="facebook group:alternative twitter"></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons on nonexistent group</h3>
+  <p>Shows empty list when a nonexistent group is specified.</p>
+  <esl-share list="group:foo"></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons via list of buttons id</h3>
+  <p>Shows specified buttons. Displays nothing in the case when specified wrong button name.</p>
+  <esl-share list="kakao pusha alladin mix myspace"></esl-share>
+  <hr>
+
+  <h3>List of share buttons which presents buttons with all action types</h3>
+  <p>This example shows a button with the native share mechanism on the device which will be inactive on the desktop browser.</p>
+  <esl-share list="copy linkedin mail native-share print"></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons with empty list</h3>
+  <p>Shows empty component without buttons.</p>
+  <esl-share list=""></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons via incorrect list</h3>
+  <p>Shows buttons only with the correct names.</p>
+  <esl-share list="twittor  copi"></esl-share>
+  <hr>
+
+  <h3>Displays list of share buttons (without group or list)</h3>
+  <p>Shows all available buttons from config.</p>
+  <esl-share share-url="https://esl-ui.com/" share-title="Exadel Smart Library"></esl-share>
+  <hr>
+
+  <h3>Trigger icon with share popup</h3>
+  <p>Displays trigger icon. Hovering or clicking on the icon shows a popup with the list of share icons.</p>
+  <esl-trigger target="#demo-share-popup" mode="toggle" track-click track-hover style="display: inline-block; width: 40px; height: 40px;">
+    <svg viewBox="0 0 483 483" fill="none" xmlns="http://www.w3.org/2000/svg">
+      <g fill="#add1fa">
+        <path d="M395.72,0c-48.204,0-87.281,39.078-87.281,87.281c0,2.036,0.164,4.03,0.309,6.029l-161.233,75.674 c-15.668-14.971-36.852-24.215-60.231-24.215c-48.204,0.001-87.282,39.079-87.282,87.282c0,48.204,39.078,87.281,87.281,87.281 c15.206,0,29.501-3.907,41.948-10.741l69.789,58.806c-3.056,8.896-4.789,18.396-4.789,28.322c0,48.204,39.078,87.281,87.281,87.281 c48.205,0,87.281-39.078,87.281-87.281s-39.077-87.281-87.281-87.281c-15.205,0-29.5,3.908-41.949,10.74l-69.788-58.805 c3.057-8.891,4.789-18.396,4.789-28.322c0-2.035-0.164-4.024-0.308-6.029l161.232-75.674c15.668,14.971,36.852,24.215,60.23,24.215 c48.203,0,87.281-39.078,87.281-87.281C482.999,39.079,443.923,0,395.72,0z"/>
+      </g>
+    </svg>
+  </esl-trigger>
+  <esl-popup id="demo-share-popup" position="top" default-params="{hideDelay: 500}" close-on-esc close-on-outside-action>
+    <esl-share list="group:alternative" style="margin: 10px;"></esl-share><span class="esl-popup-arrow"></span>
+  </esl-popup>
+</section>
diff --git a/src/modules/all.less b/src/modules/all.less
index 3e592ab87..05fab970e 100644
--- a/src/modules/all.less
+++ b/src/modules/all.less
@@ -23,3 +23,5 @@
 @import "./esl-tooltip/core.less";
 
 @import "./esl-animate/core.less";
+
+@import "./esl-share/core.less";
diff --git a/src/modules/all.ts b/src/modules/all.ts
index 0449baa81..a6dde9383 100644
--- a/src/modules/all.ts
+++ b/src/modules/all.ts
@@ -42,3 +42,6 @@ export * from './esl-animate/core';
 
 // Related Target Mixin
 export * from './esl-related-target/core';
+
+// Share
+export * from './esl-share/core';
diff --git a/src/modules/esl-share/README.md b/src/modules/esl-share/README.md
new file mode 100644
index 000000000..4712e3d44
--- /dev/null
+++ b/src/modules/esl-share/README.md
@@ -0,0 +1,156 @@
+# [ESL](../../../) Share
+
+Version: *1.0.0-beta*.
+
+Authors: *Dmytro Shovchko*.
+
+***Important Notice: the component is under beta version, it is tested and ready to use but be aware of its potential critical API changes.***
+
+<a name="intro"></a>
+
+The ESL Share component provides the capability of integrating into a web page a sharing mechanism of the page on social media platforms, such as Facebook, Twitter, and Pinterest. The available share actions depend on the device but might include the clipboard, email applications, websites, social media, etc.
+
+`ESLShareButton` is a custom element that is used for displaying the "Share on social media" button. It is intended to share the page using the action specified on the button.
+
+`ESLShare` is a custom element that is used for showing the list of social media buttons. The element's content (a set of `ESLShareButtons`) is created automatically by specifying a list of networks or groups to display. Available social networks and their groups are listed in the configuration file.
+
+### Usage
+
+Make sure you register the share actions that you are going to use on your pages. You don't need to do anything special for this, just import the necessary share actions - the registration will be done automatically.
+
+Next, you have two options for using the share component. The first option is to use only the ESLShareButton. In this case, you simply add this element to the markup and set the required configuration with the attributes. The element needs to be registered with `ESLShareButton.register()`. And that's it.
+
+The second option to use the share component is to define the component configuration and bind it to the ESLShare. After that, all you have to do is to add an element with names or groups of social networks to the ESLShare markup. The item content, consisting of a set of buttons, will be generated automatically. It's the same as you would add each button to the markup and prescribe its configuration manually.
+
+To use this option it is necessary to set the configuration for the list of buttons
+```
+ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
+```
+and then register the item
+`ESLShare.register();`
+
+### ESLShare config
+
+Config is a javascript object that contains two properties. The first one is `buttons` describing the configuration of the buttons. The second is `groups` which configures the groups. Both properties are arrays containing objects describing buttons and groups respectively.
+
+An example of a description of the button configuration:
+```
+{
+    "action": "media",
+    "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 27.99 28\"\u003e\u003cpath d\u003d\"M23 17.11l.55-4.24h-4.2v-2.71c0-1.23.34-2.06 2.1-2.06h2.25V4.29a31.62 31.62 0 00-3.28-.16c-3.24 0-5.46 2-5.46 5.61v3.13h-3.63v4.24H15V28h4.39V17.11z\"/\u003e\u003c/svg\u003e",
+    "iconBackground": "#3c5996",
+    "link": "//www.facebook.com/sharer.php?u\u003d{u}",
+    "name": "facebook",
+    "title": "Facebook"
+}
+```
+or for example the configuration of the copy button
+```
+{
+    "action": "copy",
+    "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" focusable\u003d\"false\" role\u003d\"presentation\" viewBox\u003d\"0 0 28 28\"\u003e\u003cpath d\u003d\"M17 9.69l-7.43 7.43 1.18 1.18 7.43-7.43L17 9.69z\"/\u003e\u003cpath d\u003d\"M4.31 17.8c-.481.481-.48 1.29.00138 1.77l4.02 4.02c.481.481 1.29.483 1.77.00138l4.95-4.95c.481-.481.481-1.29-7e-7-1.78l-4.02-4.02c-.481-.481-1.29-.481-1.78 0l-4.95 4.95zm1.47.887l4.36-4.36 3.44 3.44-4.36 4.36-3.44-3.44zm7-9.37c-.481.481-.481 1.29 2.8e-7 1.78l4.02 4.02c.481.481 1.29.481 1.78 0l4.95-4.95c.481-.481.48-1.29-.00138-1.77l-4.02-4.02c-.481-.481-1.29-.483-1.77-.00138l-4.95 4.95zm1.47.889l4.36-4.36 3.44 3.44-4.36 4.36-3.44-3.44z\"/\u003e\u003c/svg\u003e",
+    "iconBackground": "#a0522d",
+    "link": "",
+    "name": "copy",
+    "title": "Copy",
+    "additional": {
+        "alertText": "Copied to clipboard"
+    }
+}
+```
+What the properties of the button description object mean:
+ - `action` - the name of the action to be performed by clicking on the button (recall that the action must be registered, the import was executed)
+ - `icon` - the HTML content of the share icon
+ - `iconBackground` - the color of the icon background (the value -  CSS data type represents a color). If you do not need to set the color, set the value to `transparent`
+ - `link` - URL link (with placeholders) to share on a social network. Can contain the next placeholders:
+    - {u} or {url} - URL to share on social network (shareUrl property on the ESLShareButton instance)
+    - {t} or {title} - title to share on social network (shareTitle property on the ESLShareButton instance)
+ - `name` - string identifier of the button (no spaces)
+ - `title` - button title
+ - `additional` - additional params to pass into a button (can be used by share actions)
+
+The configuration object of the group is simple, consisting of two properties:
+ - `name` - string identifier of the group (no spaces)
+ - `list` - list of buttons included in the group
+
+An example of a description of the group configuration:
+```
+{
+    "name": "demo",
+    "list": "facebook twitter linkedin wykop copy"
+}
+```
+The group may include another group. So this configuration describing nested groups will be valid:
+```
+{
+    "name": "tier0",
+    "list": "copy print"
+},
+{
+    "name": "tier1",
+    "list": "twitter linkedin group:tier0"
+},
+{
+    "name": "tier2",
+    "list": "facebook group:tier1"
+}
+```
+
+### Share actions available for use
+
+ESLShare provides several actions available for you to use:
+ - `copy` - action for copying to the clipboard. It can use additional params `alertText` (with message text) to show an alert to indicate a successful operation
+ - `external` - action for sharing via an external application. It is used to produce actions via external applications linked via schema in URL (for example mailto:, news: or tel: )
+ - `media` - action for sharing via a link to share on a social media
+ - `native` - action for sharing that invokes the native sharing mechanism of Web Share API
+ - `print` - action for printing a page
+
+For using actions you should import the required actions before setting up the configuration and registering ESLShare components. When an unregistered action is specified for a button, the button will not be able to perform the share action and will be marked as 'unavailable'. The same behavior occurs if the action is unavailable on the user's device, e.g. native action on the user's desktop.
+
+### Setting the ESLShare configuration
+
+Before registering an ESLShare item, you must set the component configuration. To do this, use the static `ESLShare.config()` method of the component, which either receives as an argument a config object or a provider function that returns a promise of a config object.
+
+For example:
+```
+ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
+```
+
+### ESLShareButton
+
+#### Attributes / Properties
+
+ - `action` - name of share action that occurs after button click
+ - `link` - link to share on a social network
+ - `name` - social network identifier
+ - `share-url` - URL to share (current page URL by default)
+ - `share-title` - title to share (current document title by default)
+ - `additional` - additional params to pass into a button (can be used by share actions)
+ - `unavailable` - marker of availability of share button
+
+#### Public API
+
+ - `share` - the same as clicking the button, i.e. perform the share action
+
+### ESLShare
+
+#### Attributes / Properties
+
+ - `list` - list of social networks or groups of them to display (all by default). The value - a string containing the names of the buttons or groups (specified with the prefix group:) separated by spaces. For example: `"facebook reddit group:default"`
+ - `share-url` - URL to share (current page URL by default)
+ - `share-title` - title to share (current document title by default)
+ - `ready` - ready state marker
+#### Public API
+
+ - `config` - static method to get or update config with a promise of a new config object or using a config provider function
+ - `build` - builds content of component
+
+#### Events
+
+ - `esl:share:ready` - event to dispatch on ready state of ESLShare
+
+### ESLShareAction
+
+**ESLShareBaseAction** is an interface that describes share actions. Custom user's actions realizing this interface should have next public methods:
+ - `isAvailable` - checks if this action is available on the user's device
+ - `share` - performs an action to share
diff --git a/src/modules/esl-share/actions/copy-action.ts b/src/modules/esl-share/actions/copy-action.ts
new file mode 100644
index 000000000..01c550650
--- /dev/null
+++ b/src/modules/esl-share/actions/copy-action.ts
@@ -0,0 +1,35 @@
+import {ESLShareBaseAction} from '../core/esl-share-action';
+import {ESLEventUtils} from '../../esl-utils/dom/events';
+
+import type {ESLShareButton} from '../core/esl-share-button';
+
+/** Copy to clipboard action class for share buttons {@link ESLShareButton} */
+@ESLShareBaseAction.register
+export class ESLShareCopyAction extends ESLShareBaseAction {
+  public static override readonly is: string = 'copy';
+
+  /** Checks if this action is available on the user's device */
+  public override get isAvailable(): boolean {
+    return navigator.clipboard !== undefined;
+  }
+
+  /** Does an action to share */
+  public share($button: ESLShareButton): void {
+    const shareData = this.getShareData($button);
+    const {url} = shareData;
+    if (!this.isAvailable || !url) return;
+
+    navigator.clipboard.writeText(url);
+    this.showCopyAlert($button.additional?.alertText);
+  }
+
+  /** Shows alert about the successful action completion */
+  protected showCopyAlert(alertText: string): void {
+    if (!alertText) return;
+    const detail = {
+      cls: 'esl-share-alert',
+      html: `<span>${alertText}</span>`
+    };
+    ESLEventUtils.dispatch(document.body, 'esl:alert:show', {detail});
+  }
+}
diff --git a/src/modules/esl-share/actions/external-action.ts b/src/modules/esl-share/actions/external-action.ts
new file mode 100644
index 000000000..f17a83b46
--- /dev/null
+++ b/src/modules/esl-share/actions/external-action.ts
@@ -0,0 +1,20 @@
+import {ESLShareUrlGenericAction} from './url-generic-action';
+
+import type {ESLShareButton} from '../core/esl-share-button';
+
+/** Action class for share buttons {@link ESLShareButton} via an external link */
+@ESLShareUrlGenericAction.register
+export class ESLShareExternalAction extends ESLShareUrlGenericAction {
+  public static override readonly is: string = 'external';
+
+  /** Does an action to share */
+  public share($button: ESLShareButton): void {
+    const {link} = $button;
+    if (!link) return;
+
+    const shareData = this.getShareData($button);
+    const a = document.createElement('a');
+    a.href = this.buildURL(link, shareData);
+    a.click();
+  }
+}
diff --git a/src/modules/esl-share/actions/media-action.ts b/src/modules/esl-share/actions/media-action.ts
new file mode 100644
index 000000000..7ec39f82a
--- /dev/null
+++ b/src/modules/esl-share/actions/media-action.ts
@@ -0,0 +1,40 @@
+import {ESLShareUrlGenericAction} from './url-generic-action';
+
+import type {ESLShareButton} from '../core/esl-share-button';
+
+/** Action class for share buttons {@link ESLShareButton} via a link to share on a social media */
+@ESLShareUrlGenericAction.register
+export class ESLShareMediaAction extends ESLShareUrlGenericAction {
+  public static override readonly is: string = 'media';
+
+  /**
+   * Window features that apply to `window.open()`.
+   * These features include options such as the window's default size and position,
+   * whether or not to open a minimal popup window, and so forth.
+   * */
+  public static FEATURES: Record<string, number> = {
+    scrollbars: 0,
+    resizable: 1,
+    menubar: 0,
+    left: 100,
+    top: 100,
+    width: 750,
+    height: 500,
+    toolbar: 0,
+    status: 0
+  };
+
+  protected get windowFeatures(): string {
+    const features = (this.constructor as typeof ESLShareMediaAction).FEATURES;
+    return Object.entries(features).map(([key, value]) => `${key}=${value}`).join(',');
+  }
+
+  /** Does an action to share */
+  public share($button: ESLShareButton): void {
+    const {link} = $button;
+    if (!link) return;
+
+    const shareData = this.getShareData($button);
+    window.open(this.buildURL(link, shareData), '_blank', this.windowFeatures);
+  }
+}
diff --git a/src/modules/esl-share/actions/native-action.ts b/src/modules/esl-share/actions/native-action.ts
new file mode 100644
index 000000000..a5d2cb9bf
--- /dev/null
+++ b/src/modules/esl-share/actions/native-action.ts
@@ -0,0 +1,22 @@
+import {ESLShareBaseAction} from '../core/esl-share-action';
+
+import type {ESLShareButton} from '../core/esl-share-button';
+
+/** Native action class for share buttons {@link ESLShareButton} that invokes the native sharing mechanism of Web Share API */
+@ESLShareBaseAction.register
+export class ESLShareNativeAction extends ESLShareBaseAction {
+  public static override readonly is: string = 'native';
+
+  /** Checks if this action is available on the user's device */
+  public override get isAvailable(): boolean {
+    return navigator.share !== undefined;
+  }
+
+  /** Does an action to share */
+  public share($button: ESLShareButton): void {
+    if (!this.isAvailable) return;
+
+    const shareData = this.getShareData($button);
+    navigator.share(shareData);
+  }
+}
diff --git a/src/modules/esl-share/actions/print-action.ts b/src/modules/esl-share/actions/print-action.ts
new file mode 100644
index 000000000..773c097c5
--- /dev/null
+++ b/src/modules/esl-share/actions/print-action.ts
@@ -0,0 +1,14 @@
+import {ESLShareBaseAction} from '../core/esl-share-action';
+
+import type {ESLShareButton} from '../core/esl-share-button';
+
+/** Print action class for share buttons {@link ESLShareButton} */
+@ESLShareBaseAction.register
+export class ESLSharePrintAction extends ESLShareBaseAction {
+  public static override readonly is: string = 'print';
+
+  /** Does an action to share */
+  public share($button: ESLShareButton): void {
+    window.print();
+  }
+}
diff --git a/src/modules/esl-share/actions/url-generic-action.ts b/src/modules/esl-share/actions/url-generic-action.ts
new file mode 100644
index 000000000..d6ac20cce
--- /dev/null
+++ b/src/modules/esl-share/actions/url-generic-action.ts
@@ -0,0 +1,22 @@
+import {ESLShareBaseAction} from '../core/esl-share-action';
+import {format} from '../../esl-utils/misc/format';
+
+/** Base action class for URL-based actions of share buttons {@link ESLShareButton} */
+export abstract class ESLShareUrlGenericAction extends ESLShareBaseAction {
+
+  protected getFormatSource(shareData: ShareData): Record<string, string> {
+    const title = encodeURIComponent(shareData.title || '');
+    const url = encodeURIComponent(shareData.url || '');
+    return {
+      u: url,
+      t: title,
+      url,
+      title
+    };
+  }
+
+  /** Builds URL to share on a social network */
+  protected buildURL(link: string, shareData: ShareData): string {
+    return format(link, this.getFormatSource(shareData));
+  }
+}
diff --git a/src/modules/esl-share/core.less b/src/modules/esl-share/core.less
new file mode 100644
index 000000000..b3b4dda08
--- /dev/null
+++ b/src/modules/esl-share/core.less
@@ -0,0 +1,2 @@
+@import "./core/esl-share-button.less";
+@import "./core/esl-share.less";
diff --git a/src/modules/esl-share/core.ts b/src/modules/esl-share/core.ts
new file mode 100644
index 000000000..e342a0429
--- /dev/null
+++ b/src/modules/esl-share/core.ts
@@ -0,0 +1,4 @@
+export * from './core/esl-share';
+export * from './core/esl-share-action';
+export * from './core/esl-share-action-registry';
+export * from './core/esl-share-button';
diff --git a/src/modules/esl-share/core/esl-share-action-registry.ts b/src/modules/esl-share/core/esl-share-action-registry.ts
new file mode 100644
index 000000000..cc8ae978b
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-action-registry.ts
@@ -0,0 +1,41 @@
+import {memoize} from '../../esl-utils/decorators';
+
+import type {ESLShareActionType, ESLShareBaseAction} from './esl-share-action';
+import type {ESLShareButton} from './esl-share-button';
+
+/**
+ * ESLShareActionRegistry class to store share actions
+ * @author Dmytro Shovchko
+ */
+export class ESLShareActionRegistry {
+  private actionsMap: Map<string, ESLShareBaseAction> = new Map();
+
+  /** Returns action registry instance */
+  @memoize()
+  public static get instance(): ESLShareActionRegistry {
+    return new ESLShareActionRegistry();
+  }
+
+  /** Registers action */
+  public register(action: ESLShareActionType): void {
+    if (!action.is) throw new Error('Action should have a name');
+    this.actionsMap.set(action.is, new action());
+  }
+
+  /** Checks if action is registered for passed name */
+  public has(name: string): boolean {
+    return this.actionsMap.has(name);
+  }
+
+  /** Gets the action by name */
+  public get(name: string): ESLShareBaseAction | null {
+    if (!name) return null;
+    return this.actionsMap.get(name.toLowerCase()) || null;
+  }
+
+  /** Does the share action on passed Share button {@link ESLShareButton} */
+  public share(button: ESLShareButton): void {
+    const action = this.get(button.action);
+    action && action.share(button);
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-action.ts b/src/modules/esl-share/core/esl-share-action.ts
new file mode 100644
index 000000000..e8dfbe9aa
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-action.ts
@@ -0,0 +1,38 @@
+import {ESLShareActionRegistry} from './esl-share-action-registry';
+
+import type {ESLShareButton} from './esl-share-button';
+
+/** Action type definition */
+export type ESLShareActionType = (new() => ESLShareBaseAction) & typeof ESLShareBaseAction;
+
+/** Base action class for actions of share buttons {@link ESLShareButton} */
+export abstract class ESLShareBaseAction {
+  public static readonly is: string;
+
+  /** Decorator to register action */
+  public static register(this: ESLShareActionType): void;
+  /** Registers this action */
+  public static register(this: unknown, action?: ESLShareActionType): void;
+  public static register(this: any, action?: ESLShareActionType): void {
+    action = action || this;
+    if (action === ESLShareBaseAction) throw new Error('`ESLShareBaseAction` can\'t be registered.');
+    if (!(action?.prototype instanceof ESLShareBaseAction)) throw new Error('Action should be instanceof `ESLShareBaseAction`');
+    ESLShareActionRegistry.instance.register(action);
+  }
+
+  /** Checks if this action is available on the user's device */
+  public get isAvailable(): boolean {
+    return true;
+  }
+
+  /** @returns {@link ShareData} object for button  */
+  protected getShareData($button: ESLShareButton): ShareData {
+    return {
+      url: $button.urlToShare,
+      title: $button.titleToShare
+    };
+  }
+
+  /** Does an action to share */
+  public abstract share($button: ESLShareButton): void;
+}
diff --git a/src/modules/esl-share/core/esl-share-button.less b/src/modules/esl-share/core/esl-share-button.less
new file mode 100644
index 000000000..d17d50f5e
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-button.less
@@ -0,0 +1,22 @@
+esl-share-button {
+  display: inline-block;
+  width: 40px;
+  height: 40px;
+  cursor: pointer;
+
+  &:hover {
+    opacity: .6;
+  }
+
+  &[unavailable] {
+    display: none;
+  }
+
+  .esl-share-icon {
+    display: inline-block;
+    overflow: hidden;
+    background-color: #0097e7; // TODO: consider creating common variables.less file
+    width: 100%;
+    height: 100%;
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-button.shape.ts b/src/modules/esl-share/core/esl-share-button.shape.ts
new file mode 100644
index 000000000..9c2f71476
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-button.shape.ts
@@ -0,0 +1,33 @@
+import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
+import type {ESLShareButton} from './esl-share-button';
+
+/**
+ * Tag declaration interface of ESL Share Button element
+ * Used for TSX declaration
+ */
+export interface ESLShareButtonTagShape extends ESLBaseElementShape<ESLShareButton> {
+  /** Define the name of share action that occurs after button click */
+  action: string;
+  /** Define the link to share on a social network */
+  link: string;
+  /** Define the string social network identifier (no spaces) */
+  name: string;
+  /** Define additional params to pass into a button (can be used by share actions) */
+  additional?: string;
+  /** Define URL to share (current page URL by default) */
+  'share-url'?: string;
+  /** Define title to share (current document title by default) */
+  'share-title'?: string;
+
+  /** Allowed children */
+  children?: any;
+}
+
+declare global {
+  namespace JSX {
+    export interface IntrinsicElements {
+      /** {@link ESLShareButton} custom tag */
+      'esl-share-button': ESLShareButtonTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-button.ts b/src/modules/esl-share/core/esl-share-button.ts
new file mode 100644
index 000000000..b919017b2
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-button.ts
@@ -0,0 +1,106 @@
+import {ESLBaseElement} from '../../esl-base-element/core';
+import {attr, boolAttr, jsonAttr, listen} from '../../esl-utils/decorators';
+import {ENTER, SPACE} from '../../esl-utils/dom/keys';
+import {toAbsoluteUrl} from '../../esl-utils/misc/url';
+import {ESLShareActionRegistry} from './esl-share-action-registry';
+
+import type {ESLShareBaseAction} from './esl-share-action';
+import type {ESLShare} from './esl-share';
+
+function getProp<T>(name: string, targets: Record<string, any>[], fallback: T, predicate: (val: T) => boolean): T {
+  const find = targets.find((target) => predicate(target[name]));
+  return find ? find[name] : fallback;
+}
+
+/**
+ * ESLShareButton
+ * @author Dmytro Shovchko
+ *
+ * ESLShareButton is a custom element to create a "Share on social media" button.
+ */
+export class ESLShareButton extends ESLBaseElement {
+  public static override is = 'esl-share-button';
+  public static observedAttributes = ['action'];
+
+  /** Name of share action that occurs after button click */
+  @attr() public action: string;
+  /** Link to share on a social network */
+  @attr() public link: string;
+  /** String social network identifier (no spaces) */
+  @attr() public name: string;
+
+  /** URL to share (current page URL by default) */
+  @attr() public shareUrl: string;
+  /** Title to share (current document title by default) */
+  @attr() public shareTitle: string;
+
+  /** Additional params to pass into a button (can be used by share actions) */
+  @jsonAttr() public additional: Record<string, any>;
+
+  /** Marker of availability of share button */
+  @boolAttr() public unavailable: boolean;
+
+  protected get actionInstance(): ESLShareBaseAction | null {
+    return ESLShareActionRegistry.instance.get(this.action);
+  }
+
+  /** @returns parent share list {@link ESLShare} element (if exists) */
+  public get host(): ESLShare | null {
+    return this.closest('esl-share');
+  }
+
+  /** @returns title to share */
+  public get titleToShare(): string {
+    return this._getPropFromRelatedEls('shareTitle', document.title);
+  }
+
+  /** @returns URL to share */
+  public get urlToShare(): string {
+    return toAbsoluteUrl(this._getPropFromRelatedEls('shareUrl', window.location.href));
+  }
+
+  protected override attributeChangedCallback(attrName: string, oldVal: string, newVal: string): void {
+    if (!this.connected || oldVal === newVal) return;
+    if (attrName === 'action') this.updateAction();
+  }
+
+  protected override connectedCallback(): void {
+    super.connectedCallback();
+    this.initA11y();
+    this.updateAction();
+  }
+
+  /** Sets initial a11y attributes */
+  protected initA11y(): void {
+    if (!this.hasAttribute('role')) this.setAttribute('role', 'button');
+    if (this.getAttribute('role') === 'button' && !this.hasAttribute('tabindex')) {
+      this.tabIndex = 0;
+    }
+  }
+
+  /** Does an action to share */
+  public share(): void {
+    this.actionInstance?.share(this);
+  }
+
+  protected updateAction(): void {
+    this.$$attr('unavailable', !this.actionInstance?.isAvailable);
+  }
+
+  protected _getPropFromRelatedEls(name: string, fallback: string): string {
+    return getProp(name, [this, this.host ?? {}], fallback, (val: string) => !!val.length);
+  }
+
+  @listen('click')
+  protected _onClick(e: MouseEvent): void {
+    this.share();
+  }
+
+  @listen('keydown')
+  protected _onKeydown(e: KeyboardEvent): void {
+    if ([ENTER, SPACE].includes(e.key)) {
+      this.click();
+      e.preventDefault();
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share.less b/src/modules/esl-share/core/esl-share.less
new file mode 100644
index 000000000..56ffff829
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share.less
@@ -0,0 +1,4 @@
+esl-share[mode="list"] {
+  display: inline-flex;
+  flex-wrap: wrap;
+}
diff --git a/src/modules/esl-share/core/esl-share.shape.ts b/src/modules/esl-share/core/esl-share.shape.ts
new file mode 100644
index 000000000..dca07882a
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share.shape.ts
@@ -0,0 +1,29 @@
+import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
+import type {ESLShare} from './esl-share';
+
+/**
+ * Tag declaration interface of ESL Share element
+ * Used for TSX declaration
+ */
+export interface ESLShareTagShape extends ESLBaseElementShape<ESLShare> {
+  /** Define the list of social networks or groups of them to display (all by default) */
+  list?: string;
+  /** Define share buttons rendering mode */
+  mode?: string;
+  /** Define URL to share (current page URL by default) */
+  'share-url'?: string;
+  /** Define title to share (current document title by default) */
+  'share-title'?: string;
+
+  /** Children are not allowed for ESLShare */
+  children?: never[];
+}
+
+declare global {
+  namespace JSX {
+    export interface IntrinsicElements {
+      /** {@link ESLShare} custom tag */
+      'esl-share': ESLShareTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share.ts b/src/modules/esl-share/core/esl-share.ts
new file mode 100644
index 000000000..63fbf4dca
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share.ts
@@ -0,0 +1,155 @@
+import {ESLBaseElement} from '../../esl-base-element/core';
+import {attr, bind, boolAttr, prop} from '../../esl-utils/decorators';
+
+import {ESLShareButton} from './esl-share-button';
+
+/** {@link ShareConfig} provider type definition */
+export type ESLShareConfigProviderType = () => Promise<ShareConfig>;
+
+/** The definition of the sharing button */
+export interface ShareButtonConfig {
+  /** Name of the share action, which is performed after the button is pressed */
+  action: string;
+  /** HTML content of the share icon */
+  icon: string;
+  /** Color of the icon background (the value - CSS data type represents a color) */
+  iconBackground: string;
+  /**
+   * URL link (with placeholders) to share. Can contain the following placeholders:
+   * - `{u}` or `{url}` - URL to share (`shareUrl` property on the {@link ESLShareButton} instance)
+   * - `{t}` or `{title}` - title to share (`shareTitle` property on the {@link ESLShareButton} instance)
+   */
+  link: string;
+  /** String identifier of the button (no spaces) */
+  name: string;
+  /** Button title */
+  title: string;
+  /** Additional params to pass into a button */
+  additional?: Record<string, any>;
+}
+
+/** The definition of share buttons groups (named sets of share buttons) */
+export interface ShareGroupConfig {
+  /** Name of the group. The group can be accessed with the `group:` prefix in the component configuration */
+  name: string;
+  /** A list of button names separated by space */
+  list: string;
+}
+
+/** The definition of `ESLShare` component configuration */
+export interface ShareConfig {
+  /** List of sharing buttons configuration */
+  buttons: ShareButtonConfig[];
+  /** List of share button groups configurations */
+  groups: ShareGroupConfig[];
+}
+
+function getConfigSectionItem<T extends ShareButtonConfig | ShareGroupConfig>(section: T[], name: string): T | undefined {
+  return section.find((item) => item.name === name);
+}
+
+function getButtonsList(config: ShareConfig, list: string): ShareButtonConfig[] {
+  return list.split(' ').reduce((res, item) => {
+    const [btnName, groupName] = item.split('group:');
+    if (groupName) {
+      const groupConfig = getConfigSectionItem(config.groups, groupName);
+      if (groupConfig) return res.concat(getButtonsList(config, groupConfig.list));
+    } else {
+      const btnConfig = getConfigSectionItem(config.buttons, btnName);
+      if (btnConfig) res.push(btnConfig);
+    }
+    return res;
+  }, [] as ShareButtonConfig[]);
+}
+
+/**
+ * ESLShare
+ * @author Dmytro Shovchko
+ *
+ * ESLShare is a custom element to dynamically draw {@link ESLShareButton}s using simplified shared config
+ */
+export class ESLShare extends ESLBaseElement {
+  public static override is = 'esl-share';
+  protected static _config: Promise<ShareConfig> = Promise.reject('Configuration is not set');
+
+  /** Register {@link ESLShare} component and dependent {@link ESLShareButton} */
+  public static override register(): void {
+    ESLShareButton.register();
+    super.register();
+  }
+
+  /** Event to dispatch on ready state of {@link ESLShare} */
+  @prop('esl:share:ready') public SHARE_READY_EVENT: string;
+
+  /**
+   * List of social networks or groups of them to display (all by default).
+   * The value - a string containing the names of the buttons or groups (specified with
+   * the prefix group:) separated by spaces.
+   * @example "facebook reddit group:default"
+   * */
+  @attr({defaultValue: 'all'}) public list: string;
+  /** URL to share (current page URL by default) */
+  @attr() public shareUrl: string;
+  /** Title to share (current document title by default) */
+  @attr() public shareTitle: string;
+  /** Rendering mode of the share buttons ('list' by default) */
+  @attr() public mode: 'list';
+
+  /** @readonly Ready state marker */
+  @boolAttr({readonly: true}) public ready: boolean;
+
+  /**
+   * Gets or updates config with a promise of a new config object or using a config provider function.
+   * @returns Promise of the current config
+   */
+  public static config(provider?: ESLShareConfigProviderType | ShareConfig): Promise<ShareConfig> {
+    if (typeof provider === 'function') ESLShare._config = provider();
+    if (typeof provider === 'object') ESLShare._config = Promise.resolve(provider);
+    return ESLShare._config;
+  }
+
+  /** @returns config of buttons specified by the list attribute */
+  public get buttonsConfig(): Promise<ShareButtonConfig[]> {
+    return (this.constructor as typeof ESLShare).config().then((config) => {
+      return (this.list !== 'all') ? getButtonsList(config, this.list) : config.buttons;
+    });
+  }
+
+  public override connectedCallback(): void {
+    super.connectedCallback();
+    if (!this.ready) {
+      this.init();
+    }
+  }
+
+  protected init(): void {
+    if (!this.mode) this.mode = 'list';
+    this.buttonsConfig.then(this.build)
+      .then(() => this.$$fire(this.SHARE_READY_EVENT, {bubbles: false}))
+      .catch((e) => console.error(`[${this.baseTagName}]: ${e}`));
+  }
+
+  /** Builds content of component */
+  @bind
+  public build(config: ShareButtonConfig[]): void {
+    this.innerHTML = '';
+    config.forEach((btnCfg) => {
+      const btn = this.buildButton(btnCfg);
+      btn && this.appendChild(btn);
+    });
+
+    this.toggleAttribute('ready', true);
+  }
+
+  protected buildButton(cfg: ShareButtonConfig): ESLShareButton | null {
+    const $button = ESLShareButton.create();
+    Object.assign($button, cfg);
+    const $icon = document.createElement('span');
+    $icon.title = cfg.title;
+    $icon.classList.add('esl-share-icon');
+    $icon.innerHTML = cfg.icon;
+    $icon.setAttribute('style', `background-color:${cfg.iconBackground};`);
+    $button.appendChild($icon);
+    return $button;
+  }
+}
diff --git a/src/modules/esl-utils/misc.ts b/src/modules/esl-utils/misc.ts
index d6a035d4b..a09552477 100644
--- a/src/modules/esl-utils/misc.ts
+++ b/src/modules/esl-utils/misc.ts
@@ -17,3 +17,4 @@ export * from './misc/object';
 export * from './misc/format';
 export * from './misc/functions';
 export * from './misc/memoize';
+export * from './misc/url';
diff --git a/src/modules/esl-utils/misc/url.ts b/src/modules/esl-utils/misc/url.ts
new file mode 100644
index 000000000..d673c0c7f
--- /dev/null
+++ b/src/modules/esl-utils/misc/url.ts
@@ -0,0 +1,8 @@
+/**
+ * Converts relative URL to absolute URL based on the base URL.
+ * @param relative - relative URL
+ * @param base - base URL (document.baseURI by default)
+ **/
+export function toAbsoluteUrl(relative: string, base: string = document.baseURI): string {
+  return new URL(relative, base).href;
+}


Test patch:
diff --git a/src/modules/esl-utils/misc/test/url.test.ts b/src/modules/esl-utils/misc/test/url.test.ts
new file mode 100644
index 000000000..7057c0437
--- /dev/null
+++ b/src/modules/esl-utils/misc/test/url.test.ts
@@ -0,0 +1,14 @@
+import {toAbsoluteUrl} from '../url';
+
+describe('misc/url helper tests', () => {
+  test('1', () => {
+    expect(toAbsoluteUrl('')).toBe('http://localhost/');
+    expect(toAbsoluteUrl('/pathname/page.html')).toBe('http://localhost/pathname/page.html');
+    expect(toAbsoluteUrl('?query=string')).toBe('http://localhost/?query=string');
+    expect(toAbsoluteUrl('#anchor')).toBe('http://localhost/#anchor');
+    expect(toAbsoluteUrl('/page.html?query=string#anchor')).toBe('http://localhost/page.html?query=string#anchor');
+    expect(toAbsoluteUrl('https://esl-ui.com/page.html')).toBe('https://esl-ui.com/page.html');
+    expect(toAbsoluteUrl('', 'https://esl-ui.com')).toBe('https://esl-ui.com/');
+    expect(toAbsoluteUrl('/page.html', 'https://esl-ui.com/home.html?query=string#anchor')).toBe('https://esl-ui.com/page.html');
+  });
+});