vuesion/vuesion

View on GitHub
src/components/marketing/ValueProposition/ValueProposition.vue

Summary

Maintainability
Test Coverage
A
100%
<template>
  <section :class="$style.valueProposition">
    <vue-content-block>
      <vue-columns :space="[24, 24, 24, 48]" stack-phone stack-tablet-portrait stack-tablet-landscape>
        <vue-column :width="['content', 'content', 'content', 'content']" :can-grow="false">
          <vue-box :padding="[16, 16, 16, '144 0']">
            <vue-hidden small-desktop large-desktop>
              <vue-text look="h3" color="text-high" weight="semi-bold" :align="['left', 'center', 'center', 'left']">
                Built for modern product teams
              </vue-text>
            </vue-hidden>

            <vue-stack space="16">
              <vue-hidden phone tablet-portrait tablet-landscape>
                <vue-text look="description" color="text-high" weight="semi-bold">
                  Built for modern product teams
                </vue-text>
              </vue-hidden>

              <ul :class="$style.nav">
                <li
                  tabindex="0"
                  @keypress.space.enter.stop.prevent="onTabChange(0)"
                  @click.stop.prevent="onTabChange(0)"
                >
                  <vue-text look="description" :color="activeTab === 0 ? 'info' : 'text-low'">Product Manager</vue-text>
                </li>
                <li
                  tabindex="0"
                  @keypress.space.enter.stop.prevent="onTabChange(1)"
                  @click.stop.prevent="onTabChange(1)"
                >
                  <vue-text look="description" :color="activeTab === 1 ? 'info' : 'text-low'">
                    Engineering Manager
                  </vue-text>
                </li>
                <li
                  tabindex="0"
                  @keypress.space.enter.stop.prevent="onTabChange(2)"
                  @click.stop.prevent="onTabChange(2)"
                >
                  <vue-text look="description" :color="activeTab === 2 ? 'info' : 'text-low'">Designer</vue-text>
                </li>
                <li
                  tabindex="0"
                  @keypress.space.enter.stop.prevent="onTabChange(3)"
                  @click.stop.prevent="onTabChange(3)"
                >
                  <vue-text look="description" :color="activeTab === 3 ? 'info' : 'text-low'">Engineer</vue-text>
                </li>
                <li
                  tabindex="0"
                  @keypress.space.enter.stop.prevent="onTabChange(4)"
                  @click.stop.prevent="onTabChange(4)"
                >
                  <vue-text look="description" :color="activeTab === 4 ? 'info' : 'text-low'">Team</vue-text>
                </li>
              </ul>
            </vue-stack>
          </vue-box>
        </vue-column>
        <vue-column :width="['content']" :can-grow="false">
          <vue-box :padding="[16, 16, 16, 0]">
            <vue-stack :space="[64, 64, 64, 0]" :align-x="['start', 'center', 'center', 'start']">
              <vue-stack :space="[8, 8, 8, 24]" :class="[$style.valueProp, activeTab === 0 ? $style.in : $style.out]">
                <vue-badge status="info" :class="$style.mobileBadge">Product Manager</vue-badge>

                <vue-text color="text-high" look="h4" weight="semi-bold">
                  All you need for a productive product team
                </vue-text>

                <ul :class="$style.list">
                  <li>
                    <vue-text look="description" color="text-medium">
                      the design system increases the collaboration process between design, engineering, and product
                      management
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      productive from day one - more time to solve pain points for your users rather than implementing
                      common features
                    </vue-text>
                  </li>
                </ul>
              </vue-stack>

              <vue-stack :space="[8, 8, 8, 24]" :class="[$style.valueProp, activeTab === 1 ? $style.in : $style.out]">
                <vue-badge status="info" :class="$style.mobileBadge">Engineering Manager</vue-badge>

                <vue-text color="text-high" look="h4" weight="semi-bold">
                  Enable your team to work agile and stay on top of things
                </vue-text>

                <ul :class="$style.list">
                  <li>
                    <vue-text look="description" color="text-medium">
                      community best practices support your team to maintain a clean codebase
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      set up that forces testing best practices, a high test coverage and lots of example tests support
                      an agile project management style
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      the 100% customizable design system and corresponding Figma file will increase the collaboration
                      across disciplines and deliver perfect brand identity (designers will love it)
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      the accessible codebase enables everyone in the team to contribute (even PMs and Designers) and
                      makes on-boarding new team members fun
                    </vue-text>
                  </li>
                </ul>
              </vue-stack>

              <vue-stack :space="[8, 8, 8, 24]" :class="[$style.valueProp, activeTab === 2 ? $style.in : $style.out]">
                <vue-badge status="info" :class="$style.mobileBadge">Designer</vue-badge>

                <vue-text color="text-high" look="h4" weight="semi-bold">
                  All the best user experience & interface practices built-in
                </vue-text>

                <ul :class="$style.list">
                  <li>
                    <vue-text look="description" color="text-medium">
                      benefit from practices that worked well across many project types and don't fall into traps that
                      we already experienced
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      the Figma file that is 100% in sync with the implemented design system will make the work with
                      engineering fun and helps the communication and collaboration across disciplines by providing a
                      common vocabulary
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      designed for modularity and reusability
                    </vue-text>
                  </li>
                </ul>
              </vue-stack>

              <vue-stack :space="[8, 8, 8, 24]" :class="[$style.valueProp, activeTab === 3 ? $style.in : $style.out]">
                <vue-badge status="info" :class="$style.mobileBadge">Engineer</vue-badge>

                <vue-text color="text-high" look="h4" weight="semi-bold">
                  Keep your codebase clean and focus on your domain logic
                </vue-text>

                <ul :class="$style.list">
                  <li>
                    <vue-text look="description" color="text-medium">
                      most common use-cases, tools, libraries, and technologies already set up will give you more time
                      to focus on building a great product
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      set up that forces testing best practices, high test coverage and lots of examples will help the
                      team to keep the codebase agile and to welcome changing requirements
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      the 100% customizable design system and corresponding Figma file will increase the collaboration
                      across disciplines and deliver perfect brand identity (designers will love it)
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      server-side-rendering set up and ready to use to satisfy the projects SEO needs (not mandatory -
                      start with an SPA until you need it!)
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      speed up your work and keep your code consistent with code generators for components, stories,
                      tests, pages, vuex-modules, interfaces and fixtures
                    </vue-text>
                  </li>
                </ul>
              </vue-stack>

              <vue-stack :space="[8, 8, 8, 24]" :class="[$style.valueProp, activeTab === 4 ? $style.in : $style.out]">
                <vue-badge status="info" :class="$style.mobileBadge">Team</vue-badge>

                <vue-text color="text-high" look="h4" weight="semi-bold"> Happy, Happy, Happy 😊 </vue-text>

                <ul :class="$style.list">
                  <li>
                    <vue-text look="description" color="text-medium">
                      improve communication across disciplines by using the design system documentation - let everyone
                      in your project know how you call the things!
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      focus on solving pain points for your users to create an awesome product and don't waste time on
                      common features
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      ship a consistent looking product that your users will love
                    </vue-text>
                  </li>
                  <li>
                    <vue-text look="description" color="text-medium">
                      prepared to grow and scale as your project matures
                    </vue-text>
                  </li>
                </ul>
              </vue-stack>
            </vue-stack>
          </vue-box>
        </vue-column>
      </vue-columns>

      <nuxt-img
        src="/images/team-small.png"
        format="webp"
        width="924px"
        height="680px"
        alt="productive team"
        fit="fill"
        quality="50"
        loading="lazy"
        :class="[$style.image, activeTab === 0 ? $style.in : $style.out]"
      />
      <nuxt-img
        src="/images/coverage-small.png"
        format="webp"
        width="924px"
        height="680px"
        alt="agile development"
        fit="fill"
        quality="50"
        loading="lazy"
        :class="[$style.image, activeTab === 1 ? $style.in : $style.out]"
      />
      <nuxt-img
        src="/images/figma-small.png"
        format="webp"
        width="924px"
        height="680px"
        alt="includes figma file"
        fit="fill"
        quality="50"
        loading="lazy"
        :class="[$style.image, activeTab === 2 ? $style.in : $style.out]"
      />
      <nuxt-img
        src="/images/cli-small.png"
        format="webp"
        width="924px"
        height="680px"
        alt="generator CLI to automate tasks"
        fit="fill"
        quality="50"
        loading="lazy"
        :class="[$style.image, activeTab === 3 ? $style.in : $style.out]"
      />
      <nuxt-img
        src="/images/team-small.png"
        format="webp"
        width="924px"
        height="680px"
        alt="happy team"
        fit="fill"
        quality="50"
        loading="lazy"
        :class="[$style.image, activeTab === 4 ? $style.in : $style.out]"
      />
    </vue-content-block>
  </section>
</template>

<script setup lang="ts">
import { ref, useCssModule } from 'vue';
import VueColumns from '~/components/layout/VueColumns/VueColumns.vue';
import VueColumn from '~/components/layout/VueColumns/VueColumn/VueColumn.vue';
import VueText from '~/components/typography/VueText/VueText.vue';
import VueBox from '~/components/layout/VueBox/VueBox.vue';
import VueStack from '~/components/layout/VueStack/VueStack.vue';
import VueContentBlock from '~/components/layout/VueContentBlock/VueContentBlock.vue';
import VueHidden from '~/components/utils/VueHidden/VueHidden.vue';
import VueBadge from '~/components/data-display/VueBadge/VueBadge.vue';

// Deps
const $style = useCssModule();

// Data
const activeTab = ref(0);
const onTabChange = (tab: number) => {
  activeTab.value = tab;
};
</script>

<style lang="scss" module>
@import 'assets/_design-system.scss';

.valueProposition {
  position: relative;

  > div {
    height: 100%;
    overflow-x: clip;
  }

  .nav,
  .image {
    display: none;
  }

  .list {
    list-style: disc;
    padding-left: $space-20;
  }

  @include mediaMax(tabletLandscape) {
    .valueProp {
      position: relative;
      max-width: 430px;

      .mobileBadge {
        position: absolute;
        left: 0;
        top: -$space-20;
      }
    }
  }

  @include mediaMin(smallDesktop) {
    height: 800px;
    overflow: hidden;

    .nav,
    .image {
      display: block;
    }

    .mobileBadge {
      display: none;
    }

    .nav {
      padding: 0;
      margin: 0;

      li {
        display: flex;
        padding: $space-16 0;
        border-bottom: 1px solid var(--brand-border-default-medium);
        cursor: pointer;

        &:focus {
          outline: none;
          box-shadow: var(--brand-focused);
        }

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

    .out {
      transform: translateY(100%);
      opacity: 0;
    }

    .in {
      transform: translateY(0);
      opacity: 1;
    }

    .valueProp {
      position: absolute;
      top: 145px;
      max-width: 430px;
      transition: all var(--brand-transition-duration) var(--brand-easing-curve);
    }

    .image {
      position: absolute;
      top: 50px;
      right: 0;
      transform: translateX(50%);
      transition: all var(--brand-transition-duration) var(--brand-easing-curve);
      background-repeat: no-repeat;
      background-size: cover;
      background-position: left;
    }

    @include mediaMin(largeDesktop) {
      .image {
        transform: translateX(40%);
      }
    }
  }
}
</style>