Skip to content

Commit 36f498f

Browse files
feat(app): improve variable creation form UX (#725)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent a4eb7be commit 36f498f

2 files changed

Lines changed: 121 additions & 113 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@shelve/app": patch
3+
---
4+
5+
Improve variable creation form UX: cap textarea height, add visual separation between entries, and reposition controls

apps/shelve/app/components/variable/Create.vue

Lines changed: 116 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -84,135 +84,138 @@ const handlePasswordGenerated = (password: string, index: number) => variablesIn
8484
:ui="{ root: border }"
8585
class="duration-500"
8686
>
87-
<div :class="{ 'absolute': isOverDropZone, 'hidden': !isOverDropZone }" class="pointer-events-none left-0 top-0 z-40 size-full content-center items-center justify-center">
88-
<div class="icon-container flex flex-col items-center gap-2">
89-
<UIcon name="lucide:file-up" class="text-primary size-10" />
90-
<p class="text-lg font-semibold">
91-
Drop your file here
92-
</p>
93-
</div>
94-
</div>
95-
<template #header>
96-
<div :class="{ 'opacity-30': isOverDropZone }" class="flex items-center justify-between">
97-
<div class="flex flex-col">
98-
<h2 class="text-lg font-semibold">
99-
Environment Variables
100-
</h2>
101-
<p class="text-sm font-normal text-muted">
102-
Manage your environment variables
87+
<div :class="{ 'absolute': isOverDropZone, 'hidden': !isOverDropZone }" class="pointer-events-none left-0 top-0 z-40 size-full content-center items-center justify-center">
88+
<div class="icon-container flex flex-col items-center gap-2">
89+
<UIcon name="lucide:file-up" class="text-primary size-10" />
90+
<p class="text-lg font-semibold">
91+
Drop your file here
10392
</p>
10493
</div>
105-
<UDropdownMenu :items :content="{ align: 'start',side: 'right', sideOffset: 8 }">
106-
<UButton variant="ghost" icon="heroicons:ellipsis-horizontal-20-solid" />
107-
</UDropdownMenu>
10894
</div>
109-
</template>
110-
<div :class="{ 'opacity-30': isOverDropZone }" class="flex flex-col gap-3">
111-
<div class="flex w-full flex-col gap-4 md:w-1/3">
112-
<h4 class="text-sm font-semibold">
113-
Environments
114-
</h4>
115-
<div class="flex select-none gap-4">
116-
<UCheckbox
117-
v-for="env in environments"
118-
:key="env.id"
119-
v-model="selectedEnvironments[env.id]"
120-
:name="env.name"
121-
:label="capitalize(env.name)"
122-
/>
95+
<template #header>
96+
<div :class="{ 'opacity-30': isOverDropZone }" class="flex items-center justify-between">
97+
<div class="flex flex-col">
98+
<h2 class="text-lg font-semibold">
99+
Environment Variables
100+
</h2>
101+
<p class="text-sm font-normal text-muted">
102+
Manage your environment variables
103+
</p>
104+
</div>
105+
<UDropdownMenu :items :content="{ align: 'start',side: 'right', sideOffset: 8 }">
106+
<UButton variant="ghost" icon="heroicons:ellipsis-horizontal-20-solid" />
107+
</UDropdownMenu>
123108
</div>
124-
</div>
125-
<Separator class="my-1" />
126-
<div class="flex items-center gap-2">
127-
<USwitch v-model="autoUppercase" size="sm" label="Auto uppercase" />
128-
<UTooltip
129-
class="hidden sm:block"
130-
:content="{ side: 'right' }"
131-
text="Automatically uppercase all variable keys (e.g. Api_Key -> API_KEY)"
132-
>
133-
<UIcon name="lucide:info" class="text-muted size-4" />
134-
</UTooltip>
135-
</div>
136-
<div class="flex items-center gap-2 mt-2">
137-
<USwitch v-model="syncWithGitHub" size="sm" label="Sync with GitHub" :disabled="!apps || apps.length === 0" />
138-
<UTooltip
139-
class="hidden sm:block"
140-
:content="{ side: 'right' }"
141-
text="Automatically send your environment variables to GitHub secrets"
142-
>
143-
<UIcon name="lucide:info" class="text-muted size-4" />
144-
</UTooltip>
145-
<TextGradient text="New" class="font-normal text-sm" />
146-
</div>
147-
<Separator class="my-1" />
148-
<p class="text-xs font-normal text-muted">
149-
You can also paste all your environment variables (.env) as key value pairs to prefilled the form
150-
</p>
151-
<div class="mb-4 flex flex-col gap-2">
152-
<div class="hidden items-center sm:flex">
153-
<span class="w-full text-sm font-normal text-muted">Key</span>
154-
<span class="w-full text-sm font-normal text-muted">Value</span>
155-
<div class="w-[100px]" />
109+
</template>
110+
<div :class="{ 'opacity-30': isOverDropZone }" class="flex flex-col gap-3">
111+
<div class="flex w-full flex-col gap-4 md:w-1/3">
112+
<h4 class="text-sm font-semibold">
113+
Environments
114+
</h4>
115+
<div class="flex select-none gap-4">
116+
<UCheckbox
117+
v-for="env in environments"
118+
:key="env.id"
119+
v-model="selectedEnvironments[env.id]"
120+
:name="env.name"
121+
:label="capitalize(env.name)"
122+
/>
123+
</div>
124+
</div>
125+
<Separator class="my-1" />
126+
<div class="flex items-center gap-2">
127+
<USwitch v-model="autoUppercase" size="sm" label="Auto uppercase" />
128+
<UTooltip
129+
class="hidden sm:block"
130+
:content="{ side: 'right' }"
131+
text="Automatically uppercase all variable keys (e.g. Api_Key -> API_KEY)"
132+
>
133+
<UIcon name="lucide:info" class="text-muted size-4" />
134+
</UTooltip>
135+
</div>
136+
<div class="flex items-center gap-2 mt-2">
137+
<USwitch v-model="syncWithGitHub" size="sm" label="Sync with GitHub" :disabled="!apps || apps.length === 0" />
138+
<UTooltip
139+
class="hidden sm:block"
140+
:content="{ side: 'right' }"
141+
text="Automatically send your environment variables to GitHub secrets"
142+
>
143+
<UIcon name="lucide:info" class="text-muted size-4" />
144+
</UTooltip>
145+
<TextGradient text="New" class="font-normal text-sm" />
156146
</div>
157-
<div v-for="variable in variablesToCreate" :key="variable" class="flex flex-col gap-4">
158-
<div class="flex flex-col gap-1">
159-
<div class="flex flex-col items-start gap-1 sm:flex-row">
160-
<div class="w-full flex items-start gap-1">
147+
<Separator class="my-1" />
148+
<p class="text-xs font-normal text-muted">
149+
You can also paste all your environment variables (.env) as key value pairs to prefilled the form
150+
</p>
151+
<div class="mb-4 flex flex-col gap-3">
152+
<div
153+
v-for="variable in variablesToCreate"
154+
:key="variable"
155+
class="relative rounded-lg border border-default p-3"
156+
>
157+
<div class="flex items-start gap-3">
158+
<span class="text-xs text-muted tabular-nums pt-2 select-none">{{ variable }}</span>
159+
<div class="flex flex-1 flex-col gap-2">
160+
<div class="flex flex-col gap-2 sm:flex-row">
161+
<div class="w-full flex items-start gap-1">
162+
<UInput
163+
v-model="variablesInput.variables[variable - 1]!.key"
164+
required
165+
class="w-full"
166+
placeholder="e.g. API_KEY"
167+
/>
168+
<VariablePrefix v-model="variablesInput.variables[variable - 1]!.key" />
169+
</div>
170+
<div class="w-full flex items-start gap-1">
171+
<UTextarea
172+
v-model="variablesInput.variables[variable - 1]!.value"
173+
required
174+
:rows="1"
175+
:maxrows="4"
176+
class="w-full"
177+
autoresize
178+
placeholder="e.g. 123456"
179+
/>
180+
<VariableGenerator @password-generated="handlePasswordGenerated($event, variable - 1)" />
181+
</div>
182+
</div>
161183
<UInput
162-
v-model="variablesInput.variables[variable - 1]!.key"
163-
required
184+
v-model="variablesInput.variables[variable - 1]!.description"
185+
placeholder="Description (optional)"
164186
class="w-full"
165-
placeholder="e.g. API_KEY"
166187
/>
167-
<VariablePrefix v-model="variablesInput.variables[variable - 1]!.key" />
168-
</div>
169-
<div class="w-full flex items-start gap-1">
170-
<UTextarea
171-
v-model="variablesInput.variables[variable - 1]!.value"
172-
required
173-
:rows="1"
174-
class="w-full"
175-
autoresize
176-
placeholder="e.g. 123456"
177-
/>
178-
<VariableGenerator @password-generated="handlePasswordGenerated($event, variable - 1)" />
179188
</div>
180189
<UTooltip text="Remove variable" :content="{ side: 'top' }">
181-
<UButton icon="lucide:x" variant="soft" color="error" @click="removeVariable(variable - 1)" />
190+
<UButton icon="lucide:x" variant="ghost" color="error" size="xs" @click="removeVariable(variable - 1)" />
182191
</UTooltip>
183192
</div>
184-
<UInput
185-
v-model="variablesInput.variables[variable - 1]!.description"
186-
placeholder="Description (optional)"
187-
class="w-full"
188-
/>
189193
</div>
190194
</div>
191195
</div>
192-
</div>
193-
<template #footer>
194-
<div :class="{ 'opacity-30': isOverDropZone }" class="flex justify-between gap-4">
195-
<div class="flex gap-2">
196-
<UButton
197-
label="Add variable"
198-
size="xs"
199-
variant="soft"
200-
icon="heroicons:plus-circle-20-solid"
201-
@click="addVariable"
202-
/>
203-
<input ref="fileInputRef" type="file" accept="text" style="display: none;" @change="handleFileUpload">
204-
<UButton
205-
label="Import .env"
206-
size="xs"
207-
variant="soft"
208-
icon="lucide:download"
209-
@click="triggerFileInput"
210-
/>
196+
<template #footer>
197+
<div :class="{ 'opacity-30': isOverDropZone }" class="flex justify-between gap-4">
198+
<div class="flex gap-2">
199+
<UButton
200+
label="Add variable"
201+
size="xs"
202+
variant="soft"
203+
icon="heroicons:plus-circle-20-solid"
204+
@click="addVariable"
205+
/>
206+
<input ref="fileInputRef" type="file" accept="text" style="display: none;" @change="handleFileUpload">
207+
<UButton
208+
label="Import .env"
209+
size="xs"
210+
variant="soft"
211+
icon="lucide:download"
212+
@click="triggerFileInput"
213+
/>
214+
</div>
215+
<UButton label="Save" :loading="createLoading" type="submit" />
211216
</div>
212-
<UButton label="Save" :loading="createLoading" type="submit" />
213-
</div>
214-
</template>
215-
</UCard>
217+
</template>
218+
</UCard>
216219
</div>
217220
</form>
218221
</template>

0 commit comments

Comments
 (0)