feat(frontend): redesign KanbanDetail modal - remove sidebar, add editable title, subtasks with drag-drop
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { Trash2, Pencil } from 'lucide-vue-next'
|
||||
|
||||
interface Task {
|
||||
id: string
|
||||
@@ -24,6 +25,8 @@ const emit = defineEmits<{
|
||||
|
||||
const activeTab = ref<'comments' | 'history'>('comments')
|
||||
const commentInput = ref('')
|
||||
const isEditingTitle = ref(false)
|
||||
const editingTitle = ref('')
|
||||
|
||||
const mockTask: Task = {
|
||||
id: '1',
|
||||
@@ -34,32 +37,138 @@ const mockTask: Task = {
|
||||
priority: '重要且紧急 (P1)',
|
||||
createdAt: '2024-03-21 14:49:35',
|
||||
}
|
||||
const description = ref('')
|
||||
|
||||
const agents = [
|
||||
{ id: 'planner', name: '规划师', icon: '📋' },
|
||||
{ id: 'executor', name: '执行者', icon: '⚡' },
|
||||
{ id: 'knowledge', name: '知识管理员', icon: '🧠' },
|
||||
{ id: 'analyst', name: '分析师', icon: '🔍' },
|
||||
{ id: 'coder', name: '程序员', icon: '💻' },
|
||||
{ id: 'researcher', name: '研究员', icon: '🔬' },
|
||||
]
|
||||
|
||||
const selectedAgent = ref(agents[0].id)
|
||||
|
||||
const priorities = [
|
||||
{ id: 'urgent-important', name: '重要且紧急', color: '#f56565' },
|
||||
{ id: 'not-urgent-important', name: '重要不紧急', color: '#ecc94b' },
|
||||
{ id: 'urgent-not-important', name: '紧急不重要', color: '#42b9f5' },
|
||||
{ id: 'not-urgent-not-important', name: '不重要不紧急', color: '#97c950' },
|
||||
]
|
||||
|
||||
const selectedPriority = ref('urgent-important')
|
||||
|
||||
const taskStatuses = [
|
||||
{ id: 'pending', name: '未完成' },
|
||||
{ id: 'in_progress', name: '进行中' },
|
||||
{ id: 'completed', name: '已完成' },
|
||||
]
|
||||
|
||||
const selectedStatus = ref('completed')
|
||||
|
||||
interface SubTask {
|
||||
id: number
|
||||
title: string
|
||||
completed: boolean
|
||||
subAgent: string
|
||||
}
|
||||
|
||||
const subtasks = ref<SubTask[]>([])
|
||||
let subtaskIdCounter = 0
|
||||
|
||||
// Drag and drop state
|
||||
const draggedIndex = ref<number | null>(null)
|
||||
const dragOverIndex = ref<number | null>(null)
|
||||
|
||||
function onDragStart(index: number) {
|
||||
draggedIndex.value = index
|
||||
}
|
||||
|
||||
function onDragOver(event: DragEvent, index: number) {
|
||||
event.preventDefault()
|
||||
dragOverIndex.value = index
|
||||
}
|
||||
|
||||
function onDragLeave() {
|
||||
dragOverIndex.value = null
|
||||
}
|
||||
|
||||
function onDrop(event: DragEvent, targetIndex: number) {
|
||||
event.preventDefault()
|
||||
if (draggedIndex.value !== null && draggedIndex.value !== targetIndex) {
|
||||
const item = subtasks.value.splice(draggedIndex.value, 1)[0]
|
||||
subtasks.value.splice(targetIndex, 0, item)
|
||||
}
|
||||
draggedIndex.value = null
|
||||
dragOverIndex.value = null
|
||||
}
|
||||
|
||||
function onDragEnd() {
|
||||
draggedIndex.value = null
|
||||
dragOverIndex.value = null
|
||||
}
|
||||
|
||||
function formatDate() {
|
||||
return new Date().toLocaleString('zh-CN')
|
||||
}
|
||||
|
||||
function startEditTitle() {
|
||||
editingTitle.value = mockTask.title
|
||||
isEditingTitle.value = true
|
||||
}
|
||||
|
||||
function saveTitle() {
|
||||
if (editingTitle.value.trim()) {
|
||||
mockTask.title = editingTitle.value.trim()
|
||||
}
|
||||
isEditingTitle.value = false
|
||||
}
|
||||
|
||||
function addSubtask() {
|
||||
subtasks.value.push({
|
||||
id: ++subtaskIdCounter,
|
||||
title: '',
|
||||
completed: false,
|
||||
subAgent: '',
|
||||
})
|
||||
}
|
||||
|
||||
function removeSubtask(index: number) {
|
||||
subtasks.value.splice(index, 1)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="kanban-detail-overlay" :class="{ visible }" @click.self="emit('close')">
|
||||
<div class="kanban-detail-panel">
|
||||
<button class="detail-close" type="button" aria-label="Close detail" @click="emit('close')">
|
||||
×
|
||||
</button>
|
||||
|
||||
<div class="detail-header">
|
||||
<div class="task-title-section">
|
||||
<div class="task-title">
|
||||
<span class="check-icon">☑</span>
|
||||
{{ mockTask.title }}
|
||||
<input
|
||||
v-if="isEditingTitle"
|
||||
v-model="editingTitle"
|
||||
class="title-input"
|
||||
maxlength="20"
|
||||
@blur="saveTitle"
|
||||
@keyup.enter="saveTitle"
|
||||
@keyup.escape="isEditingTitle = false"
|
||||
autofocus
|
||||
/>
|
||||
<span v-else class="title-text">{{ mockTask.title }}</span>
|
||||
<button class="btn-edit-title" type="button" title="修改标题" @click="startEditTitle">
|
||||
<Pencil :size="14" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="task-meta">
|
||||
<span class="avatar">C</span>
|
||||
{{ mockTask.assignee }} 创建于:{{ mockTask.createdAt }}
|
||||
创建于:{{ mockTask.createdAt }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="status-badge" :style="{ background: quadrantColor + '20', color: quadrantColor }">
|
||||
✓
|
||||
<div class="header-actions">
|
||||
<button class="btn-delete-icon" type="button" title="删除任务">
|
||||
<Trash2 :size="16" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -70,25 +179,40 @@ function formatDate() {
|
||||
<span class="icon">☞</span>
|
||||
描述
|
||||
</div>
|
||||
<div class="description-box">
|
||||
添加详细描述...
|
||||
</div>
|
||||
<textarea
|
||||
v-model="description"
|
||||
class="description-box"
|
||||
placeholder="添加详细描述..."
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div class="task-info-list">
|
||||
<div class="info-item">
|
||||
<span class="icon">☰</span>
|
||||
负责人:<span class="avatar">C</span>{{ mockTask.assignname }}
|
||||
主负责指挥官:
|
||||
<select v-model="selectedAgent" class="agent-select">
|
||||
<option v-for="agent in agents" :key="agent.id" :value="agent.id">
|
||||
{{ agent.icon }} {{ agent.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="icon">⚑</span>
|
||||
优先级:<span class="priority-high">{{ mockTask.priority }}</span>
|
||||
优先级:
|
||||
<select v-model="selectedPriority" class="priority-select">
|
||||
<option v-for="p in priorities" :key="p.id" :value="p.id">
|
||||
{{ p.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="info-item">
|
||||
<span class="icon">📅</span>
|
||||
任务状态:<span :class="{ 'status-completed': mockTask.completed }">
|
||||
{{ mockTask.completed ? '已完成' : '进行中' }}
|
||||
</span>
|
||||
任务状态:
|
||||
<select v-model="selectedStatus" class="status-select">
|
||||
<option v-for="s in taskStatuses" :key="s.id" :value="s.id">
|
||||
{{ s.name }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -98,9 +222,44 @@ function formatDate() {
|
||||
<span class="icon">☑</span>
|
||||
子任务
|
||||
</span>
|
||||
<button class="btn-add-subtask" type="button">添加子任务</button>
|
||||
<button class="btn-add-subtask" type="button" @click="addSubtask">添加子任务</button>
|
||||
</div>
|
||||
<div v-if="subtasks.length === 0" class="subtask-empty">暂无子任务</div>
|
||||
<div v-else class="subtask-list">
|
||||
<div
|
||||
v-for="(subtask, index) in subtasks"
|
||||
:key="subtask.id"
|
||||
class="subtask-item"
|
||||
:class="{ 'drag-over': dragOverIndex === index }"
|
||||
draggable="true"
|
||||
@dragstart="onDragStart(index)"
|
||||
@dragover="onDragOver($event, index)"
|
||||
@dragleave="onDragLeave"
|
||||
@drop="onDrop($event, index)"
|
||||
@dragend="onDragEnd"
|
||||
>
|
||||
<button class="subtask-drag" type="button" title="拖动排序">⋮⋮</button>
|
||||
<input
|
||||
type="checkbox"
|
||||
v-model="subtask.completed"
|
||||
class="subtask-checkbox"
|
||||
/>
|
||||
<input
|
||||
v-model="subtask.title"
|
||||
class="subtask-input"
|
||||
:class="{ completed: subtask.completed }"
|
||||
placeholder="输入子任务名称..."
|
||||
@keyup.enter="addSubtask"
|
||||
/>
|
||||
<select v-model="subtask.subAgent" class="subtask-agent">
|
||||
<option value="">子指挥官</option>
|
||||
<option v-for="agent in agents" :key="agent.id" :value="agent.id">
|
||||
{{ agent.icon }} {{ agent.name }}
|
||||
</option>
|
||||
</select>
|
||||
<button class="subtask-delete" type="button" @click="removeSubtask(index)">×</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="subtask-empty">暂无子任务</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
@@ -120,41 +279,6 @@ function formatDate() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar">
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">✂</span>
|
||||
标记未完成
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">↻</span>
|
||||
优先级
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">👤</span>
|
||||
负责人
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">📆</span>
|
||||
计划时间
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">📎</span>
|
||||
添加附件
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">📧</span>
|
||||
关注人
|
||||
</button>
|
||||
<button class="sidebar-btn" type="button">
|
||||
<span class="icon">📁</span>
|
||||
归档
|
||||
</button>
|
||||
<button class="sidebar-btn btn-delete" type="button">
|
||||
<span class="icon">🗑</span>
|
||||
删除
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -200,23 +324,6 @@ function formatDate() {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.detail-close {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 20px;
|
||||
font-size: 28px;
|
||||
color: #ff4d4f;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
line-height: 1;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.detail-close:hover {
|
||||
color: #ff7875;
|
||||
}
|
||||
|
||||
.detail-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@@ -225,8 +332,38 @@ function formatDate() {
|
||||
border-bottom: 1px solid rgba(0, 243, 255, 0.1);
|
||||
}
|
||||
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.btn-delete-icon {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(255, 77, 79, 0.3);
|
||||
background: rgba(255, 77, 79, 0.08);
|
||||
color: #ff4d4f;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-delete-icon:hover {
|
||||
background: rgba(255, 77, 79, 0.2);
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
|
||||
.btn-delete-icon :deep(svg) {
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
.task-title-section {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
@@ -234,13 +371,71 @@ function formatDate() {
|
||||
font-weight: 600;
|
||||
color: #e0f7ff;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.check-icon {
|
||||
color: #52c41a;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.title-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.title-input {
|
||||
font-size: 22px;
|
||||
font-weight: 600;
|
||||
font-family: inherit;
|
||||
color: #e0f7ff;
|
||||
background: rgba(0, 243, 255, 0.08);
|
||||
border: 1px solid rgba(0, 243, 255, 0.3);
|
||||
border-radius: 6px;
|
||||
padding: 4px 10px;
|
||||
outline: none;
|
||||
min-width: 200px;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.title-input:focus {
|
||||
border-color: rgba(0, 243, 255, 0.6);
|
||||
box-shadow: 0 0 12px rgba(0, 245, 212, 0.2);
|
||||
}
|
||||
|
||||
.btn-edit-title {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid transparent;
|
||||
background: transparent;
|
||||
color: var(--text-dim);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.task-title:hover .btn-edit-title {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.btn-edit-title:hover {
|
||||
background: rgba(0, 243, 255, 0.1);
|
||||
border-color: rgba(0, 243, 255, 0.2);
|
||||
color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
.btn-edit-title :deep(svg) {
|
||||
stroke: currentColor;
|
||||
}
|
||||
|
||||
.task-meta {
|
||||
@@ -262,20 +457,7 @@ function formatDate() {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.status-badge {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 36px;
|
||||
}
|
||||
|
||||
.detail-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 240px;
|
||||
gap: 20px;
|
||||
padding: 20px 24px;
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@@ -320,13 +502,27 @@ function formatDate() {
|
||||
}
|
||||
|
||||
.description-box {
|
||||
width: 100%;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(0, 243, 255, 0.1);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
min-height: 60px;
|
||||
min-height: 100px;
|
||||
color: var(--text-dim);
|
||||
font-size: 14px;
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.description-box:focus {
|
||||
border-color: rgba(0, 243, 255, 0.3);
|
||||
}
|
||||
|
||||
.description-box::placeholder {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.task-info-list {
|
||||
@@ -350,6 +546,80 @@ function formatDate() {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.agent-select {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(0, 243, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #e0f7ff;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
padding: 6px 10px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.agent-select:hover {
|
||||
border-color: rgba(0, 243, 255, 0.4);
|
||||
}
|
||||
|
||||
.agent-select:focus {
|
||||
border-color: rgba(0, 243, 255, 0.5);
|
||||
}
|
||||
|
||||
.agent-select option {
|
||||
background: #0a0f1a;
|
||||
color: #e0f7ff;
|
||||
}
|
||||
|
||||
.priority-select {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(0, 243, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #e0f7ff;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
padding: 6px 10px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.priority-select:hover {
|
||||
border-color: rgba(0, 243, 255, 0.4);
|
||||
}
|
||||
|
||||
.priority-select:focus {
|
||||
border-color: rgba(0, 243, 255, 0.5);
|
||||
}
|
||||
|
||||
.priority-select option,
|
||||
.status-select option {
|
||||
background: #0a0f1a;
|
||||
color: #e0f7ff;
|
||||
}
|
||||
|
||||
.status-select {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(0, 243, 255, 0.2);
|
||||
border-radius: 6px;
|
||||
color: #e0f7ff;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
padding: 6px 10px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.status-select:hover {
|
||||
border-color: rgba(0, 243, 255, 0.4);
|
||||
}
|
||||
|
||||
.status-select:focus {
|
||||
border-color: rgba(0, 243, 255, 0.5);
|
||||
}
|
||||
|
||||
.priority-high {
|
||||
color: #ff4d4f;
|
||||
font-weight: 600;
|
||||
@@ -385,6 +655,124 @@ function formatDate() {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.subtask-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.subtask-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border: 1px solid rgba(0, 243, 255, 0.08);
|
||||
border-radius: 8px;
|
||||
transition: border-color var(--transition-fast), opacity var(--transition-fast);
|
||||
}
|
||||
|
||||
.subtask-item.drag-over {
|
||||
border-color: rgba(0, 243, 255, 0.5);
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
.subtask-checkbox {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.subtask-input {
|
||||
flex: 1;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #e0f7ff;
|
||||
font-size: 13px;
|
||||
font-family: inherit;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.subtask-input.completed {
|
||||
text-decoration: line-through;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.subtask-input::placeholder {
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.subtask-delete {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-dim);
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all var(--transition-fast);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.subtask-delete:hover {
|
||||
background: rgba(255, 77, 79, 0.2);
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.subtask-drag {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--text-dim);
|
||||
font-size: 14px;
|
||||
cursor: grab;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
transition: all var(--transition-fast);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.subtask-drag:hover {
|
||||
background: rgba(0, 243, 255, 0.1);
|
||||
color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
.subtask-agent {
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 1px solid rgba(0, 243, 255, 0.15);
|
||||
border-radius: 4px;
|
||||
color: #e0f7ff;
|
||||
font-size: 11px;
|
||||
font-family: inherit;
|
||||
padding: 4px 6px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
transition: border-color var(--transition-fast);
|
||||
flex-shrink: 0;
|
||||
min-width: 80px;
|
||||
}
|
||||
|
||||
.subtask-agent:hover {
|
||||
border-color: rgba(0, 243, 255, 0.3);
|
||||
}
|
||||
|
||||
.subtask-agent:focus {
|
||||
border-color: rgba(0, 243, 255, 0.4);
|
||||
}
|
||||
|
||||
.subtask-agent option {
|
||||
background: #0a0f1a;
|
||||
color: #e0f7ff;
|
||||
}
|
||||
|
||||
.comment-empty {
|
||||
color: var(--text-dim);
|
||||
font-size: 14px;
|
||||
@@ -436,46 +824,6 @@ function formatDate() {
|
||||
background: rgba(0, 243, 255, 0.2);
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sidebar-btn {
|
||||
padding: 10px 14px;
|
||||
border: 1px solid rgba(0, 243, 255, 0.15);
|
||||
border-radius: 6px;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
color: #e0f7ff;
|
||||
font-size: 13px;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.sidebar-btn:hover {
|
||||
border-color: rgba(0, 243, 255, 0.4);
|
||||
background: rgba(0, 243, 255, 0.08);
|
||||
}
|
||||
|
||||
.sidebar-btn .icon {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.sidebar-btn.btn-delete {
|
||||
border-color: rgba(255, 77, 79, 0.3);
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
.sidebar-btn.btn-delete:hover {
|
||||
background: rgba(255, 77, 79, 0.1);
|
||||
border-color: #ff4d4f;
|
||||
}
|
||||
|
||||
/* Scrollbar styling */
|
||||
.detail-content::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
|
||||
Reference in New Issue
Block a user