Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
560bd3b
ContextMenu系コンポーネントを追加
takusea Jul 12, 2025
114b769
BaseTextFieldにContextMenuを実装
takusea Jul 12, 2025
ca58ccc
ContextMenuを使うQDialogにallowFocusOutside属性を追加
takusea Jul 12, 2025
c3cabd5
各操作が出来ないときにdisabledになるように修正
takusea Jul 12, 2025
771a6e0
関数の定義順を整理
takusea Jul 12, 2025
5c0a8c7
propsのshortcutをoptionalに変更
takusea Jul 12, 2025
8f3117d
関数の実装をリファクタリング
takusea Jul 13, 2025
2e6b0b9
slotでContextMenuの項目を拡張できるように
takusea Jul 13, 2025
327d3c2
ContextMenuIconのホバー時のcursorをpointerに変更
takusea Jul 13, 2025
1d57c8e
選択範囲をrefで管理するように変更
takusea Jul 13, 2025
616e46b
ContextMenuを開いている際のTextFieldのスタイルを調整
takusea Jul 14, 2025
3390d66
BaseTextFieldをcontenteditableの実装に変更
takusea Jul 17, 2025
941ec5f
plaintext-onlyのcontenteditableのショートカット動作を修正
takusea Jul 17, 2025
d71cfff
BaseTextFieldの内部実装に合うように修正
takusea Jul 17, 2025
1b5ee9b
Merge branch 'VOICEVOX:main' into add-text-field-context-menu
takusea Jul 17, 2025
3b387df
Revert "plaintext-onlyのcontenteditableのショートカット動作を修正"
takusea Jul 17, 2025
589a1c9
plaintext-onlyのcontenteditableのショートカット動作を修正
takusea Jul 17, 2025
976234b
Enter押下時にchangeイベントを発行するように
takusea Jul 17, 2025
5d9a73a
placeholderが表示されるように修正
takusea Jul 18, 2025
eccb9a5
[update snapshots]
takusea Jul 18, 2025
0a1cbf3
(スナップショットを更新)
github-actions[bot] Jul 18, 2025
e734cbd
[update snapshots]
takusea Jul 19, 2025
4870463
(スナップショットを更新)
github-actions[bot] Jul 19, 2025
c5cc301
関数順を整理
takusea Jul 19, 2025
8318713
例外の文を修正
takusea Jul 20, 2025
d61b718
restoreSelectionの実行にsetTimeoutを使わないように修正
takusea Jul 23, 2025
22c8d23
空白時のカーソルの位置ズレを修正
takusea Aug 1, 2025
b380d6e
コメントを追加
takusea Aug 29, 2025
bdf5add
コメントを追加
takusea Aug 29, 2025
0a46e08
innerValueのバインディングをより一般的な記述に変更
takusea Aug 29, 2025
6f67ee8
外部からのmodelの変更が反映されるよう修正
takusea Aug 29, 2025
82f953f
選択範囲の復元時inputのfirstChildがない場合input自体を用いるように変更
takusea Aug 29, 2025
3232c7f
modelがundefinedの状態にならないようデフォルト値を追加
takusea Aug 29, 2025
2d5c2ec
不要な変更をもとに戻す
takusea Aug 29, 2025
0e1d7c9
feat: modelValueの変更のテストを追加
sevenc-nanashi Sep 2, 2025
fd31e47
fix: lintが落ちてるのを修正
sevenc-nanashi Sep 2, 2025
88e70a7
fix: TOOD -> TODO
sevenc-nanashi Sep 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/components/Base/BaseContextMenu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<template>
<ContextMenuRoot v-model:open="open">
<ContextMenuTrigger asChild>
<slot />
</ContextMenuTrigger>
<ContextMenuPortal>
<ContextMenuContent
class="ContextMenuContent"
:collisionPadding="8"
avoidCollisions
hideWhenDetached
>
<slot name="menu" />
</ContextMenuContent>
</ContextMenuPortal>
</ContextMenuRoot>
</template>

<script setup lang="ts">
import {
ContextMenuContent,
ContextMenuPortal,
ContextMenuRoot,
ContextMenuTrigger,
} from "reka-ui";

const open = defineModel<boolean>("open", { default: false });
</script>

<style lang="scss">
@use "@/styles/v2/variables" as vars;
@use "@/styles/v2/colors" as colors;

.ContextMenuContent {
min-width: 240px;
background-color: colors.$background;
border-radius: vars.$radius-2;
overflow: hidden;
padding: vars.$padding-1;
border: 1px solid colors.$border;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
z-index: vars.$z-index-dropdown;
}
</style>
60 changes: 60 additions & 0 deletions src/components/Base/BaseContextMenuItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<ContextMenuItem
:disabled
class="ContextMenuItem"
@select="$emit('select', $event)"
>
{{ label }}
<div class="shortcut">{{ shortcut }}</div>
</ContextMenuItem>
</template>

<script setup lang="ts">
import { ContextMenuItem } from "reka-ui";

defineProps<{
label: string;
shortcut?: string;
disabled?: boolean;
}>();

defineEmits<{
select: [event: Event];
}>();
</script>

<style lang="scss" scoped>
@use "@/styles/v2/variables" as vars;
@use "@/styles/v2/colors" as colors;
@use "@/styles/v2/mixin" as mixin;

.ContextMenuItem {
position: relative;
display: flex;
align-items: center;
height: vars.$size-control;
padding: 0 vars.$padding-1;
padding-left: vars.$padding-2;
border-radius: vars.$radius-1;
color: colors.$display;
cursor: pointer;

&[data-disabled] {
opacity: 0.5;
pointer-events: none;
}

&[data-highlighted] {
background-color: colors.$clear-hovered;
}

&:focus-visible {
@include mixin.on-focus;
}
}

.shortcut {
margin-left: auto;
color: colors.$display-sub;
}
</style>
18 changes: 18 additions & 0 deletions src/components/Base/BaseContextMenuSeparator.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<ContextMenuSeparator class="ContextMenuSeparator" />
</template>

<script setup lang="ts">
import { ContextMenuSeparator } from "reka-ui";
</script>

<style lang="scss" scoped>
@use "@/styles/v2/variables" as vars;
@use "@/styles/v2/colors" as colors;

.ContextMenuSeparator {
height: 1px;
background-color: colors.$border;
margin-block: vars.$padding-1;
}
</style>
22 changes: 22 additions & 0 deletions src/components/Base/BaseTextField.stories.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type { Meta, StoryObj } from "@storybook/vue3-vite";
import { expect } from "storybook/test";

import BaseTextField from "./BaseTextField.vue";
import { UnreachableError } from "@/type/utility";

const meta: Meta<typeof BaseTextField> = {
component: BaseTextField,
Expand Down Expand Up @@ -46,3 +48,23 @@ export const HasError: Story = {
</BaseTextField>`,
}),
};

export const UpdateModelValue: Story = {
name: "Update modelValue",
args: {
modelValue: "hoge",
},
play: async ({ canvasElement, args }) => {
const inputElement =
canvasElement.querySelector<HTMLDivElement>("div.input");
if (!inputElement) {
throw new UnreachableError("div.input is not found");
}
await expect(inputElement.textContent).toBe("hoge");
// @ts-expect-error modelValueがreadonlyだが、動いているかつ周りに影響がないため無視する
// TODO: ちゃんとした方法があればそちらに変更する
Comment on lines +64 to +65
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 調べてみたけど手っ取り早い方法はなさそうでした!
https://chatgpt.com/share/68b7337d-58bc-8008-9b3f-cb6bdb3caefa
一番下で提案されてる、Story.loaders使う形が一番まだマシそう。
それでもだいぶ手続き大変だけど・・・。

args.modelValue = "fuga";
await new Promise((resolve) => setTimeout(resolve, 0));
await expect(inputElement.textContent).toBe("fuga");
},
};
Loading
Loading