refactored ChannelSelector component
authorunknown <ajbura@gmail.com>
Sun, 29 Aug 2021 08:27:55 +0000 (13:57 +0530)
committerunknown <ajbura@gmail.com>
Sun, 29 Aug 2021 08:27:55 +0000 (13:57 +0530)
src/app/molecules/channel-selector/ChannelSelector.jsx
src/app/molecules/channel-selector/ChannelSelector.scss
src/app/organisms/navigation/Drawer.jsx
src/app/organisms/navigation/Drawer.scss

index 9c1a2df1c4c96a85cd66422cffdba34cc37d9f62..631dd57843680ab40605551b6d3fcbf2f540b08a 100644 (file)
@@ -9,62 +9,80 @@ import Avatar from '../../atoms/avatar/Avatar';
 import NotificationBadge from '../../atoms/badge/NotificationBadge';
 import { blurOnBubbling } from '../../atoms/button/script';
 
+function ChannelSelectorWrapper({
+  isSelected, onClick, content, options,
+}) {
+  return (
+    <div className={`channel-selector${isSelected ? ' channel-selector--selected' : ''}`}>
+      <button
+        className="channel-selector__content"
+        type="button"
+        onClick={onClick}
+        onMouseUp={(e) => blurOnBubbling(e, '.channel-selector__wrapper')}
+      >
+        {content}
+      </button>
+      <div className="channel-selector__options">{options}</div>
+    </div>
+  );
+}
+ChannelSelectorWrapper.defaultProps = {
+  options: null,
+};
+ChannelSelectorWrapper.propTypes = {
+  isSelected: PropTypes.bool.isRequired,
+  onClick: PropTypes.func.isRequired,
+  content: PropTypes.node.isRequired,
+  options: PropTypes.node,
+};
+
 function ChannelSelector({
-  selected, unread, notificationCount, alert,
-  iconSrc, imageSrc, roomId, onClick, children,
+  name, roomId, imageSrc, iconSrc,
+  isSelected, isUnread, notificationCount, isAlert,
+  options, onClick,
 }) {
   return (
-    <button
-      className={`channel-selector__button-wrapper${selected ? ' channel-selector--selected' : ''}`}
-      type="button"
-      onClick={onClick}
-      onMouseUp={(e) => blurOnBubbling(e, '.channel-selector__button-wrapper')}
-    >
-      <div className="channel-selector">
-        <div className="channel-selector__icon flex--center">
+    <ChannelSelectorWrapper
+      isSelected={isSelected}
+      content={(
+        <>
           <Avatar
-            text={children.slice(0, 1)}
+            text={name.slice(0, 1)}
             bgColor={colorMXID(roomId)}
             imageSrc={imageSrc}
             iconSrc={iconSrc}
             size="extra-small"
           />
-        </div>
-        <div className="channel-selector__text-container">
-          <Text variant="b1">{children}</Text>
-        </div>
-        <div className="channel-selector__badge-container">
-          { unread && (
+          <Text variant="b1">{name}</Text>
+          { isUnread && (
             <NotificationBadge
-              alert={alert}
+              alert={isAlert}
               content={notificationCount !== 0 ? notificationCount : null}
             />
           )}
-        </div>
-      </div>
-    </button>
+        </>
+      )}
+      options={options}
+      onClick={onClick}
+    />
   );
 }
-
 ChannelSelector.defaultProps = {
-  selected: false,
-  unread: false,
-  notificationCount: 0,
-  alert: false,
-  iconSrc: null,
   imageSrc: null,
+  iconSrc: null,
+  options: null,
 };
-
 ChannelSelector.propTypes = {
-  selected: PropTypes.bool,
-  unread: PropTypes.bool,
-  notificationCount: PropTypes.number,
-  alert: PropTypes.bool,
-  iconSrc: PropTypes.string,
-  imageSrc: PropTypes.string,
+  name: PropTypes.string.isRequired,
   roomId: PropTypes.string.isRequired,
+  imageSrc: PropTypes.string,
+  iconSrc: PropTypes.string,
+  isSelected: PropTypes.bool.isRequired,
+  isUnread: PropTypes.bool.isRequired,
+  notificationCount: PropTypes.number.isRequired,
+  isAlert: PropTypes.bool.isRequired,
+  options: PropTypes.node,
   onClick: PropTypes.func.isRequired,
-  children: PropTypes.string.isRequired,
 };
 
 export default ChannelSelector;
index 7edf1888276168c8cc843c3097bee41418bcc5ea..31385f3765fdd70f2f4286fdf0a7f30bd88ecfd9 100644 (file)
@@ -1,24 +1,35 @@
-.channel-selector__button-wrapper {
-  display: block;
-  width: calc(100% - var(--sp-extra-tight));
-  margin-left: auto;
-  padding: var(--sp-extra-tight) var(--sp-extra-tight);
-  
+.channel-selector-flex {
+  display: flex;
+  align-items: center;
+}
+.channel-selector-flexItem {
+  flex: 1;
+  min-width: 0;
+  min-height: 0;
+}
+
+.channel-selector {
+  @extend .channel-selector-flex;
+
   border: 1px solid transparent;
-  border-radius:  var(--bo-radius);
+  border-radius: var(--bo-radius);
   cursor: pointer;
+  
+  &--selected {
+    background-color: var(--bg-surface);
+    border-color: var(--bg-surface-border);
 
-  [dir=rtl] & {
-    
-    margin: {
-      left: 0;
-      right: auto;
+    & .channel-selector__options {
+      display: flex;
     }
   }
 
   @media (hover: hover) {
     &:hover {
       background-color: var(--bg-surface-hover);
+      & .channel-selector__options {
+        display: flex;
+      }
     }
   }
   &:focus {
   &:active {
     background-color: var(--bg-surface-active);
   }
+  &--selected:hover,
+  &--selected:focus,
+  &--selected:active {
+    background-color: var(--bg-surface);
+  }
 }
-.channel-selector {
-  display: flex;
-  align-items: center;
 
-  &__icon {
-    width: 24px;
-    height: 24px;
-    .avatar__border {
-      box-shadow: none;
-    }
+.channel-selector__content {
+  @extend .channel-selector-flexItem;
+  @extend .channel-selector-flex;
+  padding: 0 var(--sp-extra-tight);
+  min-height: 40px;
+  cursor: inherit;
+
+  & > .avatar-container .avatar__bordered {
+    box-shadow: none;
   }
-  &__text-container {
-    flex: 1;
-    min-width: 0;
+
+  & > .text {
+    @extend .channel-selector-flexItem;
     margin: 0 var(--sp-extra-tight);
 
-    & .text {
-      color: var(--tc-surface-normal);
-      overflow: hidden;
-      white-space: nowrap;
-      text-overflow: ellipsis;
-    }
+    color: var(--tc-surface-normal);
+    overflow: hidden;
+    white-space: nowrap;
+    text-overflow: ellipsis;
   }
 }
+.channel-selector__options {
+  @extend .channel-selector-flex;
+  display: none;
+  margin-right: var(--sp-ultra-tight);
 
-.channel-selector--selected {
-  background-color: var(--bg-surface);
-  border-color: var(--bg-surface-border);
+  [dir=rtl] & {
+    margin-right: 0;
+    margin-left: var(--sp-ultra-tight);
+  }
+
+  &:empty {
+    margin: 0 !important;
+  }
+
+  & .ic-btn-surface {
+    padding: 6px;
+    border-radius: calc(var(--bo-radius) / 2);
+  }
 }
\ No newline at end of file
index bfa1a2003aa2ccc92b3d74f85f726e3fd9628a24..fa273e07590f42e7207ec74795210ebaa17c7b60 100644 (file)
@@ -102,6 +102,9 @@ function renderSelector(room, roomId, isSelected, isDM) {
   return (
     <ChannelSelector
       key={roomId}
+      name={room.name}
+      roomId={roomId}
+      imageSrc={isDM ? imageSrc : null}
       iconSrc={
         isDM
           ? null
@@ -112,16 +115,12 @@ function renderSelector(room, roomId, isSelected, isDM) {
             return (room.getJoinRule() === 'invite' ? HashLockIC : HashIC);
           })()
       }
-      imageSrc={isDM ? imageSrc : null}
-      roomId={roomId}
-      unread={doesRoomHaveUnread(room)}
-      onClick={() => selectRoom(roomId)}
+      isSelected={isSelected}
+      isUnread={doesRoomHaveUnread(room)}
       notificationCount={room.getUnreadNotificationCount('total')}
-      alert={room.getUnreadNotificationCount('highlight') !== 0}
-      selected={isSelected}
-    >
-      {room.name}
-    </ChannelSelector>
+      isAlert={room.getUnreadNotificationCount('highlight') !== 0}
+      onClick={() => selectRoom(roomId)}
+    />
   );
 }
 
index 5e452628f9f91c53decae75803a16c8f75da9bb4..4b12bcea6251ce26d0973e56c8428fc87e7b590d 100644 (file)
 .channels-container {
   padding-bottom: var(--sp-extra-loose);
 
-  & > .channel-selector__button-wrapper:first-child {
+  & > .channel-selector {
+    width: calc(100% - var(--sp-extra-tight));
+    margin-left: auto;
+
+    [dir=rtl] & {
+      margin-left: 0;
+      margin-right: auto;
+    }
+
+  }
+
+  & > .channel-selector:first-child {
     margin-top: var(--sp-extra-tight);
   }