style: 일정 화면 UI 다듬기 (기존 디자인 규격에 통일)

- 툴바 '오늘' 버튼 제거, 컨트롤 간격을 전역 .toolbar(0.625rem)와 통일
- 타임라인 레인 hover 편집/삭제 버튼 제거(카테고리 관리는 유형 필터에서)
- 유형 필터 버튼을 기존 DropdownSelect pill 디자인으로 통일 + 수량 뱃지 제거
- '새 일정' 버튼의 스코프 .btn 재정의 제거 → 전역 .btn primary 표준 사용
- 일정/카테고리 모달을 사이트 폼 모달 규격(rem + 멤버 초대 모달)으로 재정렬,
  라벨 좌측정렬, 취소/저장 버튼을 전역 .mbtn 으로 통일
- 참석자 아바타를 공용 UserAvatar 방식(이미지/실루엣)으로 교체,
  '전 직원' 표식 크기를 아바타와 동일(20px)하게 고정(루트 14px rem 보정)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 23:24:33 +09:00
parent 346ec75553
commit d5b54c1afb
6 changed files with 217 additions and 383 deletions
@@ -1,68 +1,62 @@
<script setup lang="ts">
// 일정 참석자 아바타 — avatarUrl 있으면 이미지, 없으면 이름 첫 글자 + 파생색
// 일정 참석자 아바타 — 사이트 공용 UserAvatar 와 동일한 방식.
// 프로필 이미지가 있으면 사진, 없으면 사람 실루엣 placeholder(색상+이니셜 방식은 폐기).
import { computed } from 'vue'
const props = withDefaults(
defineProps<{
name: string
name?: string
avatarUrl?: string | null
size?: number
mono?: boolean
}>(),
{ avatarUrl: null, size: 21, mono: false },
{ name: '', avatarUrl: null, size: 21 },
)
// 이름 → 안정적 색상(시안 avColor 포팅)
const AV_COLORS = [
'#d0982a',
'#e0518d',
'#3d8bf2',
'#16a37b',
'#b3631f',
'#7c5cf0',
'#0e9594',
'#d6455d',
]
const color = computed(() => {
const sum = [...(props.name || '?')].reduce((a, c) => a + c.charCodeAt(0), 0)
return AV_COLORS[sum % AV_COLORS.length]
})
const initial = computed(() => (props.name || '?').trim()[0] ?? '?')
const bg = computed(() => (props.mono ? '#aeb4bd' : color.value))
const dim = computed(() => `${props.size}px`)
</script>
<template>
<img
v-if="avatarUrl"
class="sa"
:src="avatarUrl"
:alt="name"
:style="{ width: `${size}px`, height: `${size}px` }"
>
<span
v-else
class="sa sa-ph"
:style="{
width: `${size}px`,
height: `${size}px`,
fontSize: `${size * 0.47}px`,
background: bg,
}"
>{{ initial }}</span>
class="sa"
:style="{ width: dim, height: dim }"
>
<img
v-if="avatarUrl"
class="sa-img"
:src="avatarUrl"
:alt="name || '프로필 이미지'"
>
<svg
v-else
class="sa-ph"
viewBox="0 0 24 24"
fill="currentColor"
aria-hidden="true"
>
<path d="M12 12.5a4.25 4.25 0 1 0 0-8.5 4.25 4.25 0 0 0 0 8.5Z" />
<path d="M4.5 19.25c0-3.04 3.36-5 7.5-5s7.5 1.96 7.5 5v.75H4.5v-.75Z" />
</svg>
</span>
</template>
<style scoped>
.sa {
display: grid;
place-items: center;
border-radius: 50%;
overflow: hidden;
background: #e5e7eb;
flex-shrink: 0;
}
.sa-img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.sa-ph {
display: grid;
place-items: center;
font-weight: 700;
color: #fff;
line-height: 1;
width: 64%;
height: 64%;
color: #9aa1ac;
}
</style>
@@ -115,13 +115,13 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
</div>
<div class="modal-foot">
<button
class="btn"
class="mbtn"
@click="emit('close')"
>
취소
</button>
<button
class="btn primary"
class="mbtn primary"
:disabled="!valid"
@click="submit"
>
@@ -137,87 +137,90 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
position: fixed;
inset: 0;
z-index: 100;
background: rgba(20, 24, 33, 0.34);
background: rgba(20, 24, 33, 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
padding: 1.5rem;
}
.modal {
width: 540px;
max-width: 100%;
background: var(--panel);
border-radius: 14px;
box-shadow: 0 24px 70px rgba(20, 24, 33, 0.34);
width: 100%;
max-width: 33.75rem;
background: #fff;
border-radius: 0.875rem;
box-shadow: 0 24px 64px rgba(20, 24, 33, 0.32);
display: flex;
flex-direction: column;
}
.modal.modal-sm {
width: 408px;
max-width: 27.5rem;
}
.modal-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 17px 22px;
border-bottom: 1px solid var(--border);
padding: 1.375rem 1.5rem 1rem;
}
.modal-head h3 {
font-size: 16px;
font-size: 1.0625rem;
font-weight: 700;
letter-spacing: -0.2px;
letter-spacing: -0.01875rem;
}
.modal-x {
width: 30px;
height: 30px;
width: 2rem;
height: 2rem;
border: none;
background: transparent;
color: var(--text-3);
border-radius: 6px;
border-radius: var(--radius-sm);
cursor: pointer;
display: grid;
place-items: center;
margin-right: -5px;
margin-right: -0.3125rem;
}
.modal-x:hover {
background: #f1f2f4;
color: var(--text);
}
.modal-x svg {
width: 17px;
height: 17px;
width: 1.125rem;
height: 1.125rem;
}
.modal-body {
padding: 18px 22px;
padding: 0.5rem 1.5rem 0.75rem;
display: flex;
flex-direction: column;
gap: 14px;
gap: 1.125rem;
/* 전역 .modal-body(확인 다이얼로그용)의 가운데 정렬을 폼 모달에선 왼쪽으로 */
text-align: left;
}
.modal-foot {
display: flex;
justify-content: flex-end;
gap: 8px;
padding: 13px 22px;
gap: 0.5625rem;
padding: 1rem 1.5rem;
border-top: 1px solid var(--border);
background: #fafbfc;
border-radius: 0 0 0.875rem 0.875rem;
}
.f-field {
display: flex;
flex-direction: column;
gap: 6px;
gap: 0.5rem;
}
.f-label {
font-size: 12px;
font-size: 0.781rem;
font-weight: 600;
color: var(--text-2);
}
.f-input {
width: 100%;
height: 38px;
padding: 0 11px;
height: 2.5rem;
padding: 0 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 7px;
border-radius: var(--radius);
font-family: inherit;
font-size: 13.5px;
font-size: 0.844rem;
color: var(--text);
background: #fff;
}
@@ -232,12 +235,12 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
.cat-color {
display: flex;
align-items: center;
gap: 12px;
gap: 0.75rem;
}
.cat-dot {
width: 24px;
height: 24px;
border-radius: 7px;
width: 1.5rem;
height: 1.5rem;
border-radius: var(--radius);
flex-shrink: 0;
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.08);
}
@@ -245,9 +248,9 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
-webkit-appearance: none;
appearance: none;
flex: 1;
height: 16px;
margin: 6px 0;
border-radius: 8px;
height: 1rem;
margin: 0.375rem 0;
border-radius: 0.5rem;
cursor: pointer;
outline: none;
background: linear-gradient(
@@ -264,8 +267,8 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
.hue-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 24px;
height: 24px;
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
background: var(--cur);
border: 3px solid #fff;
@@ -273,45 +276,28 @@ onBeforeUnmount(() => document.removeEventListener('keydown', onKey))
cursor: grab;
}
.hue-slider::-moz-range-thumb {
width: 24px;
height: 24px;
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
background: var(--cur);
border: 3px solid #fff;
box-shadow: 0 1px 4px rgba(20, 24, 33, 0.4);
cursor: grab;
}
.btn {
height: 38px;
padding: 0 15px;
border-radius: var(--radius);
font-size: 13.5px;
font-weight: 600;
border: 1px solid var(--border-strong);
background: var(--panel);
color: var(--text-2);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
line-height: 1;
/* 푸터 버튼 — 전역 .mbtn(확인 다이얼로그용 flex:1) 대신 폼 모달용 우측정렬 컴팩트(멤버 초대 모달과 동일).
색/서체/테두리는 전역 .mbtn / .mbtn.primary 가 담당한다. */
.mbtn {
flex: 0 0 auto;
height: 2.375rem;
padding: 0 1rem;
}
.btn:hover {
background: #f7f8fa;
color: var(--text);
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #fff;
box-shadow: 0 1px 2px rgba(79, 70, 229, 0.4);
}
.btn.primary:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
}
.btn:disabled {
.mbtn:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.mbtn.primary:disabled,
.mbtn.primary:disabled:hover {
background: var(--accent);
border-color: var(--accent);
}
</style>
@@ -319,13 +319,13 @@ function submit(): void {
</div>
<div class="modal-foot">
<button
class="btn"
class="mbtn"
@click="emit('close')"
>
취소
</button>
<button
class="btn primary"
class="mbtn primary"
:disabled="!valid"
@click="submit"
>
@@ -337,24 +337,25 @@ function submit(): void {
</template>
<style scoped>
/* 사이트 공통 폼 모달 규격(멤버 초대 모달 + relay.css 토큰)에 맞춤 — rem 단위 */
.modal-back {
position: fixed;
inset: 0;
z-index: 100;
background: rgba(20, 24, 33, 0.34);
background: rgba(20, 24, 33, 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 24px;
padding: 1.5rem;
}
.modal {
width: 540px;
max-width: 100%;
width: 100%;
max-width: 33.75rem;
max-height: 90vh;
overflow-y: auto;
background: var(--panel);
border-radius: 14px;
box-shadow: 0 24px 70px rgba(20, 24, 33, 0.34);
background: #fff;
border-radius: 0.875rem;
box-shadow: 0 24px 64px rgba(20, 24, 33, 0.32);
display: flex;
flex-direction: column;
}
@@ -362,72 +363,74 @@ function submit(): void {
display: flex;
align-items: center;
justify-content: space-between;
padding: 17px 22px;
border-bottom: 1px solid var(--border);
padding: 1.375rem 1.5rem 1rem;
position: sticky;
top: 0;
background: var(--panel);
border-radius: 14px 14px 0 0;
background: #fff;
border-radius: 0.875rem 0.875rem 0 0;
}
.modal-head h3 {
font-size: 16px;
font-size: 1.0625rem;
font-weight: 700;
letter-spacing: -0.2px;
letter-spacing: -0.01875rem;
}
.modal-x {
width: 30px;
height: 30px;
width: 2rem;
height: 2rem;
border: none;
background: transparent;
color: var(--text-3);
border-radius: 6px;
border-radius: var(--radius-sm);
cursor: pointer;
display: grid;
place-items: center;
margin-right: -5px;
margin-right: -0.3125rem;
}
.modal-x:hover {
background: #f1f2f4;
color: var(--text);
}
.modal-x svg {
width: 17px;
height: 17px;
width: 1.125rem;
height: 1.125rem;
}
.modal-body {
padding: 18px 22px;
padding: 0.5rem 1.5rem 0.75rem;
display: flex;
flex-direction: column;
gap: 14px;
gap: 1.125rem;
/* 전역 .modal-body(확인 다이얼로그용)의 가운데 정렬을 폼 모달에선 왼쪽으로 */
text-align: left;
}
.modal-foot {
display: flex;
justify-content: flex-end;
gap: 8px;
padding: 13px 22px;
gap: 0.5625rem;
padding: 1rem 1.5rem;
border-top: 1px solid var(--border);
background: #fafbfc;
position: sticky;
bottom: 0;
background: var(--panel);
border-radius: 0 0 0.875rem 0.875rem;
}
.f-field {
display: flex;
flex-direction: column;
gap: 6px;
gap: 0.5rem;
}
.f-label {
font-size: 12px;
font-size: 0.781rem;
font-weight: 600;
color: var(--text-2);
}
.f-input {
width: 100%;
height: 38px;
padding: 0 11px;
height: 2.5rem;
padding: 0 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 7px;
border-radius: var(--radius);
font-family: inherit;
font-size: 13.5px;
font-size: 0.844rem;
color: var(--text);
background: #fff;
}
@@ -441,14 +444,14 @@ function submit(): void {
}
.f-textarea {
height: auto;
padding: 9px 11px;
padding: 0.625rem 0.75rem;
resize: vertical;
line-height: 1.55;
min-height: 72px;
line-height: 1.5;
min-height: 5.75rem;
}
.f-row {
display: flex;
gap: 12px;
gap: 0.75rem;
}
.f-row .f-field {
flex: 1;
@@ -461,13 +464,12 @@ function submit(): void {
-webkit-appearance: none;
appearance: none;
width: 100%;
height: 38px;
padding: 0 34px 0 11px;
height: 2.5rem;
padding: 0 2.125rem 0 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 7px;
border-radius: var(--radius);
font-family: inherit;
font-size: 13.5px;
font-weight: 500;
font-size: 0.844rem;
color: var(--text);
background: #fff;
cursor: pointer;
@@ -479,7 +481,7 @@ function submit(): void {
}
.f-select-chev {
position: absolute;
right: 10px;
right: 0.625rem;
top: 50%;
transform: translateY(-50%);
display: grid;
@@ -487,13 +489,13 @@ function submit(): void {
pointer-events: none;
}
.f-select-chev svg {
width: 15px;
height: 15px;
width: 0.9375rem;
height: 0.9375rem;
}
.time-row {
display: flex;
align-items: center;
gap: 10px;
gap: 0.625rem;
}
.time-input {
width: auto;
@@ -509,15 +511,15 @@ function submit(): void {
.ms-field {
display: flex;
align-items: center;
gap: 8px;
gap: 0.5rem;
width: 100%;
height: 38px;
padding: 0 10px 0 11px;
height: 2.5rem;
padding: 0 0.625rem 0 0.75rem;
border: 1px solid var(--border-strong);
border-radius: 7px;
border-radius: var(--radius);
background: #fff;
font-family: inherit;
font-size: 13.5px;
font-size: 0.844rem;
color: var(--text);
cursor: pointer;
text-align: left;
@@ -535,48 +537,47 @@ function submit(): void {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-weight: 500;
}
.ms-field .chev {
display: grid;
color: var(--text-3);
}
.ms-field .chev svg {
width: 15px;
height: 15px;
width: 0.9375rem;
height: 0.9375rem;
}
.ms-panel {
position: absolute;
top: calc(100% + 5px);
top: calc(100% + 0.375rem);
left: 0;
right: 0;
z-index: 10;
max-height: 220px;
max-height: 13.75rem;
overflow-y: auto;
background: var(--panel);
background: #fff;
border: 1px solid var(--border);
border-radius: 9px;
border-radius: 0.5625rem;
box-shadow: var(--shadow-pop);
padding: 5px;
padding: 0.375rem;
}
.ms-item {
display: flex;
align-items: center;
gap: 8px;
gap: 0.5rem;
width: 100%;
border: none;
background: none;
font-family: inherit;
font-size: 13px;
font-size: 0.8125rem;
font-weight: 600;
color: var(--text-2);
padding: 7px 8px;
border-radius: 6px;
padding: 0.4375rem 0.5rem;
border-radius: var(--radius-sm);
cursor: pointer;
text-align: left;
}
.ms-item:hover {
background: #f4f5f7;
background: #f5f6f8;
}
.ms-item.on {
color: var(--text);
@@ -595,16 +596,17 @@ function submit(): void {
place-items: center;
}
.ms-item .ms-check svg {
width: 15px;
height: 15px;
width: 0.9375rem;
height: 0.9375rem;
}
.ms-all {
/* 참석자 아바타(ScheduleAvatar :size="20" = 20px)와 동일 크기로 고정 */
width: 20px;
height: 20px;
border-radius: 50%;
display: grid;
place-items: center;
font-size: 9.5px;
font-size: 9px;
font-weight: 700;
color: #fff;
background: #9298a3;
@@ -613,49 +615,27 @@ function submit(): void {
.ms-div {
height: 1px;
background: var(--border);
margin: 4px 2px;
margin: 0.25rem 0.125rem;
}
.ms-empty {
padding: 12px 8px;
font-size: 12.5px;
padding: 0.75rem 0.5rem;
font-size: 0.781rem;
color: var(--text-3);
text-align: center;
}
.btn {
height: 38px;
padding: 0 15px;
border-radius: var(--radius);
font-size: 13.5px;
font-weight: 600;
border: 1px solid var(--border-strong);
background: var(--panel);
color: var(--text-2);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
line-height: 1;
white-space: nowrap;
/* 푸터 버튼 — 전역 .mbtn(확인 다이얼로그용 flex:1) 대신 폼 모달용 우측정렬 컴팩트(멤버 초대 모달과 동일).
색/서체/테두리는 전역 .mbtn / .mbtn.primary 가 담당한다. */
.mbtn {
flex: 0 0 auto;
height: 2.375rem;
padding: 0 1rem;
}
.btn:hover {
background: #f7f8fa;
color: var(--text);
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #fff;
box-shadow: 0 1px 2px rgba(79, 70, 229, 0.4);
}
.btn.primary:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
}
.btn:disabled {
.mbtn:disabled {
opacity: 0.45;
cursor: not-allowed;
}
.btn:disabled:hover {
.mbtn.primary:disabled,
.mbtn.primary:disabled:hover {
background: var(--accent);
border-color: var(--accent);
}
@@ -15,8 +15,6 @@ const props = defineProps<{
const emit = defineEmits<{
(e: 'select', id: string): void
(e: 'add-category'): void
(e: 'edit-category', id: string): void
(e: 'delete-category', id: string): void
}>()
const COLW = 156
@@ -153,36 +151,6 @@ function onBodyScroll(): void {
:style="{ background: lane.cat.color }"
/>
<span class="ll-name">{{ lane.cat.label }}</span>
<span class="ll-acts">
<button
class="ll-btn"
title="편집"
@click="emit('edit-category', lane.cat.id)"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M12 20h9M16.5 3.5a2.1 2.1 0 0 1 3 3L7 19l-4 1 1-4Z" /></svg>
</button>
<button
class="ll-btn"
title="삭제"
@click="emit('delete-category', lane.cat.id)"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
><path d="M3 6h18M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2m2 0v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6" /><path d="M10 11v6M14 11v6" /></svg>
</button>
</span>
</div>
<!-- 트랙 -->
@@ -357,33 +325,6 @@ function onBodyScroll(): void {
overflow: hidden;
text-overflow: ellipsis;
}
.tl-label .ll-acts {
display: none;
gap: 1px;
flex-shrink: 0;
}
.tl-label:hover .ll-acts {
display: flex;
}
.ll-btn {
width: 25px;
height: 25px;
border: none;
background: transparent;
color: var(--text-3);
border-radius: 5px;
cursor: pointer;
display: grid;
place-items: center;
}
.ll-btn:hover {
background: #eceef1;
color: var(--text);
}
.ll-btn svg {
width: 14px;
height: 14px;
}
.tl-addrow {
border-top: 1px solid var(--border);
}
@@ -30,11 +30,10 @@ onBeforeUnmount(() => document.removeEventListener('mousedown', onDoc))
const ordered = computed(() =>
[...props.categories].sort((a, b) => a.sortOrder - b.sortOrder),
)
const activeCount = computed(
() => ordered.value.filter((c) => props.activeTypeIds.has(c.id)).length,
)
const allOn = computed(
() => activeCount.value === ordered.value.length && ordered.value.length > 0,
() =>
ordered.value.length > 0 &&
ordered.value.every((c) => props.activeTypeIds.has(c.id)),
)
</script>
@@ -44,7 +43,8 @@ const allOn = computed(
class="filter"
>
<button
class="btn filter-btn"
type="button"
class="filter-btn"
:class="{ open }"
@click="open = !open"
>
@@ -58,10 +58,6 @@ const allOn = computed(
stroke-linejoin="round"
><path d="M22 3H2l8 9.46V19l4 2v-8.54L22 3z" /></svg>
</span>유형
<span
v-if="!allOn"
class="filter-badge"
>{{ activeCount }}</span>
<span class="chev">
<svg
viewBox="0 0 24 24"
@@ -168,64 +164,53 @@ const allOn = computed(
.filter {
position: relative;
}
.btn {
height: 36px;
padding: 0 15px;
border-radius: var(--radius);
font-size: 13.5px;
font-weight: 600;
border: 1px solid var(--border-strong);
background: var(--panel);
color: var(--text-2);
cursor: pointer;
/* 트리거 — 기존 정렬/필터 드롭다운(DropdownSelect)과 동일한 pill 외형 */
.filter-btn {
display: inline-flex;
align-items: center;
gap: 7px;
line-height: 1;
gap: 0.4375rem;
height: 2.25rem;
padding: 0 0.625rem;
border: 1px solid var(--border-strong);
border-radius: var(--radius);
background: #fff;
font-family: inherit;
font-size: 0.8125rem;
font-weight: 500;
color: var(--text-2);
cursor: pointer;
white-space: nowrap;
line-height: 1;
}
.btn:hover {
background: #f7f8fa;
color: var(--text);
}
.filter-btn .fic {
display: grid;
}
.filter-btn .fic svg {
width: 15px;
height: 15px;
}
.filter-btn .chev {
display: grid;
transition: transform 0.15s ease;
opacity: 0.55;
margin-left: -1px;
}
.filter-btn .chev svg {
width: 14px;
height: 14px;
.filter-btn:hover {
background: #f9fafb;
}
.filter-btn.open {
background: #f1f2f4;
color: var(--text);
border-color: var(--border-strong);
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-weak);
}
.filter-btn .fic {
display: inline-flex;
flex-shrink: 0;
color: var(--text-3);
}
.filter-btn .fic svg {
width: 0.9375rem;
height: 0.9375rem;
}
.filter-btn .chev {
display: inline-flex;
flex-shrink: 0;
color: var(--text-3);
transition: transform 0.15s ease;
}
.filter-btn .chev svg {
width: 0.875rem;
height: 0.875rem;
}
.filter-btn.open .chev {
transform: rotate(180deg);
}
.filter-badge {
background: var(--accent);
color: #fff;
font-size: 11px;
font-weight: 700;
border-radius: 9px;
min-width: 18px;
height: 18px;
padding: 0 5px;
display: grid;
place-items: center;
line-height: 1;
}
.filter-menu {
position: absolute;
top: calc(100% + 7px);
+3 -55
View File
@@ -134,12 +134,6 @@ async function onDeleteCategory(id: string): Promise<void> {
><path d="m9 18 6-6-6-6" /></svg>
</button>
</div>
<button
class="today-btn"
@click="store.goToday()"
>
오늘
</button>
<span class="range">{{ store.rangeLabel }}</span>
</div>
<div class="spacer" />
@@ -179,8 +173,6 @@ async function onDeleteCategory(id: string): Promise<void> {
:sel-id="selId"
@select="selId = $event"
@add-category="openNewCategory"
@edit-category="openEditCategory"
@delete-category="onDeleteCategory"
/>
</div>
<div
@@ -228,7 +220,8 @@ async function onDeleteCategory(id: string): Promise<void> {
.toolbar {
display: flex;
align-items: center;
gap: 14px;
/* 프로젝트 목록 등 전역 .toolbar 와 동일한 컨트롤 간격 */
gap: 0.625rem;
padding: 11px 24px;
flex-shrink: 0;
border-bottom: 1px solid var(--border);
@@ -275,55 +268,10 @@ async function onDeleteCategory(id: string): Promise<void> {
width: 16px;
height: 16px;
}
.today-btn {
height: 32px;
padding: 0 13px;
border-radius: var(--radius-sm);
border: 1px solid var(--border-strong);
background: #fff;
font-family: inherit;
font-size: 13px;
font-weight: 600;
color: var(--text-2);
cursor: pointer;
}
.today-btn:hover {
background: #f7f8fa;
color: var(--text);
}
.spacer {
flex: 1;
}
.btn {
height: 36px;
padding: 0 15px;
border-radius: var(--radius);
font-size: 13.5px;
font-weight: 600;
border: 1px solid var(--border-strong);
background: var(--panel);
color: var(--text-2);
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 6px;
line-height: 1;
white-space: nowrap;
}
.btn svg {
width: 15px;
height: 15px;
}
.btn.primary {
background: var(--accent);
border-color: var(--accent);
color: #fff;
box-shadow: 0 1px 2px rgba(79, 70, 229, 0.4);
}
.btn.primary:hover {
background: var(--accent-hover);
border-color: var(--accent-hover);
}
/* '새 일정' 버튼은 전역 .btn / .btn.primary 표준(다른 화면의 주요 버튼과 동일)을 그대로 사용 */
.content-row {
flex: 1;
min-height: 0;