src/main.ts
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import './styles.css'
createApp(App).use(ElementPlus).mount('#app')
Online Element Plus playground with Vue 3, TypeScript, editable components, enterprise tables, forms, dialogs, and instant live preview.
Choose a source file from the explorer and edit it with Monaco.
Edit package.json to add browser-compatible npm packages or change versions. Preview packages load from esm.sh. Successful previews save resolved versions for ranges and tags with your draft and shares; change the range to resolve again. Scripts and build plugins run only in downloaded projects.
Auto-run updates the browser preview as you type. Turn it off to run your changes manually.
Use the console for browser logs and errors, or evaluate a command against the preview.
Share creates a snapshot link. Download exports the source so you can continue locally.
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import './styles.css'
createApp(App).use(ElementPlus).mount('#app')
<script setup lang="ts">
import { computed, reactive, ref } from 'vue'
import { ElMessage } from 'element-plus'
import TeamTable from './components/TeamTable.vue'
type TeamStatus = 'Active' | 'Review' | 'Away'
interface TeamMember {
id: number
name: string
email: string
role: string
team: string
status: TeamStatus
joined: string
}
const search = ref('')
const statusFilter = ref<'All' | TeamStatus>('All')
const inviteOpen = ref(false)
const nextMemberId = ref(6)
const members = ref<TeamMember[]>([
{ id: 1, name: 'Maya Chen', email: '[email protected]', role: 'Product lead', team: 'Core product', status: 'Active', joined: 'Jul 08' },
{ id: 2, name: 'Noah Williams', email: '[email protected]', role: 'Staff engineer', team: 'Platform', status: 'Active', joined: 'Jun 24' },
{ id: 3, name: 'Ari Patel', email: '[email protected]', role: 'Product designer', team: 'Core product', status: 'Review', joined: 'Jun 14' },
{ id: 4, name: 'Sofia Garcia', email: '[email protected]', role: 'Data analyst', team: 'Insights', status: 'Away', joined: 'May 30' },
{ id: 5, name: 'Elliot Brown', email: '[email protected]', role: 'Growth engineer', team: 'Activation', status: 'Active', joined: 'May 17' },
])
const invitation = reactive({
name: '',
email: '',
role: 'Product designer',
})
const activeMembers = computed(
() => members.value.filter((member) => member.status === 'Active').length,
)
const reviewMembers = computed(
() => members.value.filter((member) => member.status === 'Review').length,
)
function updateStatus(id: number, status: TeamStatus) {
const member = members.value.find((item) => item.id === id)
if (!member) return
member.status = status
ElMessage.success(`${member.name} is now ${status.toLowerCase()}`)
}
function inviteMember() {
if (!invitation.name.trim() || !invitation.email.trim()) {
ElMessage.warning('Add a name and email address')
return
}
members.value.unshift({
id: nextMemberId.value++,
name: invitation.name.trim(),
email: invitation.email.trim(),
role: invitation.role,
team: 'Core product',
status: 'Review',
joined: 'Just now',
})
inviteOpen.value = false
ElMessage.success(`Invitation sent to ${invitation.name}`)
invitation.name = ''
invitation.email = ''
invitation.role = 'Product designer'
}
</script>
<template>
<el-config-provider>
<div class="workspace-shell">
<header class="topbar">
<div class="brand">
<span class="brand-mark">E+</span>
<div>
<strong>Northstar</strong>
<span>Team workspace</span>
</div>
</div>
<nav class="topbar-nav" aria-label="Workspace navigation">
<a href="#overview" class="active">Overview</a>
<a href="#team">People</a>
<a href="#activity">Activity</a>
</nav>
<div class="topbar-actions">
<el-badge :value="reviewMembers" :hidden="reviewMembers === 0">
<el-button plain>Reviews</el-button>
</el-badge>
<el-avatar :size="38">DM</el-avatar>
</div>
</header>
<main id="overview" class="page">
<section class="hero">
<div>
<p class="eyebrow">WORKSPACE ADMIN</p>
<h1>People and access</h1>
<p>
Manage your team, roles, and account access from one clear workspace.
</p>
</div>
<el-button type="primary" size="large" @click="inviteOpen = true">
Invite teammate
</el-button>
</section>
<section class="metrics" aria-label="Team metrics">
<el-card shadow="never">
<span class="metric-label">Total members</span>
<strong>{{ members.length }}</strong>
<small>Across four product teams</small>
</el-card>
<el-card shadow="never">
<span class="metric-label">Active now</span>
<strong>{{ activeMembers }}</strong>
<small class="success">All systems operational</small>
</el-card>
<el-card shadow="never">
<span class="metric-label">Pending review</span>
<strong>{{ reviewMembers }}</strong>
<small>Access requests to approve</small>
</el-card>
<el-card shadow="never" class="usage-card">
<div class="usage-heading">
<span class="metric-label">Seat usage</span>
<strong>{{ members.length }}/12</strong>
</div>
<el-progress
:percentage="Math.round((members.length / 12) * 100)"
:show-text="false"
:stroke-width="8"
/>
<small>{{ 12 - members.length }} seats available</small>
</el-card>
</section>
<el-card id="team" class="team-panel" shadow="never">
<template #header>
<div class="panel-heading">
<div>
<h2>Team directory</h2>
<p>Review member access and workspace roles.</p>
</div>
<div class="filters">
<el-input
v-model="search"
clearable
placeholder="Search members"
aria-label="Search members"
/>
<el-select
v-model="statusFilter"
aria-label="Filter by status"
style="width: 142px"
>
<el-option label="All statuses" value="All" />
<el-option label="Active" value="Active" />
<el-option label="Review" value="Review" />
<el-option label="Away" value="Away" />
</el-select>
</div>
</div>
</template>
<TeamTable
:members="members"
:query="search"
:status-filter="statusFilter"
@status-change="updateStatus"
/>
</el-card>
<section id="activity" class="activity-grid">
<el-card shadow="never">
<template #header>
<div class="compact-heading">
<strong>Account health</strong>
<el-tag type="success" effect="light" round>Healthy</el-tag>
</div>
</template>
<el-alert
title="Two-factor authentication is enabled"
description="All workspace admins are protected."
type="success"
:closable="false"
show-icon
/>
</el-card>
<el-card shadow="never">
<template #header>
<strong>Latest activity</strong>
</template>
<el-timeline>
<el-timeline-item timestamp="10 minutes ago" type="primary">
Maya updated the launch workspace
</el-timeline-item>
<el-timeline-item timestamp="Yesterday">
Noah invited a platform engineer
</el-timeline-item>
</el-timeline>
</el-card>
</section>
</main>
<el-dialog
v-model="inviteOpen"
title="Invite a teammate"
width="min(92vw, 480px)"
align-center
>
<el-form label-position="top">
<el-form-item label="Name">
<el-input v-model="invitation.name" placeholder="Alex Morgan" />
</el-form-item>
<el-form-item label="Work email">
<el-input
v-model="invitation.email"
type="email"
placeholder="[email protected]"
/>
</el-form-item>
<el-form-item label="Role">
<el-select v-model="invitation.role" style="width: 100%">
<el-option label="Product designer" value="Product designer" />
<el-option label="Software engineer" value="Software engineer" />
<el-option label="Data analyst" value="Data analyst" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="inviteOpen = false">Cancel</el-button>
<el-button type="primary" @click="inviteMember">Send invitation</el-button>
</template>
</el-dialog>
</div>
</el-config-provider>
</template>
The editor uses Monaco, the engine behind VS Code, with language-aware editing tools and familiar keyboard controls.
Edit a source file from the project explorer — the live preview recompiles automatically.
Add, rename, duplicate or delete project files as needed. Update affected imports after renaming or moving a file.
Use the console for logs and errors, and Format to tidy the active file.
Share the complete project or download a Vite project ZIP with its source files and package.json.
Element Plus 2
Vue 3 + TypeScript
Enterprise UI Components
Tables and Forms
Dialogs and Feedback
Local Component Imports
Live Preview
Auto-run updates the preview as you type. Turn it off to run manually with Run or Ctrl/⌘ + Enter.
The Console prompt can inspect browser globals and the rendered DOM, but not variables scoped inside ES modules or component state.
Console shortcuts apply when its prompt is focused. Editor shortcuts apply inside the code editor.
Code runs in a sandboxed browser preview, without Node.js, a backend, or private environment variables.
Download the project when you need build plugins, server APIs, native modules, or a production dependency workflow.