Repository: exadel-inc/esl
Pull request #1998 (2023-10-19 18:27:30)

[🚩esl-share]: rework and cleanup (#1591)
NOTE: The beta state of `esl-share` module will not be changed in bounds of 4.13.0 release. FInal release state cleanup (including documentation) is shifted to 4.14.0 milestone


Patch:
diff --git a/package.json b/package.json
index 3011b5c3b..214dfbbfb 100644
--- a/package.json
+++ b/package.json
@@ -44,8 +44,10 @@
     "modules/lib.js",
     "modules/esl-media/providers/**/*.js",
     "modules/esl-share/actions/**/*.js",
+    "modules/esl-share/buttons/**/*.js",
     "src/modules/esl-media/providers/**/*.ts",
     "src/modules/esl-share/actions/**/*.ts",
+    "src/modules/esl-share/buttons/**/*.ts",
     "src/modules/lib.ts",
     "polyfills/**/*.js",
     "src/polyfills/**/*.ts"
diff --git a/pages/src/esl-share/esl-share.less b/pages/src/esl-share/esl-share.less
index ae82a911e..5751ed9b1 100644
--- a/pages/src/esl-share/esl-share.less
+++ b/pages/src/esl-share/esl-share.less
@@ -4,10 +4,3 @@ esl-share-list esl-share-button[unavailable] {
   cursor: not-allowed;
   filter: grayscale(1);
 }
-
-esl-share-button {
-  path,
-  circle {
-    fill: #fff;
-  }
-}
diff --git a/pages/src/esl-share/esl-share.ts b/pages/src/esl-share/esl-share.ts
new file mode 100644
index 000000000..b413da462
--- /dev/null
+++ b/pages/src/esl-share/esl-share.ts
@@ -0,0 +1,11 @@
+import '@exadel/esl/modules/esl-share/buttons/all';
+import {ESLShare, ESLShareConfig} from '@exadel/esl/modules/esl-share/core';
+
+ESLShareConfig.append({name: 'site', 'list': 'facebook twitter linkedin telegram copy'});
+ESLShare.register();
+
+ESLShareConfig.set(
+  fetch('/assets/share/config.json').then((response) => response.json())
+).catch(
+  () => console.error('ESLShare: failed to load config')
+);
diff --git a/pages/src/localdev.ts b/pages/src/localdev.ts
index d3c247ae5..dcc73f7e6 100644
--- a/pages/src/localdev.ts
+++ b/pages/src/localdev.ts
@@ -34,7 +34,6 @@ import {
   ESLTooltip,
   ESLAnimate,
   ESLAnimateMixin,
-  ESLShare,
   ESLRelatedTarget
 } from '@exadel/esl/modules/all';
 
@@ -110,8 +109,8 @@ ESLTooltip.register();
 ESLAnimate.register();
 ESLAnimateMixin.register();
 
-ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
-ESLShare.register();
-
 // Register ESL Mixins
 ESLRelatedTarget.register();
+
+// Share component loading
+import (/* webpackChunkName: 'common/esl-share' */'./esl-share/esl-share');
diff --git a/pages/src/navigation/header/header.less b/pages/src/navigation/header/header.less
index e8f86e954..b1b02b4b8 100644
--- a/pages/src/navigation/header/header.less
+++ b/pages/src/navigation/header/header.less
@@ -90,7 +90,7 @@
       background: @landing-bg-color;
       border-color: gray;
     }
-    > .esl-share {
+    .esl-share-list {
       margin: 0.75rem;
       gap: 0.25rem;
     }
diff --git a/pages/src/navigation/sidebar/sidebar-share.less b/pages/src/navigation/sidebar/sidebar-share.less
index 83028aa51..498ef828e 100644
--- a/pages/src/navigation/sidebar/sidebar-share.less
+++ b/pages/src/navigation/sidebar/sidebar-share.less
@@ -2,9 +2,7 @@
 
 esl-d-sidebar {
   .sidebar-nav-item-share {
-    display: flex;
-    align-items: center;
-
+    --esl-share-icon-size: 32px;
     visibility: visible;
     opacity: 1;
     transition:
@@ -13,6 +11,7 @@ esl-d-sidebar {
 
     padding: 15px 40px 15px 25px;
     @media @sm-xl {
+      --esl-share-icon-size: 30px;
       margin-top: auto;
       margin-bottom: 0;
       padding: 30px 40px 0 21px;
@@ -22,6 +21,11 @@ esl-d-sidebar {
     }
 
     .esl-share {
+      display: flex;
+      align-items: center;
+    }
+
+    .esl-share-list {
       max-width: 100%;
       flex: 0 0 auto;
       margin: 0 -5px; // Offset for facebook icon
@@ -36,14 +40,8 @@ esl-d-sidebar {
     }
 
     .esl-share-button {
-      width: 32px;
-      height: 32px;
       overflow: hidden;
       border-radius: 7px;
-      @media @sm-xl {
-        width: 30px;
-        height: 30px;
-      }
     }
   }
 
diff --git a/pages/static/assets/share/config.json b/pages/static/assets/share/config.json
index 02bafb874..d7217482b 100644
--- a/pages/static/assets/share/config.json
+++ b/pages/static/assets/share/config.json
@@ -1,174 +1,5 @@
 {
-  "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"
diff --git a/pages/views/components/esl-share.njk b/pages/views/components/esl-share.njk
index eb8635a95..1e974649c 100644
--- a/pages/views/components/esl-share.njk
+++ b/pages/views/components/esl-share.njk
@@ -8,6 +8,7 @@ aside:
   components:
     - esl-popup
     - esl-toggleable
+    - esl-trigger
   examples:
     - share
     - popup
diff --git a/pages/views/draft/share-regression.njk b/pages/views/draft/share-regression.njk
index 422ed42f5..8a6128e2b 100644
--- a/pages/views/draft/share-regression.njk
+++ b/pages/views/draft/share-regression.njk
@@ -21,7 +21,7 @@ aside:
 {% macro shareAttrs4() %}share-url="https://esl-ui.com/examples/" share-title="Examples"{% endmacro %}
 
 <style>
-  esl-share-trigger {
+  esl-share-popup-trigger {
     margin: 10px;
   }
   .demo-trigger-svg-icon {
@@ -58,10 +58,11 @@ aside:
   <esl-share list="linkedin alladin group:alladin group:demo"></esl-share>
   <hr>
 
-  <h3>Displays list of share buttons with repeating buttons</h3>
-  <p>Shows component with repeating buttons. (should display 3 buttons LinkedIn)</p>
-  <esl-share list="linkedin linkedin linkedin"></esl-share>
-  <hr>
+{#  TODO: discuss behaviour #}
+{#  <h3>Displays list of share buttons with repeating buttons</h3>#}
+{#  <p>Shows component with repeating buttons. (should display 3 buttons LinkedIn)</p>#}
+{#  <esl-share list="linkedin linkedin linkedin"></esl-share>#}
+{#  <hr>#}
 
   <h3>Displays list of share buttons via incorrect list</h3>
   <p>Shows buttons only with the correct names. (should display only LinkedIn button)</p>
diff --git a/pages/views/examples/share.njk b/pages/views/examples/share.njk
index 5968b5c9f..80882dda4 100644
--- a/pages/views/examples/share.njk
+++ b/pages/views/examples/share.njk
@@ -10,10 +10,10 @@ aside:
 ---
 
 <style>
-  esl-share-trigger {
+  esl-share-popup-trigger {
     margin: 10px;
   }
-  esl-share-trigger svg {
+  esl-share-popup-trigger svg {
     width: 40px;
     height: 40px;
   }
@@ -22,42 +22,65 @@ aside:
 <section>
   <h2>Share example</h2>
 
-  <h3>Just a standalone share button</h3>
-  <p>The button's configuration uses attributes to specify the URL and title of the page to be shared.</p>
+  <h3>Share button examples</h3>
+  <p>Example of share button with default icon rendering.</p>
+  <esl-share-button name="linkedin" default-icon></esl-share-button>
+  <hr>
+
+  <p>Another example of share button.</p>
+  <esl-share-button name="linkedin">
+    Share me through Linkedin
+  </esl-share-button>
+  <hr>
+
+  <p>Example of share button with defining config via markup. The button's configuration uses attributes to specify the URL and title of the page to be shared.</p>
   <esl-share-button action="media" link="//www.linkedin.com/sharing/share-offsite/?url={u}" name="linkedin" share-url="https://esl-ui.com/" share-title="Exadel Smart Library" 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>
+      <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" fill="#fff"></path></svg>
     </span>
   </esl-share-button>
   <hr>
 
-  <h3>Displays list of share buttons of group 'demo'</h3>
+  <p>The same button is defined via config and the name attribute.</p>
+  <esl-share-button name="linkedin" share-url="https://esl-ui.com/" share-title="Exadel Smart Library">
+    <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" fill="#fff"></path></svg>
+    </span>
+  </esl-share-button>
+  <hr>
+
+  <h3>Share list examples</h3>
   <p>Shows buttons from a specified group.</p>
-  <esl-share list="group:demo"></esl-share>
+  <esl-share-list list="group:demo"></esl-share-list>
   <hr>
 
-  <h3>Displays list of share buttons of group 'alternative'</h3>
+  <h4>Displays list of share buttons of group 'alternative'</h4>
   <p>Shows buttons from a specified group.</p>
-  <esl-share list=" group:alternative  "></esl-share>
+  <esl-share-list list=" group:alternative  "></esl-share-list>
   <hr>
 
-  <h3>Displays list of share buttons of the mix of Facebook, the group 'alternative', and Twitter button</h3>
+  <h4>Displays list of share buttons of the mix of Facebook, the group 'alternative', and Twitter button</h4>
   <p>Shows a Facebook button, buttons from a specified group, and a Twitter button.</p>
-  <esl-share list="facebook group:alternative twitter"></esl-share>
+  <esl-share-list list="facebook group:alternative twitter"></esl-share-list>
   <hr>
 
-  <h3>List of share buttons which presents buttons with all action types</h3>
+  <h4>List of share buttons which presents buttons with all action types</h4>
   <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>
+  <esl-share-list list="copy linkedin mail native-share print"></esl-share-list>
   <hr>
 
-  <h3>Displays list of share buttons (without group or list)</h3>
+  <h4>Displays list of share buttons (without group or list)</h4>
   <p>Shows all available buttons from config. The component's configuration uses attributes to specify the URL and title of the page to be shared.</p>
-  <esl-share share-url="https://esl-ui.com/" share-title="Exadel Smart Library"></esl-share>
+  <esl-share-list share-url="https://esl-ui.com/" share-title="Exadel Smart Library"></esl-share-list>
   <hr>
 
-  <h3>Trigger icon with share popup</h3>
+  <h3>Share popup trigger example</h3>
   <p>Displays trigger icon. Hovering or clicking on the icon shows a popup with the list of share icons. The component's configuration uses attributes to specify the URL and title of the page to be shared.</p>
   <esl-share mode="popup" list="group:demo" share-url="https://esl-ui.com/" share-title="Exadel Smart Library">{% include 'static/assets/examples/share-trigger-icon.svg' %}</esl-share>
+  <hr>
 
+  <h3>Share (universal) component example (with both list and popup modes)</h3>
+  <p>Shows share list from a specified group and share popup trigger for the same group.</p>
+  <esl-share mode="list" list="group:demo"></esl-share>
+  <esl-share mode="popup" list="group:demo">{% include 'static/assets/examples/share-trigger-icon.svg' %}</esl-share>
 </section>
diff --git a/src/modules/esl-popup/core.ts b/src/modules/esl-popup/core.ts
index 9e7a69f66..e73ead432 100644
--- a/src/modules/esl-popup/core.ts
+++ b/src/modules/esl-popup/core.ts
@@ -1,4 +1,4 @@
-export type {ESLPopupShape} from './core/esl-popup.shape';
+export type {ESLPopupTagShape} from './core/esl-popup.shape';
 
 export * from './core/esl-popup';
 export * from './core/esl-popup-placeholder';
diff --git a/src/modules/esl-popup/core/esl-popup.shape.ts b/src/modules/esl-popup/core/esl-popup.shape.ts
index ba5464ace..f3a86d3fb 100644
--- a/src/modules/esl-popup/core/esl-popup.shape.ts
+++ b/src/modules/esl-popup/core/esl-popup.shape.ts
@@ -6,27 +6,37 @@ import type {PositionType} from './esl-popup-position';
  * Tag declaration interface of {@link ESLPopup} element
  * Used for TSX declaration
  */
-export interface ESLPopupShape extends ESLToggleableTagShape<ESLPopup> {
+export interface ESLPopupTagShape<T extends ESLPopup = ESLPopup> extends ESLToggleableTagShape<T> {
+  /** Classname of popups arrow element */
+  'arrow-class'?: string;
   /** Popup behavior if it does not fit in the window ('fit' by default) */
   behavior?: string;
+  /** Target to container element {@link ESLTraversingQuery} to define bounds of popups visibility (window by default) */
+  container?: string;
   /** Disable hiding the popup depending on the visibility of the activator */
-  disableActivatorObservation?: boolean;
+  'disable-activator-observation'?: boolean;
   /** Margins on the edges of the arrow. */
-  marginArrow?: string;
+  'margin-arrow'?: string;
   /** Offset of the arrow as a percentage of the popup edge (0% - at the left edge, 100% - at the right edge, for RTL it is vice versa) */
-  offsetArrow?: string;
+  'offset-arrow'?: string;
   /**
    * Popup position relative to the trigger.
    * Currently supported: 'top', 'bottom', 'left', 'right' position types ('top' by default)
    */
   position?: PositionType;
+
+  /** Default params to merge into passed action params */
+  'default-params'?: string;
+
+  /** Allowed children */
+  children?: any;
 }
 
 declare global {
   namespace JSX {
     export interface IntrinsicElements {
       /** {@link ESLPopup} custom tag */
-      'esl-popup': ESLPopupShape;
+      'esl-popup': ESLPopupTagShape;
     }
   }
 }
diff --git a/src/modules/esl-share/README.md b/src/modules/esl-share/README.md
index 856a01b31..d9ae3f921 100644
--- a/src/modules/esl-share/README.md
+++ b/src/modules/esl-share/README.md
@@ -2,7 +2,7 @@
 
 Version: *1.0.0-beta*.
 
-Authors: *Dmytro Shovchko*.
+Authors: *Dmytro Shovchko*, *Alexey Stsefanovich (ala'n)*.
 
 ***Important Notice: the component is under beta version, it is tested and ready to use but be aware of its potential critical API changes.***
 
@@ -10,35 +10,167 @@ Authors: *Dmytro Shovchko*.
 
 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.
+`<esl-share-button>` 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.
+`<esl-share-list>` is a custom element that is used for showing the list of social media buttons. The element's content (a set of `<esl-share-button>`) 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.
+
+`<esl-share-popup>` is a custom element used as a wrapper for content that can be displayed as a pop-up element. The content of the element consists of `<esl-share-button>`. `<esl-share-popup>` exists in a single instance and it refreshes its content every time its state changes to "open".
+
+`<esl-share-popup-trigger>` is a custom element, that allows triggering `<esl-share-popup>` instance state changes.
+
+`<esl-share>` is a versatile element that can function as both a list and a pop-up element. Depending on the specified value of the "mode" attribute, either an `<esl-share-list>` or an `<esl-share-popup-trigger>` is built inside. If you intend to use only one type of sharing component, it's not advisable to use this element in order to reduce the number of dependencies.
 
 ### 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.
+Now you need to configure the share buttons and their groups (if you plan to use them). There are several ways to do this. These will be described further in the relevant section.
+
+***Notice. If you don't plan to use any own custom button settings, you might be fine with the configuration from our library. Simply import the button you need from the `esl-share/buttons` folder. An additional bonus will be that in this case there is no need to register the action - the button will perform it on its own.***
+
+Next, you have several options for using the share component. The first option is to use only the `<esl-share-button>`. In this case, you simply add this element to the markup and set the required configuration using attributes. The element needs to be registered with `ESLShareButton.register()`. And that's it.
+
+```html
+<esl-share-button name="facebook" default-icon></esl-share-button>
+```
+
+The second option to use the share component is to define the component configuration and bind it to the `<esl-share-list>`. After that, all you have to do is to add an element with names or groups of social networks to the `ESLShareList` markup. The item content, consisting of a set of buttons, will be generated automatically. It's the same as adding 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 and then register the element.
+`ESLShareList.register()` (it will register `ESLShareButton` automatically).
+
+```html
+<esl-share-list list="facebook linkedin mail copy"></esl-share-list>
+```
+
+The third option for using the share component is the same as the previous one, only the list of buttons is shown inside the pop-up window. All actions are similar to the previous one, except that you add the `<esl-share-popup-trigger>` element to the markup. The list of buttons that will be displayed in the pop-up window is set in the markup as a list of names and groups, absolutely identical to `<esl-share-list>`. To use this option it is necessary to set the configuration for the list of buttons and then register the element `ESLSharePopupTrigger.register()` (it will register `ESLShareButton` and `ESLSharePopup` automatically).
 
-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.
+```html
+<esl-share-popup-trigger list="facebook linkedin mail copy"></esl-share-popup-trigger>
+```
 
-To use this option it is necessary to set the configuration for the list of buttons
+The last option for using the share component includes the previous two. That is one element, but behaves differently. You add an `<esl-share>` element to the markup, specify a list of buttons, and add the "mode" attribute, in which you specify in which of the modes ("list" or "popup") it should work, and that's it. To use this option it is necessary to set the configuration for the list of buttons and then register the element `ESLShare.register()` (it will register `ESLShareButton`, `ESLShareList`, `ESLSharePopup` and `ESLSharePopupTrigger` automatically).
+
+```html
+<esl-share list="facebook linkedin mail copy" mode="list"></esl-share>
+```
+
+### Configuring the ESLShare components
+
+ESLShare provides the ability to setup a component configuration globally. 
+This means that you do not need to configure each button separately. 
+You can set buttons and groups config globally and then it will be available for each `esl-share`, `esl-share-list`, or `esl-share-popup-trigger`. 
+All of mentioned components use the same configuration instance stored in `ESLShareConfig.instance`.
+
+To add a single button, group to the configuration, you can use the `append` method of the configuration:
 ```typescript
-ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
+// Add 'facebook' button to the configuration
+ESLShareConfig.append({
+   name: 'facebook',
+   action: 'media',
+   // ...
+});
+// Add 'mygroup' group to the configuration
+ESLShareConfig.append({
+   name: 'mygroup',
+   list: 'facebook twitter linkedin'
+});
 ```
-and then register the item
-`ESLShare.register();`
 
-### ESLShare config
+The `ESLShareConfig.append` accepts a list of buttons or groups as well:
+```typescript
+ESLShareConfig.append([
+  {
+    name: 'facebook',
+    action: 'media',
+    // ...
+  },
+  {
+    name: 'linkedin',
+    action: 'media',
+    // ...
+  }
+]);
+```
+
+The `esl-share` module provides an out of the box configuration for the most popular social networks and sharing options.
+To use it, you need to import required configuration from the `esl-share/buttons` directory it will automatically register in the `ESLShareConfig.instance`:
+
+```typescript
+// Register 'facebook' button ootb configuration
+import '@exadel/esl/modules/esl-share/buttons/facebook';
+
+// Register all buttons ootb configurations
+import '@exadel/esl/modules/esl-share/buttons/all';
+```
+
+Note: configuration of the button or group appends to the existing configuration but overrides the existing one if the button or group with the same name already exists.
+
+In case you need just a little fix up the existing configuration you can use ootb button config and then override it:
+
+```typescript
+import {facebook} from '@exadel/esl/modules/esl-share/buttons/facebook';
+// Change icon of the facebook button
+ESLShareConfig.append({
+  ...facebook,
+  icon: '<svg>...</svg>'
+});
+```
+
+You can also override the configuration of the button or group in the runtime. 
+
+The `esl-share` module supports configuration by the `ESLShareConfigInit` object
+```typescript
+export interface ESLShareConfigInit {
+  /** List of share buttons configurations */
+  buttons?: ESLShareButtonConfig[];
+  /** List of share buttons groups configurations */
+  groups?: ESLShareGroupConfig[];
+}
+```
+
+The `ESLShareConfigInit` object can be passed to the `ESLShareConfig.set` method.
+It is usefull when you have group you configuration in a single json file, or generate it in the runtime 
+(depends on the user's locale, for example).
+
+```typescript
+import config from './config.json';
+ESLShareConfig.set(config);
+```
+
+The `ESLShareConfig.set` method accepts a function that returns a promise of `ESLShareConfigInit` object 
+or a Promise of the `ESLShareConfigInit` object:
+
+```typescript
+const configProvider = () => {
+  const buttons = [];
+  if (allowPrint) buttons.push(print);
+  if (allowCopy) buttons.push(copy);
+  return {buttons};
+};
+// ...
+ESLShareConfig.set(configProvider);
+```
+
+```typescript
+// Retrive config from the server based on the user's locale
+const countryCode = document.;
+ESLShareConfig.set(fetch(`/assets/share/config.${countryCode}.json`).then((response) => response.json()));
+```
 
-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.
+
+#### ESLShare config objects
+
+Above it was told and shown how you can set the configuration of the component. 
+But how does the configuration for the button or group look like?
+
+As was mentioned above the cumulative `ESLShareConfigInit` config object consists of two properties: 
+ - `buttons` - array of button configurations
+ - `groups` - array of group configurations.
 
 An example of a description of the button configuration:
 ```json
 {
     "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",
+    "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" fill=\"#fff\" focusable\u003d\"false\" role\u003d\"presentation\" style=\"background: #3c5996;\" 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",
     "link": "//www.facebook.com/sharer.php?u\u003d{u}",
     "name": "facebook",
     "title": "Facebook"
@@ -48,8 +180,7 @@ or for example the configuration of the copy button
 ```json
 {
     "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",
+    "icon": "\u003csvg xmlns\u003d\"http://www.w3.org/2000/svg\" aria-hidden\u003d\"true\" fill=\"#fff\" focusable\u003d\"false\" role\u003d\"presentation\" style=\"background: #a0522d;\" 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",
     "link": "",
     "name": "copy",
     "title": "Copy",
@@ -58,16 +189,16 @@ or for example the configuration of the copy button
     }
 }
 ```
+
 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)
+ - `additional` - optional 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)
@@ -107,15 +238,13 @@ ESLShare provides several actions available for you to use:
 
 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:
+Note: if default configuration does not used, you should import the required actions manually:
 ```typescript
-ESLShare.config(() => fetch('/assets/share/config.json').then((response) => response.json()));
+  import '@exadel/esl/modules/esl-share/actions/copy';
+  import '@exadel/esl/modules/esl-share/actions/media';
 ```
 
+
 ### ESLShareButton
 
 #### Attributes / Properties
@@ -126,8 +255,13 @@ ESLShare.config(() => fetch('/assets/share/config.json').then((response) => resp
  - `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)
+ - `default-icon` - marker to render default icon inside button on init
  - `unavailable` - marker of availability of share button
 
+#### Observing changes in configuration
+
+The button component is notified of any configuration changes. The button will update its action if the configuration has changed. Also, the button will redraw its content if the button contains an instruction to render the default icon.
+
 #### Attributes cascading
 
 If you want to utilize URL and title overrides within any parts of the page to share using the `share-url` and `share-title` attributes, there's no need to write these attributes on each button. You can write them once on the root element of the part for which these values are valid. Alternatively, if you want to override the values for the entire document, you can set them on the body of the HTML document.
@@ -138,6 +272,52 @@ The principle of cascading is similar to CSS variables. The value is searched fr
 
  - `share` - the same as clicking the button, i.e. perform the share action
 
+### ESLShareList
+
+#### 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
+
+#### Observing changes in configuration
+
+The component is notified of any configuration changes. And, if during the check it turns out that the list of buttons inside the component changes, the component updates its content. Accordingly, in this case, the component itself also throws an event about its own content change.
+
+#### Public API
+
+ - `buttonsConfig` - getter that returns config of buttons specified by the list attribute
+
+#### Events
+
+ - `esl:share:changed` - event to dispatch on change of ESLShareList
+
+### ESLSharePopup
+
+This element is based on [ESLPopup](../esl-popup/README.md) element and exists in a single instance. Its shared instance adds directly to the document's body when any of `ESLSharePopupTrigger` requires showing this popup. It removes from the document's body on hide action. 
+`ESLSharePopup` renders buttons from the list on show action. If an `ESLSharePopup` element with the desired set of buttons already exists in the document body, the existing one will be reused. 
+
+#### Observing changes in configuration
+
+The popup is notified of any configuration changes. In this case, the component is simply hidden if it is in an open state, i.e. there is a set of rendered buttons inside. So, when you open it again, it will simply redraw the new buttons inside.
+
+#### Public API
+
+ - `sharedInstance` - static getter that returns shared instance of ESLSharePopup
+
+### ESLSharePopupTrigger
+
+A trigger element is based on [ESLTrigger](../esl-trigger/README.md) to activate the popup with share buttons, which will activate the popup when you hover over it. Also, one additional activity of the `ESLSharePopupTrigger` is to forward the `share-title` and `share-url` attributes from the root `ESLSharePopupTrigger` component (or its parents if not defined on the trigger element) to the popup. So it's possible for components with the same set of buttons but different URLs and titles to share to use the same popup.
+
+#### 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"`
+ - `popup-initial-params` - initial params to pass into popup on show action (Default: `{position: 'top', hideDelay: 220}`)
+ - `share-url` - URL to share (current page URL by default)
+ - `share-title` - title to share (current document title by default)
+ - `track-hover` - [MediaQuery](../esl-media-query/README.md) to define allowed to track hover event media. (Default: `all`)
+
 ### ESLShare
 
 #### Attributes / Properties
@@ -145,6 +325,7 @@ The principle of cascading is similar to CSS variables. The value is searched fr
  - `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)
+ - `trigger-initial-params` - initial params for the `ESLSharePopupTrigger` to be created (Default: `{trackClick: true, trackHover: true}`)
  - `mode` - rendering mode of the share buttons. The `list` and `popup` are available (list by default)
  - `ready` - ready state marker
 
@@ -152,18 +333,13 @@ The principle of cascading is similar to CSS variables. The value is searched fr
 
 There are two modes available to render buttons.
 
-In `list` mode, the buttons are drawn inside the component as a list. Nothing special.
+There are two modes available to render buttons. In list mode, the `ESLShareList` is drawn inside the component as a list. Nothing special. 
 
-When `popup` mode is specified, the buttons are created inside of a [ESLPopup](../esl-popup/README.md) element, which is built directly into the document's body. If a [ESLPopup](../esl-popup/README.md) element with the desired set of buttons already exists in the document body, the existing one will be reused. A trigger element is created inside the ESLShare component to activate the popup with share buttons, which will activate the popup when you hover over it. Also, one additional activity of the ESLShareTrigger is to forward the `share-title` and `share-url` attributes from the root ESLShare component to the popup. So it's possible for components with the same set of buttons but different URLs and title to share to use the same popup.
+Similarly, in popup mode, the `ESLSharePopupTrigger`` is drawn inside component and shows a popup with the specified list of buttons.
 
 #### 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
+ - `config` - static method to get or update config with a promise of a new config object or using a config provider function (***Deprecated***)
 
 ### ESLShareAction
 
diff --git a/src/modules/esl-share/actions/copy-action.ts b/src/modules/esl-share/actions/copy-action.ts
index 01c550650..878a3db7e 100644
--- a/src/modules/esl-share/actions/copy-action.ts
+++ b/src/modules/esl-share/actions/copy-action.ts
@@ -3,7 +3,7 @@ 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} */
+/** Copy to clipboard {@link ESLShareBaseAction} implementation */
 @ESLShareBaseAction.register
 export class ESLShareCopyAction extends ESLShareBaseAction {
   public static override readonly is: string = 'copy';
@@ -14,13 +14,13 @@ export class ESLShareCopyAction extends ESLShareBaseAction {
   }
 
   /** Does an action to share */
-  public share($button: ESLShareButton): void {
+  public override async share($button: ESLShareButton): Promise<void> {
     const shareData = this.getShareData($button);
     const {url} = shareData;
     if (!this.isAvailable || !url) return;
 
-    navigator.clipboard.writeText(url);
-    this.showCopyAlert($button.additional?.alertText);
+    await navigator.clipboard.writeText(url);
+    this.showCopyAlert($button.shareAdditional?.alertText);
   }
 
   /** Shows alert about the successful action completion */
diff --git a/src/modules/esl-share/actions/external-action.ts b/src/modules/esl-share/actions/external-action.ts
index f17a83b46..3d6ed7cee 100644
--- a/src/modules/esl-share/actions/external-action.ts
+++ b/src/modules/esl-share/actions/external-action.ts
@@ -2,19 +2,19 @@ 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 */
+/** Sharing using default browser link behaviour {@link ESLShareBaseAction} implementation */
 @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;
+  public override share($button: ESLShareButton): void {
+    const {shareLink} = $button;
+    if (!shareLink) return;
 
     const shareData = this.getShareData($button);
     const a = document.createElement('a');
-    a.href = this.buildURL(link, shareData);
+    a.href = this.buildURL(shareLink, shareData);
     a.click();
   }
 }
diff --git a/src/modules/esl-share/actions/media-action.ts b/src/modules/esl-share/actions/media-action.ts
index 7ec39f82a..aa6dbebc5 100644
--- a/src/modules/esl-share/actions/media-action.ts
+++ b/src/modules/esl-share/actions/media-action.ts
@@ -2,15 +2,18 @@ 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 */
+/**
+ * Share using nested window with social media url {@link ESLShareBaseAction} implementation.
+ * Applicable to the most of social media (e.g. Twitter, Facebook, LinkedIn, etc.)
+ */
 @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.
+   * Window features that are applicable to window.open()
+   * include options such as the default size and position of the window,
+   * whether to open a minimal popup window, and more.
    * */
   public static FEATURES: Record<string, number> = {
     scrollbars: 0,
@@ -30,11 +33,11 @@ export class ESLShareMediaAction extends ESLShareUrlGenericAction {
   }
 
   /** Does an action to share */
-  public share($button: ESLShareButton): void {
-    const {link} = $button;
-    if (!link) return;
+  public override share($button: ESLShareButton): void {
+    const {shareLink} = $button;
+    if (!shareLink) return;
 
     const shareData = this.getShareData($button);
-    window.open(this.buildURL(link, shareData), '_blank', this.windowFeatures);
+    window.open(this.buildURL(shareLink, shareData), '_blank', this.windowFeatures);
   }
 }
diff --git a/src/modules/esl-share/actions/native-action.ts b/src/modules/esl-share/actions/native-action.ts
index a5d2cb9bf..050d49471 100644
--- a/src/modules/esl-share/actions/native-action.ts
+++ b/src/modules/esl-share/actions/native-action.ts
@@ -2,7 +2,9 @@ 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 */
+/**
+ * {@link ESLShareBaseAction} implementation, that invokes the native sharing mechanism of Web Share API
+ */
 @ESLShareBaseAction.register
 export class ESLShareNativeAction extends ESLShareBaseAction {
   public static override readonly is: string = 'native';
@@ -13,7 +15,7 @@ export class ESLShareNativeAction extends ESLShareBaseAction {
   }
 
   /** Does an action to share */
-  public share($button: ESLShareButton): void {
+  public override share($button: ESLShareButton): void {
     if (!this.isAvailable) return;
 
     const shareData = this.getShareData($button);
diff --git a/src/modules/esl-share/actions/print-action.ts b/src/modules/esl-share/actions/print-action.ts
index 773c097c5..7ee80407b 100644
--- a/src/modules/esl-share/actions/print-action.ts
+++ b/src/modules/esl-share/actions/print-action.ts
@@ -1,14 +1,12 @@
 import {ESLShareBaseAction} from '../core/esl-share-action';
 
-import type {ESLShareButton} from '../core/esl-share-button';
-
-/** Print action class for share buttons {@link ESLShareButton} */
+/** Print action {@link ESLShareBaseAction} implementation */
 @ESLShareBaseAction.register
 export class ESLSharePrintAction extends ESLShareBaseAction {
   public static override readonly is: string = 'print';
 
   /** Does an action to share */
-  public share($button: ESLShareButton): void {
+  public override share(): 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
index d6ac20cce..968c091a4 100644
--- a/src/modules/esl-share/actions/url-generic-action.ts
+++ b/src/modules/esl-share/actions/url-generic-action.ts
@@ -1,7 +1,9 @@
 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} */
+/**
+ * Base {@link ESLShareBaseAction} implementation for actions, that use URL-based sharing mechanism
+ */
 export abstract class ESLShareUrlGenericAction extends ESLShareBaseAction {
 
   protected getFormatSource(shareData: ShareData): Record<string, string> {
diff --git a/src/modules/esl-share/buttons/all.ts b/src/modules/esl-share/buttons/all.ts
new file mode 100644
index 000000000..f8c3a53f3
--- /dev/null
+++ b/src/modules/esl-share/buttons/all.ts
@@ -0,0 +1,20 @@
+import './blogger';
+import './copy';
+import './facebook';
+import './hatena';
+import './kakao';
+import './line';
+import './linkedin';
+import './mail';
+import './mix';
+import './mixi';
+import './myspace';
+import './native-share';
+import './pinterest';
+import './print';
+import './pusha';
+import './reddit';
+import './sina-weibo';
+import './telegram';
+import './twitter';
+import './wykop';
diff --git a/src/modules/esl-share/buttons/blogger.ts b/src/modules/esl-share/buttons/blogger.ts
new file mode 100644
index 000000000..cde7e4459
--- /dev/null
+++ b/src/modules/esl-share/buttons/blogger.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const blogger: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #f57d00;" viewBox="0 0 32 32"><path d="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="evenodd"/></svg>',
+  link: '//blogger.com/blog-this.g?n={t}&u={u}',
+  name: 'blogger',
+  title: 'Blogger'
+};
+ESLShareConfig.append(blogger);
diff --git a/src/modules/esl-share/buttons/copy.ts b/src/modules/esl-share/buttons/copy.ts
new file mode 100644
index 000000000..217647599
--- /dev/null
+++ b/src/modules/esl-share/buttons/copy.ts
@@ -0,0 +1,17 @@
+/* eslint-disable max-len */
+import '../actions/copy-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const copy: ESLShareButtonConfig = {
+  action: 'copy',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #a0522d;" viewBox="0 0 28 28"><path d="M17 9.69l-7.43 7.43 1.18 1.18 7.43-7.43L17 9.69z"/><path d="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"/></svg>',
+  link: '',
+  name: 'copy',
+  title: 'Copy',
+  additional: {
+    alertText: 'Copied to clipboard'
+  }
+};
+ESLShareConfig.append(copy);
diff --git a/src/modules/esl-share/buttons/facebook.ts b/src/modules/esl-share/buttons/facebook.ts
new file mode 100644
index 000000000..e25dcebd6
--- /dev/null
+++ b/src/modules/esl-share/buttons/facebook.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const facebook: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #3c5996;" viewBox="0 0 27.99 28"><path d="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"/></svg>',
+  link: '//www.facebook.com/sharer.php?u={u}',
+  name: 'facebook',
+  title: 'Facebook'
+};
+ESLShareConfig.append(facebook);
diff --git a/src/modules/esl-share/buttons/hatena.ts b/src/modules/esl-share/buttons/hatena.ts
new file mode 100644
index 000000000..19ec1d0a1
--- /dev/null
+++ b/src/modules/esl-share/buttons/hatena.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const hatena: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #08aed9;" viewBox="0 0 32 32"><path d="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"/><circle cx="23" cy="21.53" r="2.04"/></svg>',
+  link: '//b.hatena.ne.jp/entry/panel/?url={u}&btitle={t}',
+  name: 'hatena',
+  title: 'Hatena'
+};
+ESLShareConfig.append(hatena);
diff --git a/src/modules/esl-share/buttons/kakao.ts b/src/modules/esl-share/buttons/kakao.ts
new file mode 100644
index 000000000..92c0a745d
--- /dev/null
+++ b/src/modules/esl-share/buttons/kakao.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const kakao: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #fab900;" viewBox="0 0 32 32"><path d="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="evenodd"/></svg>',
+  link: '//story.kakao.com/share?url={u}',
+  name: 'kakao',
+  title: 'Kakao'
+};
+ESLShareConfig.append(kakao);
diff --git a/src/modules/esl-share/buttons/line.ts b/src/modules/esl-share/buttons/line.ts
new file mode 100644
index 000000000..a43544d1c
--- /dev/null
+++ b/src/modules/esl-share/buttons/line.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const line: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #00b900;" viewBox="0 0 32 32"><path d="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="evenodd"/></svg>',
+  link: '//social-plugins.line.me/lineit/share?url={u}',
+  name: 'line',
+  title: 'LINE'
+};
+ESLShareConfig.append(line);
diff --git a/src/modules/esl-share/buttons/linkedin.ts b/src/modules/esl-share/buttons/linkedin.ts
new file mode 100644
index 000000000..9582c2c4e
--- /dev/null
+++ b/src/modules/esl-share/buttons/linkedin.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const linkedin: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #0b77b3;" 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"/></svg>',
+  link: '//www.linkedin.com/sharing/share-offsite/?url={u}',
+  name: 'linkedin',
+  title: 'LinkedIn'
+};
+ESLShareConfig.append(linkedin);
diff --git a/src/modules/esl-share/buttons/mail.ts b/src/modules/esl-share/buttons/mail.ts
new file mode 100644
index 000000000..9f83f3875
--- /dev/null
+++ b/src/modules/esl-share/buttons/mail.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/external-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const mail: ESLShareButtonConfig = {
+  action: 'external',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #ff1493;" viewBox="0 0 28 28"><path d="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"/></svg>',
+  link: 'mailto:?subject={title}&body={url}',
+  name: 'mail',
+  title: 'Mail'
+};
+ESLShareConfig.append(mail);
diff --git a/src/modules/esl-share/buttons/mix.ts b/src/modules/esl-share/buttons/mix.ts
new file mode 100644
index 000000000..17c6ae85e
--- /dev/null
+++ b/src/modules/esl-share/buttons/mix.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const mix: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #eb4924;" viewBox="0 0 32 32"><path d="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=".8"/><path d="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"/></svg>',
+  link: '//mix.com/add?url={u}',
+  name: 'mix',
+  title: 'MIX'
+};
+ESLShareConfig.append(mix);
diff --git a/src/modules/esl-share/buttons/mixi.ts b/src/modules/esl-share/buttons/mixi.ts
new file mode 100644
index 000000000..dfcfd583c
--- /dev/null
+++ b/src/modules/esl-share/buttons/mixi.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const mixi: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #cfab59;" viewBox="0 0 32 32"><path d="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"/></svg>',
+  link: '//mixi.jp/share.pl?u={u}',
+  name: 'mixi',
+  title: 'Mixi'
+};
+ESLShareConfig.append(mixi);
diff --git a/src/modules/esl-share/buttons/myspace.ts b/src/modules/esl-share/buttons/myspace.ts
new file mode 100644
index 000000000..ecbb03d4c
--- /dev/null
+++ b/src/modules/esl-share/buttons/myspace.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const myspace: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #282828;" viewBox="0 0 32 32"><path d="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="evenodd"/></svg>',
+  link: '//myspace.com/post?u={u}',
+  name: 'myspace',
+  title: 'Myspace'
+};
+ESLShareConfig.append(myspace);
diff --git a/src/modules/esl-share/buttons/native-share.ts b/src/modules/esl-share/buttons/native-share.ts
new file mode 100644
index 000000000..9fd1fbb29
--- /dev/null
+++ b/src/modules/esl-share/buttons/native-share.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/native-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const nativeShare: ESLShareButtonConfig = {
+  action: 'native',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #ff6347;" viewBox="0 0 24 24"><path d="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"/></svg>',
+  link: '',
+  name: 'native-share',
+  title: 'Share page'
+};
+ESLShareConfig.append(nativeShare);
diff --git a/src/modules/esl-share/buttons/pinterest.ts b/src/modules/esl-share/buttons/pinterest.ts
new file mode 100644
index 000000000..54eec1890
--- /dev/null
+++ b/src/modules/esl-share/buttons/pinterest.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const pinterest: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #e60023;" viewBox="0 0 24 24"><path d="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"/></svg>',
+  link: '//www.pinterest.com/pin/create/button/?url={u}&description={t}',
+  name: 'pinterest',
+  title: 'Pinterest'
+};
+ESLShareConfig.append(pinterest);
diff --git a/src/modules/esl-share/buttons/print.ts b/src/modules/esl-share/buttons/print.ts
new file mode 100644
index 000000000..5724ce17a
--- /dev/null
+++ b/src/modules/esl-share/buttons/print.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/print-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const print: ESLShareButtonConfig = {
+  action: 'print',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #2f4f4f;" viewBox="0 0 247.1 247.1"><path d="M75.4 175.5h97v6.5h-97zM75.4 194.9h97v6.5h-97z" fill="#fff"/><circle stroke-width="2" stroke-miterlimit="10" cx="178.9" cy="117.3" r="6.5" fill="#fff"/><path d="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"/></svg>',
+  link: '',
+  name: 'print',
+  title: 'Print page'
+};
+ESLShareConfig.append(print);
diff --git a/src/modules/esl-share/buttons/pusha.ts b/src/modules/esl-share/buttons/pusha.ts
new file mode 100644
index 000000000..9fa2c9df3
--- /dev/null
+++ b/src/modules/esl-share/buttons/pusha.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const pusha: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #0878ba;" viewBox="0 0 32 32"><path d="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"/></svg>',
+  link: '//www.pusha.se/posta?url={u}&title={t}',
+  name: 'pusha',
+  title: 'Pusha'
+};
+ESLShareConfig.append(pusha);
diff --git a/src/modules/esl-share/buttons/reddit.ts b/src/modules/esl-share/buttons/reddit.ts
new file mode 100644
index 000000000..806b4f2d7
--- /dev/null
+++ b/src/modules/esl-share/buttons/reddit.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const reddit: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #ff5700;" viewBox="0 0 32 32"><path d="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="evenodd"/></svg>',
+  link: '//www.reddit.com/submit?url={u}&title={t}',
+  name: 'reddit',
+  title: 'Reddit'
+};
+ESLShareConfig.append(reddit);
diff --git a/src/modules/esl-share/buttons/sina-weibo.ts b/src/modules/esl-share/buttons/sina-weibo.ts
new file mode 100644
index 000000000..789220240
--- /dev/null
+++ b/src/modules/esl-share/buttons/sina-weibo.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const sinaWeibo: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #e6162d;" viewBox="0 0 32 32"><path d="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"/><path d="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"/></svg>',
+  link: '//service.weibo.com/share/share.php?url={u}&title={t}',
+  name: 'sina-weibo',
+  title: 'Sina Weibo'
+};
+ESLShareConfig.append(sinaWeibo);
diff --git a/src/modules/esl-share/buttons/telegram.ts b/src/modules/esl-share/buttons/telegram.ts
new file mode 100644
index 000000000..bbc00323c
--- /dev/null
+++ b/src/modules/esl-share/buttons/telegram.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const telegram: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #61a8de;" viewBox="0 0 455.731 455.731"><path d="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"/></svg>',
+  link: '//t.me/share/url?url={u}&text={t}',
+  name: 'telegram',
+  title: 'Telegram'
+};
+ESLShareConfig.append(telegram);
diff --git a/src/modules/esl-share/buttons/twitter.ts b/src/modules/esl-share/buttons/twitter.ts
new file mode 100644
index 000000000..ffc43b6a7
--- /dev/null
+++ b/src/modules/esl-share/buttons/twitter.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const twitter: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #000;" viewBox="0 0 28 28"><path d="M20.2,4.3h3.3l-7.2,8.3l8.5,11.2h-6.7L13,16.9l-6,6.8H3.7l7.7-8.8L3.3,4.3h6.8l4.7,6.2L20.2,4.3z M19.1,21.8 h1.8L9.1,6.1h-2L19.1,21.8z"/></svg>',
+  link: '//twitter.com/intent/tweet?text={t}&url={u}',
+  name: 'twitter',
+  title: 'X'
+};
+ESLShareConfig.append(twitter);
diff --git a/src/modules/esl-share/buttons/wykop.ts b/src/modules/esl-share/buttons/wykop.ts
new file mode 100644
index 000000000..e960e1069
--- /dev/null
+++ b/src/modules/esl-share/buttons/wykop.ts
@@ -0,0 +1,14 @@
+/* eslint-disable max-len */
+import '../actions/media-action';
+import {ESLShareConfig} from '../core/esl-share-config';
+
+import type {ESLShareButtonConfig} from '../core/esl-share-config';
+
+export const wykop: ESLShareButtonConfig = {
+  action: 'media',
+  icon: '<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" fill="#fff" focusable="false" role="presentation" style="background: #fb803f;" viewBox="0 0 32 32"><path d="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" fill="#fff"/><path d="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"/></svg>',
+  link: '//www.wykop.pl/dodaj?url={u}&title={t}',
+  name: 'wykop',
+  title: 'Wykop'
+};
+ESLShareConfig.append(wykop);
diff --git a/src/modules/esl-share/core.less b/src/modules/esl-share/core.less
index c0270e1ab..28f98e2a2 100644
--- a/src/modules/esl-share/core.less
+++ b/src/modules/esl-share/core.less
@@ -1,3 +1,3 @@
 @import './core/esl-share-button.less';
-@import './core/esl-share-trigger.less';
-@import './core/esl-share.less';
+@import './core/esl-share-list.less';
+@import './core/esl-share-popup-trigger.less';
diff --git a/src/modules/esl-share/core.ts b/src/modules/esl-share/core.ts
index 45e215bd5..3dd93ce94 100644
--- a/src/modules/esl-share/core.ts
+++ b/src/modules/esl-share/core.ts
@@ -2,4 +2,7 @@ export * from './core/esl-share';
 export * from './core/esl-share-action';
 export * from './core/esl-share-action-registry';
 export * from './core/esl-share-button';
-export * from './core/esl-share-trigger';
+export * from './core/esl-share-config';
+export * from './core/esl-share-list';
+export * from './core/esl-share-popup';
+export * from './core/esl-share-popup-trigger';
diff --git a/src/modules/esl-share/core/esl-share-action-registry.ts b/src/modules/esl-share/core/esl-share-action-registry.ts
index cc8ae978b..bb793d48a 100644
--- a/src/modules/esl-share/core/esl-share-action-registry.ts
+++ b/src/modules/esl-share/core/esl-share-action-registry.ts
@@ -16,9 +16,11 @@ export class ESLShareActionRegistry {
     return new ESLShareActionRegistry();
   }
 
+  protected constructor() {}
+
   /** Registers action */
   public register(action: ESLShareActionType): void {
-    if (!action.is) throw new Error('Action should have a name');
+    if (!action.is) throw new Error('[ESL]: `ESLAction.is` is not defined');
     this.actionsMap.set(action.is, new action());
   }
 
@@ -35,7 +37,7 @@ export class ESLShareActionRegistry {
 
   /** Does the share action on passed Share button {@link ESLShareButton} */
   public share(button: ESLShareButton): void {
-    const action = this.get(button.action);
+    const action = this.get(button.shareAction);
     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
index e8dfbe9aa..1b7251a1e 100644
--- a/src/modules/esl-share/core/esl-share-action.ts
+++ b/src/modules/esl-share/core/esl-share-action.ts
@@ -5,7 +5,7 @@ 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} */
+/** Base action class/interface for actions that ESLShare widgets can invoke. */
 export abstract class ESLShareBaseAction {
   public static readonly is: string;
 
diff --git a/src/modules/esl-share/core/esl-share-button.less b/src/modules/esl-share/core/esl-share-button.less
index 884e0fdce..ccd91530c 100644
--- a/src/modules/esl-share/core/esl-share-button.less
+++ b/src/modules/esl-share/core/esl-share-button.less
@@ -1,7 +1,5 @@
 esl-share-button {
   display: inline-block;
-  width: 40px;
-  height: 40px;
   cursor: pointer;
 
   &:hover {
@@ -15,8 +13,7 @@ esl-share-button {
   .esl-share-icon {
     display: inline-block;
     overflow: hidden;
-    background-color: #0097e7; // TODO: consider creating common variables.less file
-    width: 100%;
-    height: 100%;
+    width: var(--esl-share-icon-size, 40px);
+    height: var(--esl-share-icon-size, 40px);
   }
 }
diff --git a/src/modules/esl-share/core/esl-share-button.shape.ts b/src/modules/esl-share/core/esl-share-button.shape.ts
index 9c2f71476..d5fc45f0b 100644
--- a/src/modules/esl-share/core/esl-share-button.shape.ts
+++ b/src/modules/esl-share/core/esl-share-button.shape.ts
@@ -18,6 +18,8 @@ export interface ESLShareButtonTagShape extends ESLBaseElementShape<ESLShareButt
   'share-url'?: string;
   /** Define title to share (current document title by default) */
   'share-title'?: string;
+  /** Marker to render default icon inside button on init */
+  'default-icon'?: boolean;
 
   /** Allowed children */
   children?: any;
diff --git a/src/modules/esl-share/core/esl-share-button.ts b/src/modules/esl-share/core/esl-share-button.ts
index 468cb0e34..17188b9fa 100644
--- a/src/modules/esl-share/core/esl-share-button.ts
+++ b/src/modules/esl-share/core/esl-share-button.ts
@@ -1,20 +1,36 @@
 import {ESLBaseElement} from '../../esl-base-element/core';
-import {attr, boolAttr, jsonAttr, listen} from '../../esl-utils/decorators';
+import {attr, boolAttr, jsonAttr, listen, memoize, prop} from '../../esl-utils/decorators';
 import {ENTER, SPACE} from '../../esl-utils/dom/keys';
+import {isEqual} from '../../esl-utils/misc/object/compare';
 import {toAbsoluteUrl} from '../../esl-utils/misc/url';
 import {ESLShareActionRegistry} from './esl-share-action-registry';
+import {ESLShareConfig} from './esl-share-config';
 
 import type {ESLShareBaseAction} from './esl-share-action';
+import type {ESLShareButtonConfig} from './esl-share-config';
 
 /**
  * ESLShareButton
  * @author Dmytro Shovchko
  *
- * ESLShareButton is a custom element to create a "Share on social media" button.
+ * ESLShareButton is a custom element to invoke a share actions, defined by {@link ESLShareBaseAction}
  */
 export class ESLShareButton extends ESLBaseElement {
   public static override is = 'esl-share-button';
-  public static observedAttributes = ['action'];
+  public static observedAttributes = ['action', 'name'];
+
+  /** Creates an instance of the ESLShareButton */
+  public static override create<T extends typeof ESLShareButton>(this: T, buttonName?: string): InstanceType<T> {
+    const $button = document.createElement(this.is) as InstanceType<T>;
+    if (buttonName) {
+      $button.name = buttonName;
+      $button.initIcon();
+    }
+    return $button;
+  }
+
+  /** Event to dispatch when {@link ESLShareButton} configuration is changed */
+  @prop('esl:share:button:changed') public SHARE_BUTTON_CHANGED_EVENT: string;
 
   /** Name of share action that occurs after button click */
   @attr() public action: string;
@@ -31,11 +47,51 @@ export class ESLShareButton extends ESLBaseElement {
   /** Additional params to pass into a button (can be used by share actions) */
   @jsonAttr() public additional: Record<string, any>;
 
+  /** Marker to render default icon inside button on init */
+  @boolAttr() public defaultIcon: boolean;
+
   /** Marker of availability of share button */
   @boolAttr() public unavailable: boolean;
 
+  /** @readonly Ready state marker */
+  @boolAttr({readonly: true}) public readonly ready: boolean;
+
+  /** @returns config of button specified by the name attribute */
+  @memoize()
+  public get config(): ESLShareButtonConfig | undefined {
+    return ESLShareConfig.instance.getButton(this.name);
+  }
+
+  /** Gets a property from attribute, or from button config if not set attribute */
+  protected get(name: 'action' | 'link'): string;
+  protected get(name: 'additional'): Record<string, any>;
+  protected get(name: 'action' | 'link' | 'additional'): string | Record<string, any> {
+    if (name === 'additional') {
+      // for object props
+      return Object.keys(this[name]).length ? this[name] : this.config?.[name] || {};
+    }
+    // for string props
+    return this[name] || this.config?.[name] || '';
+  }
+
+  /** @returns an instance of {@link ESLShareBaseAction} assigned to the button */
   protected get actionInstance(): ESLShareBaseAction | null {
-    return ESLShareActionRegistry.instance.get(this.action);
+    return ESLShareActionRegistry.instance.get(this.shareAction);
+  }
+
+  /** @returns name of action assigned to the button */
+  public get shareAction(): string {
+    return this.get('action');
+  }
+
+  /** @returns additional params assigned to the button */
+  public get shareAdditional(): Record<string, any> {
+    return this.get('additional');
+  }
+
+  /** @returns link to share on social network  */
+  public get shareLink(): string {
+    return this.get('link');
   }
 
   /** @returns title to share */
@@ -51,31 +107,59 @@ export class ESLShareButton extends ESLBaseElement {
   protected override attributeChangedCallback(attrName: string, oldVal: string, newVal: string): void {
     if (!this.connected || oldVal === newVal) return;
     if (attrName === 'action') this.updateAction();
+    if (attrName === 'name') this.updateName();
   }
 
   protected override connectedCallback(): void {
     super.connectedCallback();
+    this.init();
+  }
+
+  /** Initializes the button */
+  protected init(force?: boolean): void {
+    if (this.ready && !force) return;
+
+    if (this.defaultIcon) this.initIcon();
     this.initA11y();
     this.updateAction();
+    this.$$attr('ready', true);
   }
 
   /** Sets initial a11y attributes */
   protected initA11y(): void {
     if (!this.hasAttribute('role')) this.setAttribute('role', 'button');
-    if (this.getAttribute('role') === 'button' && !this.hasAttribute('tabindex')) {
+    if (!this.hasAttribute('tabindex') && this.getAttribute('role') === 'button') {
       this.tabIndex = 0;
     }
   }
 
+  /** Initializes the button content */
+  protected initIcon(): void {
+    if (!this.config) return;
+    const {title, icon} = this.config;
+    this.title = title;
+    this.innerHTML = icon || '';
+    const $icon = this.firstElementChild as HTMLElement;
+    if ($icon?.tagName !== 'svg') return;
+    $icon.classList.add('esl-share-icon');
+  }
+
   /** Does an action to share */
   public share(): void {
     this.actionInstance?.share(this);
   }
 
+  /** Updates on button action change */
   protected updateAction(): void {
     this.$$attr('unavailable', !this.actionInstance?.isAvailable);
   }
 
+  /** Updates on button name change */
+  protected updateName(): void {
+    memoize.clear(this, 'config');
+    this.updateAction();
+  }
+
   /** Gets attribute from the element or closest parent,
    *  returns fallback value in the case when an element with attribute not found */
   protected getShareAttr(name: string, fallback: string): string {
@@ -95,4 +179,13 @@ export class ESLShareButton extends ESLBaseElement {
       e.preventDefault();
     }
   }
+
+  @listen({event: 'change', target: ESLShareConfig.instance})
+  protected _onConfigChange(): void {
+    const {config} = this;
+    memoize.clear(this, 'config');
+    if (isEqual(this.config, config)) return;
+    this.init(true);
+    this.$$fire(this.SHARE_BUTTON_CHANGED_EVENT, {bubbles: false});
+  }
 }
diff --git a/src/modules/esl-share/core/esl-share-config.ts b/src/modules/esl-share/core/esl-share-config.ts
index 9924f6854..7b339a1c8 100644
--- a/src/modules/esl-share/core/esl-share-config.ts
+++ b/src/modules/esl-share/core/esl-share-config.ts
@@ -1,14 +1,17 @@
-/** {@link ESLShareConfig} provider type definition */
-export type ESLShareConfigProviderType = () => Promise<ESLShareConfig>;
+import {decorate, memoize} from '../../esl-utils/decorators';
+import {microtask} from '../../esl-utils/async/microtask';
+import {isObject} from '../../esl-utils/misc/object/types';
+import {uniq} from '../../esl-utils/misc/array';
+import {SyntheticEventTarget} from '../../esl-utils/dom/events/target';
+
+import type {PropertyProvider} from '../../esl-utils/misc/functions';
 
 /** The definition of the sharing button */
 export interface ESLShareButtonConfig {
   /** 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;
+  icon?: 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)
@@ -31,32 +34,140 @@ export interface ESLShareGroupConfig {
   list: string;
 }
 
-/** The definition of `ESLShare` component configuration */
-export interface ESLShareConfig {
-  /** List of sharing buttons configuration */
-  buttons: ESLShareButtonConfig[];
-  /** List of share button groups configurations */
-  groups: ESLShareGroupConfig[];
+/** Object containing {@link ESLShareButtonConfig} and {@link ESLShareGroupConfig} definitions */
+export interface ESLShareConfigInit {
+  /** List of share buttons configurations */
+  buttons?: ESLShareButtonConfig[];
+  /** List of share buttons groups configurations */
+  groups?: ESLShareGroupConfig[];
 }
 
-function getConfigSectionItem<T extends ESLShareButtonConfig | ESLShareGroupConfig>(section: T[], name: string): T | undefined {
-  return section.find((item) => item.name === name);
-}
+const isNamedObject = (obj: any): obj is Record<string, any> & {name: string} => isObject(obj) && typeof obj.name === 'string';
+const isGroupCfg = (cfg: any): cfg is ESLShareGroupConfig => isNamedObject(cfg) && typeof cfg.list === 'string';
+const isButtonCfg = (cfg: any): cfg is ESLShareButtonConfig => isNamedObject(cfg) && typeof cfg.action === 'string';
+
+/** Class for managing share buttons configurations */
+export class ESLShareConfig extends SyntheticEventTarget {
+  /** @returns ESLShareConfig shared instance */
+  @memoize()
+  public static get instance(): ESLShareConfig {
+    return new ESLShareConfig();
+  }
+
+  /**
+   * Updates the configuration with either a {@link ESLShareConfigInit} object or provider function.
+   * Every button and group specified in the new config will be added to the current configuration.
+   * @returns ESLShareConfig instance
+   */
+  public static set(cfg: ESLShareConfigInit | PropertyProvider<ESLShareConfigInit>): ESLShareConfig;
+  /**
+   * Updates the configuration with promise resolved to {@link ESLShareConfigInit} or promise provider function.
+   * Every button and group specified in the new config will be added to the current configuration.
+   * @returns Promise<ESLShareConfig> instance
+   */
+  public static set(
+    provider: Promise<Partial<ESLShareConfig>> | PropertyProvider<Promise<ESLShareConfigInit>>
+  ): Promise<ESLShareConfig>;
+  public static set(provider: any): ESLShareConfig | Promise<ESLShareConfig> {
+    if (typeof provider === 'function') return this.set(provider());
+    if (!isObject(provider)) return ESLShareConfig.instance;
+    if (provider instanceof Promise) return provider.then((cfg: ESLShareConfigInit) => this.set(cfg));
+    if (Array.isArray(provider.groups)) ESLShareConfig.instance.append(provider.groups);
+    if (Array.isArray(provider.buttons)) ESLShareConfig.instance.append(provider.buttons);
+    return ESLShareConfig.instance;
+  }
+
+  /** Appends single button or group to current configuration */
+  public static append(cfg: ESLShareButtonConfig | ESLShareGroupConfig | ESLShareButtonConfig[] | ESLShareGroupConfig[]): ESLShareConfig {
+    return ESLShareConfig.instance.append(cfg);
+  }
+
+  protected readonly _groups: Map<string, string> = new Map();
+  protected readonly _buttons: Map<string, ESLShareButtonConfig> = new Map();
+
+  protected constructor() {
+    super();
+  }
 
-/**
- * Selects the buttons for the given list and returns their configuration.
- * @returns config of buttons
- */
-export function selectButtonsForList(config: ESLShareConfig, list: string): ESLShareButtonConfig[] {
-  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(selectButtonsForList(config, groupConfig.list));
+  /** @returns list of all available groups */
+  public get groups(): ESLShareGroupConfig[] {
+    return Array.from(this._groups.entries()).map(([name, list]) => ({name, list}));
+  }
+
+  /** @returns list of all available buttons */
+  public get buttons(): ESLShareButtonConfig[] {
+    return Array.from(this._buttons.values());
+  }
+
+  /** Normalize list string by removing groups and extra whitespaces */
+  protected resolve(query: string): string[] {
+    if (/\sall\s/.test(query)) return Array.from(this._buttons.keys());
+    const groups = new Set<string>(); // Deduplicate groups
+    while (query.includes('group:')) {
+      query = query.replace(/group:(\S+)/gi, (term: string, name: string) => {
+        if (groups.has(name)) return '';
+        groups.add(name);
+        return this._groups.get(name) || '';
+      });
+    }
+    return query.split(' ').filter(Boolean);
+  }
+
+  /**
+   * Selects the buttons for the given list and returns their configuration.
+   * @returns config of buttons
+   */
+  public get(query: string): ESLShareButtonConfig[] {
+    const terms = this.resolve(query);
+    if (terms.includes('all')) return this.buttons;
+    const list = terms.map((name) => this.getButton(name));
+    return uniq(list.filter(Boolean) as ESLShareButtonConfig[]);
+  }
+
+  /** Clears the configuration */
+  public clear(): ESLShareConfig {
+    this._buttons.clear();
+    this._groups.clear();
+    this._onUpdate();
+    return this;
+  }
+
+  /**
+   * Gets the group of buttons configuration.
+   * @returns config of group
+   */
+  public getGroup(name: string): ESLShareGroupConfig | undefined {
+    const list = this._groups.get(name);
+    return list ? {name, list} : undefined;
+  }
+
+  /**
+   * Gets the button configuration.
+   * @returns config of button
+   */
+  public getButton(name: string): ESLShareButtonConfig | undefined {
+    return this._buttons.get(name);
+  }
+
+  /** Updates the configuration with a {@link ESLShareButtonConfig} or {@link ESLShareGroupConfig} */
+  protected add(config: ESLShareButtonConfig | ESLShareGroupConfig): void {
+    if (isGroupCfg(config)) this._groups.set(config.name, config.list);
+    if (isButtonCfg(config)) this._buttons.set(config.name, config);
+  }
+
+  /** Updates the configuration with a {@link ESLShareButtonConfig}(s) or {@link ESLShareGroupConfig}(s) */
+  public append(config: ESLShareButtonConfig | ESLShareGroupConfig | ESLShareButtonConfig[] | ESLShareGroupConfig[]): ESLShareConfig {
+    if (Array.isArray(config)) {
+      config.forEach(this.add, this);
     } else {
-      const btnConfig = getConfigSectionItem(config.buttons, btnName);
-      if (btnConfig) res.push(btnConfig);
+      this.add(config);
     }
-    return res;
-  }, [] as ESLShareButtonConfig[]);
+    this._onUpdate();
+    return this;
+  }
+
+  @decorate(microtask)
+  protected _onUpdate(): void {
+    this.dispatchEvent(new CustomEvent('change'));
+  }
 }
diff --git a/src/modules/esl-share/core/esl-share.less b/src/modules/esl-share/core/esl-share-list.less
similarity index 64%
rename from src/modules/esl-share/core/esl-share.less
rename to src/modules/esl-share/core/esl-share-list.less
index dc04f8478..556807cbe 100644
--- a/src/modules/esl-share/core/esl-share.less
+++ b/src/modules/esl-share/core/esl-share-list.less
@@ -1,4 +1,4 @@
-esl-share[mode='list'] {
+esl-share-list {
   display: inline-flex;
   flex-wrap: wrap;
 }
diff --git a/src/modules/esl-share/core/esl-share-list.shape.ts b/src/modules/esl-share/core/esl-share-list.shape.ts
new file mode 100644
index 000000000..a194dfa26
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-list.shape.ts
@@ -0,0 +1,27 @@
+import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
+import type {ESLShareList} from './esl-share-list';
+
+/**
+ * Tag declaration interface of ESLShareList element
+ * Used for TSX declaration
+ */
+export interface ESLShareListTagShape extends ESLBaseElementShape<ESLShareList> {
+  /** Define the list of social networks or groups of them to display (all by default) */
+  list?: 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 ESLShareList */
+  children?: never[];
+}
+
+declare global {
+  namespace JSX {
+    export interface IntrinsicElements {
+      /** {@link ESLShareList} custom tag */
+      'esl-share-list': ESLShareListTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-list.ts b/src/modules/esl-share/core/esl-share-list.ts
new file mode 100644
index 000000000..167b44992
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-list.ts
@@ -0,0 +1,78 @@
+import {ESLBaseElement} from '../../esl-base-element/core';
+import {isEqual} from '../../esl-utils/misc/object/compare';
+import {attr, boolAttr, listen, memoize, prop} from '../../esl-utils/decorators';
+import {ESLShareButton} from './esl-share-button';
+import {ESLShareConfig} from './esl-share-config';
+
+import type {ESLShareButtonConfig} from './esl-share-config';
+
+/**
+ * ESLShareList
+ * @author Dmytro Shovchko
+ *
+ * ESLShareList is a custom element to dynamically draw {@link ESLShareButton}s using simplified shared config
+ */
+export class ESLShareList extends ESLBaseElement {
+  public static override is = 'esl-share-list';
+
+  /** Register {@link ESLShareList} component and dependent {@link ESLShareButton} */
+  public static override register(): void {
+    ESLShareButton.register();
+    super.register();
+  }
+
+  /** Event to dispatch on change of {@link ESLShareList} */
+  @prop('esl:share:changed') public SHARE_CHANGED_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;
+
+  /** @readonly Ready state marker */
+  @boolAttr({readonly: true}) public ready: boolean;
+
+  /** @returns config of buttons specified by the list attribute */
+  @memoize()
+  public get buttonsConfig(): ESLShareButtonConfig[] {
+    return ESLShareConfig.instance.get(this.list);
+  }
+
+  public override connectedCallback(): void {
+    super.connectedCallback();
+    this.init();
+  }
+
+  /** Initializes the component */
+  protected init(force?: boolean): void {
+    if (this.ready && !force) return;
+    this.buildContent();
+    this.onReady();
+  }
+
+  /** Appends buttons to the component. */
+  protected buildContent(): void {
+    this.innerHTML = '';
+    this.buttonsConfig.forEach((cfg) => {
+      const btn = ESLShareButton.create(cfg.name);
+      btn && this.appendChild(btn);
+    });
+  }
+
+  /** Actions on complete init and ready component. */
+  private onReady(): void {
+    this.$$attr('ready', true);
+    this.$$fire(this.SHARE_CHANGED_EVENT, {bubbles: false});
+  }
+
+  @listen({event: 'change', target: ESLShareConfig.instance})
+  protected _onConfigChange(): void {
+    const {buttonsConfig} = this;
+    memoize.clear(this, 'buttonsConfig');
+    if (isEqual(this.buttonsConfig, buttonsConfig)) return;
+    this.init(true);
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-trigger.less b/src/modules/esl-share/core/esl-share-popup-trigger.less
similarity index 63%
rename from src/modules/esl-share/core/esl-share-trigger.less
rename to src/modules/esl-share/core/esl-share-popup-trigger.less
index e7e0a6e68..cd5d88d10 100644
--- a/src/modules/esl-share/core/esl-share-trigger.less
+++ b/src/modules/esl-share/core/esl-share-popup-trigger.less
@@ -1,4 +1,4 @@
-esl-share-trigger {
+esl-share-popup-trigger {
   display: inline-block;
   cursor: pointer;
 }
diff --git a/src/modules/esl-share/core/esl-share-popup-trigger.shape.ts b/src/modules/esl-share/core/esl-share-popup-trigger.shape.ts
new file mode 100644
index 000000000..714315626
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-popup-trigger.shape.ts
@@ -0,0 +1,27 @@
+import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
+import type {ESLSharePopupTrigger} from './esl-share-popup-trigger';
+
+/**
+ * Tag declaration interface of ESLSharePopupTrigger element
+ * Used for TSX declaration
+ */
+export interface ESLSharePopupTriggerTagShape extends ESLBaseElementShape<ESLSharePopupTrigger> {
+  /** Define the list of social networks or groups of them to display at popup (all by default) */
+  list?: 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 ESLSharePopupTrigger} custom tag */
+      'esl-share-popup-trigger': ESLSharePopupTriggerTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-popup-trigger.ts b/src/modules/esl-share/core/esl-share-popup-trigger.ts
new file mode 100644
index 000000000..c778ed418
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-popup-trigger.ts
@@ -0,0 +1,100 @@
+import {attr, jsonAttr} from '../../esl-utils/decorators';
+import {ESLTraversingQuery} from '../../esl-traversing-query/core';
+import {ESLTrigger} from '../../esl-trigger/core';
+import {ESLSharePopup} from './esl-share-popup';
+
+import type {ESLToggleable} from '../../esl-toggleable/core/esl-toggleable';
+import type {ESLSharePopupActionParams} from './esl-share-popup';
+
+/**
+ * ESLSharePopupTrigger component
+ * @author Dmytro Shovchko
+ *
+ * ESLSharePopupTrigger is a component that allows triggering {@link ESLSharePopup} instance state changes.
+ */
+export class ESLSharePopupTrigger extends ESLTrigger {
+  public static override is = 'esl-share-popup-trigger';
+
+  /** Register {@link ESLSharePopupTrigger} component and dependent {@link ESLSharePopup} */
+  public static override register(): void {
+    ESLSharePopup.register();
+    super.register();
+  }
+
+  /**
+   * 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;
+
+  /** Hover event tracking media query. Default: `all` */
+  @attr({defaultValue: 'all'}) public override trackHover: string;
+
+  /** Default initial params to pass into the popup */
+  @jsonAttr<ESLSharePopupActionParams>({defaultValue: {
+    position: 'top',
+    hideDelay: 300
+  }})
+  public popupInitialParams: ESLSharePopupActionParams;
+
+  /** Target observable Toggleable */
+  public override get $target(): ESLToggleable | null {
+    return ESLSharePopup.sharedInstance;
+  }
+  public override set $target(value: any) {}
+
+  /** Checks that the target is in active state */
+  public override get isTargetActive(): boolean {
+    return !!this.$target?.open && this.$target?.activator === this;
+  }
+
+  /** The text writing directionality of the element */
+  protected get currentDir(): string {
+    return getComputedStyle(this).direction;
+  }
+
+  /** The base language of the element */
+  protected get currentLang(): string {
+    const el = this.closest('[lang]');
+    return (el) ? (el as HTMLElement).lang : '';
+  }
+
+  /** Container element that defines bounds of popups visibility */
+  protected get $containerEl(): HTMLElement | undefined {
+    const container = this.getClosestRelatedAttr('container');
+    return container ? ESLTraversingQuery.first(container, this) as HTMLElement : undefined;
+  }
+
+  /** Update `$target` Toggleable  from `target` selector */
+  public override updateTargetFromSelector(): void {}
+
+  /** Gets attribute value from the closest element with group behavior settings */
+  protected getClosestRelatedAttr(attrName: string): string | null {
+    const relatedAttrName = `${this.baseTagName}-${attrName}`;
+    const $closest = this.closest(`[${relatedAttrName}]`);
+    return $closest ? $closest.getAttribute(relatedAttrName) : null;
+  }
+
+  /** Merges params to pass to the toggleable */
+  protected override mergeToggleableParams(this: ESLSharePopupTrigger, ...params: ESLSharePopupActionParams[]): ESLSharePopupActionParams {
+    return Object.assign({
+      initiator: 'share',
+      activator: this,
+      containerEl: this.$containerEl,
+      list: this.list,
+      dir: this.currentDir,
+      lang: this.currentLang
+    }, this.popupInitialParams, ...params);
+  }
+}
+
+declare global {
+  export interface ESLLibrary {
+    SharePopupTrigger: typeof ESLSharePopupTrigger;
+  }
+  export interface HTMLElementTagNameMap {
+    'esl-share-popup-trigger': ESLSharePopupTrigger;
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-popup.shape.ts b/src/modules/esl-share/core/esl-share-popup.shape.ts
new file mode 100644
index 000000000..a14606a3d
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-popup.shape.ts
@@ -0,0 +1,20 @@
+import type {ESLTooltipTagShape} from '../../esl-tooltip/core/esl-tooltip.shape';
+import type {ESLSharePopup} from './esl-share-popup';
+
+/**
+ * Tag declaration interface of ESL Share Popup element
+ * Used for TSX declaration
+ */
+export interface ESLSharePopupTagShape extends ESLTooltipTagShape<ESLSharePopup> {
+  /** Allowed children */
+  children?: any;
+}
+
+declare global {
+  namespace JSX {
+    export interface IntrinsicElements {
+      /** {@link ESLSharePopup} custom tag */
+      'esl-share-popup': ESLSharePopupTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-popup.ts b/src/modules/esl-share/core/esl-share-popup.ts
new file mode 100644
index 000000000..0e273a9da
--- /dev/null
+++ b/src/modules/esl-share/core/esl-share-popup.ts
@@ -0,0 +1,111 @@
+import {ESLTooltip} from '../../esl-tooltip/core/esl-tooltip';
+import {bind, listen, memoize} from '../../esl-utils/decorators';
+import {ESLShareButton} from './esl-share-button';
+import {ESLShareConfig} from './esl-share-config';
+
+import type {ESLToggleableActionParams} from '../../esl-toggleable/core';
+import type {TooltipActionParams} from '../../esl-tooltip/core/esl-tooltip';
+import type {ESLShareButtonConfig} from './esl-share-config';
+
+function stringifyButtonsList(btns: ESLShareButtonConfig[]): string {
+  return btns.map((btn) => btn.name).join(',');
+}
+
+export interface ESLSharePopupActionParams extends TooltipActionParams {
+  /** list of social networks or groups of them to display */
+  list?: string;
+}
+
+/**
+ * ESLSharePopup component
+ * @author Dmytro Shovchko
+ *
+ * ESLSharePopup is an extension of {@link ESLPopup} that:
+ * - exists as a singleton
+ * - renders a list of {@link ESLShareButton}s based on the {@link ESLShareConfig} config from host {@link ESLShare} component
+ * - forwards the sharing attributes from the host share {@link ESLShare} component
+ */
+export class ESLSharePopup extends ESLTooltip {
+  static override is = 'esl-share-popup';
+
+  /** List of attributes to forward from the activator to the {@link ESLSharePopup} */
+  public static forwardedAttrs = ['share-title', 'share-url'];
+
+  /** Register {@link ESLSharePopup} component and dependent {@link ESLShareButton} */
+  public static override register(): void {
+    ESLShareButton.register();
+    super.register();
+  }
+
+  /** Shared instance of ESLSharePopup */
+  @memoize()
+  public static override get sharedInstance(): ESLSharePopup {
+    return ESLSharePopup.create();
+  }
+
+  /** Hashstring with a list of buttons already rendered in the popup */
+  protected _list: string = '';
+
+  /**
+   * Actions to execute before showing of popup.
+   * @returns false if the show task should be canceled
+   */
+  protected override onBeforeShow(params: ESLToggleableActionParams): boolean | void {
+    const result = super.onBeforeShow(params);
+    if (params.list) {
+      const buttonsList = ESLShareConfig.instance.get(params.list);
+      this.appendButtonsFromList(buttonsList);
+    }
+    this.forwardAttributes();
+    return result;
+  }
+
+  /** Checks that the button list from the config was already rendered in the popup. */
+  protected isEqual(config: ESLShareButtonConfig[]): boolean {
+    return stringifyButtonsList(config) === this._list;
+  }
+
+  /** Appends a button to the popup. */
+  @bind
+  protected appendButton(btnCfg: ESLShareButtonConfig): void {
+    const btn = ESLShareButton.create(btnCfg.name);
+    btn && this.appendChild(btn);
+  }
+
+  /** Appends buttons from the list to the popup. */
+  protected appendButtonsFromList(config: ESLShareButtonConfig[]): void {
+    if (this.isEqual(config)) return;
+    this.innerHTML = '';
+    config.forEach(this.appendButton);
+    memoize.clear(this, '$arrow');
+    this._list = stringifyButtonsList(config);
+  }
+
+  /**
+   * Forwards share attributes from the activator (or its parents) to the {@link ESLSharePopup} instance.
+   * Skips empty attributes
+   */
+  protected forwardAttributes(): void {
+    const {activator} = this;
+    if (!activator) return;
+    ESLSharePopup.forwardedAttrs.forEach((name) => {
+      const el = activator.closest(`[${name}]`);
+      const value = el && el.getAttribute(name);
+      this.$$attr(name, value);
+    });
+  }
+
+  @listen({event: 'change', target: ESLShareConfig.instance})
+  protected _onConfigChange(): void {
+    this.hide();
+  }
+}
+
+declare global {
+  export interface ESLLibrary {
+    SharePopup: typeof ESLSharePopup;
+  }
+  export interface HTMLElementTagNameMap {
+    'esl-share-popup': ESLSharePopup;
+  }
+}
diff --git a/src/modules/esl-share/core/esl-share-trigger.shape.ts b/src/modules/esl-share/core/esl-share-trigger.shape.ts
deleted file mode 100644
index 3bd80bcc6..000000000
--- a/src/modules/esl-share/core/esl-share-trigger.shape.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import type {ESLBaseElementShape} from '../../esl-base-element/core/esl-base-element.shape';
-import type {ESLShareTrigger} from './esl-share-trigger';
-
-/**
- * Tag declaration interface of ESLShareTrigger element
- * Used for TSX declaration
- */
-export interface ESLShareTriggerTagShape extends ESLBaseElementShape<ESLShareTrigger> {
-  /** Allowed children */
-  children?: any;
-}
-
-declare global {
-  namespace JSX {
-    export interface IntrinsicElements {
-      /** {@link ESLShareTrigger} custom tag */
-      'esl-share-trigger': ESLShareTriggerTagShape;
-    }
-  }
-}
diff --git a/src/modules/esl-share/core/esl-share-trigger.ts b/src/modules/esl-share/core/esl-share-trigger.ts
deleted file mode 100644
index fd0705547..000000000
--- a/src/modules/esl-share/core/esl-share-trigger.ts
+++ /dev/null
@@ -1,37 +0,0 @@
-import {ESLTrigger} from '../../esl-trigger/core';
-
-import type {ESLToggleableActionParams} from '../../esl-toggleable/core/esl-toggleable';
-
-/**
- * ESLShareTrigger component
- * @author Dmytro Shovchko
- *
- * ESLShareTrigger is an extension of {@link ESLTrigger} that
- * - controls an internal popup of {@link ESLShare} module in `popup` rendering mode.
- * - forwards the sharing attributes from the parent share {@link ESLShare} component to its associated instance of {@link ESLPopup}
- */
-export class ESLShareTrigger extends ESLTrigger {
-  public static override is = 'esl-share-trigger';
-
-  /** List of attributes to forward from the host to the target share {@link ESLPopup} */
-  public static forwardedAttrs = ['share-title', 'share-url'];
-
-  /** Shows the target {@link ESLPopup} with a passed params */
-  public override showTarget(params: ESLToggleableActionParams = {}): void {
-    super.showTarget(params);
-
-    this.forwardAttributes();
-  }
-
-  /**
-   * Forwards share attributes from the host (or its parents) to the target share {@link ESLPopup} instance.
-   * Skips empty attributes
-   */
-  protected forwardAttributes(): void {
-    ESLShareTrigger.forwardedAttrs.forEach((name) => {
-      const el = this.closest(`[${name}]`);
-      const value = el && el.getAttribute(name);
-      if (value) this.$target?.$$attr(name, value);
-    });
-  }
-}
diff --git a/src/modules/esl-share/core/esl-share.ts b/src/modules/esl-share/core/esl-share.ts
index 8ce9b96fb..e41339094 100644
--- a/src/modules/esl-share/core/esl-share.ts
+++ b/src/modules/esl-share/core/esl-share.ts
@@ -1,55 +1,41 @@
 import {ESLBaseElement} from '../../esl-base-element/core';
-import {ESLPopup} from '../../esl-popup/core';
-import {sequentialUID} from '../../esl-utils/misc/uid';
-import {attr, bind, boolAttr, prop} from '../../esl-utils/decorators';
-import {selectButtonsForList} from './esl-share-config';
-import {ESLShareButton} from './esl-share-button';
-import {ESLShareTrigger} from './esl-share-trigger';
+import {attr, bind, boolAttr, jsonAttr} from '../../esl-utils/decorators';
+import {ESLShareList} from './esl-share-list';
+import {ESLSharePopupTrigger} from './esl-share-popup-trigger';
+import {ESLShareConfig} from './esl-share-config';
 
-import type {PopupActionParams} from '../../esl-popup/core';
-import type {ESLShareConfig, ESLShareButtonConfig} from './esl-share-config';
-
-/** {@link ShareConfig} provider type definition */
-export type ESLShareConfigProviderType = () => Promise<ESLShareConfig>;
+import type {ESLSharePopupActionParams} from './esl-share-popup';
 
 /**
  * ESLShare
  * @author Dmytro Shovchko
  *
- * ESLShare is a custom element to dynamically draw {@link ESLShareButton}s using simplified shared config
+ * ESLShare is a custom element to dynamically draw {@link ESLShareList}
+ * or {@link ESLSharePopupTrigger} depending on the specified mode
  */
 export class ESLShare extends ESLBaseElement {
   public static override is = 'esl-share';
-  protected static _config: Promise<ESLShareConfig>;
-  protected static _popupStore: Map<string, ESLPopup> = new Map<string, ESLPopup>();
 
-  /** Register {@link ESLShare} component and dependent {@link ESLShareButton} */
+  /** Register {@link ESLShare} component and dependent {@link ESLShareList} and {@link ESLSharePopupTrigger} */
   public static override register(): void {
-    ESLShareButton.register();
-    ESLShareTrigger.register();
+    ESLShareList.register();
+    ESLSharePopupTrigger.register();
     super.register();
   }
 
   /**
-   * Gets or updates config with a promise of a new config object or using a config provider function.
+   * Updates the configuration with either a new config object or by using a configuration provider function.
+   * Every button and group specified in the new config will be added to the current configuration.
    * @returns Promise of the current config
+   * @deprecated alias for ESLShareConfig.set(), will be removed soon
    */
-  public static config(provider?: ESLShareConfigProviderType | ESLShareConfig): Promise<ESLShareConfig> {
-    if (typeof provider === 'function') ESLShare._config = provider();
-    if (typeof provider === 'object') ESLShare._config = Promise.resolve(provider);
-    return ESLShare._config ?? Promise.reject('Configuration is not set');
-  }
+  public static readonly config = ESLShareConfig.set;
 
-  /** Event to dispatch on ready state of {@link ESLShare} */
-  @prop('esl:share:ready') public SHARE_READY_EVENT: string;
-
-  /** Default initial params to pass into the newly created popup */
-  @prop({
-    position: 'top',
-    defaultParams: {
-      hideDelay: 200
-    }
-  }) protected popupInitialParams: PopupActionParams;
+  /** Default initial params to pass into the popup trigger */
+  @jsonAttr<ESLSharePopupActionParams>({defaultValue: {
+    trackClick: true,
+    trackHover: true
+  }}) public triggerInitialParams: ESLSharePopupTrigger;
 
   /**
    * List of social networks or groups of them to display (all by default).
@@ -70,95 +56,45 @@ export class ESLShare extends ESLBaseElement {
 
   protected _content: string;
 
-  /** @returns config of buttons specified by the list attribute */
-  public get buttonsConfig(): Promise<ESLShareButtonConfig[]> {
-    return (this.constructor as typeof ESLShare).config().then((config) => {
-      return (this.list !== 'all') ? selectButtonsForList(config, this.list) : config.buttons;
-    });
-  }
-
   public override connectedCallback(): void {
     super.connectedCallback();
     this.init();
   }
 
-  protected init(): void {
-    if (this.ready) return;
+  /** Initializes the component */
+  protected init(force?: boolean): void {
+    if (this.ready && !force) return;
     if (!this.mode) this.mode = 'list';
     if (!this._content) this._content = this.innerHTML;
-    this.buttonsConfig
-      .then(this.buildContent)
-      .then(() => this.$$fire(this.SHARE_READY_EVENT, {bubbles: false}))
-      .catch((e) => console.error(`[${this.baseTagName}]: ${e}`));
+    this.buildContent();
+    this.onReady();
   }
 
-  /** Builds component's content from received `ESLShareButtonConfig` list */
+  /** Builds component's content. */
   @bind
-  protected buildContent(btnConfig: ESLShareButtonConfig[]): void {
+  protected buildContent(): void {
     this.innerHTML = '';
-
-    if (this.mode === 'list') {
-      this.appendButtonsTo(this, btnConfig);
-      return;
-    }
-
-    const $popup = this.getStoredPopup() || this.createPopup(btnConfig);
-    this.appendTrigger(`#${$popup.id}`);
+    this.mode === 'list' ? this.appendList() : this.appendPopupTrigger();
   }
 
-  /** Appends buttons to the passed element. */
-  protected appendButtonsTo($el: Element, btnConfig: ESLShareButtonConfig[]): void {
-    btnConfig.forEach((cfg) => {
-      const btn = this.createButton(cfg);
-      btn && $el.appendChild(btn);
-    });
+  /** Appends share list to the share component. */
+  protected appendList(): void {
+    const $list = ESLShareList.create();
+    $list.list = this.list;
+    this.appendChild($list);
   }
 
-  /** Appends trigger to the share component. */
-  protected appendTrigger(target: string): void {
-    const $trigger = ESLShareTrigger.create();
-    Object.assign($trigger, {
-      target,
-      trackClick: true,
-      trackHover: true
-    });
+  /** Appends share popup trigger to the share component. */
+  protected appendPopupTrigger(): void {
+    const {list} = this;
+    const $trigger = ESLSharePopupTrigger.create();
+    Object.assign($trigger, this.triggerInitialParams, {list});
     $trigger.innerHTML = this._content;
     this.appendChild($trigger);
   }
 
-  /** Creates share button. */
-  protected createButton(cfg: ESLShareButtonConfig): 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;
-  }
-
-  /** Creates popup element with share buttons. */
-  protected createPopup(btnConfig: ESLShareButtonConfig[]): ESLPopup {
-    const $popup = ESLPopup.create();
-    const id = sequentialUID(this.baseTagName + '-');
-    Object.assign($popup, {id, ...this.popupInitialParams});
-    $popup.appendArrow();
-    document.body.appendChild($popup);
-    this.storePopup($popup);
-
-    this.appendButtonsTo($popup, btnConfig);
-    return $popup;
-  }
-
-  /** Gets popup element from the popup's store. */
-  protected getStoredPopup(): ESLPopup | undefined {
-    return (this.constructor as typeof ESLShare)._popupStore.get(this.list);
-  }
-
-  /** Adds popup element to the popup's store. */
-  protected storePopup(value: ESLPopup): void {
-    (this.constructor as typeof ESLShare)._popupStore.set(this.list, value);
+  /** Actions on complete init and ready component. */
+  private onReady(): void {
+    this.$$attr('ready', true);
   }
 }
diff --git a/src/modules/esl-tooltip/core.ts b/src/modules/esl-tooltip/core.ts
index 24b28a3c0..0d4e01c8e 100644
--- a/src/modules/esl-tooltip/core.ts
+++ b/src/modules/esl-tooltip/core.ts
@@ -1,1 +1,3 @@
+export type {ESLTooltipTagShape} from './core/esl-tooltip.shape';
+
 export * from './core/esl-tooltip';
diff --git a/src/modules/esl-tooltip/core/esl-tooltip.shape.ts b/src/modules/esl-tooltip/core/esl-tooltip.shape.ts
new file mode 100644
index 000000000..e8118e785
--- /dev/null
+++ b/src/modules/esl-tooltip/core/esl-tooltip.shape.ts
@@ -0,0 +1,20 @@
+import type {ESLPopupTagShape} from '../../esl-popup/core/esl-popup.shape';
+import type {ESLTooltip} from './esl-tooltip';
+
+/**
+ * Tag declaration interface of {@link ESLTooltip} element
+ * Used for TSX declaration
+ */
+export interface ESLTooltipTagShape<T extends ESLTooltip = ESLTooltip> extends ESLPopupTagShape<T> {
+  /** Disable arrow at Tooltip */
+  'disable-arrow'?: boolean;
+}
+
+declare global {
+  namespace JSX {
+    export interface IntrinsicElements {
+      /** {@link ESLTooltip} custom tag */
+      'esl-tooltip': ESLTooltipTagShape;
+    }
+  }
+}
diff --git a/src/modules/esl-trigger/core/esl-trigger.ts b/src/modules/esl-trigger/core/esl-trigger.ts
index f60dbebc4..4008b0c70 100644
--- a/src/modules/esl-trigger/core/esl-trigger.ts
+++ b/src/modules/esl-trigger/core/esl-trigger.ts
@@ -98,7 +98,7 @@ export class ESLTrigger extends ESLBaseElement {
   /** Value to setup aria-label */
   public get a11yLabel(): string | null {
     if (!this.$target) return null;
-    return (this.$target.open ? this.a11yLabelActive : this.a11yLabelInactive) || null;
+    return (this.isTargetActive ? this.a11yLabelActive : this.a11yLabelInactive) || null;
   }
 
   /** Marker to allow track hover */
@@ -110,6 +110,11 @@ export class ESLTrigger extends ESLBaseElement {
     return ESLMediaQuery.for(this.trackClick).matches;
   }
 
+  /** Checks that the target is in active state */
+  public get isTargetActive(): boolean {
+    return !!this.$target?.open;
+  }
+
   @ready
   protected override connectedCallback(): void {
     super.connectedCallback();
@@ -172,16 +177,16 @@ export class ESLTrigger extends ESLBaseElement {
    * Does not produce `esl:change:active` event
    */
   public updateState(): boolean {
-    const isActive = !!this.$target?.open;
+    const {isTargetActive} = this;
     const wasActive = this.active;
 
-    this.toggleAttribute('active', isActive);
+    this.toggleAttribute('active', isTargetActive);
     const clsTarget = ESLTraversingQuery.first(this.activeClassTarget, this) as HTMLElement;
-    clsTarget && CSSClassUtils.toggle(clsTarget, this.activeClass, isActive);
+    clsTarget && CSSClassUtils.toggle(clsTarget, this.activeClass, isTargetActive);
 
     this.updateA11y();
 
-    return isActive !== wasActive;
+    return isTargetActive !== wasActive;
   }
 
   /** Handles ESLToggleable state change */


Test patch:
diff --git a/src/modules/esl-share/test/buttons/blogger.test.ts b/src/modules/esl-share/test/buttons/blogger.test.ts
new file mode 100644
index 000000000..7a54e9993
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/blogger.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/blogger';
+
+describe(
+  'ESLShare: "blogger" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "blogger" button object config matches button config',
+  createButtonMatchingTestPlan('blogger', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/button-test-plan-factory.ts b/src/modules/esl-share/test/buttons/button-test-plan-factory.ts
new file mode 100644
index 000000000..ba8af21b1
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/button-test-plan-factory.ts
@@ -0,0 +1,46 @@
+import {ESLShareConfig} from '../../core/esl-share-config';
+import {ESLShareActionRegistry} from '../../core/esl-share-action-registry';
+
+export function createImportCheckTestPlan(actionName: string): () => void {
+  return () => {
+    test('config instance has 1 button', () => {
+      expect(ESLShareConfig.instance.buttons.length).toBe(1);
+    });
+
+    test(`"${actionName}" action was registered when importing the button`, () => {
+      expect(ESLShareActionRegistry.instance.has(actionName)).toBe(true);
+    });
+  };
+}
+
+export function createButtonMatchingTestPlan(name: string, action: string): () => void {
+  return () => {
+    test('button from config has action property', () => {
+      expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('action');
+    });
+
+    test(`button from config has action property set to "${action}"`, () => {
+      expect(ESLShareConfig.instance.buttons[0].action).toBe(action);
+    });
+
+    test('button from config has icon property', () => {
+      expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('icon');
+    });
+
+    test('button from config has link property', () => {
+      expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('link');
+    });
+
+    test('button from config has name property', () => {
+      expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('name');
+    });
+
+    test(`button from config has name property set to "${name}"`, () => {
+      expect(ESLShareConfig.instance.buttons[0].name).toBe(name);
+    });
+
+    test('button from config has title property', () => {
+      expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('title');
+    });
+  };
+}
diff --git a/src/modules/esl-share/test/buttons/copy.test.ts b/src/modules/esl-share/test/buttons/copy.test.ts
new file mode 100644
index 000000000..b32902ebd
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/copy.test.ts
@@ -0,0 +1,20 @@
+import {ESLShareConfig} from '../../core/esl-share-config';
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/copy';
+
+describe(
+  'ESLShare: "copy" button import appends button to config and registers the "copy" action',
+  createImportCheckTestPlan('copy')
+);
+
+describe(
+  'ESLShare: "copy" button object config matches button config',
+  createButtonMatchingTestPlan('copy', 'copy')
+);
+
+describe('ESLShare: "copy" button has specific unique properties', () => {
+  test('button from config has additional property', () => {
+    expect(ESLShareConfig.instance.buttons[0]).toHaveProperty('additional');
+  });
+});
diff --git a/src/modules/esl-share/test/buttons/facebook.test.ts b/src/modules/esl-share/test/buttons/facebook.test.ts
new file mode 100644
index 000000000..ca62cc937
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/facebook.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/facebook';
+
+describe(
+  'ESLShare: "facebook" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "facebook" button object config matches button config',
+  createButtonMatchingTestPlan('facebook', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/hatena.test.ts b/src/modules/esl-share/test/buttons/hatena.test.ts
new file mode 100644
index 000000000..068820d6c
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/hatena.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/hatena';
+
+describe(
+  'ESLShare: "hatena" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "hatena" button object config matches button config',
+  createButtonMatchingTestPlan('hatena', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/kakao.test.ts b/src/modules/esl-share/test/buttons/kakao.test.ts
new file mode 100644
index 000000000..e29fdf9d0
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/kakao.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/kakao';
+
+describe(
+  'ESLShare: "kakao" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "kakao" button object config matches button config',
+  createButtonMatchingTestPlan('kakao', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/line.test.ts b/src/modules/esl-share/test/buttons/line.test.ts
new file mode 100644
index 000000000..a177e7f29
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/line.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/line';
+
+describe(
+  'ESLShare: "line" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "line" button object config matches button config',
+  createButtonMatchingTestPlan('line', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/linkedin.test.ts b/src/modules/esl-share/test/buttons/linkedin.test.ts
new file mode 100644
index 000000000..78f5552eb
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/linkedin.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/linkedin';
+
+describe(
+  'ESLShare: "linkedin" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "linkedin" button object config matches button config',
+  createButtonMatchingTestPlan('linkedin', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/mail.test.ts b/src/modules/esl-share/test/buttons/mail.test.ts
new file mode 100644
index 000000000..362705fe0
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/mail.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/mail';
+
+describe(
+  'ESLShare: "mail" button import appends button to config and registers the "external" action',
+  createImportCheckTestPlan('external')
+);
+
+describe(
+  'ESLShare: "mail" button object config matches button config',
+  createButtonMatchingTestPlan('mail', 'external')
+);
diff --git a/src/modules/esl-share/test/buttons/mix.test.ts b/src/modules/esl-share/test/buttons/mix.test.ts
new file mode 100644
index 000000000..e8b6edebb
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/mix.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/mix';
+
+describe(
+  'ESLShare: "mix" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "mix" button object config matches button config',
+  createButtonMatchingTestPlan('mix', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/mixi.test.ts b/src/modules/esl-share/test/buttons/mixi.test.ts
new file mode 100644
index 000000000..e93c7e8bc
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/mixi.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/mixi';
+
+describe(
+  'ESLShare: "mixi" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "mixi" button object config matches button config',
+  createButtonMatchingTestPlan('mixi', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/myspace.test.ts b/src/modules/esl-share/test/buttons/myspace.test.ts
new file mode 100644
index 000000000..bdf2eb775
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/myspace.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/myspace';
+
+describe(
+  'ESLShare: "myspace" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "myspace" button object config matches button config',
+  createButtonMatchingTestPlan('myspace', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/native-share.test.ts b/src/modules/esl-share/test/buttons/native-share.test.ts
new file mode 100644
index 000000000..27b2bbd45
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/native-share.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/native-share';
+
+describe(
+  'ESLShare: "native-share" button import appends button to config and registers the "native" action',
+  createImportCheckTestPlan('native')
+);
+
+describe(
+  'ESLShare: "native-share" button object config matches button config',
+  createButtonMatchingTestPlan('native-share', 'native')
+);
diff --git a/src/modules/esl-share/test/buttons/pinterest.test.ts b/src/modules/esl-share/test/buttons/pinterest.test.ts
new file mode 100644
index 000000000..2f43f84bf
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/pinterest.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/pinterest';
+
+describe(
+  'ESLShare: "pinterest" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "pinterest" button object config matches button config',
+  createButtonMatchingTestPlan('pinterest', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/print.test.ts b/src/modules/esl-share/test/buttons/print.test.ts
new file mode 100644
index 000000000..a1cc9a011
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/print.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/print';
+
+describe(
+  'ESLShare: "print" button import appends button to config and registers the "print" action',
+  createImportCheckTestPlan('print')
+);
+
+describe(
+  'ESLShare: "print" button object config matches button config',
+  createButtonMatchingTestPlan('print', 'print')
+);
diff --git a/src/modules/esl-share/test/buttons/pusha.test.ts b/src/modules/esl-share/test/buttons/pusha.test.ts
new file mode 100644
index 000000000..a328ec2c1
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/pusha.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/pusha';
+
+describe(
+  'ESLShare: "pusha" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "pusha" button object config matches button config',
+  createButtonMatchingTestPlan('pusha', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/reddit.test.ts b/src/modules/esl-share/test/buttons/reddit.test.ts
new file mode 100644
index 000000000..157026a2b
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/reddit.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/reddit';
+
+describe(
+  'ESLShare: "reddit" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "reddit" button object config matches button config',
+  createButtonMatchingTestPlan('reddit', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/sina-weibo.test.ts b/src/modules/esl-share/test/buttons/sina-weibo.test.ts
new file mode 100644
index 000000000..e9c1e8b12
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/sina-weibo.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/sina-weibo';
+
+describe(
+  'ESLShare: "sina-weibo" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "sina-weibo" button object config matches button config',
+  createButtonMatchingTestPlan('sina-weibo', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/telegram.test.ts b/src/modules/esl-share/test/buttons/telegram.test.ts
new file mode 100644
index 000000000..083bffc21
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/telegram.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/telegram';
+
+describe(
+  'ESLShare: "telegram" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "telegram" button object config matches button config',
+  createButtonMatchingTestPlan('telegram', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/twitter.test.ts b/src/modules/esl-share/test/buttons/twitter.test.ts
new file mode 100644
index 000000000..00b4e30ea
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/twitter.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/twitter';
+
+describe(
+  'ESLShare: "twitter" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "twitter" button object config matches button config',
+  createButtonMatchingTestPlan('twitter', 'media')
+);
diff --git a/src/modules/esl-share/test/buttons/wykop.test.ts b/src/modules/esl-share/test/buttons/wykop.test.ts
new file mode 100644
index 000000000..67857d6e1
--- /dev/null
+++ b/src/modules/esl-share/test/buttons/wykop.test.ts
@@ -0,0 +1,13 @@
+import {createImportCheckTestPlan, createButtonMatchingTestPlan} from './button-test-plan-factory';
+
+import '../../buttons/wykop';
+
+describe(
+  'ESLShare: "wykop" button import appends button to config and registers the "media" action',
+  createImportCheckTestPlan('media')
+);
+
+describe(
+  'ESLShare: "wykop" button object config matches button config',
+  createButtonMatchingTestPlan('wykop', 'media')
+);
diff --git a/src/modules/esl-share/test/esl-share-config.test.ts b/src/modules/esl-share/test/esl-share-config.test.ts
new file mode 100644
index 000000000..78f0be572
--- /dev/null
+++ b/src/modules/esl-share/test/esl-share-config.test.ts
@@ -0,0 +1,252 @@
+import {promisifyTimeout} from '../../esl-utils/async/promise/timeout';
+import {ESLShareConfig} from '../core/esl-share-config';
+import type {ESLShareButtonConfig, ESLShareGroupConfig} from '../core/esl-share-config';
+
+describe('ESLShareConfig tests', () => {
+  const SAMPLE_GROUP_1: ESLShareGroupConfig = {name: 'group1', list: 'sn1 sn2'};
+  const SAMPLE_GROUP_2: ESLShareGroupConfig = {name: 'group2', list: 'sn2 sn3 sn4'};
+  const SAMPLE_GROUP_3: ESLShareGroupConfig = {name: 'group3', list: 'group:group1 group:group2'};
+  const SAMPLE_BUTTON_1: ESLShareButtonConfig = {name: 'sn1', title: 'SN1', action: 'media', link: 'https://sn1.com'};
+  const SAMPLE_BUTTON_2: ESLShareButtonConfig = {name: 'sn2', title: 'SN2', action: 'media', link: 'https://sn2.com', icon: '<svg id="svg-2"></svg>'};
+  const SAMPLE_BUTTON_3: ESLShareButtonConfig = {name: 'sn3', title: 'SN3', action: 'media', link: 'https://sn3.com'};
+  const SAMPLE_BUTTON_4: ESLShareButtonConfig = {name: 'sn4', title: 'SN4', action: 'media', link: 'https://sn4.com', icon: '<svg id="svg-4"></svg>'};
+  const SAMPLE_BUTTON_5: ESLShareButtonConfig = {name: 'sn-5', title: 'SN5', action: 'media', link: 'https://sn5.com'};
+
+  describe('Getting ESLShareConfig state', () => {
+    const instance: ESLShareConfig = new (ESLShareConfig as any)();
+    const groups: ESLShareGroupConfig[] = [SAMPLE_GROUP_1, SAMPLE_GROUP_2, SAMPLE_GROUP_3];
+    const buttons: ESLShareButtonConfig[] = [SAMPLE_BUTTON_1, SAMPLE_BUTTON_2, SAMPLE_BUTTON_3, SAMPLE_BUTTON_4, SAMPLE_BUTTON_5];
+    instance.append(groups).append(buttons);
+
+    test.each([
+      ['sn1', SAMPLE_BUTTON_1],
+      ['sn2', SAMPLE_BUTTON_2],
+      ['sn3', SAMPLE_BUTTON_3],
+      ['sn4', SAMPLE_BUTTON_4],
+      ['sn-5', SAMPLE_BUTTON_5]
+    ])('ESLShareConfig.prototype.getButton resolves existing group %s', (name: string, button: any) => {
+      expect(instance.getButton(name)).toEqual(button);
+    });
+
+    test.each([
+      '', 'sn6', 'group1'
+    ])('ESLShareConfig.prototype.getButton does not resolves non-existing group %s', (name: string) => {
+      expect(instance.getButton(name)).toBeUndefined();
+    });
+
+    test.each([
+      ['group1', SAMPLE_GROUP_1],
+      ['group2', SAMPLE_GROUP_2],
+      ['group3', SAMPLE_GROUP_3]
+    ])('ESLShareConfig.prototype.getGroup resolves existing group %s', (name: string, group: any) => {
+      expect(instance.getGroup(name)).toEqual(group);
+    });
+
+    test.each([
+      '', 'group0', 'sn1'
+    ])('ESLShareConfig.prototype.getGroup does not resolves non-existing group %s', (name: string) => {
+      expect(instance.getGroup(name)).toBeUndefined();
+    });
+
+    test('ESLShareConfig.prototype.get(\'all\') resolves all buttons', () => {
+      expect(instance.get('all')).toEqual(buttons);
+    });
+
+    test.each([
+      'allstart',
+      'middleallterm',
+      'endall',
+      'hello-all-1',
+      'group:all'
+    ])('ESLShareConfig.prototype.get(%s) does not resolves to all buttons as nonexistent', (name) => {
+      expect(instance.get(name)).toEqual([]);
+    });
+
+    test.each([
+      ['all', ['sn1', 'sn2', 'sn3', 'sn4', 'sn-5']],
+      ['group1', []],
+      ['group2', []],
+      ['group:group1', ['sn1', 'sn2']],
+      ['group:group2', ['sn2', 'sn3', 'sn4']],
+      ['group:group3', ['sn1', 'sn2', 'sn3', 'sn4']],
+      ['sn1', ['sn1']],
+      ['sn2', ['sn2']],
+      ['', []]
+    ])('ESLShareConfig.prototype.get resolves %s query to list %s', (name: string, list: string[]) => {
+      const result = instance.get(name);
+      expect(result.map((cfg) => cfg.name)).toEqual(list);
+      for (const res of result) {
+        expect(res).toEqual(expect.objectContaining({
+          name: expect.any(String),
+          title: expect.any(String),
+          action: expect.any(String),
+          link: expect.any(String)
+        }));
+      }
+    });
+  });
+
+  describe('ESLShareConfig resolve recursive config', () => {
+    const instance: ESLShareConfig = new (ESLShareConfig as any)();
+
+    beforeEach(() => instance.clear());
+
+    test('ESLShareConfig.prototype.get resolves group referencing itself to empty list', () => {
+      instance.append({name: 'group', list: 'group:group'});
+      expect(instance.get('group:group')).toEqual([]);
+    });
+
+    test('ESLShareConfig.prototype.get ignors non-existing groups', () => {
+      instance.append(SAMPLE_BUTTON_1);
+      instance.append({name: 'group', list: 'group:group'});
+      expect(instance.get('sn1 group:group')).toContain(SAMPLE_BUTTON_1);
+    });
+  });
+
+  describe('Setting ESLShareConfig state', () => {
+    const instance: ESLShareConfig = new (ESLShareConfig as any)();
+    beforeEach(() => instance.clear());
+
+    test('ESLShareConfig.prototype.append appends buttons', () => {
+      instance.append([SAMPLE_BUTTON_1, SAMPLE_BUTTON_2]);
+      expect(instance.buttons.length).toBe(2);
+      expect(instance.groups.length).toBe(0);
+    });
+
+    test('ESLShareConfig.prototype.append appends groups', () => {
+      instance.append([SAMPLE_GROUP_1, SAMPLE_GROUP_2]);
+      expect(instance.buttons.length).toBe(0);
+      expect(instance.groups.length).toBe(2);
+    });
+
+    test('ESLShareConfig.prototype.append does not create duplicates', () => {
+      instance.append([SAMPLE_BUTTON_1, SAMPLE_BUTTON_1]).append(SAMPLE_BUTTON_1);
+      expect(instance.buttons.length).toBe(1);
+      expect(instance.groups.length).toBe(0);
+    });
+
+    test('ESLShareConfig.prototype.append accepts single button config', () => {
+      instance.append(SAMPLE_BUTTON_1);
+      expect(instance.buttons.length).toBe(1);
+      expect(instance.groups.length).toBe(0);
+    });
+
+    test('ESLShareConfig.prototype.append accepts single group config', () => {
+      instance.append(SAMPLE_GROUP_1);
+      expect(instance.buttons.length).toBe(0);
+      expect(instance.groups.length).toBe(1);
+    });
+  });
+
+
+  describe('ESLShareConfig notify about changes', () => {
+    const instance: ESLShareConfig = new (ESLShareConfig as any)();
+    const callback = jest.fn();
+
+    beforeEach(async () => {
+      callback.mockClear();
+      instance.clear();
+      await Promise.resolve();
+      instance.addEventListener(callback);
+    });
+    afterEach(() => instance.removeEventListener(callback));
+
+    test('ESLShareConfig.prototype.append notifies about buttons change', async () => {
+      instance.addEventListener(callback);
+      expect(callback).toBeCalledTimes(0);
+      instance.append(SAMPLE_BUTTON_1);
+      expect(callback).toBeCalledTimes(0);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about groups change', async () => {
+      instance.addEventListener(callback);
+      expect(callback).toBeCalledTimes(0);
+      instance.append(SAMPLE_GROUP_1);
+      expect(callback).toBeCalledTimes(0);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about buttons change', async () => {
+      instance.append([SAMPLE_BUTTON_1, SAMPLE_BUTTON_2]);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about groups change', async () => {
+      instance.append([SAMPLE_GROUP_1, SAMPLE_GROUP_2]);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about multiple change in macro-task once', async () => {
+      instance.append(SAMPLE_BUTTON_1);
+      instance.append(SAMPLE_GROUP_1);
+      instance.append(SAMPLE_BUTTON_2);
+      instance.append(SAMPLE_GROUP_2);
+      expect(callback).toBeCalledTimes(0);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about multiple change of separate tasks', async () => {
+      instance.append(SAMPLE_BUTTON_1);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+      await promisifyTimeout(0);
+      instance.append(SAMPLE_GROUP_1);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(2);
+    });
+
+    test('ESLShareConfig.prototype.append notifies about config reset', async () => {
+      instance.append(SAMPLE_BUTTON_1);
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(1);
+      instance.clear();
+      await Promise.resolve();
+      expect(callback).toBeCalledTimes(2);
+    });
+  });
+
+  describe('ESLShareConfig static API', () => {
+    test('ESLShareConfig instance is a singleton', () => {
+      expect(ESLShareConfig.instance).toBeInstanceOf(ESLShareConfig);
+      expect(ESLShareConfig.instance).toBe(ESLShareConfig.instance);
+    });
+
+    test('ESLShareConfig.set appends a button', () => {
+      ESLShareConfig.set({buttons: [SAMPLE_BUTTON_1]});
+      expect(ESLShareConfig.instance.buttons.length).toBe(1);
+      expect(ESLShareConfig.instance.groups.length).toBe(0);
+    });
+
+    test('ESLShareConfig.set appends a group', () => {
+      ESLShareConfig.set({groups: [SAMPLE_GROUP_1]});
+      expect(ESLShareConfig.instance.buttons.length).toBe(1);
+      expect(ESLShareConfig.instance.groups.length).toBe(1);
+    });
+
+    test('ESLShareConfig.set accepts empty config', () => {
+      ESLShareConfig.set({});
+      expect(ESLShareConfig.instance.buttons.length).toBe(1);
+      expect(ESLShareConfig.instance.groups.length).toBe(1);
+    });
+
+    test('ESLShareConfig.set accepts provider function', () => {
+      ESLShareConfig.set(() => ({buttons: [SAMPLE_BUTTON_2]}));
+      expect(ESLShareConfig.instance.buttons.length).toBe(2);
+      expect(ESLShareConfig.instance.groups.length).toBe(1);
+    });
+
+    test('ESLShareConfig.set accepts provider promise', async () => {
+      const promise = Promise.resolve({buttons: [SAMPLE_BUTTON_3]});
+      ESLShareConfig.set(promise);
+      await promise;
+      expect(ESLShareConfig.instance.buttons.length).toBe(3);
+      expect(ESLShareConfig.instance.groups.length).toBe(1);
+    });
+  });
+});