Team
A member list with invitation and removal callbacks.
Give your AI assistant this page as context.
Connect your library with MCPLoading Vue preview…
blocks/teamUsage
Choose Vue in the Studio and export your saved library, or install this item through its connected CLI/MCP. Vue setup and Nuxt integration.
<script setup lang="ts">
import TeamBlock from './components/blocks/team.vue'
</script>
<!-- Supply the required props and callbacks listed in Source and props. -->Design system
This Vue component consumes the same CodeRocket tokens as the React version. Import the compiled styles and wrap your app in ThemeScope. Tailwind is optional.
Behavior and accessibility
Vue uses native events, v-model and slots. Reka UI handles keyboard and focus behavior in complex primitives. Connect actions to your own application and review labels, contrast and mobile behavior in context. Components are experimental during early access.
The full ZIP also includes examples/block-showcase.vue, with populated block props, illustrations and local sample callbacks to adapt to your application.
Source and props
This is the exact Vue single-file component delivered by the export. Related helpers and dependencies are included automatically.
<script setup lang="ts">
import WorkspaceHeading from "./workspace-heading.vue";
import ActionForm from "./action-form.vue";
import type { FormAction } from "./common";
import Card from "../ui/card.vue";
import Dialog from "../ui/dialog.vue";
import Button from "../ui/button.vue";
import Field from "../ui/field.vue";
import Input from "../ui/input.vue";
import Avatar from "../ui/avatar.vue";
import Badge from "../ui/badge.vue";
import { UserRoundPlus, UsersRound, Trash2 } from "@lucide/vue";
import { ref } from "vue";
import type { TeamMember } from "./common";
const props = defineProps<{
members: TeamMember[];
onInvite: FormAction;
onRemove: (id: string) => void | Promise<void>;
}>();
const removing = ref<string | null>(null),
error = ref(false);
async function remove(id: string) {
if (removing.value) return;
removing.value = id;
error.value = false;
try {
await props.onRemove(id);
} catch {
error.value = true;
} finally {
removing.value = null;
}
}
</script>
<template>
<Card class="cr-workspace-block cr-workspace-team"
><WorkspaceHeading
eyebrow="People & access"
title="Your team"
description="Good work starts with the right people."
><template #action
><Dialog
title="Invite someone to your team"
description="Enter the email address of the person you’d like to invite."
:footer="null"
><template #trigger
><Button variant="outline"
><UserRoundPlus :size="16" aria-hidden="true" />Invite
member</Button
></template
><ActionForm
:on-submit="onInvite"
submit-label="Send invitation"
success-message="Invitation sent."
><Field label="Email address"
><Input
name="email"
type="email"
autocomplete="email"
placeholder="colleague@company.com"
required /></Field></ActionForm></Dialog></template
></WorkspaceHeading>
<div class="cr-workspace-list-heading">
<span><UsersRound :size="15" aria-hidden="true" />Team members</span
><Badge variant="outline"
>{{ members.length }}
{{ members.length === 1 ? "member" : "members" }}</Badge
>
</div>
<ul class="cr-workspace-list cr-workspace-member-list">
<li v-for="member in members" :key="member.id">
<Avatar :name="member.name" :size="36" />
<div class="cr-workspace-person">
<strong>{{ member.name }}</strong
><span>{{ member.email }}</span>
</div>
<Badge variant="outline">{{ member.role }}</Badge
><Button
variant="ghost"
size="sm"
class="cr-workspace-icon-button"
:disabled="!!removing"
:loading="removing === member.id"
:aria-label="`Remove ${member.name}`"
@click="remove(member.id)"
><Trash2 v-if="removing !== member.id" :size="16" aria-hidden="true"
/></Button>
</li>
</ul>
<p v-if="!members.length" class="cr-block-empty">
No team members yet. Invite someone to get started.
</p>
<p v-if="error" role="alert" class="cr-description">
Unable to remove this member.
</p></Card
>
</template>