diff --git a/package.json b/package.json
index 5ca469e5..512261d1 100644
--- a/package.json
+++ b/package.json
@@ -7,6 +7,7 @@
     "@testing-library/jest-dom": "^5.11.4",
     "@testing-library/react": "^11.1.0",
     "@testing-library/user-event": "^12.1.10",
+    "@tippy.js/react": "^3.1.1",
     "autosize": "^4.0.2",
     "axios": "^0.21.1",
     "body-scroll-lock": "^2.6.4",
diff --git a/src/components/boris/BorisComments/index.tsx b/src/components/boris/BorisComments/index.tsx
new file mode 100644
index 00000000..7cddfd67
--- /dev/null
+++ b/src/components/boris/BorisComments/index.tsx
@@ -0,0 +1,40 @@
+import React, { FC } from 'react';
+import styles from './styles.module.scss';
+import { Group } from '~/components/containers/Group';
+import { NodeCommentForm } from '~/components/node/NodeCommentForm';
+import { NodeNoComments } from '~/components/node/NodeNoComments';
+import { NodeComments } from '~/components/node/NodeComments';
+import { Footer } from '~/components/main/Footer';
+import { Card } from '~/components/containers/Card';
+import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
+import { selectAuthUser } from '~/redux/auth/selectors';
+import { IComment, INode } from '~/redux/types';
+
+interface IProps {
+  isLoadingComments: boolean;
+  commentCount: number;
+  node: INode;
+  comments: IComment[];
+}
+
+const BorisComments: FC<IProps> = ({ isLoadingComments, node, commentCount, comments }) => {
+  const user = useShallowSelect(selectAuthUser);
+
+  return (
+    <Card className={styles.content}>
+      <Group className={styles.grid}>
+        {user.is_user && <NodeCommentForm isBefore nodeId={node.id} />}
+
+        {isLoadingComments ? (
+          <NodeNoComments is_loading count={7} />
+        ) : (
+          <NodeComments comments={comments} count={commentCount} user={user} order="ASC" />
+        )}
+      </Group>
+
+      <Footer />
+    </Card>
+  );
+};
+
+export { BorisComments };
diff --git a/src/components/boris/BorisComments/styles.module.scss b/src/components/boris/BorisComments/styles.module.scss
new file mode 100644
index 00000000..1dcd3c24
--- /dev/null
+++ b/src/components/boris/BorisComments/styles.module.scss
@@ -0,0 +1,18 @@
+@import "~/styles/variables.scss";
+
+.content {
+  flex: 4;
+  z-index: 2;
+  border-radius: $radius;
+  padding: 0;
+  background: $node_bg;
+  box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px;
+
+  @include desktop {
+    flex: 2.5;
+  }
+
+  @media(max-width: 1024px) {
+    flex: 2;
+  }
+}
diff --git a/src/components/boris/BorisUIDemo/index.tsx b/src/components/boris/BorisUIDemo/index.tsx
new file mode 100644
index 00000000..bba0c86a
--- /dev/null
+++ b/src/components/boris/BorisUIDemo/index.tsx
@@ -0,0 +1,51 @@
+import React, { FC } from 'react';
+import { Card } from '~/components/containers/Card';
+import styles from './styles.module.scss';
+import markdown from '~/styles/common/markdown.module.scss';
+import { Group } from '~/components/containers/Group';
+import { Button } from '~/components/input/Button';
+
+interface IProps {}
+
+const BorisUIDemo: FC<IProps> = () => (
+  <Card className={styles.card}>
+    <div className={markdown.wrapper}>
+      <h1>UI</h1>
+      <p>
+        Простая демонстрация элементов интерфейса. Используется, в основном, как подсказка при
+        разработке
+      </p>
+
+      <h2>Кнопки</h2>
+
+      <h4>Цвета</h4>
+
+      <Group horizontal className={styles.sample}>
+        <Button>Primary</Button>
+        <Button color="secondary">Secondary</Button>
+        <Button color="outline">Outline</Button>
+        <Button color="gray">Gray</Button>
+        <Button color="link">Link</Button>
+      </Group>
+
+      <h4>Размеры</h4>
+
+      <Group horizontal className={styles.sample}>
+        <Button size="micro">Micro</Button>
+        <Button size="mini">Mini</Button>
+        <Button size="normal">Normal</Button>
+        <Button size="big">Big</Button>
+        <Button size="giant">Giant</Button>
+      </Group>
+
+      <h4>Варианты</h4>
+      <Group horizontal className={styles.sample}>
+        <Button iconRight="check">iconRight</Button>
+        <Button iconLeft="send">iconLeft</Button>
+        <Button round>Round</Button>
+      </Group>
+    </div>
+  </Card>
+);
+
+export { BorisUIDemo };
diff --git a/src/components/boris/BorisUIDemo/styles.module.scss b/src/components/boris/BorisUIDemo/styles.module.scss
new file mode 100644
index 00000000..5d9eacfd
--- /dev/null
+++ b/src/components/boris/BorisUIDemo/styles.module.scss
@@ -0,0 +1,11 @@
+.card {
+  flex: 3;
+  align-self: stretch;
+  position: relative;
+  z-index: 1;
+  padding: 20px 30px;
+}
+
+.sample {
+  flex-wrap: wrap;
+}
diff --git a/src/components/input/Button/index.tsx b/src/components/input/Button/index.tsx
index 1f2a02a6..6d9e3801 100644
--- a/src/components/input/Button/index.tsx
+++ b/src/components/input/Button/index.tsx
@@ -6,11 +6,15 @@ import React, {
   createElement,
   memo,
   useRef,
+  useEffect,
+  useMemo,
 } from 'react';
 import styles from './styles.module.scss';
 import { Icon } from '~/components/input/Icon';
 import { IIcon } from '~/redux/types';
 import { usePopper } from 'react-popper';
+import Tippy from '@tippy.js/react';
+import 'tippy.js/dist/tippy.css';
 
 type IButtonProps = DetailedHTMLProps<
   ButtonHTMLAttributes<HTMLButtonElement>,
@@ -23,7 +27,6 @@ type IButtonProps = DetailedHTMLProps<
   seamless?: boolean;
   transparent?: boolean;
   title?: string;
-  non_submitting?: boolean;
   is_loading?: boolean;
   stretchy?: boolean;
   iconOnly?: boolean;
@@ -41,7 +44,6 @@ const Button: FC<IButtonProps> = memo(
     children,
     seamless = false,
     transparent = false,
-    non_submitting = false,
     is_loading,
     title,
     stretchy,
@@ -52,23 +54,9 @@ const Button: FC<IButtonProps> = memo(
     round,
     ...props
   }) => {
-    const tooltip = useRef<HTMLSpanElement | null>(null);
-    const pop = usePopper(tooltip?.current?.parentElement, tooltip.current, {
-      placement: 'top',
-      modifiers: [
-        {
-          name: 'offset',
-          options: {
-            offset: [0, 5],
-          },
-        },
-      ],
-    });
-
-    return createElement(
-      seamless || non_submitting ? 'div' : 'button',
-      {
-        className: classnames(styles.button, className, styles[size], styles[color], {
+    const computedClassName = useMemo(
+      () =>
+        classnames(styles.button, className, styles[size], styles[color], {
           seamless,
           transparent,
           disabled,
@@ -79,18 +67,17 @@ const Button: FC<IButtonProps> = memo(
           has_icon_right: !!iconRight,
           round,
         }),
-        ...props,
-      },
-      [
-        iconLeft && <Icon icon={iconLeft} size={20} key={0} className={styles.icon_left} />,
-        title ? <span>{title}</span> : children || null,
-        iconRight && <Icon icon={iconRight} size={20} key={2} className={styles.icon_right} />,
-        !!label && (
-          <span ref={tooltip} className={styles.tooltip} style={pop.styles.popper} key="tooltip">
-            {label}
-          </span>
-        ),
-      ]
+      [seamless, round, disabled, className, is_loading, stretchy, iconLeft, iconRight, size, color]
+    );
+
+    return (
+      <Tippy content={label || ''} enabled={!!label}>
+        <button className={computedClassName} {...props}>
+          {iconLeft && <Icon icon={iconLeft} size={20} key={0} className={styles.icon_left} />}
+          {!!title ? <span>{title}</span> : children}
+          {iconRight && <Icon icon={iconRight} size={20} key={2} className={styles.icon_right} />}
+        </button>
+      </Tippy>
     );
   }
 );
diff --git a/src/components/input/Button/styles.module.scss b/src/components/input/Button/styles.module.scss
index 255b3594..118131c7 100644
--- a/src/components/input/Button/styles.module.scss
+++ b/src/components/input/Button/styles.module.scss
@@ -184,32 +184,56 @@
   font: $font_12_semibold;
   padding: 0 15px;
   border-radius: $radius / 2;
+
+  &:global(.round) {
+    border-radius: 10px;
+  }
 }
 .mini {
   height: 28px;
   border-radius: $radius / 2;
+
+  &:global(.round) {
+    border-radius: 14px;
+  }
 }
 .small {
   height: 32px;
-  // border-radius: $radius / 2;
 
   svg {
     width: 24px;
     height: 24px;
   }
+
+  &:global(.round) {
+    border-radius: 16px;
+  }
 }
+
 .normal {
   height: 38px;
+
+  &:global(.round) {
+    border-radius: 19px;
+  }
 }
 
 .big {
   height: 40px;
+
+  &:global(.round) {
+    border-radius: 20px;
+  }
 }
 
 .giant {
   height: 50px;
   padding: 0 15px;
   min-width: 50px;
+
+  &:global(.round) {
+    border-radius: 25px;
+  }
 }
 
 .disabled {
@@ -234,14 +258,13 @@
   z-index: 2;
   border-radius: $input_radius;
   text-transform: none;
-  opacity: 0;
-  pointer-events: none;
   touch-action: none;
   transition: opacity 0.1s;
   border: 1px solid transparentize(white, 0.9);
+  //visibility: hidden;
 
   .button:hover & {
-    opacity: 1;
+    visibility: visible;
     font: $font_14_semibold;
   }
 }
diff --git a/src/containers/dialogs/EditorDialog/index.tsx b/src/containers/dialogs/EditorDialog/index.tsx
index a5a42243..998ccb59 100644
--- a/src/containers/dialogs/EditorDialog/index.tsx
+++ b/src/containers/dialogs/EditorDialog/index.tsx
@@ -95,7 +95,11 @@ const EditorDialogUnconnected: FC<IProps> = ({
           maxLength={256}
         />
 
-        <Button title="Сохранить" iconRight="check" />
+        <Button
+          title="Сохранить"
+          iconRight="check"
+          color={data.is_promoted ? 'primary' : 'secondary'}
+        />
       </Group>
     </Padder>
   );
diff --git a/src/containers/node/BorisLayout/index.tsx b/src/containers/node/BorisLayout/index.tsx
index d2593ad4..d0af2db5 100644
--- a/src/containers/node/BorisLayout/index.tsx
+++ b/src/containers/node/BorisLayout/index.tsx
@@ -2,16 +2,11 @@ import React, { FC, useEffect } from 'react';
 import { selectNode, selectNodeComments } from '~/redux/node/selectors';
 import { selectUser } from '~/redux/auth/selectors';
 import { useDispatch } from 'react-redux';
-import { NodeComments } from '~/components/node/NodeComments';
 import styles from './styles.module.scss';
 import { Group } from '~/components/containers/Group';
 import boris from '~/sprites/boris_robot.svg';
-import { NodeNoComments } from '~/components/node/NodeNoComments';
 import { useRandomPhrase } from '~/constants/phrases';
-import { NodeCommentForm } from '~/components/node/NodeCommentForm';
 import isBefore from 'date-fns/isBefore';
-import { Card } from '~/components/containers/Card';
-import { Footer } from '~/components/main/Footer';
 import { BorisStats } from '~/components/boris/BorisStats';
 import { useShallowSelect } from '~/utils/hooks/useShallowSelect';
 import { selectBorisStats } from '~/redux/boris/selectors';
@@ -20,6 +15,10 @@ import { nodeLoadNode } from '~/redux/node/actions';
 import { borisLoadStats } from '~/redux/boris/actions';
 import { Container } from '~/containers/main/Container';
 import StickyBox from 'react-sticky-box/dist/esnext';
+import { BorisComments } from '~/components/boris/BorisComments';
+import { URLS } from '~/constants/urls';
+import { Route, Switch } from 'react-router-dom';
+import { BorisUIDemo } from '~/components/boris/BorisUIDemo';
 
 type IProps = {};
 
@@ -69,24 +68,18 @@ const BorisLayout: FC<IProps> = () => {
         </div>
 
         <div className={styles.container}>
-          <Card className={styles.content}>
-            <Group className={styles.grid}>
-              {user.is_user && <NodeCommentForm isBefore nodeId={node.current.id} />}
+          {
+            <Switch>
+              <Route path={`${URLS.BORIS}/ui`} component={BorisUIDemo} />
 
-              {node.is_loading_comments ? (
-                <NodeNoComments is_loading count={7} />
-              ) : (
-                <NodeComments
-                  comments={comments}
-                  count={node.comment_count}
-                  user={user}
-                  order="ASC"
-                />
-              )}
-            </Group>
-
-            <Footer />
-          </Card>
+              <BorisComments
+                isLoadingComments={node.is_loading_comments}
+                commentCount={node.comment_count}
+                node={node.current}
+                comments={node.comments}
+              />
+            </Switch>
+          }
 
           <Group className={styles.stats}>
             <StickyBox className={styles.sticky} offsetTop={72} offsetBottom={10}>
diff --git a/src/containers/node/BorisLayout/styles.module.scss b/src/containers/node/BorisLayout/styles.module.scss
index f6e3c8ad..44c56d9b 100644
--- a/src/containers/node/BorisLayout/styles.module.scss
+++ b/src/containers/node/BorisLayout/styles.module.scss
@@ -7,22 +7,6 @@
   flex-direction: column;
 }
 
-.content {
-  flex: 4;
-  z-index: 2;
-  border-radius: $radius;
-  padding: 0;
-  background: $node_bg;
-  box-shadow: inset transparentize(mix($wisegreen, white, 60%), 0.6) 0 1px;
-
-  @include desktop {
-    flex: 2.5;
-  }
-
-  @media(max-width: 1024px) {
-    flex: 2;
-  }
-}
 
 .grid {
   padding: $gap;
diff --git a/yarn.lock b/yarn.lock
index a3992a4e..b2d4bc5e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1594,6 +1594,14 @@
   dependencies:
     "@babel/runtime" "^7.10.2"
 
+"@tippy.js/react@^3.1.1":
+  version "3.1.1"
+  resolved "https://registry.yarnpkg.com/@tippy.js/react/-/react-3.1.1.tgz#027e4595e55f31430741fe8e0d92aaddfbe47efd"
+  integrity sha512-KF45vW/jKh/nBXk/2zzTFslv/T46zOMkIoDJ56ymZ+M00yHttk58J5wZ29oqGqDIUnobWSZD+cFpbR4u/UUvgw==
+  dependencies:
+    prop-types "^15.6.2"
+    tippy.js "^5.1.1"
+
 "@types/aria-query@^4.2.0":
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
@@ -8330,6 +8338,11 @@ pnp-webpack-plugin@1.6.4:
   dependencies:
     ts-pnp "^1.1.6"
 
+popper.js@^1.16.0:
+  version "1.16.1"
+  resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1.tgz#2a223cb3dc7b6213d740e40372be40de43e65b1b"
+  integrity sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==
+
 portfinder@^1.0.26:
   version "1.0.28"
   resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778"
@@ -10972,6 +10985,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3:
   resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754"
   integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==
 
+tippy.js@^5.1.1:
+  version "5.2.1"
+  resolved "https://registry.yarnpkg.com/tippy.js/-/tippy.js-5.2.1.tgz#e08d7332c103a15e427124d710d881fca82365d6"
+  integrity sha512-66UT6JRVn3dXNCORE+0UvUK3JZqV/VhLlU6HTDm3FmrweUUFUxUGvT8tUQ7ycMp+uhuLAwQw6dBabyC+iKf/MA==
+  dependencies:
+    popper.js "^1.16.0"
+
 tmp@^0.0.33:
   version "0.0.33"
   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"