diff --git a/src/components/Sing/SequencerNote.vue b/src/components/Sing/SequencerNote.vue index a54e535f4e..5e29c6d8e4 100644 --- a/src/components/Sing/SequencerNote.vue +++ b/src/components/Sing/SequencerNote.vue @@ -3,7 +3,8 @@ class="note" :class="{ selected: noteState === 'SELECTED', - overlapping: noteState === 'OVERLAPPING', + overlapping: hasOverlappingError, + 'invalid-phrase': hasPhraseError, 'below-pitch': showPitch, }" :style="{ @@ -35,6 +36,26 @@ @keydown.stop="onLyricInputKeyDown" @blur="onLyricInputBlur" /> + + ノートが重なっています + + + フレーズが生成できません。歌詞は日本語1文字までです。 + @@ -50,7 +71,12 @@ import { import ContextMenu from "@/components/Menu/ContextMenu.vue"; import { MenuItemButton } from "@/components/Menu/type"; -type NoteState = "NORMAL" | "SELECTED" | "OVERLAPPING"; +type NoteState = + | "NORMAL" + | "SELECTED" + | "RESIZING_LEFT" + | "RESIZING_RIGHT" + | "MOVING"; const vFocus = { mounted(el: HTMLInputElement) { @@ -102,11 +128,27 @@ const noteState = computed((): NoteState => { if (props.isSelected) { return "SELECTED"; } - if (state.overlappingNoteIds.has(props.note.id)) { - return "OVERLAPPING"; - } return "NORMAL"; }); + +// ノートの重なりエラー +const hasOverlappingError = computed(() => { + return state.overlappingNoteIds.has(props.note.id); +}); + +// フレーズ生成エラー +const hasPhraseError = computed(() => { + const phrases = state.phrases; + return Array.from(phrases.values()).some((phrase) => { + if (phrase.state !== "COULD_NOT_RENDER") { + return false; + } + if (phrase.notes.some((note) => note.id === props.note.id)) { + return true; + } + }); +}); + const lyric = computed({ get() { return props.note.lyric; @@ -209,19 +251,32 @@ const onLyricInputBlur = () => { &.selected { // 色は仮 .note-bar { - background-color: hsl(33, 100%, 50%); + background-color: hsl(130, 35%, 90%); + border: 2px solid colors.$primary; } &.below-pitch { .note-bar { - background-color: rgba(hsl(33, 100%, 50%), 0.18); + background-color: rgba(hsl(130, 100%, 50%), 0.18); } } } - &.overlapping { + &.overlapping, + &.invalid-phrase { .note-bar { - background-color: hsl(130, 35%, 85%); + background-color: rgba(colors.$warning-rgb, 0.5); + } + + .note-lyric { + opacity: 0.6; + } + + &.selected { + .note-bar { + background-color: rgba(colors.$warning-rgb, 0.5); + border-color: colors.$warning; + } } } } @@ -274,8 +329,10 @@ const onLyricInputBlur = () => { position: absolute; bottom: 0; font-weight: 700; - width: 2rem; - border: 1px solid hsl(33, 100%, 73%); + min-width: 3rem; + max-width: 6rem; + border: 0; + outline: 2px solid colors.$primary; border-radius: 0.25rem; }