Settings
Profile, notifications and a danger zone as stacked panels in one form — Enter saves, Discard restores — with a sticky save bar.
BlessForm · BlessPanel · BlessField · BlessInput · BlessTextarea · BlessSelect · BlessCheckbox · BlessAvatar · BlessButton · BlessAlertDialog
<script setup lang="ts">
import { reactive, ref } from "vue";
import {
BlessAlertDialog,
BlessAvatar,
BlessButton,
BlessCheckbox,
BlessField,
BlessForm,
BlessInput,
BlessPanel,
BlessSelect,
BlessText,
BlessTextarea,
useToast,
} from "blessing-ui";
const saved = {
name: "加藤 恵",
email: "megumi@example.com",
bio: "同じクラスの、目立たない女の子。",
lang: "ja",
emails: true,
push: false,
digest: true,
};
const form = reactive({ ...saved });
const langs = [
{ value: "ja", label: "日本語" },
{ value: "en", label: "English" },
];
const confirmDelete = ref(false);
const { success, info } = useToast();
function save() {
Object.assign(saved, form);
success("Settings saved");
}
function discard() {
Object.assign(form, saved);
info("Changes discarded");
}
</script>
<template>
<!-- a form, so Enter in any field saves -->
<BlessForm class="settings" @submit="save">
<BlessText as="h1" size="lg" weight="light">Settings</BlessText>
<BlessPanel title="Profile" :level="2">
<div class="settings__avatar">
<BlessAvatar :name="form.name" size="lg" />
<BlessButton size="sm" variant="outline">Change photo</BlessButton>
</div>
<div class="settings__grid">
<BlessField label="Name"><BlessInput v-model="form.name" /></BlessField>
<BlessField label="Email"><BlessInput v-model="form.email" type="email" /></BlessField>
</div>
<BlessField label="Bio" description="Shown on your public profile."
><BlessTextarea v-model="form.bio" :rows="2" autogrow
/></BlessField>
<BlessField label="Language"><BlessSelect v-model="form.lang" :options="langs" /></BlessField>
</BlessPanel>
<BlessPanel title="Notifications" :level="2">
<div class="settings__checks">
<!-- checkboxes, not switches: these apply on Save, and a switch promises it's done now -->
<BlessCheckbox v-model="form.emails">Email me about account activity</BlessCheckbox>
<BlessCheckbox v-model="form.push">Push notifications</BlessCheckbox>
<BlessCheckbox v-model="form.digest">Weekly digest</BlessCheckbox>
</div>
</BlessPanel>
<BlessPanel title="Danger zone" :level="2" class="settings__danger">
<BlessText as="p" size="sm" muted
>Deleting your account removes all your data. This cannot be undone.</BlessText
>
<BlessButton color="danger" variant="outline" size="sm" @click="confirmDelete = true"
>Delete account</BlessButton
>
</BlessPanel>
<div class="settings__bar">
<BlessButton variant="ghost" @click="discard">Discard</BlessButton>
<BlessButton type="submit">Save changes</BlessButton>
</div>
<BlessAlertDialog
v-model="confirmDelete"
title="Delete account?"
confirm-label="Delete"
@confirm="confirmDelete = false"
>
Everything goes: profile, history, files. Type your password on the next screen to confirm.
</BlessAlertDialog>
</BlessForm>
</template>
<style scoped>
.settings {
display: grid;
gap: var(--bless-space-6);
max-width: 640px;
margin: 0 auto;
padding: var(--bless-space-8) var(--bless-space-6);
}
.settings__avatar {
display: flex;
align-items: center;
gap: var(--bless-space-4);
margin-bottom: var(--bless-space-4);
}
.settings__grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--bless-space-4);
}
.settings :deep(.bless-field) {
margin-bottom: var(--bless-space-4);
}
.settings__checks {
display: grid;
gap: var(--bless-space-3);
}
.settings__danger :deep(.bless-panel__title) {
color: var(--bless-color-danger-text);
}
.settings__danger p {
margin-bottom: var(--bless-space-3);
}
.settings__bar {
position: sticky;
bottom: 0;
display: flex;
justify-content: flex-end;
gap: var(--bless-space-2);
padding: var(--bless-space-3) 0;
background: var(--bless-color-bg);
border-top: var(--bless-border-width) solid var(--bless-color-border);
}
</style>
Into your app
Copy the folder to src/features/settings/ (Nuxt: app/features/settings/) and render index.vue from a page. Load saved from your API and send form in save(); Discard already puts saved back.