diff --git a/package-lock.json b/package-lock.json
index 89c56f571..3c9eec3ea 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"skyway-js": "^4.4.5",
"text-field-edit": "^3.2.0",
"throttle-debounce": "^5.0.0",
+ "ts-pattern": "^5.0.5",
"turndown": "^7.1.1",
"turndown-plugin-gfm": "^1.0.2",
"vue": "^3.3.4",
@@ -10706,6 +10707,11 @@
"node": ">=14"
}
},
+ "node_modules/ts-pattern": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/ts-pattern/-/ts-pattern-5.0.5.tgz",
+ "integrity": "sha512-tL0w8U/pgaacOmkb9fRlYzWEUDCfVjjv9dD4wHTgZ61MjhuMt46VNWTG747NqW6vRzoWIKABVhFSOJ82FvXrfA=="
+ },
"node_modules/tslib": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz",
diff --git a/package.json b/package.json
index ac5d800a0..eb6f25ab8 100644
--- a/package.json
+++ b/package.json
@@ -42,6 +42,7 @@
"skyway-js": "^4.4.5",
"text-field-edit": "^3.2.0",
"throttle-debounce": "^5.0.0",
+ "ts-pattern": "^5.0.5",
"turndown": "^7.1.1",
"turndown-plugin-gfm": "^1.0.2",
"vue": "^3.3.4",
diff --git a/src/components/GroupManager/GroupListGroupEdit.vue b/src/components/GroupManager/GroupListGroupEdit.vue
index a4436b452..986477471 100644
--- a/src/components/GroupManager/GroupListGroupEdit.vue
+++ b/src/components/GroupManager/GroupListGroupEdit.vue
@@ -29,7 +29,12 @@
:members="group.members"
/>
-
+
diff --git a/src/components/Main/MainView/ChannelView/ChannelHeader/ChannelHeaderRelationPanel.vue b/src/components/Main/MainView/ChannelView/ChannelHeader/ChannelHeaderRelationPanel.vue
index 03194fd7d..4cf74f46f 100644
--- a/src/components/Main/MainView/ChannelView/ChannelHeader/ChannelHeaderRelationPanel.vue
+++ b/src/components/Main/MainView/ChannelView/ChannelHeader/ChannelHeaderRelationPanel.vue
@@ -16,7 +16,7 @@
diff --git a/src/components/Main/MainView/ClipsView/ClipsSidebar/ClipsSidebarContent.vue b/src/components/Main/MainView/ClipsView/ClipsSidebar/ClipsSidebarContent.vue
index bdde60c74..000cb27bc 100644
--- a/src/components/Main/MainView/ClipsView/ClipsSidebar/ClipsSidebarContent.vue
+++ b/src/components/Main/MainView/ClipsView/ClipsSidebar/ClipsSidebarContent.vue
@@ -23,7 +23,12 @@
-
+
diff --git a/src/components/Main/MainView/MessageElement/MessageEditor.vue b/src/components/Main/MainView/MessageElement/MessageEditor.vue
index 84b2f4d7f..2fa82db69 100644
--- a/src/components/Main/MainView/MessageElement/MessageEditor.vue
+++ b/src/components/Main/MainView/MessageElement/MessageEditor.vue
@@ -32,7 +32,7 @@
-
+
-
+
diff --git a/src/components/Settings/ThemeTab/EditTheme.vue b/src/components/Settings/ThemeTab/EditTheme.vue
index 929e22177..72ddafd8c 100644
--- a/src/components/Settings/ThemeTab/EditTheme.vue
+++ b/src/components/Settings/ThemeTab/EditTheme.vue
@@ -5,14 +5,14 @@
label="エクスポート"
@click="onImportClick"
:disabled="isImporterOpen"
- color="secondary"
+ type="tertiary"
:class="$style.element"
/>
-->
@@ -20,7 +20,8 @@
-->
@@ -31,7 +32,7 @@
diff --git a/src/components/UI/FormButton.vue b/src/components/UI/FormButton.vue
index e29a84838..d4fca9676 100644
--- a/src/components/UI/FormButton.vue
+++ b/src/components/UI/FormButton.vue
@@ -3,7 +3,8 @@
:class="$style.container"
:disabled="loading || disabled"
:data-is-loading="$boolAttr(loading)"
- :data-color="color"
+ :data-type="type"
+ :data-is-danger="$boolAttr(isDanger)"
>
{{ label }}
import { computed } from 'vue'
import LoadingSpinner from '/@/components/UI/LoadingSpinner.vue'
+import { match, P } from 'ts-pattern'
-const props = withDefaults(
- defineProps<{
- label?: string
- loading?: boolean
- disabled?: boolean
- color?: 'primary' | 'secondary' | 'error' | 'tertiary'
- }>(),
- {
- label: '',
- loading: false,
- disabled: false,
- color: 'primary' as const
- }
-)
+interface Type {
+ type?: 'primary' | 'secondary' | 'tertiary'
+ isDanger?: boolean
+}
+
+interface NonDangerType extends Type {
+ type?: 'primary' | 'secondary' | 'tertiary'
+ isDanger?: false
+}
+interface DangerType extends Type {
+ type?: 'primary' | 'secondary'
+ isDanger: true
+}
+
+type Props = {
+ label?: string
+ loading?: boolean
+ disabled?: boolean
+} & (NonDangerType | DangerType)
+
+const props = withDefaults(defineProps(), {
+ label: '',
+ loading: false,
+ disabled: false,
+ type: 'primary',
+ isDanger: false
+})
const spinnerColor = computed(() => {
- switch (props.color) {
- case 'tertiary':
- return 'accent-primary'
- default:
- return 'white'
- }
+ return match([props.type, props.isDanger] as const)
+ .with(['primary', P._], () => 'white' as const)
+ .with(['secondary', true], () => 'accent-error' as const)
+ .with(['secondary', false], () => 'accent-primary' as const)
+ .with(['tertiary', P._], () => 'ui-secondary' as const)
+ .exhaustive()
})
@@ -57,20 +72,26 @@ const spinnerColor = computed(() => {
&[data-is-loading] {
cursor: wait;
}
- &[data-color='primary'] {
+ &[data-type='primary'] {
@include color-common-text-white-primary;
@include background-accent-primary;
+ border-color: $theme-ui-primary-default;
+ }
+ &[data-type='secondary'] {
+ @include color-accent-primary;
border-color: $theme-accent-primary-default;
}
- &[data-color='secondary'] {
+ &[data-type='tertiary'] {
@include color-ui-secondary;
border-color: $theme-ui-secondary-default;
}
- &[data-color='tertiary'] {
- @include color-accent-primary;
- border-color: $theme-accent-primary-default;
+
+ &[data-type='primary'][data-is-danger] {
+ @include color-common-text-white-primary;
+ @include background-accent-error;
+ border-color: $theme-accent-error-default;
}
- &[data-color='error'] {
+ &[data-type='secondary'][data-is-danger] {
color: $theme-accent-error-default;
border-color: $theme-accent-error-default;
}
diff --git a/src/components/UI/LoadingSpinner.vue b/src/components/UI/LoadingSpinner.vue
index cde9dbf11..2bfef2f70 100644
--- a/src/components/UI/LoadingSpinner.vue
+++ b/src/components/UI/LoadingSpinner.vue
@@ -5,7 +5,7 @@