---
name: account-access
title: Account Access
url: https://ui.frontic.com/components/sections/account-access.md
tier: sections
install: npx @frontic/ui add account-access
files:
  - components/sections/account-access/AccountAccess.vue
  - components/sections/account-access/index.ts
registryDependencies:
  - alert
  - button
  - card
  - field
  - input
  - item
  - switch
dependencies:
  - "@lucide/vue"
---

# Account Access

Sign-in and security settings card: a pending-change notice, email and password with change actions, a two-factor switch, and account deletion.

## Install

```sh
npx @frontic/ui add account-access
```

Built from: [Alert](https://ui.frontic.com/components/ui/alert.md), [Button](https://ui.frontic.com/components/ui/button.md), [Card](https://ui.frontic.com/components/ui/card.md), [Field](https://ui.frontic.com/components/ui/field.md), [Input](https://ui.frontic.com/components/ui/input.md), [Item](https://ui.frontic.com/components/ui/item.md), [Switch](https://ui.frontic.com/components/ui/switch.md)

npm packages: `@lucide/vue`

## Examples

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { AccountAccess } from '@/components/sections/account-access'

const email = ref('lena.berg@example.com')
const password = ref('summit-ridge-2026')
const twoFactor = ref(true)
</script>

<template>
  <div class="mx-auto w-full max-w-md">
    <AccountAccess
      v-model:email="email"
      v-model:password="password"
      v-model:two-factor="twoFactor"
      description="How you get into your Basecamp Store account."
      notice-title="Confirm your new email"
      notice-description="We sent a link to lena.berg@posteo.de. It expires on 10 Oct."
      password-hint="Last changed on 14 March 2026."
      two-factor-hint="Authenticator app, added 2 Sep 2026."
    />
  </div>
</template>
```

## API reference

### AccountAccess

Lets the shopper change email and password, switch two-factor on and delete the account.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `string` | `'Sign-in & security'` | The card's heading. |
| `description` | `string` | `'How you get into your account.'` | Shown under the heading. |
| `noticeTitle` | `string` |  | A pending change to confirm, shown as a notice above the fields. |
| `noticeDescription` | `string` |  | Shown under the notice's title. |
| `emailLabel` | `string` | `'Email'` | Shown above the email field. |
| `passwordLabel` | `string` | `'Password'` | Shown above the password field. |
| `passwordHint` | `string` |  | Under the password, e.g. when it was last changed. |
| `changeLabel` | `string` | `'Change'` | Shown on the buttons that save a new email or password. |
| `twoFactorLabel` | `string` | `'Two-factor authentication'` | Shown beside the two-factor switch. |
| `twoFactorHint` | `string` |  | Under the two-factor switch, e.g. which method is set up. |
| `deleteTitle` | `string` | `'Delete account'` | Shown as the title of the row that deletes the account. |
| `deleteDescription` | `string` | `'Erases orders and saved addresses.'` | Shown under the delete row's title, e.g. what deleting erases. |
| `deleteLabel` | `string` | `'Delete'` | Shown on the button that deletes the account. |
| `surface` | `'raised' \| 'bare'` | `'raised'` | Bare drops the edge, shadow and inset, for a section placed inside another Card. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `email` | `string` | `''` | The email in the email field, sent with `changeEmail`. |
| `password` | `string` | `''` | The new password typed into the password field, sent with `changePassword`. |
| `twoFactor` | `boolean` | `false` | Whether two-factor authentication is switched on. |

| Event | Payload | Description |
| --- | --- | --- |
| `delete` |  | Fires when the customer asks to delete their account. |
| `update:email` | `value: string` | Fires with the new value when `email` changes; `v-model:email` binds it. |
| `update:password` | `value: string` | Fires with the new value when `password` changes; `v-model:password` binds it. |
| `update:twoFactor` | `value: boolean` | Fires with the new value when `twoFactor` changes; `v-model:twoFactor` binds it. |
| `changeEmail` | `email: string` | Fires with the entered email when the customer asks to change their email address. |
| `changePassword` | `password: string` | Fires with the entered password when the customer asks to change their password. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-surface` | `'raised' \| 'bare'` | Carries the `surface` prop. |

## Styling

| Part | Recipe |
| --- | --- |
| `delete-title` | [`account-access-delete-title`](https://ui.frontic.com/DESIGN.md#account-access-delete-title) |

## Source

`components/sections/account-access/AccountAccess.vue`

```vue
<script lang="ts">
/** Lets the shopper change email and password, switch two-factor on and delete the account. */
export default {}
</script>

<script setup lang="ts">
import { MailCheckIcon } from '@lucide/vue'

import type { HTMLAttributes } from 'vue'
import { useId } from 'vue'
import { Alert, AlertDescription, AlertTitle } from '@library/components/ui/alert'
import { Button } from '@library/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@library/components/ui/card'
import { Field, FieldContent, FieldDescription, FieldLabel } from '@library/components/ui/field'
import { Input } from '@library/components/ui/input'
import { Item, ItemActions, ItemContent, ItemDescription, ItemTitle } from '@library/components/ui/item'
import { Switch } from '@library/components/ui/switch'

const props = withDefaults(
  defineProps<{
    /** The card's heading. */
    title?: string
    /** Shown under the heading. */
    description?: string
    /** A pending change to confirm, shown as a notice above the fields. */
    noticeTitle?: string
    /** Shown under the notice's title. */
    noticeDescription?: string
    /** Shown above the email field. */
    emailLabel?: string
    /** Shown above the password field. */
    passwordLabel?: string
    /** Under the password, e.g. when it was last changed. */
    passwordHint?: string
    /** Shown on the buttons that save a new email or password. */
    changeLabel?: string
    /** Shown beside the two-factor switch. */
    twoFactorLabel?: string
    /** Under the two-factor switch, e.g. which method is set up. */
    twoFactorHint?: string
    /** Shown as the title of the row that deletes the account. */
    deleteTitle?: string
    /** Shown under the delete row's title, e.g. what deleting erases. */
    deleteDescription?: string
    /** Shown on the button that deletes the account. */
    deleteLabel?: string
    /** Bare drops the edge, shadow and inset, for a section placed inside another Card. */
    surface?: 'raised' | 'bare'
    class?: HTMLAttributes['class']
  }>(),
  {
    surface: 'raised',
    title: 'Sign-in & security',
    description: 'How you get into your account.',
    emailLabel: 'Email',
    passwordLabel: 'Password',
    changeLabel: 'Change',
    twoFactorLabel: 'Two-factor authentication',
    deleteTitle: 'Delete account',
    deleteDescription: 'Erases orders and saved addresses.',
    deleteLabel: 'Delete',
  },
)
const emit = defineEmits<{
  /** Fires with the entered email when the customer asks to change their email address. */
  changeEmail: [email: string]
  /** Fires with the entered password when the customer asks to change their password. */
  changePassword: [password: string]
  /** Fires when the customer asks to delete their account. */
  delete: []
}>()

/** The email in the email field, sent with `changeEmail`. */
const email = defineModel<string>('email', { default: '' })
/** The new password typed into the password field, sent with `changePassword`. */
const password = defineModel<string>('password', { default: '' })
/** Whether two-factor authentication is switched on. */
const twoFactor = defineModel<boolean>('twoFactor', { default: false })

const id = useId()
</script>

<template>
  <Card :surface="surface" :class="props.class">
    <CardHeader>
      <CardTitle>{{ title }}</CardTitle>
      <CardDescription v-if="description">{{ description }}</CardDescription>
    </CardHeader>
    <CardContent>
      <div class="flex flex-col gap-6">
        <Alert v-if="noticeTitle" variant="info">
          <template #icon><MailCheckIcon data-icon /></template>
          <AlertTitle>{{ noticeTitle }}</AlertTitle>
          <AlertDescription v-if="noticeDescription">{{ noticeDescription }}</AlertDescription>
        </Alert>
        <Field>
          <FieldLabel :for="`${id}-email`">{{ emailLabel }}</FieldLabel>
          <div class="flex gap-2">
            <Input :id="`${id}-email`" v-model="email" type="email" autocomplete="email" />
            <Button variant="outline" color="neutral" @click="emit('changeEmail', email)">{{ changeLabel }}</Button>
          </div>
        </Field>
        <Field>
          <FieldLabel :for="`${id}-password`">{{ passwordLabel }}</FieldLabel>
          <div class="flex gap-2">
            <Input :id="`${id}-password`" v-model="password" type="password" autocomplete="new-password" />
            <Button variant="outline" color="neutral" @click="emit('changePassword', password)">{{ changeLabel }}</Button>
          </div>
          <FieldDescription v-if="passwordHint">{{ passwordHint }}</FieldDescription>
        </Field>
        <Field orientation="horizontal">
          <FieldContent>
            <FieldLabel :for="`${id}-2fa`">{{ twoFactorLabel }}</FieldLabel>
            <FieldDescription v-if="twoFactorHint">{{ twoFactorHint }}</FieldDescription>
          </FieldContent>
          <Switch :id="`${id}-2fa`" v-model="twoFactor" />
        </Field>
        <Item variant="outline" size="sm">
          <ItemContent>
            <ItemTitle>
              <span data-slot="account-access-delete-title" class="fui-account-access-delete-title">{{ deleteTitle }}</span>
            </ItemTitle>
            <ItemDescription v-if="deleteDescription">{{ deleteDescription }}</ItemDescription>
          </ItemContent>
          <ItemActions>
            <Button variant="soft" color="destructive" size="sm" @click="emit('delete')">{{ deleteLabel }}</Button>
          </ItemActions>
        </Item>
      </div>
    </CardContent>
  </Card>
</template>
```
