web/satellite: My Access Table style changes and search functionality (#4767)

Styled Access Grant Table according to new flow UX
Added search functionality to My Access Table. 
Separated search styles into 2 components


Co-authored-by: Moby von Briesen <mobyvb@gmail.com>
Co-authored-by: hovex023 <97616907+hovex023@users.noreply.github.com>
This commit is contained in:
cl-mitch 2022-05-20 09:54:26 -05:00 committed by GitHub
parent 7a2d2a36ca
commit 2b0016af62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 578 additions and 69 deletions

View File

@ -1,6 +1,5 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="access-grants">
<div v-if="!isNewAccessGrantFlow" class="access-grants__title-area">
@ -104,50 +103,102 @@
</div>
</div>
</div>
<VLoader v-if="areGrantsFetching" width="100px" height="100px" class="grants-loader" />
<div v-if="accessGrantsList.length && !areGrantsFetching" class="access-grants-items">
<SortAccessGrantsHeader :on-header-click-callback="onHeaderSectionClickCallback" />
<div class="access-grants-items__content">
<VList
:data-set="accessGrantsList"
:item-component="itemComponent"
:on-item-click="toggleSelection"
<div v-if="isNewAccessGrantFlow">
<div class="access-grants__header-container">
<h3 class="access-grants__header-container__title">My Accesses</h3>
<div class="access-grants__header-container__divider" />
<VHeader
class="access-header-component"
placeholder="Accesses"
:search="fetch"
style-type="access"
/>
</div>
<VPagination
v-if="totalPageCount > 1"
ref="pagination"
class="pagination-area"
:total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"
<VLoader v-if="areGrantsFetching" width="100px" height="100px" class="grants-loader" />
<div v-if="accessGrantsList.length && !areGrantsFetching" class="access-grants-items2">
<SortAccessGrantsHeader2
:on-header-click-callback="onHeaderSectionClickCallback"
/>
<div class="access-grants-items2__content">
<VList
:data-set="accessGrantsList"
:item-component="itemComponent2"
/>
</div>
<div class="access-grants-items2__footer">
<span class="access-grants-items2__footer__total-accesses">
{{ accessGrantsList.length }} Access Grants
</span>
<VPagination
v-if="totalPageCount > 1"
ref="pagination"
class="access-grants-items2__footer__pagination-area"
:total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"
/>
</div>
</div>
<div
v-if="!accessGrantsList.length && !areGrantsFetching"
class="access-grants-items2__empty-state"
>
<span class="access-grants-items2__empty-state__text">
No Results Found
</span>
</div>
<ConfirmDeletePopup
v-if="isDeleteClicked"
@close="onClearSelection"
@reset-pagination="resetPagination"
/>
</div>
<div v-if="!isNewAccessGrantFlow">
<VLoader v-if="areGrantsFetching" width="100px" height="100px" class="grants-loader" />
<div v-if="accessGrantsList.length && !areGrantsFetching" class="access-grants-items">
<SortAccessGrantsHeader :on-header-click-callback="onHeaderSectionClickCallback" />
<div class="access-grants-items__content">
<VList
:data-set="accessGrantsList"
:item-component="itemComponent"
:on-item-click="toggleSelection"
/>
</div>
<VPagination
v-if="totalPageCount > 1"
ref="pagination"
class="pagination-area"
:total-page-count="totalPageCount"
:on-page-click-callback="onPageClick"
/>
</div>
<EmptyState v-if="!accessGrantsList.length && !areGrantsFetching" />
<ConfirmDeletePopup
v-if="isDeleteClicked"
@close="onClearSelection"
@reset-pagination="resetPagination"
/>
</div>
<EmptyState v-if="!accessGrantsList.length && !areGrantsFetching" />
<ConfirmDeletePopup
v-if="isDeleteClicked"
@close="onClearSelection"
@reset-pagination="resetPagination"
/>
<router-view />
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { MetaUtils } from '@/utils/meta';
import AccessGrantsItem from '@/components/accessGrants/AccessGrantsItem.vue';
import AccessGrantsItem2 from '@/components/accessGrants/AccessGrantsItem2.vue';
import ConfirmDeletePopup from '@/components/accessGrants/ConfirmDeletePopup.vue';
import EmptyState from '@/components/accessGrants/EmptyState.vue';
import SortAccessGrantsHeader from '@/components/accessGrants/SortingHeader.vue';
import SortAccessGrantsHeader2 from '@/components/accessGrants/SortingHeader2.vue';
import VButton from '@/components/common/VButton.vue';
import VList from '@/components/common/VList.vue';
import VLoader from '@/components/common/VLoader.vue';
import VHeader from '@/components/common/VHeader.vue';
import VPagination from '@/components/common/VPagination.vue';
import AccessGrantsIcon from '@/../static/images/accessGrants/accessGrantsIcon.svg';
import CLIIcon from '@/../static/images/accessGrants/cli.svg';
import S3Icon from '@/../static/images/accessGrants/s3.svg';
import { RouteConfig } from '@/router';
import { ACCESS_GRANTS_ACTIONS } from '@/store/modules/accessGrants';
import { AccessGrant, AccessGrantsOrderBy } from '@/types/accessGrants';
@ -159,12 +210,11 @@ const {
CLEAR_SELECTION,
SET_SORT_BY,
SET_SORT_DIRECTION,
SET_SEARCH_QUERY,
} = ACCESS_GRANTS_ACTIONS;
declare interface ResetPagination {
resetPageIndex(): void;
}
// @vue/component
@Component({
components: {
@ -173,23 +223,19 @@ declare interface ResetPagination {
EmptyState,
S3Icon,
SortAccessGrantsHeader,
SortAccessGrantsHeader2,
VList,
VPagination,
VButton,
ConfirmDeletePopup,
VLoader,
VHeader,
},
})
export default class AccessGrants extends Vue {
private FIRST_PAGE = 1;
/**
* Indicates if delete confirmation state should appear.
*/
private isDeleteClicked = false;
public areGrantsFetching = true;
public $refs!: {
pagination: HTMLElement & ResetPagination;
};
@ -207,13 +253,11 @@ export default class AccessGrants extends Vue {
public async mounted(): Promise<void> {
try {
await this.$store.dispatch(FETCH, this.FIRST_PAGE);
this.areGrantsFetching = false;
} catch (error) {
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
}
}
/**
* Lifecycle hook before component destruction.
* Clears existing access grants selection.
@ -221,7 +265,6 @@ export default class AccessGrants extends Vue {
public beforeDestroy(): void {
this.onClearSelection();
}
/**
* Toggles access grant selection.
* @param accessGrant
@ -229,7 +272,6 @@ export default class AccessGrants extends Vue {
public async toggleSelection(accessGrant: AccessGrant): Promise<void> {
await this.$store.dispatch(TOGGLE_SELECTION, accessGrant);
}
/**
* Fetches access grants page by clicked index.
* @param index
@ -241,7 +283,6 @@ export default class AccessGrants extends Vue {
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
}
}
/**
* Used for sorting.
* @param sortBy
@ -255,12 +296,10 @@ export default class AccessGrants extends Vue {
} catch (error) {
await this.$notify.error(`Unable to fetch Access Grants. ${error.message}`);
}
if (this.totalPageCount > 1) {
this.resetPagination();
}
}
/**
* Resets pagination to default state.
*/
@ -269,21 +308,18 @@ export default class AccessGrants extends Vue {
this.$refs.pagination.resetPageIndex();
}
}
/**
* Starts create access grant flow.
*/
public onCreateClick(): void {
this.$router.push(RouteConfig.AccessGrants.with(RouteConfig.CreateAccessGrant).with(RouteConfig.NameStep).path);
}
/**
* Holds on button click login for deleting access grant process.
*/
public onDeleteClick(): void {
this.isDeleteClicked = true;
}
/**
* Clears access grants selection.
*/
@ -291,28 +327,39 @@ export default class AccessGrants extends Vue {
await this.$store.dispatch(CLEAR_SELECTION);
this.isDeleteClicked = false;
}
/**
* Returns delete access grants button label.
* Fetches Access records by name depending on search query.
*/
public async fetch(searchQuery: string): Promise<void> {
await this.$store.dispatch(SET_SEARCH_QUERY, searchQuery);
try {
await this.$store.dispatch(FETCH, 1);
} catch (error) {
await this.$notify.error(`Unable to fetch accesses: ${error.message}`);
}
}
public get deleteButtonLabel(): string {
return `Remove Selected (${this.selectedAccessGrantsAmount})`;
}
/**
* Returns access grants pages count from store.
*/
public get totalPageCount(): number {
return this.$store.state.accessGrantsModule.page.pageCount;
}
/**
* Returns AccessGrant item component.
*/
public get itemComponent(): typeof AccessGrantsItem {
return AccessGrantsItem;
}
/**
* Returns AccessGrant2 item component.
*/
public get itemComponent2(): typeof AccessGrantsItem2 {
return AccessGrantsItem2;
}
/**
* Returns access grants from store.
*/
@ -326,9 +373,9 @@ export default class AccessGrants extends Vue {
public get selectedAccessGrantsAmount(): number {
return this.$store.state.accessGrantsModule.selectedAccessGrantsIds.length;
}
}
</script>
<style scoped lang="scss">
@mixin grant-flow-card {
display: inline-block;
@ -433,9 +480,85 @@ export default class AccessGrants extends Vue {
border-radius: 0 0 8px 8px;
}
}
.access-grants-items2 {
position: relative;
&__content {
background-color: #fff;
display: flex;
flex-direction: column;
justify-content: flex-start;
}
&__footer {
background-color: #fff;
display: flex;
justify-content: space-between;
align-items: center;
height: 80px;
width: 100%;
border: 1px solid #e5e7eb;
border-radius: 0 0 8px 8px;
&__total-accesses {
height: 20px;
padding-left: 20px;
margin-left: 18px;
color: #2c353a;
}
&__pagination-area {
padding-right: 20px;
margin-bottom: 25px;
}
}
&__empty-state {
height: 75px;
width: auto;
background: white;
border-radius: 6px;
margin-top: 10px;
border: 1px solid #dadfe7;
display: flex;
justify-content: center;
&__text {
font-family: sans-serif;
font-size: 40px;
font-weight: 700;
margin: auto 0;
}
}
}
.access-grants__header-container {
&__header-container {
height: 90px;
}
&__title {
font-family: 'font_bold', sans-serif;
margin-top: 20px;
}
&__divider {
height: 1px;
width: auto;
background-color: #dadfe7;
margin-top: 10px;
}
&__access-header-component {
height: 55px !important;
margin-top: 15px;
}
}
}
.grants-loader {
margin-top: 50px;
}
</style>
</style>

View File

@ -112,4 +112,5 @@ export default class AccessGrantsItem extends Vue {
.date-item-container {
width: 40%;
}
</style>

View File

@ -0,0 +1,177 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="grants-item-container">
<div class="grants-item-container__common-info">
<div class="name-container" :title="itemData.name">
<p class="name">{{ itemData.name }}</p>
</div>
</div>
<div class="grants-item-container__common-info date-item-container">
<p class="date">{{ itemData.localDate() }}</p>
</div>
<div class="grants-item-container__common-info menu-item-container">
<p class="ellipses" @click="togglePopupVisibility">...</p>
<div
v-if="popupVisible"
v-click-outside="popupVisible"
class="popup-menu"
>
<p class="popup-menu__popup-details">
See Details
</p>
<div class="popup-menu__popup-divider" />
<p class="popup-menu__popup-delete">
Delete Access
</p>
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { AccessGrant } from '@/types/accessGrants';
// @vue/component
@Component({
components: {
},
})
export default class AccessGrantsItem extends Vue {
@Prop({ default: new AccessGrant('', '', new Date(), '') })
private readonly itemData: AccessGrant;
private popupVisible = false;
public togglePopupVisibility(): void {
this.popupVisible = !this.popupVisible;
}
}
</script>
<style scoped lang="scss">
@mixin popup-menu-button {
padding: 0 15px;
height: 50%;
line-height: 55px;
text-align: left;
font-family: 'font_regular', sans-serif;
color: #1b2533;
transition: 100ms;
}
.grants-item-container {
display: flex;
align-items: center;
justify-content: flex-start;
height: 83px;
background-color: #fff;
border: 1px solid #e5e7eb;
border-bottom: 0;
width: 100%;
&__common-info {
display: flex;
align-items: center;
justify-content: flex-start;
width: 60%;
}
}
.checkbox-container {
margin-left: 28px;
min-width: 21px;
min-height: 21px;
border-radius: 4px;
border: 1px solid #1b2533;
&__image {
display: none;
}
}
.name-container {
max-width: calc(100% - 131px);
margin-right: 15px;
}
.name {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 21px;
color: #354049;
margin-left: 38px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.date {
font-family: 'font_regular', sans-serif;
font-size: 16px;
line-height: 21px;
color: #354049;
margin: 0;
}
.ellipses {
margin: 0 auto 20px;
font-size: 30px;
font-weight: 1000;
color: #7c8794;
cursor: pointer;
}
.popup-menu {
width: 160px;
height: 100px;
position: absolute;
right: 70px;
bottom: -90px;
z-index: 1;
background: #fff;
border-radius: 10px;
box-shadow: 0 20px 34px rgb(10 27 44 / 28%);
&__popup-details {
@include popup-menu-button;
border-radius: 10px 10px 0 0;
&:hover {
background-color: #354049;
cursor: pointer;
color: #fff;
}
}
&__popup-divider {
height: 1px;
background-color: #e5e7eb;
}
&__popup-delete {
@include popup-menu-button;
border-radius: 0 0 10px 10px;
&:hover {
background-color: #b53737;
cursor: pointer;
color: #fff;
}
}
}
.date-item-container {
width: 50%;
}
.menu-item-container {
width: 10%;
position: relative;
}
</style>

View File

@ -0,0 +1,120 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="sort-header-container">
<div class="sort-header-container__name-item" @click="onHeaderItemClick(AccessGrantsOrderBy.NAME)">
<p class="sort-header-container__name-item__title">NAME</p>
<VerticalArrows
:is-active="areAccessGrantsSortedByName"
:direction="getSortDirection"
/>
</div>
<div class="sort-header-container__date-item" @click="onHeaderItemClick(AccessGrantsOrderBy.CREATED_AT)">
<p class="sort-header-container__date-item__title creation-date">DATE CREATED</p>
<VerticalArrows
:is-active="!areAccessGrantsSortedByName"
:direction="getSortDirection"
/>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import VerticalArrows from '@/components/common/VerticalArrows.vue';
import { AccessGrantsOrderBy, OnHeaderClickCallback } from '@/types/accessGrants';
import { SortDirection } from '@/types/common';
// @vue/component
@Component({
components: {
VerticalArrows,
},
})
export default class SortAccessGrantsHeader extends Vue {
@Prop({default: () => new Promise(() => false)})
private readonly onHeaderClickCallback: OnHeaderClickCallback;
public AccessGrantsOrderBy = AccessGrantsOrderBy;
public sortBy: AccessGrantsOrderBy = AccessGrantsOrderBy.NAME;
public sortDirection: SortDirection = SortDirection.ASCENDING;
/**
* Used for arrow styling.
*/
public get getSortDirection(): SortDirection {
return this.sortDirection === SortDirection.DESCENDING ? SortDirection.ASCENDING : SortDirection.DESCENDING;
}
public get areAccessGrantsSortedByName(): boolean {
return this.sortBy === AccessGrantsOrderBy.NAME;
}
/**
* Sets sorting kind if different from current.
* If same, changes sort direction.
* @param sortBy
*/
public async onHeaderItemClick(sortBy: AccessGrantsOrderBy): Promise<void> {
if (this.sortBy !== sortBy) {
this.sortBy = sortBy;
this.sortDirection = SortDirection.ASCENDING;
await this.onHeaderClickCallback(this.sortBy, this.sortDirection);
return;
}
this.sortDirection = this.sortDirection === SortDirection.DESCENDING ?
SortDirection.ASCENDING
: SortDirection.DESCENDING;
await this.onHeaderClickCallback(this.sortBy, this.sortDirection);
}
}
</script>
<style scoped lang="scss">
.sort-header-container {
display: flex;
width: calc(100% - 32px);
height: 40px;
background-color: #fff;
margin-top: 31px;
padding: 16px 16px 0;
border-radius: 8px 8px 0 0;
border: 1px solid #e5e7eb;
border-bottom: 0;
&__name-item,
&__date-item {
width: 50%;
display: flex;
align-items: center;
margin: 0;
cursor: pointer;
&__title {
font-family: 'font_medium', sans-serif;
font-size: 16px;
margin: 0 0 0 23px;
color: #2a2a32;
}
.creation-date {
margin-left: 0;
}
}
&__date-item {
&__title {
margin: 0;
}
}
}
</style>

View File

@ -6,11 +6,20 @@
<div class="header-container__buttons-area">
<slot />
</div>
<VSearch
ref="search"
:placeholder="placeholder"
:search="search"
/>
<div v-if="styleType === 'common'">
<VSearch
ref="search"
:placeholder="placeholder"
:search="search"
/>
</div>
<div v-if="styleType === 'access'">
<VSearchAlternateStyling
ref="search"
:placeholder="placeholder"
:search="search"
/>
</div>
</div>
</template>
@ -18,6 +27,7 @@
import { Component, Prop, Vue } from 'vue-property-decorator';
import VSearch from '@/components/common/VSearch.vue';
import VSearchAlternateStyling from '@/components/common/VSearchAlternateStyling.vue';
declare type searchCallback = (search: string) => Promise<void>;
@ -25,9 +35,12 @@ declare type searchCallback = (search: string) => Promise<void>;
@Component({
components: {
VSearch,
VSearchAlternateStyling,
},
})
export default class VHeader extends Vue {
@Prop({default: 'common'})
private readonly styleType: string;
@Prop({default: ''})
private readonly placeholder: string;
@Prop({default: function(): searchCallback {

View File

@ -54,7 +54,6 @@ export default class VSearch extends Vue {
*/
public onMouseEnter(): void {
this.inputWidth = '540px';
this.$refs.input.focus();
}
@ -103,8 +102,4 @@ export default class VSearch extends Vue {
background-size: 22px 22px;
background-position: top 16px right 16px;
}
::placeholder {
color: #afb7c1;
}
</style>
</style>

View File

@ -0,0 +1,77 @@
// Copyright (C) 2019 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<input
v-model="searchQuery"
class="access-search-input"
:placeholder="`Search ${placeholder}`"
type="text"
autocomplete="off"
@input="processSearchQuery"
>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
declare type searchCallback = (search: string) => Promise<void>;
// @vue/component
@Component
export default class VSearch extends Vue {
@Prop({default: ''})
private readonly placeholder: string;
@Prop({default: function(): searchCallback {
return async function(_: string) {};
}})
private readonly search: searchCallback;
private searchQuery = '';
public $refs!: {
input: HTMLElement;
};
public get searchString(): string {
return this.searchQuery;
}
/**
* Clears search query.
*/
public clearSearch(): void {
this.searchQuery = '';
this.processSearchQuery();
}
public async processSearchQuery(): Promise<void> {
await this.search(this.searchQuery);
}
}
</script>
<style scoped lang="scss">
.access-search-input {
position: absolute;
left: 0;
bottom: 0;
padding: 0 10px 0 50px;
box-sizing: border-box;
outline: none;
border: 1px solid #d8dee3;
border-radius: 10px;
height: 56px;
width: 250px;
font-family: 'font_regular', sans-serif;
font-size: 16px;
background-color: #fff;
background-image: url('../../../static/images/common/search-gray.png');
background-repeat: no-repeat;
background-size: 22px 22px;
background-position: top 16px left 16px;
}
::placeholder {
color: #afb7c1;
}
</style>

View File

@ -87,4 +87,4 @@ self.onmessage = async function (event) {
default:
self.postMessage(new Error('provided message event type is not supported'));
}
};
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 762 B

View File

@ -3,6 +3,9 @@
exports[`HeaderComponent.vue renders correctly 1`] = `
<div class="header-container">
<div class="header-container__buttons-area"></div>
<vsearch-stub placeholder="" search="[Function]"></vsearch-stub>
<div>
<vsearch-stub placeholder="" search="[Function]"></vsearch-stub>
</div>
<!---->
</div>
`;

View File

@ -5,7 +5,7 @@ exports[`BucketArea.vue renders correctly with bucket 1`] = `
<div class="buckets-overflow">
<div class="buckets-header">
<p class="buckets-header__title">Usage per bucket</p>
<vheader-stub placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
<vheader-stub styletype="common" placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
</div>
<div class="buckets-container">
<sortingheader-stub></sortingheader-stub>
@ -22,7 +22,7 @@ exports[`BucketArea.vue renders correctly with pagination 1`] = `
<div class="buckets-overflow">
<div class="buckets-header">
<p class="buckets-header__title">Usage per bucket</p>
<vheader-stub placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
<vheader-stub styletype="common" placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
</div>
<div class="buckets-container">
<sortingheader-stub></sortingheader-stub>
@ -48,7 +48,7 @@ exports[`BucketArea.vue renders correctly without search results 1`] = `
<div class="buckets-overflow">
<div class="buckets-header">
<p class="buckets-header__title">Usage per bucket</p>
<vheader-stub placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
<vheader-stub styletype="common" placeholder="Buckets" search="[Function]" class="buckets-header-component"></vheader-stub>
</div>
<!---->
<div class="empty-search-result-area">

View File

@ -7,7 +7,7 @@ exports[`Team HeaderArea renders correctly 1`] = `
<vinfo-stub title="" buttonlabel="" onbuttonclick="[Function]" class="team-header-container__title-area__info-button"></vinfo-stub>
</div>
<div class="team-header-container__wrapper">
<vheader-stub placeholder="Team Members" search="[Function]">
<vheader-stub styletype="common" placeholder="Team Members" search="[Function]">
<div class="header-default-state">
<vbutton-stub label="+ Add" width="122px" height="48px" fontsize="16px" borderradius="6px" onpress="[Function]" class="button"></vbutton-stub>
</div>
@ -28,7 +28,7 @@ exports[`Team HeaderArea renders correctly with 1 selected user and delete click
<vinfo-stub title="" buttonlabel="" onbuttonclick="[Function]" class="team-header-container__title-area__info-button"></vinfo-stub>
</div>
<div class="team-header-container__wrapper">
<vheader-stub placeholder="Team Members" search="[Function]">
<vheader-stub styletype="common" placeholder="Team Members" search="[Function]">
<!---->
<!---->
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete <b>1</b> user?</span>
@ -52,7 +52,7 @@ exports[`Team HeaderArea renders correctly with 2 selected users and delete clic
<vinfo-stub title="" buttonlabel="" onbuttonclick="[Function]" class="team-header-container__title-area__info-button"></vinfo-stub>
</div>
<div class="team-header-container__wrapper">
<vheader-stub placeholder="Team Members" search="[Function]">
<vheader-stub styletype="common" placeholder="Team Members" search="[Function]">
<!---->
<!---->
<div class="header-after-delete-click"><span class="header-after-delete-click__delete-confirmation">Are you sure you want to delete <b>2</b> users?</span>
@ -76,7 +76,7 @@ exports[`Team HeaderArea renders correctly with opened Add team member popup 1`]
<vinfo-stub title="" buttonlabel="" onbuttonclick="[Function]" class="team-header-container__title-area__info-button"></vinfo-stub>
</div>
<div class="team-header-container__wrapper">
<vheader-stub placeholder="Team Members" search="[Function]">
<vheader-stub styletype="common" placeholder="Team Members" search="[Function]">
<div class="header-default-state">
<vbutton-stub label="+ Add" width="122px" height="48px" fontsize="16px" borderradius="6px" onpress="[Function]" class="button"></vbutton-stub>
</div>
@ -97,7 +97,7 @@ exports[`Team HeaderArea renders correctly with selected users 1`] = `
<vinfo-stub title="" buttonlabel="" onbuttonclick="[Function]" class="team-header-container__title-area__info-button"></vinfo-stub>
</div>
<div class="team-header-container__wrapper">
<vheader-stub placeholder="Team Members" search="[Function]">
<vheader-stub styletype="common" placeholder="Team Members" search="[Function]">
<!---->
<div class="header-selected-members">
<vbutton-stub label="Delete" width="122px" height="48px" fontsize="16px" borderradius="6px" onpress="[Function]" class="button deletion"></vbutton-stub>