~cytrogen/masto-fe

fb0d2de8fed305541b5d86dcedbdd94283999f9d — Eugen Rochko 2 years ago 83ae40e
[Glitch] Change design of dropdowns in web UI

Port e4fd9503ec7c941299ff6572f2e426e75f211e7d to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
M app/javascript/flavours/glitch/components/dropdown_menu.jsx => app/javascript/flavours/glitch/components/dropdown_menu.jsx +2 -2
@@ 121,10 121,10 @@ class DropdownMenu extends PureComponent {
      return <li key={`sep-${i}`} className='dropdown-menu__separator' />;
    }

    const { text, href = '#', target = '_blank', method } = option;
    const { text, href = '#', target = '_blank', method, dangerous } = option;

    return (
      <li className='dropdown-menu__item' key={`${text}-${i}`}>
      <li className={classNames('dropdown-menu__item', { 'dropdown-menu__item--dangerous': dangerous })} key={`${text}-${i}`}>
        <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}>
          {text}
        </a>

M app/javascript/flavours/glitch/components/status_action_bar.jsx => app/javascript/flavours/glitch/components/status_action_bar.jsx +6 -6
@@ 243,21 243,21 @@ class StatusActionBar extends ImmutablePureComponent {

    if (writtenByMe) {
      menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
      menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
      menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick, dangerous: true });
    } else {
      menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
      menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
      menu.push(null);

      if (!this.props.onFilter) {
        menu.push({ text: intl.formatMessage(messages.filter), action: this.handleFilterClick });
        menu.push({ text: intl.formatMessage(messages.filter), action: this.handleFilterClick, dangerous: true });
        menu.push(null);
      }

      menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
      menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
      menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
      menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport, dangerous: true });

      if (((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) || (isRemote && (permissions & PERMISSION_MANAGE_FEDERATION) === PERMISSION_MANAGE_FEDERATION)) {
        menu.push(null);

M app/javascript/flavours/glitch/features/account/components/header.jsx => app/javascript/flavours/glitch/features/account/components/header.jsx +4 -4
@@ 272,16 272,16 @@ class Header extends ImmutablePureComponent {
      if (account.getIn(['relationship', 'muting'])) {
        menu.push({ text: intl.formatMessage(messages.unmute, { name: account.get('username') }), action: this.props.onMute });
      } else {
        menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute });
        menu.push({ text: intl.formatMessage(messages.mute, { name: account.get('username') }), action: this.props.onMute, dangerous: true });
      }

      if (account.getIn(['relationship', 'blocking'])) {
        menu.push({ text: intl.formatMessage(messages.unblock, { name: account.get('username') }), action: this.props.onBlock });
      } else {
        menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock });
        menu.push({ text: intl.formatMessage(messages.block, { name: account.get('username') }), action: this.props.onBlock, dangerous: true });
      }

      menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport });
      menu.push({ text: intl.formatMessage(messages.report, { name: account.get('username') }), action: this.props.onReport, dangerous: true });
    }

    if (signedIn && isRemote) {


@@ 290,7 290,7 @@ class Header extends ImmutablePureComponent {
      if (account.getIn(['relationship', 'domain_blocking'])) {
        menu.push({ text: intl.formatMessage(messages.unblockDomain, { domain: remoteDomain }), action: this.props.onUnblockDomain });
      } else {
        menu.push({ text: intl.formatMessage(messages.blockDomain, { domain: remoteDomain }), action: this.props.onBlockDomain });
        menu.push({ text: intl.formatMessage(messages.blockDomain, { domain: remoteDomain }), action: this.props.onBlockDomain, dangerous: true });
      }
    }


M app/javascript/flavours/glitch/features/status/components/action_bar.jsx => app/javascript/flavours/glitch/features/status/components/action_bar.jsx +5 -5
@@ 176,15 176,15 @@ class ActionBar extends PureComponent {
      menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick });
      menu.push(null);
      menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
      menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick });
      menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.redraft), action: this.handleRedraftClick, dangerous: true });
    } else {
      menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
      menu.push({ text: intl.formatMessage(messages.direct, { name: status.getIn(['account', 'username']) }), action: this.handleDirectClick });
      menu.push(null);
      menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
      menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
      menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
      menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick, dangerous: true });
      menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport, dangerous: true });
      if (((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) || (isRemote && (permissions & PERMISSION_MANAGE_FEDERATION) === PERMISSION_MANAGE_FEDERATION)) {
        menu.push(null);
        if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS) {

M app/javascript/flavours/glitch/styles/components/misc.scss => app/javascript/flavours/glitch/styles/components/misc.scss +22 -154
@@ 534,36 534,18 @@ body > [data-popper-placement] {
}

.dropdown-animation {
  animation: dropdown 300ms cubic-bezier(0.1, 0.7, 0.1, 1);
  animation: dropdown 150ms cubic-bezier(0.1, 0.7, 0.1, 1);

  @keyframes dropdown {
    from {
      opacity: 0;
      transform: scaleX(0.85) scaleY(0.75);
    }

    to {
      opacity: 1;
      transform: scaleX(1) scaleY(1);
    }
  }

  &.top {
    transform-origin: bottom;
  }

  &.right {
    transform-origin: left;
  }

  &.bottom {
    transform-origin: top;
  }

  &.left {
    transform-origin: right;
  }

  .reduce-motion & {
    animation: none;
  }


@@ 579,16 561,17 @@ body > [data-popper-placement] {
}

.dropdown-menu__separator {
  border-bottom: 1px solid darken($ui-secondary-color, 8%);
  margin: 5px 7px 6px;
  border-bottom: 1px solid var(--dropdown-border-color);
  margin: 5px 0;
  height: 0;
}

.dropdown-menu {
  background: $ui-secondary-color;
  padding: 4px 0;
  background: var(--dropdown-background-color);
  border: 1px solid var(--dropdown-border-color);
  padding: 4px;
  border-radius: 4px;
  box-shadow: 2px 4px 15px rgba($base-shadow-color, 0.4);
  box-shadow: var(--dropdown-shadow);
  z-index: 9999;

  &__text-button {


@@ 609,12 592,13 @@ body > [data-popper-placement] {

  &__container {
    &__header {
      border-bottom: 1px solid darken($ui-secondary-color, 8%);
      padding: 4px 14px;
      padding-bottom: 8px;
      border-bottom: 1px solid var(--dropdown-border-color);
      padding: 10px 14px;
      padding-bottom: 14px;
      margin-bottom: 4px;
      font-size: 13px;
      line-height: 18px;
      color: $inverted-text-color;
      color: $darker-text-color;
    }

    &__list {


@@ 635,103 619,43 @@ body > [data-popper-placement] {
  }
}

.dropdown-menu__arrow {
  position: absolute;

  &::before {
    content: '';
    display: block;
    width: 14px;
    height: 5px;
    background-color: $ui-secondary-color;
    mask-image: url("data:image/svg+xml;utf8,<svg width='14' height='5' xmlns='http://www.w3.org/2000/svg'><path d='M7 0L0 5h14L7 0z' fill='white'/></svg>");
  }

  &.top {
    bottom: -5px;

    &::before {
      transform: rotate(180deg);
    }
  }

  &.right {
    inset-inline-start: -9px;

    &::before {
      transform: rotate(-90deg);
    }
  }

  &.bottom {
    top: -5px;
  }

  &.left {
    inset-inline-end: -9px;

    &::before {
      transform: rotate(90deg);
    }
  }
}

.dropdown-menu__item {
  font-size: 13px;
  line-height: 18px;
  font-weight: 500;
  display: block;
  color: $inverted-text-color;

  &--dangerous {
    color: $error-value-color;
  }

  a,
  button {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
    font: inherit;
    display: block;
    width: 100%;
    padding: 4px 14px;
    padding: 10px 14px;
    border: 0;
    margin: 0;
    background: transparent;
    box-sizing: border-box;
    text-decoration: none;
    background: $ui-secondary-color;
    color: inherit;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    text-align: inherit;
    border-radius: 4px;

    &:focus,
    &:hover,
    &:active {
      background: $ui-highlight-color;
      color: $secondary-text-color;
      background: var(--dropdown-border-color);
      outline: 0;
    }
  }
}

.dropdown-menu__item--text {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding: 4px 14px;
}

.dropdown-menu__item.edited-timestamp__history__item {
  border-bottom: 1px solid darken($ui-secondary-color, 8%);

  &:last-child {
    border-bottom: 0;
  }

  &.dropdown-menu__item--text,
  a,
  button {
    padding: 8px 14px;
  }
}

.inline-account {
  display: inline-flex;
  align-items: center;


@@ 747,62 671,6 @@ body > [data-popper-placement] {
  }
}

.dropdown--active .dropdown__content {
  display: block;
  line-height: 18px;
  max-width: 311px;
  inset-inline-end: 0;
  text-align: start;
  z-index: 9999;

  & > ul {
    list-style: none;
    background: $ui-secondary-color;
    padding: 4px 0;
    border-radius: 4px;
    box-shadow: 0 0 15px rgba($base-shadow-color, 0.4);
    min-width: 140px;
    position: relative;
  }

  &.dropdown__right {
    inset-inline-end: 0;
  }

  &.dropdown__left {
    & > ul {
      inset-inline-start: -98px;
    }
  }

  & > ul > li > a {
    font-size: 13px;
    line-height: 18px;
    display: block;
    padding: 4px 14px;
    box-sizing: border-box;
    text-decoration: none;
    background: $ui-secondary-color;
    color: $inverted-text-color;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;

    &:focus {
      outline: 0;
    }

    &:hover {
      background: $ui-highlight-color;
      color: $secondary-text-color;
    }
  }
}

.dropdown__icon {
  vertical-align: middle;
}

.static-content {
  padding: 10px;
  padding-top: 20px;

M app/javascript/flavours/glitch/styles/variables.scss => app/javascript/flavours/glitch/styles/variables.scss +7 -0
@@ 67,3 67,10 @@ $ui-avatar-border-size: 8%;

// More variables
$dismiss-overlay-width: 4rem;

:root {
  --dropdown-border-color: #{lighten($ui-base-color, 12%)};
  --dropdown-background-color: #{lighten($ui-base-color, 4%)};
  --dropdown-shadow: 0 20px 25px -5px #{rgba($base-shadow-color, 0.25)},
    0 8px 10px -6px #{rgba($base-shadow-color, 0.25)};
}