diff --git a/package-lock.json b/package-lock.json index 4b08371ee6..5e4592652a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -85,7 +85,7 @@ "license-checker-rseidelsohn": "4.3.0", "markdownlint-cli": "0.37.0", "prettier": "3.2.5", - "sass": "1.32.13", + "sass": "1.77.8", "storybook": "8.1.10", "ts-node": "10.9.1", "typescript": "5.5.2", @@ -14708,6 +14708,13 @@ "url": "https://opencollective.com/immer" } }, + "node_modules/immutable": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "dev": true, + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -20598,18 +20605,21 @@ } }, "node_modules/sass": { - "version": "1.32.13", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.32.13.tgz", - "integrity": "sha512-dEgI9nShraqP7cXQH+lEXVf73WOPCse0QlFzSD8k+1TcOxCMwVXfQlr0jtoluZysQOyJGnfr21dLvYKDJq8HkA==", + "version": "1.77.8", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz", + "integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==", "dev": true, + "license": "MIT", "dependencies": { - "chokidar": ">=3.0.0 <4.0.0" + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" }, "bin": { "sass": "sass.js" }, "engines": { - "node": ">=8.9.0" + "node": ">=14.0.0" } }, "node_modules/sax": { diff --git a/package.json b/package.json index 12347ee644..9654bb8b61 100644 --- a/package.json +++ b/package.json @@ -116,7 +116,7 @@ "license-checker-rseidelsohn": "4.3.0", "markdownlint-cli": "0.37.0", "prettier": "3.2.5", - "sass": "1.32.13", + "sass": "1.77.8", "storybook": "8.1.10", "ts-node": "10.9.1", "typescript": "5.5.2", diff --git a/public/themes/dark.json b/public/themes/dark.json index 6249fc8be4..a3bef2b9bf 100644 --- a/public/themes/dark.json +++ b/public/themes/dark.json @@ -13,12 +13,6 @@ "warning": "#F27483", "text-splitter-hover": "#394152", "active-point-focus": "#292F38", - "active-point-hover": "#272A2F", - "sequencer-whitekey-cell": "#393939", - "sequencer-blackkey-cell": "#2D2D2D", - "sequencer-main-divider": "#121212", - "sequencer-sub-divider": "#2C2C2C", - "sequencer-white-key": "#EEEEEE", - "sequencer-black-key": "#555555" + "active-point-hover": "#272A2F" } } diff --git a/public/themes/default.json b/public/themes/default.json index b9ec04f40e..9d04773fd8 100644 --- a/public/themes/default.json +++ b/public/themes/default.json @@ -13,12 +13,6 @@ "warning": "#C10015", "text-splitter-hover": "#CCDDFF", "active-point-focus": "#E0EAFF", - "active-point-hover": "#EEF3FF", - "sequencer-whitekey-cell": "#F5F7F5", - "sequencer-blackkey-cell": "#EAECEA", - "sequencer-main-divider": "#B0B0B0", - "sequencer-sub-divider": "#CECECE", - "sequencer-white-key": "#FFFFFF", - "sequencer-black-key": "#333333" + "active-point-hover": "#EEF3FF" } } diff --git a/src/components/Dialog/CharacterTryListenCard.vue b/src/components/Dialog/CharacterTryListenCard.vue index 02e656ff80..d8838da856 100644 --- a/src/components/Dialog/CharacterTryListenCard.vue +++ b/src/components/Dialog/CharacterTryListenCard.vue @@ -184,7 +184,7 @@ const rollStyleIndex = (speakerUuid: SpeakerId, diff: number) => { width: 100%; height: 100%; .style-icon { - $icon-size: vars.$character-item-size / 2; + $icon-size: calc(vars.$character-item-size / 2); width: $icon-size; height: $icon-size; border-radius: 5px; diff --git a/src/components/Dialog/DefaultStyleListDialog.vue b/src/components/Dialog/DefaultStyleListDialog.vue index 97665abce1..685bc5b653 100644 --- a/src/components/Dialog/DefaultStyleListDialog.vue +++ b/src/components/Dialog/DefaultStyleListDialog.vue @@ -276,7 +276,7 @@ const openStyleSelectDialog = (characterInfo: CharacterInfo) => { width: 100%; height: 100%; .style-icon { - $icon-size: $character-item-size / 2; + $icon-size: calc(vars.$character-item-size / 2); width: $icon-size; height: $icon-size; border-radius: 5px; diff --git a/src/components/Dialog/DefaultStyleSelectDialog.vue b/src/components/Dialog/DefaultStyleSelectDialog.vue index 252c877355..7f0bcfa405 100644 --- a/src/components/Dialog/DefaultStyleSelectDialog.vue +++ b/src/components/Dialog/DefaultStyleSelectDialog.vue @@ -298,7 +298,7 @@ const closeDialog = () => { width: 100%; height: 100%; .style-icon { - $icon-size: $style-item-size / 2; + $icon-size: calc($style-item-size / 2); width: $icon-size; height: $icon-size; border-radius: 5px; diff --git a/src/components/Sing/CharacterMenuButton/MenuButton.vue b/src/components/Sing/CharacterMenuButton/MenuButton.vue index e2a08fa357..8a9e8fec82 100644 --- a/src/components/Sing/CharacterMenuButton/MenuButton.vue +++ b/src/components/Sing/CharacterMenuButton/MenuButton.vue @@ -38,3 +38,31 @@ const selectedSinger = computed(() => { return store.getters.SELECTED_TRACK.singer; }); + + diff --git a/src/components/Sing/CharacterMenuButton/SelectedCharacter.vue b/src/components/Sing/CharacterMenuButton/SelectedCharacter.vue index b2c2287444..926ad94ce8 100644 --- a/src/components/Sing/CharacterMenuButton/SelectedCharacter.vue +++ b/src/components/Sing/CharacterMenuButton/SelectedCharacter.vue @@ -1,27 +1,23 @@ diff --git a/src/components/Sing/SequencerShadowNote.vue b/src/components/Sing/SequencerShadowNote.vue index 988717451a..3ee27ec639 100644 --- a/src/components/Sing/SequencerShadowNote.vue +++ b/src/components/Sing/SequencerShadowNote.vue @@ -60,13 +60,14 @@ const width = computed(() => { pointer-events: none; .shadow-line { + border-radius: 1px; position: absolute; top: 50%; left: 0; width: 100%; height: 2px; transform: translateY(-50%); - background-color: colors.$sequencer-main-divider; + background-color: var(--scheme-color-sing-shadow-note); } } diff --git a/src/components/Sing/ToolBar/EditTargetSwicher.vue b/src/components/Sing/ToolBar/EditTargetSwicher.vue index f6c74f9579..70d91d118b 100644 --- a/src/components/Sing/ToolBar/EditTargetSwicher.vue +++ b/src/components/Sing/ToolBar/EditTargetSwicher.vue @@ -1,37 +1,43 @@ - - - diff --git a/src/components/Sing/ToolBar/ToolBar.vue b/src/components/Sing/ToolBar/ToolBar.vue index f717403fc8..8eaef4a4a6 100644 --- a/src/components/Sing/ToolBar/ToolBar.vue +++ b/src/components/Sing/ToolBar/ToolBar.vue @@ -4,70 +4,92 @@
- - - - - -
+
-
/
+ + + +
@@ -81,14 +103,14 @@ @@ -106,31 +128,33 @@ flat dense round - icon="undo" class="sing-undo-button" :disable="!canUndo" @click="undo" - /> + > + + + > + + - + store.getters.SELECTED_TRACK_ID); +const beatsOptions = computed(() => { + return Array.from({ length: 32 }, (_, i) => ({ + label: (i + 1).toString(), + value: i + 1, + })); +}); + +const beatTypeOptions = computed(() => { + return [2, 4, 8, 16, 32].map((beatType) => ({ + label: beatType.toString(), + value: beatType, + })); +}); + const bpmInputBuffer = ref(120); const beatsInputBuffer = ref(4); const beatTypeInputBuffer = ref(4); @@ -278,20 +316,30 @@ const setBpmInputBuffer = (bpmStr: string | number | null) => { bpmInputBuffer.value = bpmValue; }; -const setBeatsInputBuffer = (beatsStr: string | number | null) => { - const beatsValue = Number(beatsStr); - if (!isValidBeats(beatsValue)) { +const setBeats = (beats: { label: string; value: number }) => { + if (!isValidBeats(beats.value)) { return; } - beatsInputBuffer.value = beatsValue; + void store.dispatch("COMMAND_SET_TIME_SIGNATURE", { + timeSignature: { + measureNumber: 1, + beats: beats.value, + beatType: timeSignatures.value[0].beatType, + }, + }); }; -const setBeatTypeInputBuffer = (beatTypeStr: string | number | null) => { - const beatTypeValue = Number(beatTypeStr); - if (!isValidBeatType(beatTypeValue)) { +const setBeatType = (beatType: { label: string; value: number }) => { + if (!isValidBeatType(beatType.value)) { return; } - beatTypeInputBuffer.value = beatTypeValue; + void store.dispatch("COMMAND_SET_TIME_SIGNATURE", { + timeSignature: { + measureNumber: 1, + beats: timeSignatures.value[0].beats, + beatType: beatType.value, + }, + }); }; const setKeyRangeAdjustmentInputBuffer = ( @@ -324,18 +372,6 @@ const setTempo = () => { }); }; -const setTimeSignature = () => { - const beats = beatsInputBuffer.value; - const beatType = beatTypeInputBuffer.value; - void store.dispatch("COMMAND_SET_TIME_SIGNATURE", { - timeSignature: { - measureNumber: 1, - beats, - beatType, - }, - }); -}; - const setKeyRangeAdjustment = () => { const keyRangeAdjustment = keyRangeAdjustmentInputBuffer.value; void store.dispatch("COMMAND_SET_KEY_RANGE_ADJUSTMENT", { @@ -451,29 +487,80 @@ onUnmounted(() => { diff --git a/src/components/Talk/AudioCell.vue b/src/components/Talk/AudioCell.vue index 63d957739e..e7fbd99a51 100644 --- a/src/components/Talk/AudioCell.vue +++ b/src/components/Talk/AudioCell.vue @@ -679,6 +679,7 @@ const isMultipleEngine = computed(() => store.state.engineIds.length > 1); position: relative; padding: 0.4rem 0.5rem; margin: 0.2rem 0.5rem; + gap: 0px 1rem; &:focus { // divはフォーカスするとデフォルトで青い枠が出るので消す outline: none; @@ -695,8 +696,6 @@ const isMultipleEngine = computed(() => store.state.engineIds.length > 1); margin-bottom: 0.6rem; } - gap: 0px 1rem; - .active-arrow { left: -1rem; height: 2rem; diff --git a/src/composables/useCursorState.ts b/src/composables/useCursorState.ts new file mode 100644 index 0000000000..bf7f716538 --- /dev/null +++ b/src/composables/useCursorState.ts @@ -0,0 +1,48 @@ +import { ref, computed } from "vue"; + +// カーソル状態 +export enum CursorState { + UNSET = "unset", + EW_RESIZE = "ew-resize", + MOVE = "move", + CROSSHAIR = "crosshair", + DRAW = "draw", + ERASE = "erase", +} + +// カーソル状態を管理するカスタムコンポーザブル +export const useCursorState = () => { + const cursorState = ref(CursorState.UNSET); + + const cursorClass = computed(() => { + switch (cursorState.value) { + case CursorState.EW_RESIZE: + return "cursor-ew-resize"; + case CursorState.CROSSHAIR: + return "cursor-crosshair"; + case CursorState.MOVE: + return "cursor-move"; + case CursorState.DRAW: + return "cursor-draw"; + case CursorState.ERASE: + return "cursor-erase"; + default: + return ""; + } + }); + + const setCursorState = (state: CursorState) => { + cursorState.value = state; + }; + + const resetCursorState = () => { + cursorState.value = CursorState.UNSET; + }; + + return { + cursorState, + cursorClass, + setCursorState, + resetCursorState, + }; +}; diff --git a/src/sing/viewHelper.ts b/src/sing/viewHelper.ts index 2cf9ed2c7a..106616a473 100644 --- a/src/sing/viewHelper.ts +++ b/src/sing/viewHelper.ts @@ -134,6 +134,15 @@ export async function calculatePitchDataHash(pitchData: PitchData) { export type MouseButton = "LEFT_BUTTON" | "RIGHT_BUTTON" | "OTHER_BUTTON"; +export type PreviewMode = + | "IDLE" + | "ADD_NOTE" + | "MOVE_NOTE" + | "RESIZE_NOTE_RIGHT" + | "RESIZE_NOTE_LEFT" + | "DRAW_PITCH" + | "ERASE_PITCH"; + export function getButton(event: MouseEvent): MouseButton { // macOSの場合、Ctrl+クリックは右クリック if (isMac && event.button === 0 && event.ctrlKey) { diff --git a/src/styles/_index.scss b/src/styles/_index.scss index dad189293b..d12e38a1a6 100644 --- a/src/styles/_index.scss +++ b/src/styles/_index.scss @@ -2,6 +2,8 @@ @use './colors' as colors; @use './v2/variables' as vars-v2; @use './v2/colors' as colors-v2; +@use './v2/sing-colors'; // ソング用カラー +@use './v2/cursor'; // カーソル @import "./fonts"; // 優先度を強引に上げる diff --git a/src/styles/v2/cursor.scss b/src/styles/v2/cursor.scss new file mode 100644 index 0000000000..b706c98022 --- /dev/null +++ b/src/styles/v2/cursor.scss @@ -0,0 +1,25 @@ +.cursor-default { + cursor: default; +} + +.cursor-pointer { + cursor: pointer; +} + +.cursor-crosshair { + cursor: crosshair; +} + +.cursor-ew-resize { + cursor: ew-resize; +} + +.cursor-move { + cursor: move; +} + +.cursor-draw { + cursor: + url("/draw-cursor.png") 2 30, + auto; +} \ No newline at end of file diff --git a/src/styles/v2/sing-colors.scss b/src/styles/v2/sing-colors.scss new file mode 100644 index 0000000000..96c4189d30 --- /dev/null +++ b/src/styles/v2/sing-colors.scss @@ -0,0 +1,674 @@ +/* + +## 利用 + +基本的にはMaterialDesign3のカラーシステムに近い考え方であり +おおざっぱなロールごと(primary/secondaryなど)のベース彩度+色相は固定し、 +詳細なロール(on-primary/secondary-containerなど)に応じて明度のみ変更する形です + +https://m3.material.io/styles/color/roles + +## 各ロール + +- primary: +主要・強調される操作可能部のカラー・ブランドカラーです + +- secondary: +主要でない操作可能部のカラーです + +- tertiary: +現時点での利用部分想定としては一時的・未決定部などでプライマリ・セカンダリで表現しきれない場合に利用します +eg: ノートのプレビュー / 一時的に全ソロのインジケータ / シンガー発音時インジケータ / 失敗がありうる場合の待ちなど + +- error: +エラー・警告です + +- neutral +背景、テキスト、境界線など、UI全体で使用される中立的なカラーです +ユーザーの注意を引くことなく、背景やサポート的な役割を果たす要素です + +- neutral-variant +背景、セクションの区切り、低コントラストなUI要素などに利用します +操作可能なUI要素のカラーです + +- link +外部リンクなどのリンクを表すカラーです + +## カラースキームの指定 + +以下のようにCSS変数を指定します + +background-color: var(--scheme-color-primary); +color: var(--scheme-color-on-primary); + +## カスタマイズサンプル + +OKLab(OKLCH)で指定します + +l: 明度 / c: 彩度 / h: 色相 + +50%明度プライマリを指定: + color: oklch(var(--lr-50) var(--primary-c) var(--primary-h)); + +50%明度プライマリを指定: CSS Variables+相対CSSの場合 + color: oklch(from var(--primary-key) l calc(var(--lr-50))); + +ロールカラー指定: --on-primaryのdarkテーマの値を指定したサンプル + --on-primary-dark: oklch(var(--lr-10) var(--primary-c) var(--primary-h)); + +エイリアス指定: 特定のロール(この場合はneutral)だが明度が違う + --sing-piano-key-white-dark: oklch(var(--lr-70) var(--neutral-c) var(--neutral-h)); + +プライマリと色調を揃えた新規カラー指定: (色相が150度異なる紫になる) + color: oklch(from var(--primary-key) l calc(var(--lr-60)) c h calc(var(--primary-c) + 150))); + +--- + +TODO: ほとんどの場合、 + +- role/on-role/role-container/on-role-containerの4つ +- 必要あればそれぞれのhover/active/focus/disabledの状態 + +のスタイルを指定することになるため、明度ルールが安定したらmixin化するか検討する。 + +eg: 常にホバー時は+5%明度上げるのであれば +&:hover: oklch(from var(--primary) l calc(...lr-50をlr-55にするmixin)); + +*/ + +@use "sass:math"; + +/* +カラースキーム計算基準 +*/ +:root { + // 基準彩度 + --primary-c: 0.098; + // 元実装(v0.20.0)のprimary(light) #a5d4ad: OKLCH彩度 0.073 + // 元実装(v0.20.0)のprimary(dark): #86C591: OKLCH彩度 0.098 + // たとえば元のprimary(light)に揃えたいならここを0.073にする + --secondary-c: 0.036; + --tertiary-c: var(--primary-c); + --error-c: 0.196; + --neutral-c: 0.003; + --neutral-variant-c: 0.006; + --link-c: 0.196; + + // 基準色相 + --primary-h: 149.64; // VOICEVOXプライマリ #a5d4adの色相 + --secondary-h: var(--primary-h); + --tertiary-h: calc(var(--primary-h) - 60); // -60度 + --error-h: 19.64; + --neutral-h: calc(var(--primary-h) + 120); + --neutral-variant-h: var(--primary-h); + --link-h: 256; // `styles/v2/colors.scss` におけるprimitive-blueの色相 +} + +/* +明度LUT +OKLCHのL値を相対明度(おおむねガンマ補正2.2に近い)に補正した%単位値 +そのままのL値を使うとディスプレイにおいては知覚的にリニアな明るさにならないため補正しています +eg: 50%: --lr-50 + +参考: https://bottosson.github.io/posts/colorpicker/#intermission---a-new-lightness-estimate-for-oklab +参考議論: https://github.com/VOICEVOX/voicevox/issues/1810#issuecomment-2260529835 +参考議論: https://github.com/VOICEVOX/voicevox/issues/1810#issuecomment-2260631491 +*/ + +@function LtoLr($L) { + $k1: 0.206; + $k2: 0.03; + $k3: calc((1 + $k2) / (1 + $k1)); + + $l: calc($L / 100); + $Lr: calc( + ( + $k3 * $l - $k2 + + math.sqrt(math.pow($k3 * $l - $k2, 2) + 4 * $k1 * $k3 * $l) + ) / 2 + ); + @return $Lr; +} + +/* +明度LUTをCSS変数として定義 +*/ +:root { + @for $i from 0 through 100 { + $L: $i; + $Lr: LtoLr($L); + --lr-#{$i}: #{calc(($Lr * 10000) / 10000)}; // 小数点以下4桁 + } +} + +/* +OKLCHでのカラースキーム +他の定義と混ざらないようにするため、prefixとして--scheme-color-をつけています + +eg: セカンダリコンテナ(90%明度) +--scheme-color-secondary-container: oklch(var(--lr-90) var(--secondary-c) var(--secondary-h)); + +FIXME: +SASSのmapなどで構造化+mixin一括処理などで処理可能ですが、 +リファクタリング課題(元が動的生成用のTypeScriptコードのため) +*/ + +/* +ライトテーマ +*/ +:root[is-dark-theme="false"] { + --scheme-color-primary: oklch(var(--lr-40) var(--primary-c) var(--primary-h)); + --scheme-color-on-primary: oklch( + var(--lr-100) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-container: oklch( + var(--lr-90) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-container: oklch( + var(--lr-10) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-fixed: oklch( + var(--lr-90) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-fixed-dim: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-fixed: oklch( + var(--lr-10) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-fixed-variant: oklch( + var(--lr-30) var(--primary-c) var(--primary-h) + ); + + --scheme-color-secondary: oklch( + var(--lr-40) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary: oklch( + var(--lr-100) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-container: oklch( + var(--lr-90) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-container: oklch( + var(--lr-10) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-fixed: oklch( + var(--lr-90) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-fixed-dim: oklch( + var(--lr-80) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-fixed: oklch( + var(--lr-10) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-fixed-variant: oklch( + var(--lr-30) var(--secondary-c) var(--secondary-h) + ); + + --scheme-color-tertiary: oklch( + var(--lr-40) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary: oklch( + var(--lr-100) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-container: oklch( + var(--lr-90) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-container: oklch( + var(--lr-10) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-fixed: oklch( + var(--lr-90) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-fixed-dim: oklch( + var(--lr-80) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-fixed: oklch( + var(--lr-10) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-fixed-variant: oklch( + var(--lr-30) var(--tertiary-c) var(--tertiary-h) + ); + + --scheme-color-error: oklch(var(--lr-40) var(--error-c) var(--error-h)); + --scheme-color-on-error: oklch(var(--lr-100) var(--error-c) var(--error-h)); + --scheme-color-error-container: oklch( + var(--lr-90) var(--error-c) var(--error-h) + ); + --scheme-color-on-error-container: oklch( + var(--lr-10) var(--error-c) var(--error-h) + ); + + --scheme-color-background: oklch( + var(--lr-99) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-on-background: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface: oklch(var(--lr-99) var(--neutral-c) var(--neutral-h)); + --scheme-color-on-surface: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-variant: oklch( + var(--lr-90) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-on-surface-variant: oklch( + var(--lr-30) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-outline: oklch( + var(--lr-50) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-outline-variant: oklch( + var(--lr-80) var(--neutral-variant-c) var(--neutral-variant-h) + ); + + --scheme-color-shadow: oklch(var(--lr-0) var(--neutral-c) var(--neutral-h)); + --scheme-color-scrim: oklch(var(--lr-0) var(--neutral-c) var(--neutral-h)); + --scheme-color-inverse-surface: oklch( + var(--lr-20) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-inverse-on-surface: oklch( + var(--lr-95) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-inverse-primary: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + + --scheme-color-surface-dim: oklch( + var(--lr-87) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-bright: oklch( + var(--lr-98) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-lowest: oklch( + var(--lr-90) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-low: oklch( + var(--lr-92) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container: oklch( + var(--lr-94) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-high: oklch( + var(--lr-96) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-highest: oklch( + var(--lr-100) var(--neutral-c) var(--neutral-h) + ); + + /* カスタムカラー */ + --scheme-color-link: oklch(var(--lr-40) var(--link-c) var(--link-h)); + --scheme-color-on-link: oklch(var(--lr-100) var(--link-c) var(--link-h)); + --scheme-color-link-container: oklch( + var(--lr-90) var(--link-c) var(--link-h) + ); + --scheme-color-on-link-container: oklch( + var(--lr-10) var(--link-c) var(--link-h) + ); + + /* ソング用エイリアスカラー */ + --scheme-color-sing-toolbar-container: oklch( + var(--lr-99) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-playback-button-container: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-on-playback-button-container: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-cell-white: oklch( + var(--lr-100) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-cell-black: oklch( + var(--lr-96) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-measure-line: oklch( + var(--lr-75) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-beat-line: oklch( + var(--lr-85) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-vertical-line: oklch( + var(--lr-94) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-octave-line: oklch( + var(--lr-80) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-horizontal-line: oklch( + var(--lr-94) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-ruler-surface: oklch( + var(--lr-90) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-ruler-measure-line: oklch( + var(--lr-65) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-ruler-beat-line: oklch( + var(--lr-75) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-piano-key-white: oklch( + var(--lr-99) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-piano-key-black: oklch( + var(--lr-45) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-piano-keys-right-border: oklch( + var(--lr-70) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-note-bar-container: oklch( + var(--lr-90) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-sing-on-note-bar-container: oklch( + var(--lr-10) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-sing-note-bar-border: oklch( + var(--lr-60) var(--secondary-c) var(--secondary-h) + ); + + --scheme-color-sing-note-bar-selected-container: oklch( + var(--lr-96) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-on-note-bar-selected-container: oklch( + var(--lr-10) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-note-bar-selected-border: oklch( + var(--lr-60) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-note-bar-selected-outline: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + + --scheme-color-sing-note-bar-below-pitch-container: oklch( + var(--lr-90) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-sing-note-bar-below-pitch-invalid-container: oklch( + var(--lr-90) var(--secondary-c) var(--error-h) + ); + + --scheme-color-sing-note-bar-preview-container: oklch( + var(--lr-90) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-on-note-bar-preview-container: oklch( + var(--lr-10) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-note-bar-preview-border: oklch( + var(--lr-60) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-note-bar-preview-outline: oklch( + var(--lr-80) var(--tertiary-c) var(--tertiary-h) + ); + + --scheme-color-sing-shadow-note: oklch( + var(--lr-84) var(--neutral-variant-c) var(--neutral-variant-h) + ); +} + +/* ダークテーマ */ +:root[is-dark-theme="true"] { + --scheme-color-primary: oklch(var(--lr-80) var(--primary-c) var(--primary-h)); + --scheme-color-on-primary: oklch( + var(--lr-20) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-container: oklch( + var(--lr-30) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-container: oklch( + var(--lr-90) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-fixed: oklch( + var(--lr-90) var(--primary-c) var(--primary-h) + ); + --scheme-color-primary-fixed-dim: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-fixed: oklch( + var(--lr-10) var(--primary-c) var(--primary-h) + ); + --scheme-color-on-primary-fixed-variant: oklch( + var(--lr-30) var(--primary-c) var(--primary-h) + ); + + --scheme-color-secondary: oklch( + var(--lr-80) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary: oklch( + var(--lr-20) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-container: oklch( + var(--lr-30) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-container: oklch( + var(--lr-90) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-fixed: oklch( + var(--lr-90) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-secondary-fixed-dim: oklch( + var(--lr-80) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-fixed: oklch( + var(--lr-10) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-on-secondary-fixed-variant: oklch( + var(--lr-30) var(--secondary-c) var(--secondary-h) + ); + + --scheme-color-tertiary: oklch( + var(--lr-80) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary: oklch( + var(--lr-20) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-container: oklch( + var(--lr-30) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-container: oklch( + var(--lr-90) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-fixed: oklch( + var(--lr-90) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-tertiary-fixed-dim: oklch( + var(--lr-80) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-fixed: oklch( + var(--lr-10) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-on-tertiary-fixed-variant: oklch( + var(--lr-30) var(--tertiary-c) var(--tertiary-h) + ); + + --scheme-color-error: oklch(var(--lr-80) var(--error-c) var(--error-h)); + --scheme-color-on-error: oklch(var(--lr-20) var(--error-c) var(--error-h)); + --scheme-color-error-container: oklch( + var(--lr-30) var(--error-c) var(--error-h) + ); + --scheme-color-on-error-container: oklch( + var(--lr-90) var(--error-c) var(--error-h) + ); + + --scheme-color-shadow: oklch(var(--lr-0) var(--neutral-c) var(--neutral-h)); + --scheme-color-scrim: oklch(var(--lr-0) var(--neutral-c) var(--neutral-h)); + --scheme-color-inverse-surface: oklch( + var(--lr-90) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-inverse-on-surface: oklch( + var(--lr-20) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-inverse-primary: oklch( + var(--lr-40) var(--primary-c) var(--primary-h) + ); + + --scheme-color-background: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-on-background: oklch( + var(--lr-90) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface: oklch(var(--lr-6) var(--neutral-c) var(--neutral-h)); + --scheme-color-on-surface: oklch( + var(--lr-90) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-variant: oklch( + var(--lr-30) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-on-surface-variant: oklch( + var(--lr-80) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-outline: oklch( + var(--lr-60) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-outline-variant: oklch( + var(--lr-30) var(--neutral-variant-c) var(--neutral-variant-h) + ); + + --scheme-color-surface-dim: oklch( + var(--lr-6) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-bright: oklch( + var(--lr-24) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-lowest: oklch( + var(--lr-4) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-low: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container: oklch( + var(--lr-12) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-high: oklch( + var(--lr-17) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-surface-container-highest: oklch( + var(--lr-24) var(--neutral-c) var(--neutral-h) + ); + + /* カスタムカラー */ + --scheme-color-link: oklch(var(--lr-80) var(--link-c) var(--link-h)); + --scheme-color-on-link: oklch(var(--lr-20) var(--link-c) var(--link-h)); + --scheme-color-link-container: oklch( + var(--lr-30) var(--link-c) var(--link-h) + ); + --scheme-color-on-link-container: oklch( + var(--lr-90) var(--link-c) var(--link-h) + ); + + /* ソング用エイリアスカラー */ + --scheme-color-sing-toolbar-container: oklch( + var(--lr-17) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-playback-button-container: oklch( + var(--lr-70) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-on-playback-button-container: oklch( + var(--lr-10) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-cell-white: oklch( + var(--lr-20) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-cell-black: oklch( + var(--lr-16) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-measure-line: oklch( + var(--lr-40) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-beat-line: oklch( + var(--lr-4) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-vertical-line: oklch( + var(--lr-14) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-grid-octave-line: oklch( + var(--lr-4) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-grid-horizontal-line: oklch( + var(--lr-14) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-ruler-surface: oklch( + var(--lr-30) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-ruler-measure-line: oklch( + var(--lr-60) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-ruler-beat-line: oklch( + var(--lr-50) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-piano-key-white: oklch( + var(--lr-70) var(--neutral-c) var(--neutral-h) + ); + --scheme-color-sing-piano-key-black: oklch( + var(--lr-20) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-piano-keys-right-border: oklch( + var(--lr-35) var(--neutral-c) var(--neutral-h) + ); + + --scheme-color-sing-note-bar-container: oklch( + var(--lr-70) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-sing-on-note-bar-container: oklch( + var(--lr-10) var(--secondary-c) var(--secondary-h) + ); + --scheme-color-sing-note-bar-border: oklch( + var(--lr-85) var(--secondary-c) var(--secondary-h) + ); + + --scheme-color-sing-note-bar-selected-container: oklch( + var(--lr-80) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-on-note-bar-selected-container: oklch( + var(--lr-10) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-note-bar-selected-border: oklch( + var(--lr-95) var(--primary-c) var(--primary-h) + ); + --scheme-color-sing-note-bar-selected-outline: oklch( + var(--lr-60) var(--primary-c) var(--primary-h) + ); + + --scheme-color-sing-note-bar-error-container: oklch( + var(--lr-90) var(--secondary-c) var(--error-h) + ); + --scheme-color-sing-on-note-bar-error-container: oklch( + var(--lr-10) var(--secondary-c) var(--error-h) + ); + + --scheme-color-sing-note-bar-below-pitch-container: oklch( + var(--lr-27) var(--neutral-variant-c) var(--neutral-variant-h) + ); + --scheme-color-sing-note-bar-below-pitch-invalid-container: oklch( + var(--lr-27) var(--secondary-c) var(--error-h) + ); + + --scheme-color-sing-note-bar-preview-container: oklch( + var(--lr-70) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-on-note-bar-preview-container: oklch( + var(--lr-10) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-note-bar-preview-border: oklch( + var(--lr-85) var(--tertiary-c) var(--tertiary-h) + ); + --scheme-color-sing-note-bar-preview-outline: oklch( + var(--lr-60) var(--tertiary-c) var(--tertiary-h) + ); + + --scheme-color-sing-shadow-note: oklch( + var(--lr-40) var(--neutral-variant-c) var(--neutral-variant-h) + ); +} diff --git a/src/styles/v2/variables.scss b/src/styles/v2/variables.scss index a81a396bf8..6018a9a5f6 100644 --- a/src/styles/v2/variables.scss +++ b/src/styles/v2/variables.scss @@ -24,3 +24,14 @@ $radius-2: calc(var(--radius-basis) * 2); $transition-duration: 100ms; $z-index-tooltip: 9999; + +$z-index-dropdown: 1000; +$z-index-fixed: 1020; +$z-index-dialog: 1050; + +$z-index-sing-background: 0; +$z-index-sing-note: 10; +$z-index-sing-note-lyric: 20; +$z-index-sing-pitch: 30; +$z-index-sing-playhead: 40; +$z-index-sing-lyric-input: 50; diff --git "a/tests/e2e/browser/song/\343\202\275\343\203\263\343\202\260.spec.ts" "b/tests/e2e/browser/song/\343\202\275\343\203\263\343\202\260.spec.ts" index b0f6dfb1c8..01b7b6ee31 100644 --- "a/tests/e2e/browser/song/\343\202\275\343\203\263\343\202\260.spec.ts" +++ "b/tests/e2e/browser/song/\343\202\275\343\203\263\343\202\260.spec.ts" @@ -1,4 +1,4 @@ -import { test, expect, Page, Locator } from "@playwright/test"; +import { test, expect, Page } from "@playwright/test"; import { gotoHome, navigateToMain } from "../../navigators"; @@ -69,18 +69,34 @@ test("ダブルクリックで歌詞を編集できる", async ({ page }) => { const sequencer = page.getByLabel("シーケンサ"); - const getCurrentNoteLyric = async (note: Locator) => - await note.getByTestId("note-lyric").textContent(); + const getCurrentNoteLyric = async () => + await sequencer.locator(".note-lyric").first().textContent(); + // ノートを追加し、表示されるまで待つ await sequencer.click({ position: { x: 107, y: 171 } }); + await page.waitForSelector(".note"); - const note = sequencer.locator(".note"); - const beforeLyric = await getCurrentNoteLyric(note); + // ノートの歌詞を取得 + const note = sequencer.locator(".note").first(); + const beforeLyric = await getCurrentNoteLyric(); - await sequencer.click({ position: { x: 107, y: 171 }, clickCount: 2 }); // ダブルクリック + // ノートをダブルクリックし、入力フィールドが表示されるまで待つ + await note.dblclick(); + await page.waitForSelector(".lyric-input"); - await sequencer.locator(".lyric-input").fill("あ"); - await page.keyboard.press("Enter"); - const afterLyric = await getCurrentNoteLyric(note); + // 歌詞を入力し、Enterキーを押す + const lyricInput = sequencer.locator(".lyric-input"); + await lyricInput.fill("あ"); + await lyricInput.press("Enter"); + + // 変更が反映されるまで待つ + await page.waitForFunction(() => { + const lyricElement = document.querySelector(".note-lyric"); + return lyricElement && lyricElement.textContent === "あ"; + }); + + // 歌詞が変更されたことを確認 + const afterLyric = await getCurrentNoteLyric(); expect(afterLyric).not.toEqual(beforeLyric); + expect(afterLyric).toEqual("あ"); });