refactor: migrate all input fields to StyledInput (#5306)
* feat: StyledInput component * migrate: auth pages to styledInput * migrate: search/filter inputs * migrate: dashboard inputs * migrate: app frontend * migrate: search related inputs * migrate: all of app-frontend * fix: missing inputs on app-frontend * migrate: frontend * feat: multiline * migrate: textareas * fix: storybook use text-primary * fix: lint * fix: merge conflict * feat: cleanup
This commit is contained in:
@@ -20,12 +20,12 @@
|
||||
<label for="days" class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-contrast"> Days to credit </span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="days"
|
||||
v-model.number="days"
|
||||
class="w-32"
|
||||
v-model="days"
|
||||
wrapper-class="w-32"
|
||||
type="number"
|
||||
min="1"
|
||||
:min="1"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
@@ -36,11 +36,10 @@
|
||||
<span class="text-lg font-semibold text-contrast"> Node hostnames </span>
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
id="node-input"
|
||||
v-model="nodeInput"
|
||||
class="w-32"
|
||||
type="text"
|
||||
wrapper-class="w-32"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<ButtonStyled color="blue" color-fill="text">
|
||||
@@ -93,14 +92,13 @@
|
||||
class="text-muted flex flex-col gap-2 rounded-lg border border-surface-5 bg-button-bg p-4"
|
||||
>
|
||||
<span>Hi {user.name},</span>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="message-batch"
|
||||
v-model="message"
|
||||
rows="3"
|
||||
class="w-full overflow-hidden !bg-surface-3"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="message-batch"
|
||||
v-model="message"
|
||||
multiline
|
||||
:rows="3"
|
||||
input-class="!bg-surface-3"
|
||||
/>
|
||||
<span>
|
||||
To make up for it, we've added {{ days }} day{{ pluralize(days) }} to your Modrinth
|
||||
Servers subscription.
|
||||
@@ -137,6 +135,7 @@ import {
|
||||
Combobox,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
TagItem,
|
||||
Toggle,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
@@ -25,15 +25,14 @@
|
||||
</span>
|
||||
<span>Server IDs (one per line or comma-separated.)</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="server-ids"
|
||||
v-model="serverIdsInput"
|
||||
rows="4"
|
||||
class="w-full bg-surface-3"
|
||||
placeholder="123e4569-e89b-12d3-a456-426614174005 123e9569-e89b-12d3-a456-413678919876"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="server-ids"
|
||||
v-model="serverIdsInput"
|
||||
multiline
|
||||
:rows="4"
|
||||
input-class="bg-surface-3"
|
||||
placeholder="123e4569-e89b-12d3-a456-426614174005 123e9569-e89b-12d3-a456-413678919876"
|
||||
/>
|
||||
<span v-if="parsedServerIds.length" class="text-sm text-secondary">
|
||||
{{ parsedServerIds.length }} server{{ parsedServerIds.length === 1 ? '' : 's' }} selected
|
||||
</span>
|
||||
@@ -49,11 +48,10 @@
|
||||
<span>Add nodes to transfer (comma or space-separated).</span>
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
id="node-input"
|
||||
v-model="nodeInput"
|
||||
class="w-64"
|
||||
type="text"
|
||||
wrapper-class="w-64"
|
||||
autocomplete="off"
|
||||
placeholder="us-vin200, us-vin201"
|
||||
@keydown.enter.prevent="addNodes"
|
||||
@@ -88,11 +86,10 @@
|
||||
<span class="text-lg font-semibold text-contrast">Tag transferred nodes</span>
|
||||
<span>Optional tag to add to the transferred nodes.</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="tag-nodes"
|
||||
v-model="tagNodes"
|
||||
class="max-w-[12rem]"
|
||||
type="text"
|
||||
wrapper-class="max-w-[12rem]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
@@ -117,11 +114,10 @@
|
||||
<span>Optional preferred node tags for node selection.</span>
|
||||
</label>
|
||||
<div class="flex items-center gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
id="tag-input"
|
||||
v-model="tagInput"
|
||||
class="w-40"
|
||||
type="text"
|
||||
wrapper-class="w-40"
|
||||
autocomplete="off"
|
||||
placeholder="ovh-gen4"
|
||||
@keydown.enter.prevent="addTag"
|
||||
@@ -151,11 +147,11 @@
|
||||
:format-label="(item) => scheduleOptionLabels[item]"
|
||||
:capitalize="false"
|
||||
/>
|
||||
<input
|
||||
<StyledInput
|
||||
v-if="scheduleOption === 'later'"
|
||||
v-model="scheduledDate"
|
||||
type="datetime-local"
|
||||
class="mt-2 max-w-[16rem]"
|
||||
wrapper-class="mt-2 max-w-[16rem]"
|
||||
autocomplete="off"
|
||||
/>
|
||||
</div>
|
||||
@@ -168,15 +164,14 @@
|
||||
</span>
|
||||
<span>Provide a reason for this transfer batch.</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="reason"
|
||||
v-model="reason"
|
||||
rows="2"
|
||||
class="w-full bg-surface-3"
|
||||
placeholder="Node maintenance scheduled"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="reason"
|
||||
v-model="reason"
|
||||
multiline
|
||||
:rows="2"
|
||||
input-class="bg-surface-3"
|
||||
placeholder="Node maintenance scheduled"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex gap-2">
|
||||
@@ -205,6 +200,7 @@ import {
|
||||
Combobox,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
TagItem,
|
||||
Toggle,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
@@ -13,10 +13,13 @@
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
<div class="iconified-input w-full">
|
||||
<SearchIcon aria-hidden="true" />
|
||||
<input v-model="searchQuery" type="text" placeholder="Search versions" />
|
||||
</div>
|
||||
<StyledInput
|
||||
v-model="searchQuery"
|
||||
:icon="SearchIcon"
|
||||
type="text"
|
||||
placeholder="Search versions"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
<div
|
||||
class="flex h-72 select-none flex-col gap-3 overflow-y-auto rounded-xl border border-solid border-surface-5 p-3 py-4"
|
||||
>
|
||||
@@ -64,7 +67,7 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Labrinth } from '@modrinth/api-client'
|
||||
import { SearchIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled, Chips } from '@modrinth/ui'
|
||||
import { ButtonStyled, Chips, StyledInput } from '@modrinth/ui'
|
||||
import { useMagicKeys } from '@vueuse/core'
|
||||
import { computed, nextTick, onMounted, ref } from 'vue'
|
||||
|
||||
|
||||
@@ -16,26 +16,24 @@
|
||||
<span class="font-semibold text-contrast">
|
||||
Version number <span class="text-red">*</span>
|
||||
</span>
|
||||
<input
|
||||
<StyledInput
|
||||
id="version-number"
|
||||
v-model="draftVersion.version_number"
|
||||
:disabled="isUploading"
|
||||
placeholder="Enter version number, e.g. 1.2.3-alpha.1"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
maxlength="32"
|
||||
:maxlength="32"
|
||||
/>
|
||||
<span> The version number differentiates this specific version from others. </span>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<span class="font-semibold text-contrast"> Version subtitle </span>
|
||||
<input
|
||||
<StyledInput
|
||||
id="version-number"
|
||||
v-model="draftVersion.name"
|
||||
placeholder="Enter subtitle..."
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
maxlength="256"
|
||||
:maxlength="256"
|
||||
:disabled="isUploading"
|
||||
/>
|
||||
</div>
|
||||
@@ -55,7 +53,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { Chips, MarkdownEditor } from '@modrinth/ui'
|
||||
import { Chips, MarkdownEditor, StyledInput } from '@modrinth/ui'
|
||||
|
||||
import { useImageUpload } from '~/composables/image-upload.ts'
|
||||
import { injectManageVersionContext } from '~/providers/version/manage-version-modal'
|
||||
|
||||
@@ -9,11 +9,10 @@
|
||||
<span class="text-brand-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="name"
|
||||
v-model="name"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
:maxlength="64"
|
||||
:placeholder="formatMessage(messages.namePlaceholder)"
|
||||
autocomplete="off"
|
||||
:disabled="hasHitLimit"
|
||||
@@ -26,15 +25,14 @@
|
||||
}}</span>
|
||||
<span>{{ formatMessage(messages.summaryDescription) }}</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
multiline
|
||||
:maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<p class="m-0">
|
||||
{{ formatMessage(messages.collectionInfo, { count: projectIds.length }) }}
|
||||
@@ -64,6 +62,7 @@ import {
|
||||
defineMessages,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
@@ -172,10 +171,6 @@ defineExpose({
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 5rem;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-top: var(--gap-md);
|
||||
}
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
<span class="text-brand-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="name"
|
||||
v-model="name"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
:maxlength="64"
|
||||
:placeholder="formatMessage(messages.namePlaceholder)"
|
||||
autocomplete="off"
|
||||
:disabled="hasHitLimit"
|
||||
@input="updateSlug"
|
||||
@update:model-value="updateSlug"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -29,14 +28,13 @@
|
||||
</label>
|
||||
<div class="text-input-wrapper">
|
||||
<div class="text-input-wrapper__before">https://modrinth.com/organization/</div>
|
||||
<input
|
||||
<StyledInput
|
||||
id="slug"
|
||||
v-model="slug"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
:maxlength="64"
|
||||
autocomplete="off"
|
||||
:disabled="hasHitLimit"
|
||||
@input="setManualSlug"
|
||||
@update:model-value="setManualSlug"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -48,15 +46,14 @@
|
||||
</span>
|
||||
<span>{{ formatMessage(messages.summaryDescription) }}</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
multiline
|
||||
:maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<p class="m-0">
|
||||
{{ formatMessage(messages.ownershipInfo) }}
|
||||
@@ -87,6 +84,7 @@ import {
|
||||
defineMessages,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { ref } from 'vue'
|
||||
@@ -214,10 +212,6 @@ defineExpose({
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 5rem;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
margin-top: var(--gap-md);
|
||||
}
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
<span class="text-brand-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="name"
|
||||
v-model="name"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
:maxlength="64"
|
||||
:placeholder="formatMessage(messages.namePlaceholder)"
|
||||
autocomplete="off"
|
||||
:disabled="hasHitLimit"
|
||||
@input="updatedName()"
|
||||
@update:model-value="updatedName()"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
@@ -29,14 +28,13 @@
|
||||
</label>
|
||||
<div class="text-input-wrapper">
|
||||
<div class="text-input-wrapper__before">https://modrinth.com/project/</div>
|
||||
<input
|
||||
<StyledInput
|
||||
id="slug"
|
||||
v-model="slug"
|
||||
type="text"
|
||||
maxlength="64"
|
||||
:maxlength="64"
|
||||
autocomplete="off"
|
||||
:disabled="hasHitLimit"
|
||||
@input="manualSlug = true"
|
||||
@update:model-value="manualSlug = true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -65,15 +63,14 @@
|
||||
</span>
|
||||
<span>{{ formatMessage(messages.summaryDescription) }}</span>
|
||||
</label>
|
||||
<div class="textarea-wrapper">
|
||||
<textarea
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="additional-information"
|
||||
v-model="description"
|
||||
multiline
|
||||
:maxlength="256"
|
||||
:placeholder="formatMessage(messages.summaryPlaceholder)"
|
||||
:disabled="hasHitLimit"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2">
|
||||
<ButtonStyled class="w-24">
|
||||
@@ -102,6 +99,7 @@ import {
|
||||
defineMessages,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-center gap-2">
|
||||
<div class="relative flex-1">
|
||||
<input
|
||||
<StyledInput
|
||||
ref="amountInput"
|
||||
:value="modelValue"
|
||||
:model-value="modelValue"
|
||||
type="number"
|
||||
step="0.01"
|
||||
:step="0.01"
|
||||
:min="minAmount"
|
||||
:max="safeMaxAmount"
|
||||
:disabled="isDisabled"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.amountPlaceholder)"
|
||||
class="w-full rounded-[14px] bg-surface-4 py-2.5 pl-4 pr-4 text-contrast placeholder:text-secondary"
|
||||
@input="handleInput"
|
||||
wrapper-class="w-full"
|
||||
@update:model-value="handleStyledInput"
|
||||
/>
|
||||
</div>
|
||||
<Combobox
|
||||
@@ -54,10 +54,11 @@ import {
|
||||
Combobox,
|
||||
commonMessages,
|
||||
formFieldPlaceholders,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { formatMoney } from '@modrinth/utils'
|
||||
import { computed, nextTick, ref, watch } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
@@ -81,7 +82,7 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const { formatMessage } = useVIntl()
|
||||
const amountInput = ref<HTMLInputElement | null>(null)
|
||||
const amountInput = ref<InstanceType<typeof StyledInput> | null>(null)
|
||||
|
||||
const safeMaxAmount = computed(() => {
|
||||
return Math.max(0, props.maxAmount)
|
||||
@@ -101,26 +102,19 @@ const isAboveMaximum = computed(() => {
|
||||
return props.modelValue !== undefined && props.modelValue > safeMaxAmount.value
|
||||
})
|
||||
|
||||
async function setMaxAmount() {
|
||||
function setMaxAmount() {
|
||||
const maxValue = safeMaxAmount.value
|
||||
emit('update:modelValue', maxValue)
|
||||
|
||||
await nextTick()
|
||||
if (amountInput.value) {
|
||||
amountInput.value.value = maxValue.toFixed(2)
|
||||
}
|
||||
}
|
||||
|
||||
function handleInput(event: Event) {
|
||||
const input = event.target as HTMLInputElement
|
||||
const value = input.value
|
||||
function handleStyledInput(val: string | number) {
|
||||
const value = String(val)
|
||||
|
||||
if (value && value.includes('.')) {
|
||||
const parts = value.split('.')
|
||||
if (parts[1] && parts[1].length > 2) {
|
||||
const rounded = Math.floor(parseFloat(value) * 100) / 100
|
||||
emit('update:modelValue', rounded)
|
||||
input.value = rounded.toString()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -131,14 +125,10 @@ function handleInput(event: Event) {
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
async (newAmount) => {
|
||||
(newAmount) => {
|
||||
if (newAmount !== undefined && newAmount !== null) {
|
||||
if (newAmount > safeMaxAmount.value) {
|
||||
emit('update:modelValue', safeMaxAmount.value)
|
||||
await nextTick()
|
||||
if (amountInput.value) {
|
||||
amountInput.value.value = safeMaxAmount.value.toFixed(2)
|
||||
}
|
||||
} else if (newAmount < 0) {
|
||||
emit('update:modelValue', 0)
|
||||
}
|
||||
|
||||
@@ -41,11 +41,10 @@
|
||||
>
|
||||
</label>
|
||||
<div class="flex flex-row gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="venmoHandle"
|
||||
type="text"
|
||||
:placeholder="formatMessage(messages.venmoHandlePlaceholder)"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
<ButtonStyled color="brand">
|
||||
<button
|
||||
@@ -113,6 +112,7 @@ import {
|
||||
formFieldLabels,
|
||||
IntlFormatted,
|
||||
normalizeChildren,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
|
||||
@@ -56,21 +56,19 @@
|
||||
</span>
|
||||
<div class="flex flex-col gap-3 sm:flex-row sm:gap-4">
|
||||
<div class="flex flex-1 flex-col gap-2.5">
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.bankAccountOwnerFirstName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.firstNamePlaceholder)"
|
||||
autocomplete="given-name"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2.5">
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.bankAccountOwnerLastName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.lastNamePlaceholder)"
|
||||
autocomplete="family-name"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,13 +91,12 @@
|
||||
class="h-10"
|
||||
/>
|
||||
|
||||
<input
|
||||
<StyledInput
|
||||
v-else
|
||||
v-model="formData.bankName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.bankNamePlaceholder)"
|
||||
autocomplete="off"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -111,14 +108,14 @@
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<input
|
||||
<StyledInput
|
||||
v-if="['text', 'email', 'tel'].includes(field.type)"
|
||||
v-model="formData[field.name]"
|
||||
:type="field.type"
|
||||
:type="field.type === 'tel' ? undefined : field.type === 'text' ? undefined : field.type"
|
||||
:inputmode="field.type === 'tel' ? 'tel' : undefined"
|
||||
:placeholder="field.placeholder ? formatMessage(field.placeholder) : undefined"
|
||||
:pattern="field.pattern"
|
||||
:autocomplete="field.autocomplete || 'off'"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
|
||||
<Combobox
|
||||
@@ -134,11 +131,11 @@
|
||||
class="h-10"
|
||||
/>
|
||||
|
||||
<input
|
||||
<StyledInput
|
||||
v-else-if="field.type === 'date'"
|
||||
v-model="formData[field.name]"
|
||||
type="date"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
|
||||
<span v-if="field.helpText" class="text-sm text-secondary">
|
||||
@@ -162,12 +159,11 @@
|
||||
<span v-if="dynamicDocumentNumberField.required" class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.documentNumber"
|
||||
:type="dynamicDocumentNumberField.type"
|
||||
:placeholder="dynamicDocumentNumberField.placeholder"
|
||||
autocomplete="off"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -244,6 +240,7 @@ import {
|
||||
getCurrencyIcon,
|
||||
IntlFormatted,
|
||||
normalizeChildren,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
|
||||
@@ -32,12 +32,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.businessName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.businessNamePlaceholder)"
|
||||
autocomplete="organization"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -48,12 +47,12 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.email"
|
||||
type="email"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.emailPlaceholder)"
|
||||
autocomplete="email"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -66,12 +65,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.firstName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.firstNamePlaceholder)"
|
||||
autocomplete="given-name"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2.5">
|
||||
@@ -81,12 +79,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.lastName"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.lastNamePlaceholder)"
|
||||
autocomplete="family-name"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,12 +95,12 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.dateOfBirth"
|
||||
type="date"
|
||||
:max="maxDate"
|
||||
autocomplete="bday"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,12 +112,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.physicalAddress.address1"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.addressPlaceholder)"
|
||||
autocomplete="address-line1"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -130,12 +126,11 @@
|
||||
{{ formatMessage(formFieldLabels.addressLine2) }}
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.physicalAddress.address2"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.address2Placeholder)"
|
||||
autocomplete="address-line2"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-2.5 text-contrast placeholder:text-secondary"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -147,12 +142,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.physicalAddress.city"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.cityPlaceholder)"
|
||||
autocomplete="address-level2"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2.5">
|
||||
@@ -170,13 +164,12 @@
|
||||
searchable
|
||||
search-placeholder="Search subdivisions..."
|
||||
/>
|
||||
<input
|
||||
<StyledInput
|
||||
v-else
|
||||
v-model="formData.physicalAddress.state"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.statePlaceholder)"
|
||||
autocomplete="address-level1"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -189,12 +182,11 @@
|
||||
<span class="text-red">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="formData.physicalAddress.zip"
|
||||
type="text"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.postalCodePlaceholder)"
|
||||
autocomplete="postal-code"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-1 flex-col gap-2.5">
|
||||
@@ -224,6 +216,7 @@ import {
|
||||
defineMessages,
|
||||
formFieldLabels,
|
||||
formFieldPlaceholders,
|
||||
StyledInput,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
// TODO: Switch to using Muralpay's improved endpoint when it's available.
|
||||
|
||||
@@ -39,12 +39,12 @@
|
||||
>{{ formatMessage(formFieldLabels.email) }} <span class="text-red">*</span></span
|
||||
>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="deliveryEmail"
|
||||
type="email"
|
||||
:placeholder="formatMessage(formFieldPlaceholders.emailPlaceholder)"
|
||||
autocomplete="email"
|
||||
class="w-full rounded-[14px] bg-surface-4 px-4 py-3 text-contrast placeholder:text-secondary sm:py-2.5"
|
||||
wrapper-class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -149,19 +149,17 @@
|
||||
|
||||
<div v-if="showGiftCardSelector && useFixedDenominations" class="flex flex-col gap-2.5">
|
||||
<template v-if="useDenominationSuggestions">
|
||||
<div class="iconified-input w-full">
|
||||
<SearchIcon aria-hidden="true" />
|
||||
<input
|
||||
v-model.number="denominationSearchInput"
|
||||
type="number"
|
||||
step="0.01"
|
||||
:min="0"
|
||||
:disabled="effectiveMinAmount > roundedMaxAmount"
|
||||
:placeholder="formatMessage(messages.enterDenominationPlaceholder)"
|
||||
class="!bg-surface-4"
|
||||
@input="hasTouchedSuggestions = true"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
v-model="denominationSearchInput"
|
||||
type="number"
|
||||
:icon="SearchIcon"
|
||||
:step="0.01"
|
||||
:min="0"
|
||||
:disabled="effectiveMinAmount > roundedMaxAmount"
|
||||
:placeholder="formatMessage(messages.enterDenominationPlaceholder)"
|
||||
wrapper-class="w-full"
|
||||
@update:model-value="hasTouchedSuggestions = true"
|
||||
/>
|
||||
<Transition
|
||||
enter-active-class="transition-opacity duration-200 ease-out"
|
||||
enter-from-class="opacity-0"
|
||||
@@ -350,6 +348,7 @@ import {
|
||||
IntlFormatted,
|
||||
normalizeChildren,
|
||||
paymentMethodMessages,
|
||||
StyledInput,
|
||||
useDebugLogger,
|
||||
useVIntl,
|
||||
} from '@modrinth/ui'
|
||||
|
||||
@@ -149,13 +149,13 @@
|
||||
:disabled="false"
|
||||
:heading-buttons="false"
|
||||
/>
|
||||
<textarea
|
||||
<StyledInput
|
||||
v-else
|
||||
v-model="message"
|
||||
type="text"
|
||||
class="bg-bg-input h-[400px] w-full rounded-lg border border-solid border-surface-5 px-3 py-2 font-mono text-base"
|
||||
multiline
|
||||
placeholder="No message generated."
|
||||
autocomplete="off"
|
||||
input-class="h-[400px] font-mono"
|
||||
@input="persistState"
|
||||
/>
|
||||
</div>
|
||||
@@ -298,13 +298,12 @@
|
||||
<span v-if="input.required" class="required">*</span>
|
||||
</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
:id="`input-${getActionId(action)}-${inputIndex}`"
|
||||
v-model="textInputValues[`${getActionId(action)}-${inputIndex}`]"
|
||||
type="text"
|
||||
:placeholder="input.placeholder"
|
||||
autocomplete="off"
|
||||
@input="persistState"
|
||||
@update:model-value="persistState"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
@@ -471,6 +470,7 @@ import {
|
||||
MarkdownEditor,
|
||||
OverflowMenu,
|
||||
type OverflowMenuOption,
|
||||
StyledInput,
|
||||
useDebugLogger,
|
||||
} from '@modrinth/ui'
|
||||
import {
|
||||
|
||||
@@ -34,35 +34,32 @@
|
||||
<label for="proof">
|
||||
<span class="label__title">Proof</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="proof"
|
||||
v-model="(modPackData[currentIndex] as ModerationUnknownModpackItem).proof"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Enter proof of status..."
|
||||
@input="persistAll()"
|
||||
@update:model-value="persistAll()"
|
||||
/>
|
||||
<label for="link">
|
||||
<span class="label__title">Link</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="link"
|
||||
v-model="(modPackData[currentIndex] as ModerationUnknownModpackItem).url"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Enter link of project..."
|
||||
@input="persistAll()"
|
||||
@update:model-value="persistAll()"
|
||||
/>
|
||||
<label for="title">
|
||||
<span class="label__title">Title</span>
|
||||
</label>
|
||||
<input
|
||||
<StyledInput
|
||||
id="title"
|
||||
v-model="(modPackData[currentIndex] as ModerationUnknownModpackItem).title"
|
||||
type="text"
|
||||
autocomplete="off"
|
||||
placeholder="Enter title of project..."
|
||||
@input="persistAll()"
|
||||
@update:model-value="persistAll()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -146,7 +143,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { LeftArrowIcon, RightArrowIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled } from '@modrinth/ui'
|
||||
import { ButtonStyled, StyledInput } from '@modrinth/ui'
|
||||
import type {
|
||||
ModerationFlameModpackItem,
|
||||
ModerationJudgements,
|
||||
|
||||
@@ -63,19 +63,17 @@
|
||||
</nav>
|
||||
|
||||
<div class="flex flex-shrink-0 items-center gap-2">
|
||||
<div class="iconified-input w-full sm:w-[280px]">
|
||||
<SearchIcon aria-hidden="true" class="!text-secondary" />
|
||||
<input
|
||||
id="search-folder"
|
||||
:value="searchQuery"
|
||||
type="search"
|
||||
name="search"
|
||||
autocomplete="off"
|
||||
class="h-10 w-full rounded-[14px] border-0 bg-surface-4 text-sm"
|
||||
placeholder="Search files"
|
||||
@input="$emit('update:searchQuery', ($event.target as HTMLInputElement).value)"
|
||||
/>
|
||||
</div>
|
||||
<StyledInput
|
||||
id="search-folder"
|
||||
:model-value="searchQuery"
|
||||
:icon="SearchIcon"
|
||||
type="search"
|
||||
name="search"
|
||||
autocomplete="off"
|
||||
placeholder="Search files"
|
||||
wrapper-class="w-full sm:w-[280px]"
|
||||
@update:model-value="$emit('update:searchQuery', $event)"
|
||||
/>
|
||||
|
||||
<ButtonStyled type="outlined">
|
||||
<OverflowMenu
|
||||
@@ -128,7 +126,7 @@ import {
|
||||
SearchIcon,
|
||||
UploadIcon,
|
||||
} from '@modrinth/assets'
|
||||
import { ButtonStyled, OverflowMenu } from '@modrinth/ui'
|
||||
import { ButtonStyled, OverflowMenu, StyledInput } from '@modrinth/ui'
|
||||
|
||||
defineProps<{
|
||||
breadcrumbSegments: string[]
|
||||
|
||||
@@ -3,14 +3,12 @@
|
||||
<form class="flex flex-col gap-4 md:w-[600px]" @submit.prevent="handleSubmit">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="font-semibold text-contrast">Name</div>
|
||||
<input
|
||||
<StyledInput
|
||||
ref="createInput"
|
||||
v-model="itemName"
|
||||
autofocus
|
||||
type="text"
|
||||
class="bg-bg-input w-full rounded-lg p-4"
|
||||
wrapper-class="bg-bg-input w-full rounded-lg p-4"
|
||||
:placeholder="`e.g. ${type === 'file' ? 'config.yml' : 'plugins'}`"
|
||||
required
|
||||
/>
|
||||
<div v-if="submitted && error" class="text-red">{{ error }}</div>
|
||||
</div>
|
||||
@@ -34,7 +32,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { PlusIcon, XIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled, NewModal } from '@modrinth/ui'
|
||||
import { ButtonStyled, NewModal, StyledInput } from '@modrinth/ui'
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
<NewModal ref="modal" :header="`Moving ${item?.name}`">
|
||||
<form class="flex flex-col gap-4 md:w-[600px]" @submit.prevent="handleSubmit">
|
||||
<div class="flex flex-col gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
ref="destinationInput"
|
||||
v-model="destination"
|
||||
autofocus
|
||||
type="text"
|
||||
class="bg-bg-input w-full rounded-lg p-4"
|
||||
wrapper-class="bg-bg-input w-full rounded-lg p-4"
|
||||
placeholder="e.g. /mods/modname"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 text-nowrap">
|
||||
@@ -38,7 +36,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ArrowBigUpDashIcon, XIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled, NewModal } from '@modrinth/ui'
|
||||
import { ButtonStyled, NewModal, StyledInput } from '@modrinth/ui'
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
|
||||
const destinationInput = ref<HTMLInputElement | null>(null)
|
||||
|
||||
@@ -3,13 +3,11 @@
|
||||
<form class="flex flex-col gap-4 md:w-[600px]" @submit.prevent="handleSubmit">
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="font-semibold text-contrast">Name</div>
|
||||
<input
|
||||
<StyledInput
|
||||
ref="renameInput"
|
||||
v-model="itemName"
|
||||
autofocus
|
||||
type="text"
|
||||
class="bg-bg-input w-full rounded-lg p-4"
|
||||
required
|
||||
wrapper-class="bg-bg-input w-full rounded-lg p-4"
|
||||
/>
|
||||
<div v-if="submitted && error" class="text-red">{{ error }}</div>
|
||||
</div>
|
||||
@@ -33,7 +31,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { EditIcon, XIcon } from '@modrinth/assets'
|
||||
import { ButtonStyled, NewModal } from '@modrinth/ui'
|
||||
import { ButtonStyled, NewModal, StyledInput } from '@modrinth/ui'
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
|
||||
const props = defineProps<{
|
||||
|
||||
@@ -33,16 +33,14 @@
|
||||
</li>
|
||||
</ol>
|
||||
<p v-else class="mb-1 mt-0">Copy and paste the direct download URL of a .zip file.</p>
|
||||
<input
|
||||
<StyledInput
|
||||
ref="urlInput"
|
||||
v-model="url"
|
||||
autofocus
|
||||
:disabled="submitted"
|
||||
type="text"
|
||||
data-1p-ignore
|
||||
data-lpignore="true"
|
||||
data-protonpass-ignore="true"
|
||||
required
|
||||
:placeholder="
|
||||
cf
|
||||
? 'https://www.curseforge.com/minecraft/modpacks/.../files/6412259'
|
||||
@@ -81,6 +79,7 @@ import {
|
||||
injectModrinthServerContext,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
StyledInput,
|
||||
} from '@modrinth/ui'
|
||||
import { ModrinthServersFetchError } from '@modrinth/utils'
|
||||
import { computed, nextTick, ref } from 'vue'
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
<div class="contents">
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="relative w-full">
|
||||
<input
|
||||
<StyledInput
|
||||
v-model="searchInput"
|
||||
type="text"
|
||||
type="search"
|
||||
:icon="SearchIcon"
|
||||
placeholder="Search logs"
|
||||
class="h-12 !w-full !pl-10 !pr-48"
|
||||
wrapper-class="h-12 !w-full"
|
||||
input-class="!pr-48"
|
||||
:disabled="loading"
|
||||
@keydown.escape="clearSearch"
|
||||
/>
|
||||
<SearchIcon class="absolute left-4 top-1/2 -translate-y-1/2" />
|
||||
<ButtonStyled v-if="searchInput && !loading" @click="clearSearch">
|
||||
<button class="absolute right-2 top-1/2 -translate-y-1/2">
|
||||
<XIcon class="h-5 w-5" />
|
||||
@@ -298,7 +299,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { CopyIcon, EyeIcon, RightArrowIcon, SearchIcon, XIcon } from '@modrinth/assets'
|
||||
import { NewModal } from '@modrinth/ui'
|
||||
import { NewModal, StyledInput } from '@modrinth/ui'
|
||||
import ButtonStyled from '@modrinth/ui/src/components/base/ButtonStyled.vue'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
ServerNotice,
|
||||
StyledInput,
|
||||
TagItem,
|
||||
} from '@modrinth/ui'
|
||||
import type { ServerNotice as ServerNoticeType } from '@modrinth/utils'
|
||||
@@ -180,11 +181,10 @@ defineExpose({ show, hide })
|
||||
<span v-else class="mb-2"> No nodes assigned yet </span>
|
||||
</div>
|
||||
<div class="flex w-[45rem] items-center gap-2">
|
||||
<input
|
||||
<StyledInput
|
||||
id="server-assign-field"
|
||||
v-model="inputField"
|
||||
class="w-full"
|
||||
type="text"
|
||||
wrapper-class="w-full"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<ButtonStyled color="green" color-fill="text">
|
||||
|
||||
@@ -506,23 +506,6 @@ const requestedStatus = computed(() => props.project.requested_status ?? 'approv
|
||||
padding: var(--spacing-card-md);
|
||||
}
|
||||
|
||||
.resizable-textarea-wrapper {
|
||||
margin-bottom: var(--spacing-card-sm);
|
||||
|
||||
textarea {
|
||||
padding: var(--spacing-card-bg);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chips {
|
||||
margin-bottom: var(--spacing-card-md);
|
||||
}
|
||||
|
||||
.preview {
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.thread-id {
|
||||
margin-bottom: var(--spacing-card-md);
|
||||
font-weight: bold;
|
||||
|
||||
Reference in New Issue
Block a user