0
# Feedback
1
2
Components for providing user feedback, displaying status, and handling user interactions through alerts, notifications, progress indicators, and modal dialogs.
3
4
## Capabilities
5
6
### VAlert
7
8
Alert component for displaying important messages and notifications with various severity levels.
9
10
```typescript { .api }
11
/**
12
* Alert component for notifications and messages
13
*/
14
const VAlert: Component;
15
16
interface AlertProps {
17
/** Alert message text */
18
text?: string;
19
/** Alert title */
20
title?: string;
21
/** Alert type/color */
22
type?: 'success' | 'info' | 'warning' | 'error';
23
/** Alert color */
24
color?: string;
25
/** Alert variant */
26
variant?: 'flat' | 'elevated' | 'tonal' | 'outlined' | 'text' | 'plain';
27
/** Alert density */
28
density?: 'default' | 'comfortable' | 'compact';
29
/** Closable alert */
30
closable?: boolean;
31
/** Close icon */
32
closeIcon?: string;
33
/** Close label for accessibility */
34
closeLabel?: string;
35
/** Prepend icon */
36
prependIcon?: string;
37
/** Append icon */
38
appendIcon?: string;
39
/** Icon for the alert type */
40
icon?: string | boolean;
41
/** Border location */
42
border?: boolean | 'top' | 'end' | 'bottom' | 'start';
43
/** Prominent style */
44
prominent?: boolean;
45
/** Alert width */
46
width?: string | number;
47
/** Maximum width */
48
maxWidth?: string | number;
49
/** Minimum width */
50
minWidth?: string | number;
51
/** Alert height */
52
height?: string | number;
53
/** Maximum height */
54
maxHeight?: string | number;
55
/** Minimum height */
56
minHeight?: string | number;
57
/** Elevation level */
58
elevation?: number | string;
59
/** Rounded corners */
60
rounded?: boolean | string | number;
61
/** Tile style (no border radius) */
62
tile?: boolean;
63
}
64
65
// Events
66
interface AlertEvents {
67
'click:close': (event: MouseEvent) => void;
68
'click:prepend': (event: MouseEvent) => void;
69
'click:append': (event: MouseEvent) => void;
70
}
71
```
72
73
**Usage Examples:**
74
75
```vue
76
<template>
77
<!-- Basic alerts -->
78
<v-alert type="success" text="Operation completed successfully!" />
79
80
<v-alert type="warning" title="Warning" text="Please review your settings." />
81
82
<v-alert type="error" closable @click:close="handleClose">
83
<v-alert-title>Error occurred</v-alert-title>
84
Unable to save changes. Please try again.
85
</v-alert>
86
87
<!-- Custom styled alert -->
88
<v-alert
89
color="purple"
90
variant="tonal"
91
prominent
92
border="start"
93
icon="mdi-information"
94
>
95
<strong>Pro Tip:</strong> You can customize alerts with different variants and borders.
96
</v-alert>
97
98
<!-- Alert with actions -->
99
<v-alert type="info" closable>
100
<div class="d-flex align-center">
101
<div class="flex-grow-1">New update available</div>
102
<v-btn size="small" variant="outlined">Update</v-btn>
103
</div>
104
</v-alert>
105
</template>
106
107
<script setup>
108
const handleClose = () => {
109
console.log('Alert closed');
110
};
111
</script>
112
```
113
114
### VSnackbar
115
116
Toast notification component for displaying temporary messages with optional actions.
117
118
```typescript { .api }
119
/**
120
* Snackbar toast notification component
121
*/
122
const VSnackbar: Component;
123
124
interface SnackbarProps {
125
/** Snackbar visibility */
126
modelValue?: boolean;
127
/** Snackbar text content */
128
text?: string;
129
/** Display timeout in milliseconds */
130
timeout?: number | string;
131
/** Multi-line layout */
132
multiLine?: boolean;
133
/** Vertical positioning */
134
vertical?: boolean;
135
/** Snackbar location */
136
location?:
137
| 'top' | 'bottom' | 'left' | 'right' | 'center'
138
| 'top left' | 'top right' | 'bottom left' | 'bottom right'
139
| 'top center' | 'bottom center' | 'center left' | 'center right';
140
/** Snackbar color */
141
color?: string;
142
/** Snackbar variant */
143
variant?: 'flat' | 'elevated' | 'tonal' | 'outlined' | 'text' | 'plain';
144
/** Rounded corners */
145
rounded?: boolean | string | number;
146
/** Tile style */
147
tile?: boolean;
148
/** Elevation level */
149
elevation?: number | string;
150
/** Minimum width */
151
minWidth?: string | number;
152
/** Maximum width */
153
maxWidth?: string | number;
154
/** Width */
155
width?: string | number;
156
/** Height */
157
height?: string | number;
158
/** Z-index */
159
zIndex?: number | string;
160
/** Close on content click */
161
closeOnContentClick?: boolean;
162
/** Close on back navigation */
163
closeOnBack?: boolean;
164
}
165
166
// Events
167
interface SnackbarEvents {
168
'update:modelValue': (visible: boolean) => void;
169
}
170
```
171
172
**Usage Examples:**
173
174
```vue
175
<template>
176
<!-- Basic snackbar -->
177
<v-snackbar
178
v-model="snackbar"
179
:timeout="3000"
180
>
181
{{ snackbarText }}
182
<template #actions>
183
<v-btn color="pink" variant="text" @click="snackbar = false">
184
Close
185
</v-btn>
186
</template>
187
</v-snackbar>
188
189
<!-- Multi-line snackbar -->
190
<v-snackbar
191
v-model="multiLineSnackbar"
192
multi-line
193
location="top"
194
>
195
This is a multi-line snackbar message that can contain longer text content.
196
<template #actions>
197
<v-btn color="primary" variant="text" @click="handleAction">
198
Action
199
</v-btn>
200
<v-btn variant="text" @click="multiLineSnackbar = false">
201
Dismiss
202
</v-btn>
203
</template>
204
</v-snackbar>
205
206
<!-- Vertical snackbar -->
207
<v-snackbar
208
v-model="verticalSnackbar"
209
vertical
210
location="top right"
211
>
212
<div class="text-subtitle-1 pb-2">Notification</div>
213
<p>Your changes have been saved successfully.</p>
214
215
<template #actions>
216
<v-btn color="success" variant="text" @click="verticalSnackbar = false">
217
OK
218
</v-btn>
219
</template>
220
</v-snackbar>
221
</template>
222
223
<script setup>
224
const snackbar = ref(false);
225
const snackbarText = ref('Operation completed');
226
const multiLineSnackbar = ref(false);
227
const verticalSnackbar = ref(false);
228
229
const showSnackbar = (message) => {
230
snackbarText.value = message;
231
snackbar.value = true;
232
};
233
</script>
234
```
235
236
### VProgressLinear
237
238
Linear progress indicator for showing task completion or loading states.
239
240
```typescript { .api }
241
/**
242
* Linear progress indicator component
243
*/
244
const VProgressLinear: Component;
245
246
interface ProgressLinearProps {
247
/** Progress value (0-100) */
248
modelValue?: number | string;
249
/** Buffer value for buffered progress */
250
buffer?: number | string;
251
/** Indeterminate progress animation */
252
indeterminate?: boolean;
253
/** Reverse progress direction */
254
reverse?: boolean;
255
/** Stream animation */
256
stream?: boolean;
257
/** Progress bar color */
258
color?: string;
259
/** Background color */
260
bgColor?: string;
261
/** Buffer color */
262
bufferColor?: string;
263
/** Progress bar height */
264
height?: number | string;
265
/** Rounded ends */
266
rounded?: boolean;
267
/** Striped pattern */
268
striped?: boolean;
269
/** Location on page */
270
location?: 'top' | 'bottom';
271
/** Absolute positioning */
272
absolute?: boolean;
273
/** Active state */
274
active?: boolean;
275
}
276
277
// Events
278
interface ProgressLinearEvents {
279
'update:modelValue': (value: number) => void;
280
}
281
```
282
283
**Usage Examples:**
284
285
```vue
286
<template>
287
<!-- Basic progress bar -->
288
<v-progress-linear
289
v-model="progress"
290
color="primary"
291
height="8"
292
/>
293
294
<!-- Indeterminate progress -->
295
<v-progress-linear
296
indeterminate
297
color="cyan"
298
/>
299
300
<!-- Buffered progress -->
301
<v-progress-linear
302
v-model="downloadProgress"
303
:buffer="bufferProgress"
304
color="success"
305
height="6"
306
/>
307
308
<!-- Striped progress -->
309
<v-progress-linear
310
v-model="uploadProgress"
311
striped
312
color="warning"
313
height="10"
314
/>
315
316
<!-- Top page loading indicator -->
317
<v-progress-linear
318
:model-value="pageLoadProgress"
319
location="top"
320
color="primary"
321
:active="loading"
322
/>
323
</template>
324
325
<script setup>
326
const progress = ref(75);
327
const downloadProgress = ref(65);
328
const bufferProgress = ref(85);
329
const uploadProgress = ref(40);
330
const pageLoadProgress = ref(0);
331
const loading = ref(false);
332
333
// Simulate loading
334
const simulateProgress = () => {
335
loading.value = true;
336
pageLoadProgress.value = 0;
337
338
const interval = setInterval(() => {
339
pageLoadProgress.value += 10;
340
if (pageLoadProgress.value >= 100) {
341
clearInterval(interval);
342
loading.value = false;
343
}
344
}, 100);
345
};
346
</script>
347
```
348
349
### VProgressCircular
350
351
Circular progress indicator for loading states and progress visualization.
352
353
```typescript { .api }
354
/**
355
* Circular progress indicator component
356
*/
357
const VProgressCircular: Component;
358
359
interface ProgressCircularProps {
360
/** Progress value (0-100) */
361
modelValue?: number | string;
362
/** Indeterminate progress animation */
363
indeterminate?: boolean;
364
/** Progress circle color */
365
color?: string;
366
/** Background color */
367
bgColor?: string;
368
/** Circle size */
369
size?: number | string;
370
/** Stroke width */
371
width?: number | string;
372
/** Rotate angle */
373
rotate?: number | string;
374
}
375
376
// Events
377
interface ProgressCircularEvents {
378
'update:modelValue': (value: number) => void;
379
}
380
```
381
382
**Usage Examples:**
383
384
```vue
385
<template>
386
<!-- Basic circular progress -->
387
<v-progress-circular
388
v-model="circularProgress"
389
color="primary"
390
/>
391
392
<!-- Indeterminate spinner -->
393
<v-progress-circular
394
indeterminate
395
color="purple"
396
:size="64"
397
:width="6"
398
/>
399
400
<!-- Large progress with custom styling -->
401
<v-progress-circular
402
v-model="taskProgress"
403
:size="120"
404
:width="8"
405
color="success"
406
>
407
{{ Math.ceil(taskProgress) }}%
408
</v-progress-circular>
409
410
<!-- Small loading spinner -->
411
<v-progress-circular
412
indeterminate
413
:size="20"
414
:width="2"
415
color="grey"
416
/>
417
</template>
418
419
<script setup>
420
const circularProgress = ref(45);
421
const taskProgress = ref(78.5);
422
</script>
423
```
424
425
### VSkeletonLoader
426
427
Skeleton loader for displaying placeholder content while data is loading.
428
429
```typescript { .api }
430
/**
431
* Skeleton loader for content placeholders
432
*/
433
const VSkeletonLoader: Component;
434
435
interface SkeletonLoaderProps {
436
/** Loading state */
437
loading?: boolean;
438
/** Skeleton type/template */
439
type?: string | string[];
440
/** Boilerplate mode */
441
boilerplate?: boolean;
442
/** Skeleton color */
443
color?: string;
444
/** Skeleton width */
445
width?: string | number;
446
/** Skeleton height */
447
height?: string | number;
448
/** Maximum width */
449
maxWidth?: string | number;
450
/** Maximum height */
451
maxHeight?: string | number;
452
/** Minimum width */
453
minWidth?: string | number;
454
/** Minimum height */
455
minHeight?: string | number;
456
/** Elevation level */
457
elevation?: number | string;
458
/** Rounded corners */
459
rounded?: boolean | string | number;
460
}
461
462
// Built-in skeleton types
463
type SkeletonType =
464
| 'text' | 'sentences' | 'paragraph'
465
| 'heading' | 'subtitle' | 'chip'
466
| 'button' | 'avatar' | 'thumbnail'
467
| 'image' | 'card' | 'card-avatar'
468
| 'article' | 'table' | 'table-heading'
469
| 'table-tbody' | 'table-tfoot' | 'table-row-divider'
470
| 'list-item' | 'list-item-avatar' | 'list-item-two-line'
471
| 'list-item-avatar-two-line' | 'list-item-three-line'
472
| 'list-item-avatar-three-line' | 'divider'
473
| 'card-heading' | 'card-text' | 'card-actions';
474
```
475
476
**Usage Examples:**
477
478
```vue
479
<template>
480
<!-- Basic skeleton loader -->
481
<v-skeleton-loader
482
:loading="loading"
483
type="card"
484
>
485
<v-card>
486
<v-card-title>{{ data.title }}</v-card-title>
487
<v-card-text>{{ data.content }}</v-card-text>
488
</v-card>
489
</v-skeleton-loader>
490
491
<!-- Multiple skeleton types -->
492
<v-skeleton-loader
493
:loading="loading"
494
type="card-avatar, article, actions"
495
>
496
<div>
497
<!-- Actual content when loaded -->
498
<div class="d-flex align-center mb-4">
499
<v-avatar>{{ user.initials }}</v-avatar>
500
<div class="ml-3">
501
<div class="text-h6">{{ user.name }}</div>
502
<div class="text-caption">{{ user.role }}</div>
503
</div>
504
</div>
505
<p>{{ article.content }}</p>
506
<v-btn>Read More</v-btn>
507
</div>
508
</v-skeleton-loader>
509
510
<!-- Custom skeleton -->
511
<v-skeleton-loader
512
:loading="loading"
513
boilerplate
514
type="heading, paragraph"
515
width="300"
516
>
517
<div>
518
<h2>{{ post.title }}</h2>
519
<p>{{ post.excerpt }}</p>
520
</div>
521
</v-skeleton-loader>
522
523
<!-- List skeleton -->
524
<v-skeleton-loader
525
:loading="loadingUsers"
526
type="list-item-avatar-two-line"
527
v-for="n in 5"
528
:key="n"
529
>
530
<v-list-item
531
v-for="user in users"
532
:key="user.id"
533
:prepend-avatar="user.avatar"
534
:title="user.name"
535
:subtitle="user.email"
536
/>
537
</v-skeleton-loader>
538
</template>
539
540
<script setup>
541
const loading = ref(true);
542
const loadingUsers = ref(true);
543
const data = ref({});
544
const users = ref([]);
545
546
onMounted(async () => {
547
// Simulate data loading
548
await new Promise(resolve => setTimeout(resolve, 2000));
549
loading.value = false;
550
loadingUsers.value = false;
551
552
data.value = {
553
title: 'Loaded Content',
554
content: 'This content was loaded after the skeleton.'
555
};
556
});
557
</script>
558
```
559
560
### VTooltip
561
562
Tooltip component for displaying contextual information on hover or focus.
563
564
```typescript { .api }
565
/**
566
* Tooltip overlay component
567
*/
568
const VTooltip: Component;
569
570
interface TooltipProps {
571
/** Tooltip visibility */
572
modelValue?: boolean;
573
/** Tooltip text content */
574
text?: string;
575
/** Tooltip location relative to activator */
576
location?:
577
| 'top' | 'bottom' | 'left' | 'right' | 'center'
578
| 'top start' | 'top end' | 'bottom start' | 'bottom end'
579
| 'left start' | 'left end' | 'right start' | 'right end';
580
/** Tooltip offset from activator */
581
offset?: number | string | number[];
582
/** Disabled state */
583
disabled?: boolean;
584
/** Show delay in milliseconds */
585
openDelay?: number | string;
586
/** Hide delay in milliseconds */
587
closeDelay?: number | string;
588
/** Tooltip content width */
589
width?: string | number;
590
/** Maximum width */
591
maxWidth?: string | number;
592
/** Minimum width */
593
minWidth?: string | number;
594
/** Tooltip height */
595
height?: string | number;
596
/** Maximum height */
597
maxHeight?: string | number;
598
/** Minimum height */
599
minHeight?: string | number;
600
/** Z-index */
601
zIndex?: number | string;
602
/** Activator element */
603
activator?: string | Element;
604
/** Tooltip content color */
605
contentColor?: string;
606
}
607
608
// Events
609
interface TooltipEvents {
610
'update:modelValue': (visible: boolean) => void;
611
}
612
```
613
614
**Usage Examples:**
615
616
```vue
617
<template>
618
<!-- Basic tooltip -->
619
<v-tooltip text="This is a helpful tooltip">
620
<template #activator="{ props }">
621
<v-btn v-bind="props">Hover me</v-btn>
622
</template>
623
</v-tooltip>
624
625
<!-- Custom positioned tooltip -->
626
<v-tooltip
627
location="bottom"
628
:open-delay="500"
629
:close-delay="200"
630
>
631
<template #activator="{ props }">
632
<v-icon v-bind="props">mdi-help-circle</v-icon>
633
</template>
634
<span>This tooltip appears below with a delay</span>
635
</v-tooltip>
636
637
<!-- Rich content tooltip -->
638
<v-tooltip max-width="300">
639
<template #activator="{ props }">
640
<v-chip v-bind="props" color="primary">
641
Rich Tooltip
642
</v-chip>
643
</template>
644
<div>
645
<strong>Advanced Tooltip</strong>
646
<br>
647
<em>This tooltip contains multiple lines and rich formatting.</em>
648
<v-divider class="my-2" />
649
<small>Click for more details</small>
650
</div>
651
</v-tooltip>
652
653
<!-- Programmatic tooltip -->
654
<v-tooltip
655
v-model="tooltipVisible"
656
location="top"
657
activator="#target-element"
658
>
659
Programmatically controlled tooltip
660
</v-tooltip>
661
</template>
662
663
<script setup>
664
const tooltipVisible = ref(false);
665
666
const showTooltip = () => {
667
tooltipVisible.value = true;
668
setTimeout(() => {
669
tooltipVisible.value = false;
670
}, 3000);
671
};
672
</script>
673
```
674
675
### VDialog
676
677
Modal dialog component for displaying content in an overlay window.
678
679
```typescript { .api }
680
/**
681
* Modal dialog overlay component
682
*/
683
const VDialog: Component;
684
685
interface DialogProps {
686
/** Dialog visibility */
687
modelValue?: boolean;
688
/** Dialog width */
689
width?: string | number;
690
/** Maximum width */
691
maxWidth?: string | number;
692
/** Minimum width */
693
minWidth?: string | number;
694
/** Dialog height */
695
height?: string | number;
696
/** Maximum height */
697
maxHeight?: string | number;
698
/** Minimum height */
699
minHeight?: string | number;
700
/** Fullscreen mode */
701
fullscreen?: boolean;
702
/** Persistent dialog (no outside click close) */
703
persistent?: boolean;
704
/** No click animation */
705
noClickAnimation?: boolean;
706
/** Scrollable content */
707
scrollable?: boolean;
708
/** Scrim (backdrop) color */
709
scrim?: boolean | string;
710
/** Z-index */
711
zIndex?: number | string;
712
/** Activator element */
713
activator?: string | Element;
714
/** Attach to element */
715
attach?: boolean | string | Element;
716
/** Close on back navigation */
717
closeOnBack?: boolean;
718
/** Close on escape key */
719
closeOnEscape?: boolean;
720
/** Eager mounting */
721
eager?: boolean;
722
/** Location strategy */
723
locationStrategy?: 'static' | 'connected';
724
/** Scroll strategy */
725
scrollStrategy?: 'block' | 'close' | 'reposition' | 'none';
726
/** Transition name */
727
transition?: string | boolean | object;
728
/** Opacity */
729
opacity?: number | string;
730
}
731
732
// Events
733
interface DialogEvents {
734
'update:modelValue': (visible: boolean) => void;
735
'click:outside': (event: Event) => void;
736
'keydown': (event: KeyboardEvent) => void;
737
'after-enter': () => void;
738
'after-leave': () => void;
739
}
740
```
741
742
**Usage Examples:**
743
744
```vue
745
<template>
746
<!-- Basic dialog -->
747
<v-dialog v-model="dialog" max-width="500">
748
<template #activator="{ props }">
749
<v-btn v-bind="props">Open Dialog</v-btn>
750
</template>
751
752
<v-card>
753
<v-card-title>Dialog Title</v-card-title>
754
<v-card-text>
755
This is the dialog content. You can put any content here.
756
</v-card-text>
757
<v-card-actions>
758
<v-spacer />
759
<v-btn @click="dialog = false">Cancel</v-btn>
760
<v-btn color="primary" @click="handleConfirm">Confirm</v-btn>
761
</v-card-actions>
762
</v-card>
763
</v-dialog>
764
765
<!-- Fullscreen dialog -->
766
<v-dialog v-model="fullscreenDialog" fullscreen>
767
<template #activator="{ props }">
768
<v-btn v-bind="props">Fullscreen</v-btn>
769
</template>
770
771
<v-card>
772
<v-toolbar color="primary">
773
<v-toolbar-title>Fullscreen Dialog</v-toolbar-title>
774
<v-spacer />
775
<v-btn icon @click="fullscreenDialog = false">
776
<v-icon>mdi-close</v-icon>
777
</v-btn>
778
</v-toolbar>
779
780
<v-card-text>
781
<div style="height: 1000px;">
782
Large scrollable content goes here...
783
</div>
784
</v-card-text>
785
</v-card>
786
</v-dialog>
787
788
<!-- Persistent dialog -->
789
<v-dialog v-model="persistentDialog" persistent max-width="400">
790
<v-card>
791
<v-card-title>Confirm Action</v-card-title>
792
<v-card-text>
793
This action cannot be undone. Are you sure you want to proceed?
794
</v-card-text>
795
<v-card-actions>
796
<v-btn @click="persistentDialog = false">Cancel</v-btn>
797
<v-btn color="error" @click="handleDelete">Delete</v-btn>
798
</v-card-actions>
799
</v-card>
800
</v-dialog>
801
802
<!-- Scrollable dialog -->
803
<v-dialog v-model="scrollableDialog" scrollable max-width="500" max-height="400">
804
<v-card>
805
<v-card-title>Terms of Service</v-card-title>
806
<v-divider />
807
<v-card-text>
808
<div v-for="n in 50" :key="n">
809
Line {{ n }}: Lorem ipsum dolor sit amet consectetur...
810
</div>
811
</v-card-text>
812
<v-divider />
813
<v-card-actions>
814
<v-btn @click="scrollableDialog = false">Disagree</v-btn>
815
<v-btn color="primary" @click="acceptTerms">Agree</v-btn>
816
</v-card-actions>
817
</v-card>
818
</v-dialog>
819
</template>
820
821
<script setup>
822
const dialog = ref(false);
823
const fullscreenDialog = ref(false);
824
const persistentDialog = ref(false);
825
const scrollableDialog = ref(false);
826
827
const handleConfirm = () => {
828
console.log('Confirmed');
829
dialog.value = false;
830
};
831
832
const handleDelete = () => {
833
console.log('Deleted');
834
persistentDialog.value = false;
835
};
836
837
const acceptTerms = () => {
838
console.log('Terms accepted');
839
scrollableDialog.value = false;
840
};
841
</script>
842
```
843
844
### VBottomSheet
845
846
Bottom sheet modal component that slides up from the bottom of the screen.
847
848
```typescript { .api }
849
/**
850
* Bottom sheet modal component
851
*/
852
const VBottomSheet: Component;
853
854
interface BottomSheetProps {
855
/** Bottom sheet visibility */
856
modelValue?: boolean;
857
/** Inset mode (doesn't cover full width) */
858
inset?: boolean;
859
/** Maximum width */
860
maxWidth?: string | number;
861
/** Maximum height */
862
maxHeight?: string | number;
863
/** Sheet width */
864
width?: string | number;
865
/** Sheet height */
866
height?: string | number;
867
/** Persistent sheet (no outside click close) */
868
persistent?: boolean;
869
/** No click animation */
870
noClickAnimation?: boolean;
871
/** Scrollable content */
872
scrollable?: boolean;
873
/** Scrim (backdrop) */
874
scrim?: boolean | string;
875
/** Z-index */
876
zIndex?: number | string;
877
/** Attach to element */
878
attach?: boolean | string | Element;
879
/** Close on back navigation */
880
closeOnBack?: boolean;
881
/** Close on escape key */
882
closeOnEscape?: boolean;
883
/** Eager mounting */
884
eager?: boolean;
885
/** Transition name */
886
transition?: string | boolean | object;
887
}
888
889
// Events
890
interface BottomSheetEvents {
891
'update:modelValue': (visible: boolean) => void;
892
'click:outside': (event: Event) => void;
893
'keydown': (event: KeyboardEvent) => void;
894
}
895
```
896
897
**Usage Examples:**
898
899
```vue
900
<template>
901
<!-- Basic bottom sheet -->
902
<v-bottom-sheet v-model="bottomSheet">
903
<template #activator="{ props }">
904
<v-btn v-bind="props">Open Bottom Sheet</v-btn>
905
</template>
906
907
<v-card>
908
<v-card-title>Bottom Sheet</v-card-title>
909
<v-card-text>
910
This content slides up from the bottom of the screen.
911
</v-card-text>
912
<v-card-actions>
913
<v-spacer />
914
<v-btn @click="bottomSheet = false">Close</v-btn>
915
</v-card-actions>
916
</v-card>
917
</v-bottom-sheet>
918
919
<!-- Inset bottom sheet -->
920
<v-bottom-sheet v-model="insetBottomSheet" inset>
921
<v-card class="text-center">
922
<v-card-text>
923
<v-avatar size="80" color="primary">
924
<v-icon size="40">mdi-account</v-icon>
925
</v-avatar>
926
<div class="text-h6 mt-4">User Profile</div>
927
<p class="text-body-2">Quick actions for user account</p>
928
</v-card-text>
929
<v-card-actions class="justify-center">
930
<v-btn prepend-icon="mdi-pencil">Edit</v-btn>
931
<v-btn prepend-icon="mdi-cog">Settings</v-btn>
932
</v-card-actions>
933
</v-card>
934
</v-bottom-sheet>
935
936
<!-- Scrollable bottom sheet -->
937
<v-bottom-sheet v-model="scrollableBottomSheet" scrollable>
938
<v-card>
939
<v-card-title>Menu Options</v-card-title>
940
<v-divider />
941
<v-card-text style="height: 300px;">
942
<v-list>
943
<v-list-item
944
v-for="item in menuItems"
945
:key="item.id"
946
:prepend-icon="item.icon"
947
:title="item.title"
948
@click="selectMenuItem(item)"
949
/>
950
</v-list>
951
</v-card-text>
952
</v-card>
953
</v-bottom-sheet>
954
</template>
955
956
<script setup>
957
const bottomSheet = ref(false);
958
const insetBottomSheet = ref(false);
959
const scrollableBottomSheet = ref(false);
960
961
const menuItems = [
962
{ id: 1, title: 'Profile', icon: 'mdi-account' },
963
{ id: 2, title: 'Settings', icon: 'mdi-cog' },
964
{ id: 3, title: 'Help', icon: 'mdi-help-circle' },
965
{ id: 4, title: 'About', icon: 'mdi-information' },
966
// ... more items
967
];
968
969
const selectMenuItem = (item) => {
970
console.log('Selected:', item.title);
971
scrollableBottomSheet.value = false;
972
};
973
</script>
974
```
975
976
## Types
977
978
```typescript { .api }
979
// Location types for positioning
980
type Location =
981
| 'top' | 'bottom' | 'left' | 'right' | 'center'
982
| 'top start' | 'top end' | 'bottom start' | 'bottom end'
983
| 'left start' | 'left end' | 'right start' | 'right end'
984
| 'top left' | 'top right' | 'bottom left' | 'bottom right'
985
| 'top center' | 'bottom center' | 'center left' | 'center right';
986
987
// Alert and notification types
988
type AlertType = 'success' | 'info' | 'warning' | 'error';
989
990
// Component variants
991
type ComponentVariant = 'flat' | 'elevated' | 'tonal' | 'outlined' | 'text' | 'plain';
992
993
// Density options
994
type Density = 'default' | 'comfortable' | 'compact';
995
996
// Border positions
997
type BorderPosition = 'top' | 'end' | 'bottom' | 'start';
998
999
// Progress value type
1000
type ProgressValue = number | string;
1001
1002
// Overlay strategies
1003
type LocationStrategy = 'static' | 'connected';
1004
type ScrollStrategy = 'block' | 'close' | 'reposition' | 'none';
1005
```