@umbra.ui/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/controls/Dropdown/types.d.ts +5 -0
- package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
- package/dist/components/controls/Dropdown/types.js +1 -0
- package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
- package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
- package/dist/components/controls/SegmentedControl/types.js +1 -0
- package/dist/components/dialogs/Alert/types.d.ts +7 -0
- package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
- package/dist/components/dialogs/Alert/types.js +1 -0
- package/dist/components/dialogs/Toast/types.d.ts +34 -0
- package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/types.js +10 -0
- package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
- package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/useToast.js +90 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/tooltip.js +33 -0
- package/dist/components/indicators/Tooltip/types.d.ts +14 -0
- package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/types.js +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
- package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
- package/dist/components/inputs/Tags/types.d.ts +93 -0
- package/dist/components/inputs/Tags/types.d.ts.map +1 -0
- package/dist/components/inputs/Tags/types.js +216 -0
- package/dist/components/inputs/search/types.d.ts +9 -0
- package/dist/components/inputs/search/types.d.ts.map +1 -0
- package/dist/components/inputs/search/types.js +1 -0
- package/dist/components/navigation/adaptive/types.d.ts +16 -0
- package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/types.js +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewResize.js +146 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
- package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
- package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
- package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
- package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
- package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/types.js +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
- package/dist/components/navigation/types.d.ts +8 -0
- package/dist/components/navigation/types.d.ts.map +1 -0
- package/dist/components/navigation/types.js +1 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
- package/dist/components/pickers/CollectionPicker/types.js +1 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
- package/dist/components/pickers/ColorPicker/colors.js +266 -0
- package/dist/components/pickers/FilePicker/types.d.ts +10 -0
- package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
- package/dist/components/pickers/FilePicker/types.js +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/theme.d.ts +73 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +279 -0
- package/dist/themes/blank.d.ts +7 -0
- package/dist/themes/blank.d.ts.map +1 -0
- package/dist/themes/blank.js +543 -0
- package/dist/themes/crimson-dark.d.ts +4 -0
- package/dist/themes/crimson-dark.d.ts.map +1 -0
- package/dist/themes/crimson-dark.js +552 -0
- package/dist/themes/cyan-light.d.ts +4 -0
- package/dist/themes/cyan-light.d.ts.map +1 -0
- package/dist/themes/cyan-light.js +552 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +551 -0
- package/dist/themes/gold-dark.d.ts +4 -0
- package/dist/themes/gold-dark.d.ts.map +1 -0
- package/dist/themes/gold-dark.js +552 -0
- package/dist/themes/grass-dark.d.ts +4 -0
- package/dist/themes/grass-dark.d.ts.map +1 -0
- package/dist/themes/grass-dark.js +552 -0
- package/dist/themes/indigo.d.ts +4 -0
- package/dist/themes/indigo.d.ts.map +1 -0
- package/dist/themes/indigo.js +552 -0
- package/dist/themes/light.d.ts +4 -0
- package/dist/themes/light.d.ts.map +1 -0
- package/dist/themes/light.js +551 -0
- package/dist/themes/orange-dark.d.ts +4 -0
- package/dist/themes/orange-dark.d.ts.map +1 -0
- package/dist/themes/orange-dark.js +551 -0
- package/dist/themes/orange-light.d.ts +4 -0
- package/dist/themes/orange-light.d.ts.map +1 -0
- package/dist/themes/orange-light.js +551 -0
- package/package.json +62 -0
- package/src/components/controls/Button/Button.vue +417 -0
- package/src/components/controls/Button/README.md +348 -0
- package/src/components/controls/Button/theme.css +200 -0
- package/src/components/controls/Checkbox/Checkbox.vue +164 -0
- package/src/components/controls/Checkbox/README.md +441 -0
- package/src/components/controls/Checkbox/theme.css +36 -0
- package/src/components/controls/Dropdown/Dropdown.vue +476 -0
- package/src/components/controls/Dropdown/README.md +370 -0
- package/src/components/controls/Dropdown/theme.css +50 -0
- package/src/components/controls/Dropdown/types.ts +6 -0
- package/src/components/controls/IconButton/IconButton.vue +267 -0
- package/src/components/controls/IconButton/README.md +502 -0
- package/src/components/controls/IconButton/theme.css +89 -0
- package/src/components/controls/Radio/README.md +591 -0
- package/src/components/controls/Radio/Radio.vue +89 -0
- package/src/components/controls/Radio/theme.css +14 -0
- package/src/components/controls/RangeSlider/README.md +608 -0
- package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/src/components/controls/RangeSlider/theme.css +80 -0
- package/src/components/controls/SegmentedControl/README.md +587 -0
- package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/src/components/controls/SegmentedControl/theme.css +60 -0
- package/src/components/controls/SegmentedControl/types.ts +5 -0
- package/src/components/controls/Slider/README.md +627 -0
- package/src/components/controls/Slider/Slider.vue +260 -0
- package/src/components/controls/Slider/theme.css +74 -0
- package/src/components/controls/Stepper/README.md +601 -0
- package/src/components/controls/Stepper/Stepper.vue +103 -0
- package/src/components/controls/Stepper/theme.css +53 -0
- package/src/components/controls/Switch/README.md +667 -0
- package/src/components/controls/Switch/Switch.vue +127 -0
- package/src/components/controls/Switch/theme.css +42 -0
- package/src/components/dialogs/Alert/Alert.vue +218 -0
- package/src/components/dialogs/Alert/README.md +450 -0
- package/src/components/dialogs/Alert/theme.css +44 -0
- package/src/components/dialogs/Alert/types.ts +11 -0
- package/src/components/dialogs/Toast/README.md +522 -0
- package/src/components/dialogs/Toast/Toast.vue +296 -0
- package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/src/components/dialogs/Toast/theme.css +44 -0
- package/src/components/dialogs/Toast/types.ts +46 -0
- package/src/components/dialogs/Toast/useToast.ts +127 -0
- package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/src/components/indicators/ProgressBar/README.md +744 -0
- package/src/components/indicators/ProgressBar/theme.css +36 -0
- package/src/components/indicators/Tooltip/README.md +723 -0
- package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/src/components/indicators/Tooltip/theme.css +18 -0
- package/src/components/indicators/Tooltip/tooltip.ts +48 -0
- package/src/components/indicators/Tooltip/types.ts +15 -0
- package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/src/components/inputs/AutogrowTextView/README.md +643 -0
- package/src/components/inputs/AutogrowTextView/theme.css +28 -0
- package/src/components/inputs/InputCard/InputCard.vue +600 -0
- package/src/components/inputs/InputCard/README.md +636 -0
- package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/src/components/inputs/InputEmail/README.md +764 -0
- package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/src/components/inputs/InputNumber/README.md +749 -0
- package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/src/components/inputs/InputPhone/README.md +636 -0
- package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/src/components/inputs/InputSecure/README.md +771 -0
- package/src/components/inputs/InputText/InputText.vue +225 -0
- package/src/components/inputs/InputText/README.md +844 -0
- package/src/components/inputs/OTP/OTP.vue +349 -0
- package/src/components/inputs/OTP/README.md +736 -0
- package/src/components/inputs/OTP/theme.css +50 -0
- package/src/components/inputs/StringCapture/README.md +718 -0
- package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/src/components/inputs/StringCapture/theme.css +86 -0
- package/src/components/inputs/Tags/README.md +897 -0
- package/src/components/inputs/Tags/TagBar.vue +793 -0
- package/src/components/inputs/Tags/TagCreation.vue +219 -0
- package/src/components/inputs/Tags/TagPicker.vue +380 -0
- package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/src/components/inputs/Tags/theme.css +121 -0
- package/src/components/inputs/Tags/types.ts +346 -0
- package/src/components/inputs/search/README.md +759 -0
- package/src/components/inputs/search/SearchBar.vue +394 -0
- package/src/components/inputs/search/SearchResults.vue +310 -0
- package/src/components/inputs/search/theme.css +187 -0
- package/src/components/inputs/search/types.ts +8 -0
- package/src/components/inputs/theme.css +102 -0
- package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/src/components/menus/ActionMenu/README.md +825 -0
- package/src/components/menus/ActionMenu/theme.css +93 -0
- package/src/components/models/Popover/Popover.vue +551 -0
- package/src/components/models/Popover/README.md +885 -0
- package/src/components/models/Popover/theme.css +52 -0
- package/src/components/models/Sheet/README.md +1159 -0
- package/src/components/models/Sheet/Sheet.vue +465 -0
- package/src/components/models/Sheet/theme.css +72 -0
- package/src/components/models/Sidebar/README.md +1228 -0
- package/src/components/models/Sidebar/Sidebar.vue +480 -0
- package/src/components/models/Sidebar/theme.css +90 -0
- package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/src/components/navigation/adaptive/README.md +768 -0
- package/src/components/navigation/adaptive/types.ts +19 -0
- package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/src/components/navigation/adaptive/useViewResize.ts +211 -0
- package/src/components/navigation/navstack/NavigationStack.vue +180 -0
- package/src/components/navigation/navstack/README.md +994 -0
- package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/src/components/navigation/slideover/README.md +1275 -0
- package/src/components/navigation/slideover/SlideoverController.vue +287 -0
- package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/src/components/navigation/splitview/README.md +1115 -0
- package/src/components/navigation/splitview/SplitViewController.vue +176 -0
- package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/src/components/navigation/tabcontroller/README.md +919 -0
- package/src/components/navigation/tabcontroller/TabController.vue +307 -0
- package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/src/components/navigation/tabcontroller/types.ts +24 -0
- package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/src/components/navigation/theme.css +91 -0
- package/src/components/navigation/types.ts +7 -0
- package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/src/components/pickers/CollectionPicker/README.md +1115 -0
- package/src/components/pickers/CollectionPicker/theme.css +14 -0
- package/src/components/pickers/CollectionPicker/types.ts +11 -0
- package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/src/components/pickers/ColorPicker/README.md +1439 -0
- package/src/components/pickers/ColorPicker/colors.ts +299 -0
- package/src/components/pickers/ColorPicker/theme.css +32 -0
- package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/src/components/pickers/DatePicker/README.md +1195 -0
- package/src/components/pickers/DatePicker/theme.css +22 -0
- package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/src/components/pickers/FilePicker/README.md +1542 -0
- package/src/components/pickers/FilePicker/theme.css +48 -0
- package/src/components/pickers/FilePicker/types.ts +10 -0
- package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/src/components/pickers/IconPicker/README.md +1161 -0
- package/src/components/pickers/IconPicker/theme.css +28 -0
- package/src/components/pickers/theme.css +82 -0
- package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/src/components/views/MarkdownViewer/README.md +833 -0
- package/src/components/views/MarkdownViewer/theme.css +130 -0
- package/src/index.ts +263 -0
- package/src/theme.ts +378 -0
- package/src/themes/crimson-dark.ts +556 -0
- package/src/themes/cyan-light.ts +556 -0
- package/src/themes/dark.ts +557 -0
- package/src/themes/gold-dark.ts +556 -0
- package/src/themes/grass-dark.ts +556 -0
- package/src/themes/indigo.ts +556 -0
- package/src/themes/light.ts +557 -0
- package/src/themes/orange-dark.ts +557 -0
- package/src/themes/orange-light.ts +557 -0
- package/src/vue.d.ts +45 -0
|
@@ -0,0 +1,1159 @@
|
|
|
1
|
+
# Sheet
|
|
2
|
+
|
|
3
|
+
A flexible and animated sheet component built with Vue 3 Composition API and TypeScript. The Sheet component provides a powerful interface for displaying modal content with smooth slide animations, customizable positioning, and comprehensive backdrop options.
|
|
4
|
+
|
|
5
|
+
## Installation/Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { Sheet } from "@umbra-ui/core";
|
|
9
|
+
import type { SheetProps } from "@umbra-ui/core";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Dependencies:**
|
|
13
|
+
|
|
14
|
+
- Vue 3.x
|
|
15
|
+
- gsap (for animations)
|
|
16
|
+
|
|
17
|
+
## Basic Usage
|
|
18
|
+
|
|
19
|
+
```vue
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
import { ref } from "vue";
|
|
22
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
23
|
+
|
|
24
|
+
const isSheetOpen = ref(false);
|
|
25
|
+
|
|
26
|
+
const handleOpen = () => {
|
|
27
|
+
console.log("Sheet opened");
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const handleClose = () => {
|
|
31
|
+
console.log("Sheet closed");
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const handleBackdropClick = () => {
|
|
35
|
+
console.log("Backdrop clicked");
|
|
36
|
+
};
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<div>
|
|
41
|
+
<Button @click="isSheetOpen = true">Open Sheet</Button>
|
|
42
|
+
|
|
43
|
+
<Sheet
|
|
44
|
+
v-model="isSheetOpen"
|
|
45
|
+
side="bottom"
|
|
46
|
+
:dismiss-on-backdrop="true"
|
|
47
|
+
@open="handleOpen"
|
|
48
|
+
@close="handleClose"
|
|
49
|
+
@backdrop-click="handleBackdropClick"
|
|
50
|
+
>
|
|
51
|
+
<div class="sheet-content">
|
|
52
|
+
<h2>Sheet Title</h2>
|
|
53
|
+
<p>This is the sheet content. It can contain any HTML elements.</p>
|
|
54
|
+
<Button @click="isSheetOpen = false">Close</Button>
|
|
55
|
+
</div>
|
|
56
|
+
</Sheet>
|
|
57
|
+
</div>
|
|
58
|
+
</template>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.sheet-content {
|
|
62
|
+
padding: 2rem;
|
|
63
|
+
min-height: 200px;
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Props
|
|
69
|
+
|
|
70
|
+
| Prop Name | Type | Required | Default | Description |
|
|
71
|
+
| ------------------- | ---------------------------------------- | -------- | --------------- | ---------------------------------------------- |
|
|
72
|
+
| `modelValue` | `boolean` | Yes | - | Controls the open/closed state of the sheet |
|
|
73
|
+
| `side` | `"top" \| "bottom" \| "left" \| "right"` | No | `"bottom"` | The side from which the sheet slides in |
|
|
74
|
+
| `dismissOnBackdrop` | `boolean` | No | `true` | Whether clicking the backdrop closes the sheet |
|
|
75
|
+
| `width` | `string` | No | `"90vw"` | Width of the sheet |
|
|
76
|
+
| `height` | `string` | No | `"50vh"` | Height of the sheet |
|
|
77
|
+
| `maxWidth` | `string` | No | `"540px"` | Maximum width of the sheet |
|
|
78
|
+
| `maxHeight` | `string` | No | `"fit-content"` | Maximum height of the sheet |
|
|
79
|
+
| `animationDuration` | `number` | No | `0.5` | Animation duration in seconds |
|
|
80
|
+
| `animationType` | `"slide" \| "ghost"` | No | `"slide"` | Animation type: slide or ghost |
|
|
81
|
+
| `backdropStyle` | `"blur" \| "dim"` | No | `"blur"` | Backdrop style: blur or dim |
|
|
82
|
+
| `zIndex` | `number` | No | `1000` | Z-index for the sheet |
|
|
83
|
+
| `teleportTo` | `string \| HTMLElement` | No | `"body"` | Teleport target element |
|
|
84
|
+
|
|
85
|
+
## Events
|
|
86
|
+
|
|
87
|
+
| Event Name | Payload Type | Description |
|
|
88
|
+
| ------------------- | ------------ | ------------------------------------------- |
|
|
89
|
+
| `update:modelValue` | `boolean` | Emitted when the sheet open state changes |
|
|
90
|
+
| `backdrop-click` | `void` | Emitted when the backdrop is clicked |
|
|
91
|
+
| `open` | `void` | Emitted when the sheet opens |
|
|
92
|
+
| `close` | `void` | Emitted when the sheet closes |
|
|
93
|
+
| `after-enter` | `void` | Emitted after the open animation completes |
|
|
94
|
+
| `after-leave` | `void` | Emitted after the close animation completes |
|
|
95
|
+
|
|
96
|
+
## Slots
|
|
97
|
+
|
|
98
|
+
| Slot Name | Description |
|
|
99
|
+
| --------- | -------------------------------------- |
|
|
100
|
+
| `default` | The content displayed inside the sheet |
|
|
101
|
+
|
|
102
|
+
## Exposed Methods/Refs
|
|
103
|
+
|
|
104
|
+
The Sheet component exposes the following methods and properties via template refs:
|
|
105
|
+
|
|
106
|
+
| Method/Property | Type | Description |
|
|
107
|
+
| --------------- | -------------- | -------------------------------------- |
|
|
108
|
+
| `open` | `() => void` | Opens the sheet programmatically |
|
|
109
|
+
| `close` | `() => void` | Closes the sheet programmatically |
|
|
110
|
+
| `isVisible` | `Ref<boolean>` | Reactive reference to visibility state |
|
|
111
|
+
| `isAnimating` | `Ref<boolean>` | Reactive reference to animation state |
|
|
112
|
+
|
|
113
|
+
### Example Usage
|
|
114
|
+
|
|
115
|
+
```vue
|
|
116
|
+
<script setup lang="ts">
|
|
117
|
+
import { ref } from "vue";
|
|
118
|
+
import { Sheet } from "@umbra-ui/core";
|
|
119
|
+
|
|
120
|
+
const sheetRef = ref<InstanceType<typeof Sheet> | null>(null);
|
|
121
|
+
|
|
122
|
+
const openSheet = () => {
|
|
123
|
+
sheetRef.value?.open();
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const closeSheet = () => {
|
|
127
|
+
sheetRef.value?.close();
|
|
128
|
+
};
|
|
129
|
+
</script>
|
|
130
|
+
|
|
131
|
+
<template>
|
|
132
|
+
<Sheet ref="sheetRef" :model-value="false">
|
|
133
|
+
<div class="content">
|
|
134
|
+
<p>Sheet content</p>
|
|
135
|
+
<button @click="closeSheet">Close</button>
|
|
136
|
+
</div>
|
|
137
|
+
</Sheet>
|
|
138
|
+
</template>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Animation Types
|
|
142
|
+
|
|
143
|
+
### Slide Animation
|
|
144
|
+
|
|
145
|
+
- **Default animation type**
|
|
146
|
+
- Sheet slides in from the specified side
|
|
147
|
+
- Uses smooth easing with GPU acceleration
|
|
148
|
+
- Best for modal dialogs and forms
|
|
149
|
+
|
|
150
|
+
### Ghost Animation
|
|
151
|
+
|
|
152
|
+
- Sheet fades in with scale effect
|
|
153
|
+
- More subtle appearance
|
|
154
|
+
- Good for notifications and overlays
|
|
155
|
+
- Uses opacity and scale transforms
|
|
156
|
+
|
|
157
|
+
## Backdrop Styles
|
|
158
|
+
|
|
159
|
+
### Blur Backdrop
|
|
160
|
+
|
|
161
|
+
- **Default backdrop style**
|
|
162
|
+
- Semi-transparent with blur effect
|
|
163
|
+
- Modern, iOS-like appearance
|
|
164
|
+
- Uses `backdrop-filter: blur(10px)`
|
|
165
|
+
|
|
166
|
+
### Dim Backdrop
|
|
167
|
+
|
|
168
|
+
- Simple semi-transparent overlay
|
|
169
|
+
- No blur effect
|
|
170
|
+
- More traditional modal appearance
|
|
171
|
+
- Better performance on older devices
|
|
172
|
+
|
|
173
|
+
## CSS Customization
|
|
174
|
+
|
|
175
|
+
The Sheet component uses CSS custom properties for theming and customization:
|
|
176
|
+
|
|
177
|
+
### Light Theme Variables
|
|
178
|
+
|
|
179
|
+
```css
|
|
180
|
+
/* Sheet colors */
|
|
181
|
+
--sheet-bg: #ffffff;
|
|
182
|
+
--sheet-shadow: rgba(0, 0, 0, 0.1);
|
|
183
|
+
--sheet-inset-shadow: rgba(255, 255, 255, 0.8);
|
|
184
|
+
|
|
185
|
+
/* Sheet backdrop colors */
|
|
186
|
+
--sheet-backdrop-blur-bg: rgba(0, 0, 0, 0.3);
|
|
187
|
+
--sheet-backdrop-dim-bg: rgba(0, 0, 0, 0.7);
|
|
188
|
+
|
|
189
|
+
/* Sheet scrollbar colors */
|
|
190
|
+
--sheet-scrollbar-thumb: rgba(0, 0, 0, 0.2);
|
|
191
|
+
--sheet-scrollbar-thumb-hover: rgba(0, 0, 0, 0.3);
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Dark Theme Variables
|
|
195
|
+
|
|
196
|
+
```css
|
|
197
|
+
/* Sheet colors */
|
|
198
|
+
--sheet-bg: #111111;
|
|
199
|
+
--sheet-shadow: rgba(0, 0, 0, 0.21);
|
|
200
|
+
--sheet-inset-shadow: rgba(255, 255, 255, 0.1);
|
|
201
|
+
|
|
202
|
+
/* Sheet backdrop colors */
|
|
203
|
+
--sheet-backdrop-blur-bg: rgba(0, 0, 0, 0.3);
|
|
204
|
+
--sheet-backdrop-dim-bg: rgba(0, 0, 0, 0.85);
|
|
205
|
+
|
|
206
|
+
/* Sheet scrollbar colors */
|
|
207
|
+
--sheet-scrollbar-thumb: rgba(255, 255, 255, 0.2);
|
|
208
|
+
--sheet-scrollbar-thumb-hover: rgba(255, 255, 255, 0.3);
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Key Features
|
|
212
|
+
|
|
213
|
+
### Smart Positioning
|
|
214
|
+
|
|
215
|
+
- **Four Directions**: Slide in from top, bottom, left, or right
|
|
216
|
+
- **Responsive Sizing**: Configurable width, height, and max dimensions
|
|
217
|
+
- **Viewport Awareness**: Automatically respects viewport boundaries
|
|
218
|
+
- **Safe Area Support**: Handles mobile device safe areas
|
|
219
|
+
|
|
220
|
+
### Animation System
|
|
221
|
+
|
|
222
|
+
- **GSAP Animations**: Smooth, performant animations using GSAP
|
|
223
|
+
- **Two Animation Types**: Slide and ghost animations
|
|
224
|
+
- **GPU Acceleration**: Hardware-accelerated transforms
|
|
225
|
+
- **Customizable Duration**: Configurable animation timing
|
|
226
|
+
|
|
227
|
+
### User Experience
|
|
228
|
+
|
|
229
|
+
- **Backdrop Interaction**: Click backdrop to dismiss (configurable)
|
|
230
|
+
- **Keyboard Support**: Escape key closes sheet
|
|
231
|
+
- **Body Scroll Lock**: Prevents background scrolling when open
|
|
232
|
+
- **Teleport Support**: Renders outside component tree
|
|
233
|
+
|
|
234
|
+
### Visual Features
|
|
235
|
+
|
|
236
|
+
- **Backdrop Styles**: Blur or dim backdrop options
|
|
237
|
+
- **Custom Scrollbars**: Styled scrollbars for better UX
|
|
238
|
+
- **Shadow Effects**: Subtle shadows and inset highlights
|
|
239
|
+
- **Border Radius**: Rounded corners for modern appearance
|
|
240
|
+
|
|
241
|
+
## Examples
|
|
242
|
+
|
|
243
|
+
### Basic Sheet
|
|
244
|
+
|
|
245
|
+
```vue
|
|
246
|
+
<script setup lang="ts">
|
|
247
|
+
import { ref } from "vue";
|
|
248
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
249
|
+
|
|
250
|
+
const isOpen = ref(false);
|
|
251
|
+
|
|
252
|
+
const handleOpen = () => {
|
|
253
|
+
console.log("Sheet opened");
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const handleClose = () => {
|
|
257
|
+
console.log("Sheet closed");
|
|
258
|
+
};
|
|
259
|
+
</script>
|
|
260
|
+
|
|
261
|
+
<template>
|
|
262
|
+
<div class="basic-sheet">
|
|
263
|
+
<h3>Basic Sheet</h3>
|
|
264
|
+
|
|
265
|
+
<Button @click="isOpen = true">Open Sheet</Button>
|
|
266
|
+
|
|
267
|
+
<Sheet
|
|
268
|
+
v-model="isOpen"
|
|
269
|
+
side="bottom"
|
|
270
|
+
:dismiss-on-backdrop="true"
|
|
271
|
+
@open="handleOpen"
|
|
272
|
+
@close="handleClose"
|
|
273
|
+
>
|
|
274
|
+
<div class="sheet-content">
|
|
275
|
+
<h2>Sheet Title</h2>
|
|
276
|
+
<p>This is a basic sheet with default settings.</p>
|
|
277
|
+
<p>
|
|
278
|
+
It slides in from the bottom and can be dismissed by clicking the
|
|
279
|
+
backdrop.
|
|
280
|
+
</p>
|
|
281
|
+
<div class="actions">
|
|
282
|
+
<Button @click="isOpen = false">Close</Button>
|
|
283
|
+
</div>
|
|
284
|
+
</div>
|
|
285
|
+
</Sheet>
|
|
286
|
+
|
|
287
|
+
<p class="status">Sheet is {{ isOpen ? "open" : "closed" }}</p>
|
|
288
|
+
</div>
|
|
289
|
+
</template>
|
|
290
|
+
|
|
291
|
+
<style module>
|
|
292
|
+
.basic-sheet {
|
|
293
|
+
padding: 2rem;
|
|
294
|
+
border: 1px solid #e0e0e0;
|
|
295
|
+
border-radius: 0.5rem;
|
|
296
|
+
max-width: 400px;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.sheet-content {
|
|
300
|
+
padding: 2rem;
|
|
301
|
+
min-height: 200px;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.sheet-content h2 {
|
|
305
|
+
margin: 0 0 1rem 0;
|
|
306
|
+
color: #333;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.sheet-content p {
|
|
310
|
+
margin: 0 0 1rem 0;
|
|
311
|
+
color: #666;
|
|
312
|
+
line-height: 1.5;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.actions {
|
|
316
|
+
display: flex;
|
|
317
|
+
gap: 0.75rem;
|
|
318
|
+
justify-content: flex-end;
|
|
319
|
+
margin-top: 1.5rem;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.status {
|
|
323
|
+
margin-top: 1rem;
|
|
324
|
+
color: #666;
|
|
325
|
+
font-size: 0.875rem;
|
|
326
|
+
}
|
|
327
|
+
</style>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Different Sides
|
|
331
|
+
|
|
332
|
+
```vue
|
|
333
|
+
<script setup lang="ts">
|
|
334
|
+
import { ref } from "vue";
|
|
335
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
336
|
+
|
|
337
|
+
const sides = ["top", "bottom", "left", "right"];
|
|
338
|
+
const openSheets = ref<Record<string, boolean>>({});
|
|
339
|
+
|
|
340
|
+
const toggleSheet = (side: string) => {
|
|
341
|
+
openSheets.value[side] = !openSheets.value[side];
|
|
342
|
+
};
|
|
343
|
+
</script>
|
|
344
|
+
|
|
345
|
+
<template>
|
|
346
|
+
<div class="sides-demo">
|
|
347
|
+
<h3>Sheet Sides</h3>
|
|
348
|
+
<p>Click the buttons to see different slide directions:</p>
|
|
349
|
+
|
|
350
|
+
<div class="sides-grid">
|
|
351
|
+
<div v-for="side in sides" :key="side" class="side-item">
|
|
352
|
+
<Button @click="toggleSheet(side)" size="small">
|
|
353
|
+
{{ side }}
|
|
354
|
+
</Button>
|
|
355
|
+
|
|
356
|
+
<Sheet
|
|
357
|
+
v-model="openSheets[side]"
|
|
358
|
+
:side="side"
|
|
359
|
+
:dismiss-on-backdrop="true"
|
|
360
|
+
>
|
|
361
|
+
<div class="side-content">
|
|
362
|
+
<h4>{{ side }} Sheet</h4>
|
|
363
|
+
<p>This sheet slides in from the {{ side }}.</p>
|
|
364
|
+
<Button @click="openSheets[side] = false" size="small">
|
|
365
|
+
Close
|
|
366
|
+
</Button>
|
|
367
|
+
</div>
|
|
368
|
+
</Sheet>
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
</div>
|
|
372
|
+
</template>
|
|
373
|
+
|
|
374
|
+
<style module>
|
|
375
|
+
.sides-demo {
|
|
376
|
+
padding: 2rem;
|
|
377
|
+
border: 1px solid #e0e0e0;
|
|
378
|
+
border-radius: 0.5rem;
|
|
379
|
+
max-width: 600px;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
.sides-grid {
|
|
383
|
+
display: grid;
|
|
384
|
+
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
|
385
|
+
gap: 1rem;
|
|
386
|
+
margin-top: 1rem;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.side-item {
|
|
390
|
+
display: flex;
|
|
391
|
+
justify-content: center;
|
|
392
|
+
align-items: center;
|
|
393
|
+
min-height: 60px;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
.side-content {
|
|
397
|
+
padding: 1.5rem;
|
|
398
|
+
min-height: 150px;
|
|
399
|
+
text-align: center;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.side-content h4 {
|
|
403
|
+
margin: 0 0 1rem 0;
|
|
404
|
+
color: #333;
|
|
405
|
+
text-transform: capitalize;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
.side-content p {
|
|
409
|
+
margin: 0 0 1rem 0;
|
|
410
|
+
color: #666;
|
|
411
|
+
}
|
|
412
|
+
</style>
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
### Ghost Animation
|
|
416
|
+
|
|
417
|
+
```vue
|
|
418
|
+
<script setup lang="ts">
|
|
419
|
+
import { ref } from "vue";
|
|
420
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
421
|
+
|
|
422
|
+
const isGhostOpen = ref(false);
|
|
423
|
+
</script>
|
|
424
|
+
|
|
425
|
+
<template>
|
|
426
|
+
<div class="ghost-sheet">
|
|
427
|
+
<h3>Ghost Animation</h3>
|
|
428
|
+
<p>This sheet uses the ghost animation type with scale and fade effects:</p>
|
|
429
|
+
|
|
430
|
+
<Button @click="isGhostOpen = true">Open Ghost Sheet</Button>
|
|
431
|
+
|
|
432
|
+
<Sheet
|
|
433
|
+
v-model="isGhostOpen"
|
|
434
|
+
side="bottom"
|
|
435
|
+
animation-type="ghost"
|
|
436
|
+
:animation-duration="0.4"
|
|
437
|
+
:dismiss-on-backdrop="true"
|
|
438
|
+
>
|
|
439
|
+
<div class="ghost-content">
|
|
440
|
+
<h2>Ghost Sheet</h2>
|
|
441
|
+
<p>This sheet uses the ghost animation type.</p>
|
|
442
|
+
<p>It fades in with a scale effect instead of sliding.</p>
|
|
443
|
+
<div class="features">
|
|
444
|
+
<h4>Features:</h4>
|
|
445
|
+
<ul>
|
|
446
|
+
<li>Scale + opacity animation</li>
|
|
447
|
+
<li>Faster animation duration</li>
|
|
448
|
+
<li>Subtle appearance</li>
|
|
449
|
+
<li>Good for notifications</li>
|
|
450
|
+
</ul>
|
|
451
|
+
</div>
|
|
452
|
+
<div class="actions">
|
|
453
|
+
<Button @click="isGhostOpen = false">Close</Button>
|
|
454
|
+
</div>
|
|
455
|
+
</div>
|
|
456
|
+
</Sheet>
|
|
457
|
+
</div>
|
|
458
|
+
</template>
|
|
459
|
+
|
|
460
|
+
<style module>
|
|
461
|
+
.ghost-sheet {
|
|
462
|
+
padding: 2rem;
|
|
463
|
+
border: 1px solid #e0e0e0;
|
|
464
|
+
border-radius: 0.5rem;
|
|
465
|
+
max-width: 400px;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.ghost-content {
|
|
469
|
+
padding: 2rem;
|
|
470
|
+
min-height: 300px;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.ghost-content h2 {
|
|
474
|
+
margin: 0 0 1rem 0;
|
|
475
|
+
color: #333;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
.ghost-content p {
|
|
479
|
+
margin: 0 0 1rem 0;
|
|
480
|
+
color: #666;
|
|
481
|
+
line-height: 1.5;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
.features {
|
|
485
|
+
margin: 1.5rem 0;
|
|
486
|
+
padding: 1rem;
|
|
487
|
+
background-color: #f8f9fa;
|
|
488
|
+
border-radius: 0.25rem;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.features h4 {
|
|
492
|
+
margin: 0 0 0.5rem 0;
|
|
493
|
+
color: #333;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.features ul {
|
|
497
|
+
margin: 0;
|
|
498
|
+
padding-left: 1.25rem;
|
|
499
|
+
color: #666;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
.features li {
|
|
503
|
+
margin-bottom: 0.25rem;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
.actions {
|
|
507
|
+
display: flex;
|
|
508
|
+
gap: 0.75rem;
|
|
509
|
+
justify-content: flex-end;
|
|
510
|
+
margin-top: 1.5rem;
|
|
511
|
+
}
|
|
512
|
+
</style>
|
|
513
|
+
```
|
|
514
|
+
|
|
515
|
+
### Form Sheet
|
|
516
|
+
|
|
517
|
+
```vue
|
|
518
|
+
<script setup lang="ts">
|
|
519
|
+
import { ref } from "vue";
|
|
520
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
521
|
+
|
|
522
|
+
const isFormOpen = ref(false);
|
|
523
|
+
const formData = ref({
|
|
524
|
+
name: "",
|
|
525
|
+
email: "",
|
|
526
|
+
message: "",
|
|
527
|
+
});
|
|
528
|
+
|
|
529
|
+
const handleSubmit = () => {
|
|
530
|
+
console.log("Form submitted:", formData.value);
|
|
531
|
+
isFormOpen.value = false;
|
|
532
|
+
// Reset form
|
|
533
|
+
formData.value = { name: "", email: "", message: "" };
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
const handleCancel = () => {
|
|
537
|
+
isFormOpen.value = false;
|
|
538
|
+
// Reset form
|
|
539
|
+
formData.value = { name: "", email: "", message: "" };
|
|
540
|
+
};
|
|
541
|
+
</script>
|
|
542
|
+
|
|
543
|
+
<template>
|
|
544
|
+
<div class="form-sheet">
|
|
545
|
+
<h3>Form Sheet</h3>
|
|
546
|
+
|
|
547
|
+
<Button @click="isFormOpen = true">Contact Us</Button>
|
|
548
|
+
|
|
549
|
+
<Sheet
|
|
550
|
+
v-model="isFormOpen"
|
|
551
|
+
side="bottom"
|
|
552
|
+
:dismiss-on-backdrop="false"
|
|
553
|
+
height="80vh"
|
|
554
|
+
max-height="600px"
|
|
555
|
+
>
|
|
556
|
+
<div class="form-content">
|
|
557
|
+
<div class="form-header">
|
|
558
|
+
<h2>Contact Form</h2>
|
|
559
|
+
<button @click="handleCancel" class="close-btn">×</button>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
<form @submit.prevent="handleSubmit" class="form">
|
|
563
|
+
<div class="form-group">
|
|
564
|
+
<label for="name">Name</label>
|
|
565
|
+
<input
|
|
566
|
+
id="name"
|
|
567
|
+
v-model="formData.name"
|
|
568
|
+
type="text"
|
|
569
|
+
required
|
|
570
|
+
placeholder="Your name"
|
|
571
|
+
/>
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
<div class="form-group">
|
|
575
|
+
<label for="email">Email</label>
|
|
576
|
+
<input
|
|
577
|
+
id="email"
|
|
578
|
+
v-model="formData.email"
|
|
579
|
+
type="email"
|
|
580
|
+
required
|
|
581
|
+
placeholder="your@email.com"
|
|
582
|
+
/>
|
|
583
|
+
</div>
|
|
584
|
+
|
|
585
|
+
<div class="form-group">
|
|
586
|
+
<label for="message">Message</label>
|
|
587
|
+
<textarea
|
|
588
|
+
id="message"
|
|
589
|
+
v-model="formData.message"
|
|
590
|
+
required
|
|
591
|
+
placeholder="Your message..."
|
|
592
|
+
rows="4"
|
|
593
|
+
></textarea>
|
|
594
|
+
</div>
|
|
595
|
+
|
|
596
|
+
<div class="form-actions">
|
|
597
|
+
<Button type="button" @click="handleCancel" variant="secondary">
|
|
598
|
+
Cancel
|
|
599
|
+
</Button>
|
|
600
|
+
<Button type="submit">Send Message</Button>
|
|
601
|
+
</div>
|
|
602
|
+
</form>
|
|
603
|
+
</div>
|
|
604
|
+
</Sheet>
|
|
605
|
+
</div>
|
|
606
|
+
</template>
|
|
607
|
+
|
|
608
|
+
<style module>
|
|
609
|
+
.form-sheet {
|
|
610
|
+
padding: 2rem;
|
|
611
|
+
border: 1px solid #e0e0e0;
|
|
612
|
+
border-radius: 0.5rem;
|
|
613
|
+
max-width: 400px;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
.form-content {
|
|
617
|
+
height: 100%;
|
|
618
|
+
display: flex;
|
|
619
|
+
flex-direction: column;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.form-header {
|
|
623
|
+
display: flex;
|
|
624
|
+
justify-content: space-between;
|
|
625
|
+
align-items: center;
|
|
626
|
+
padding: 1.5rem 2rem 1rem;
|
|
627
|
+
border-bottom: 1px solid #e0e0e0;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
.form-header h2 {
|
|
631
|
+
margin: 0;
|
|
632
|
+
color: #333;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.close-btn {
|
|
636
|
+
background: none;
|
|
637
|
+
border: none;
|
|
638
|
+
font-size: 1.5rem;
|
|
639
|
+
cursor: pointer;
|
|
640
|
+
padding: 0;
|
|
641
|
+
width: 32px;
|
|
642
|
+
height: 32px;
|
|
643
|
+
display: flex;
|
|
644
|
+
align-items: center;
|
|
645
|
+
justify-content: center;
|
|
646
|
+
border-radius: 50%;
|
|
647
|
+
color: #666;
|
|
648
|
+
transition: background-color 0.2s;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
.close-btn:hover {
|
|
652
|
+
background-color: #f0f0f0;
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
.form {
|
|
656
|
+
flex: 1;
|
|
657
|
+
padding: 2rem;
|
|
658
|
+
overflow-y: auto;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.form-group {
|
|
662
|
+
margin-bottom: 1.5rem;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.form-group label {
|
|
666
|
+
display: block;
|
|
667
|
+
margin-bottom: 0.5rem;
|
|
668
|
+
font-weight: 500;
|
|
669
|
+
color: #333;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
.form-group input,
|
|
673
|
+
.form-group textarea {
|
|
674
|
+
width: 100%;
|
|
675
|
+
padding: 0.75rem;
|
|
676
|
+
border: 1px solid #ddd;
|
|
677
|
+
border-radius: 0.25rem;
|
|
678
|
+
font-size: 1rem;
|
|
679
|
+
font-family: inherit;
|
|
680
|
+
box-sizing: border-box;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
.form-group input:focus,
|
|
684
|
+
.form-group textarea:focus {
|
|
685
|
+
outline: none;
|
|
686
|
+
border-color: #007bff;
|
|
687
|
+
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.form-actions {
|
|
691
|
+
display: flex;
|
|
692
|
+
gap: 0.75rem;
|
|
693
|
+
justify-content: flex-end;
|
|
694
|
+
margin-top: 2rem;
|
|
695
|
+
padding-top: 1rem;
|
|
696
|
+
border-top: 1px solid #e0e0e0;
|
|
697
|
+
}
|
|
698
|
+
</style>
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Custom Styled Sheet
|
|
702
|
+
|
|
703
|
+
```vue
|
|
704
|
+
<script setup lang="ts">
|
|
705
|
+
import { ref } from "vue";
|
|
706
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
707
|
+
|
|
708
|
+
const isCustomOpen = ref(false);
|
|
709
|
+
</script>
|
|
710
|
+
|
|
711
|
+
<template>
|
|
712
|
+
<div class="custom-sheet">
|
|
713
|
+
<h3>Custom Styled Sheet</h3>
|
|
714
|
+
|
|
715
|
+
<Button @click="isCustomOpen = true" class="custom-trigger">
|
|
716
|
+
Open Custom Sheet
|
|
717
|
+
</Button>
|
|
718
|
+
|
|
719
|
+
<Sheet
|
|
720
|
+
v-model="isCustomOpen"
|
|
721
|
+
side="right"
|
|
722
|
+
:animation-duration="0.6"
|
|
723
|
+
backdrop-style="dim"
|
|
724
|
+
width="400px"
|
|
725
|
+
height="100vh"
|
|
726
|
+
max-width="400px"
|
|
727
|
+
>
|
|
728
|
+
<div class="custom-content">
|
|
729
|
+
<div class="custom-header">
|
|
730
|
+
<h2>Custom Sheet</h2>
|
|
731
|
+
<p>This sheet has custom styling and positioning.</p>
|
|
732
|
+
</div>
|
|
733
|
+
|
|
734
|
+
<div class="custom-body">
|
|
735
|
+
<div class="feature-list">
|
|
736
|
+
<div class="feature-item">
|
|
737
|
+
<div class="feature-icon">🎨</div>
|
|
738
|
+
<div class="feature-text">
|
|
739
|
+
<h4>Custom Colors</h4>
|
|
740
|
+
<p>Gradient backgrounds and custom styling</p>
|
|
741
|
+
</div>
|
|
742
|
+
</div>
|
|
743
|
+
|
|
744
|
+
<div class="feature-item">
|
|
745
|
+
<div class="feature-icon">⚡</div>
|
|
746
|
+
<div class="feature-text">
|
|
747
|
+
<h4>Right Side</h4>
|
|
748
|
+
<p>Slides in from the right side</p>
|
|
749
|
+
</div>
|
|
750
|
+
</div>
|
|
751
|
+
|
|
752
|
+
<div class="feature-item">
|
|
753
|
+
<div class="feature-icon">🔧</div>
|
|
754
|
+
<div class="feature-text">
|
|
755
|
+
<h4>Custom Size</h4>
|
|
756
|
+
<p>Fixed width and full height</p>
|
|
757
|
+
</div>
|
|
758
|
+
</div>
|
|
759
|
+
</div>
|
|
760
|
+
</div>
|
|
761
|
+
|
|
762
|
+
<div class="custom-footer">
|
|
763
|
+
<Button @click="isCustomOpen = false" class="custom-close">
|
|
764
|
+
Close
|
|
765
|
+
</Button>
|
|
766
|
+
</div>
|
|
767
|
+
</div>
|
|
768
|
+
</Sheet>
|
|
769
|
+
</div>
|
|
770
|
+
</template>
|
|
771
|
+
|
|
772
|
+
<style module>
|
|
773
|
+
.custom-sheet {
|
|
774
|
+
padding: 2rem;
|
|
775
|
+
border: 1px solid #e0e0e0;
|
|
776
|
+
border-radius: 0.5rem;
|
|
777
|
+
max-width: 400px;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
.custom-trigger {
|
|
781
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
782
|
+
color: white;
|
|
783
|
+
border: none;
|
|
784
|
+
padding: 0.75rem 1.5rem;
|
|
785
|
+
border-radius: 0.5rem;
|
|
786
|
+
font-weight: 600;
|
|
787
|
+
transition: transform 0.2s;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
.custom-trigger:hover {
|
|
791
|
+
transform: translateY(-2px);
|
|
792
|
+
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.custom-content {
|
|
796
|
+
height: 100%;
|
|
797
|
+
display: flex;
|
|
798
|
+
flex-direction: column;
|
|
799
|
+
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
|
|
800
|
+
color: white;
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
.custom-header {
|
|
804
|
+
padding: 2rem;
|
|
805
|
+
text-align: center;
|
|
806
|
+
background: rgba(255, 255, 255, 0.1);
|
|
807
|
+
backdrop-filter: blur(10px);
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.custom-header h2 {
|
|
811
|
+
margin: 0 0 0.5rem 0;
|
|
812
|
+
font-size: 1.5rem;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.custom-header p {
|
|
816
|
+
margin: 0;
|
|
817
|
+
opacity: 0.9;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.custom-body {
|
|
821
|
+
flex: 1;
|
|
822
|
+
padding: 2rem;
|
|
823
|
+
overflow-y: auto;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.feature-list {
|
|
827
|
+
display: flex;
|
|
828
|
+
flex-direction: column;
|
|
829
|
+
gap: 1.5rem;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.feature-item {
|
|
833
|
+
display: flex;
|
|
834
|
+
align-items: flex-start;
|
|
835
|
+
gap: 1rem;
|
|
836
|
+
padding: 1rem;
|
|
837
|
+
background: rgba(255, 255, 255, 0.1);
|
|
838
|
+
border-radius: 0.5rem;
|
|
839
|
+
backdrop-filter: blur(5px);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
.feature-icon {
|
|
843
|
+
font-size: 1.5rem;
|
|
844
|
+
width: 2rem;
|
|
845
|
+
text-align: center;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.feature-text h4 {
|
|
849
|
+
margin: 0 0 0.25rem 0;
|
|
850
|
+
font-size: 1rem;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
.feature-text p {
|
|
854
|
+
margin: 0;
|
|
855
|
+
font-size: 0.875rem;
|
|
856
|
+
opacity: 0.8;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.custom-footer {
|
|
860
|
+
padding: 2rem;
|
|
861
|
+
background: rgba(255, 255, 255, 0.1);
|
|
862
|
+
backdrop-filter: blur(10px);
|
|
863
|
+
display: flex;
|
|
864
|
+
justify-content: center;
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
.custom-close {
|
|
868
|
+
background: rgba(255, 255, 255, 0.2);
|
|
869
|
+
color: white;
|
|
870
|
+
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
871
|
+
padding: 0.75rem 2rem;
|
|
872
|
+
border-radius: 0.5rem;
|
|
873
|
+
font-weight: 600;
|
|
874
|
+
transition: all 0.2s;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
.custom-close:hover {
|
|
878
|
+
background: rgba(255, 255, 255, 0.3);
|
|
879
|
+
transform: translateY(-1px);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/* Override sheet CSS variables */
|
|
883
|
+
:global(.custom-sheet) {
|
|
884
|
+
--sheet-bg: transparent;
|
|
885
|
+
--sheet-shadow: none;
|
|
886
|
+
--sheet-inset-shadow: none;
|
|
887
|
+
--sheet-backdrop-dim-bg: rgba(0, 0, 0, 0.8);
|
|
888
|
+
}
|
|
889
|
+
</style>
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### Settings Panel
|
|
893
|
+
|
|
894
|
+
```vue
|
|
895
|
+
<script setup lang="ts">
|
|
896
|
+
import { ref } from "vue";
|
|
897
|
+
import { Sheet, Button } from "@umbra-ui/core";
|
|
898
|
+
|
|
899
|
+
const isSettingsOpen = ref(false);
|
|
900
|
+
const settings = ref({
|
|
901
|
+
notifications: true,
|
|
902
|
+
darkMode: false,
|
|
903
|
+
autoSave: true,
|
|
904
|
+
language: "en",
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
const handleSave = () => {
|
|
908
|
+
console.log("Settings saved:", settings.value);
|
|
909
|
+
isSettingsOpen.value = false;
|
|
910
|
+
};
|
|
911
|
+
</script>
|
|
912
|
+
|
|
913
|
+
<template>
|
|
914
|
+
<div class="settings-sheet">
|
|
915
|
+
<h3>Settings Panel</h3>
|
|
916
|
+
|
|
917
|
+
<Button @click="isSettingsOpen = true">Open Settings</Button>
|
|
918
|
+
|
|
919
|
+
<Sheet
|
|
920
|
+
v-model="isSettingsOpen"
|
|
921
|
+
side="right"
|
|
922
|
+
width="350px"
|
|
923
|
+
height="100vh"
|
|
924
|
+
max-width="350px"
|
|
925
|
+
:dismiss-on-backdrop="false"
|
|
926
|
+
>
|
|
927
|
+
<div class="settings-content">
|
|
928
|
+
<div class="settings-header">
|
|
929
|
+
<h2>Settings</h2>
|
|
930
|
+
<button @click="isSettingsOpen = false" class="close-btn">×</button>
|
|
931
|
+
</div>
|
|
932
|
+
|
|
933
|
+
<div class="settings-body">
|
|
934
|
+
<div class="setting-group">
|
|
935
|
+
<h3>Preferences</h3>
|
|
936
|
+
|
|
937
|
+
<div class="setting-item">
|
|
938
|
+
<div class="setting-info">
|
|
939
|
+
<h4>Notifications</h4>
|
|
940
|
+
<p>Receive push notifications</p>
|
|
941
|
+
</div>
|
|
942
|
+
<label class="toggle">
|
|
943
|
+
<input v-model="settings.notifications" type="checkbox" />
|
|
944
|
+
<span class="slider"></span>
|
|
945
|
+
</label>
|
|
946
|
+
</div>
|
|
947
|
+
|
|
948
|
+
<div class="setting-item">
|
|
949
|
+
<div class="setting-info">
|
|
950
|
+
<h4>Dark Mode</h4>
|
|
951
|
+
<p>Use dark theme</p>
|
|
952
|
+
</div>
|
|
953
|
+
<label class="toggle">
|
|
954
|
+
<input v-model="settings.darkMode" type="checkbox" />
|
|
955
|
+
<span class="slider"></span>
|
|
956
|
+
</label>
|
|
957
|
+
</div>
|
|
958
|
+
|
|
959
|
+
<div class="setting-item">
|
|
960
|
+
<div class="setting-info">
|
|
961
|
+
<h4>Auto Save</h4>
|
|
962
|
+
<p>Automatically save changes</p>
|
|
963
|
+
</div>
|
|
964
|
+
<label class="toggle">
|
|
965
|
+
<input v-model="settings.autoSave" type="checkbox" />
|
|
966
|
+
<span class="slider"></span>
|
|
967
|
+
</label>
|
|
968
|
+
</div>
|
|
969
|
+
</div>
|
|
970
|
+
|
|
971
|
+
<div class="setting-group">
|
|
972
|
+
<h3>Language</h3>
|
|
973
|
+
|
|
974
|
+
<div class="setting-item">
|
|
975
|
+
<div class="setting-info">
|
|
976
|
+
<h4>Language</h4>
|
|
977
|
+
<p>Select your preferred language</p>
|
|
978
|
+
</div>
|
|
979
|
+
<select v-model="settings.language" class="select">
|
|
980
|
+
<option value="en">English</option>
|
|
981
|
+
<option value="es">Spanish</option>
|
|
982
|
+
<option value="fr">French</option>
|
|
983
|
+
<option value="de">German</option>
|
|
984
|
+
</select>
|
|
985
|
+
</div>
|
|
986
|
+
</div>
|
|
987
|
+
</div>
|
|
988
|
+
|
|
989
|
+
<div class="settings-footer">
|
|
990
|
+
<Button @click="isSettingsOpen = false" variant="secondary">
|
|
991
|
+
Cancel
|
|
992
|
+
</Button>
|
|
993
|
+
<Button @click="handleSave">Save Changes</Button>
|
|
994
|
+
</div>
|
|
995
|
+
</div>
|
|
996
|
+
</Sheet>
|
|
997
|
+
</div>
|
|
998
|
+
</template>
|
|
999
|
+
|
|
1000
|
+
<style module>
|
|
1001
|
+
.settings-sheet {
|
|
1002
|
+
padding: 2rem;
|
|
1003
|
+
border: 1px solid #e0e0e0;
|
|
1004
|
+
border-radius: 0.5rem;
|
|
1005
|
+
max-width: 400px;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.settings-content {
|
|
1009
|
+
height: 100%;
|
|
1010
|
+
display: flex;
|
|
1011
|
+
flex-direction: column;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
.settings-header {
|
|
1015
|
+
display: flex;
|
|
1016
|
+
justify-content: space-between;
|
|
1017
|
+
align-items: center;
|
|
1018
|
+
padding: 1.5rem 2rem 1rem;
|
|
1019
|
+
border-bottom: 1px solid #e0e0e0;
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
.settings-header h2 {
|
|
1023
|
+
margin: 0;
|
|
1024
|
+
color: #333;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.close-btn {
|
|
1028
|
+
background: none;
|
|
1029
|
+
border: none;
|
|
1030
|
+
font-size: 1.5rem;
|
|
1031
|
+
cursor: pointer;
|
|
1032
|
+
padding: 0;
|
|
1033
|
+
width: 32px;
|
|
1034
|
+
height: 32px;
|
|
1035
|
+
display: flex;
|
|
1036
|
+
align-items: center;
|
|
1037
|
+
justify-content: center;
|
|
1038
|
+
border-radius: 50%;
|
|
1039
|
+
color: #666;
|
|
1040
|
+
transition: background-color 0.2s;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
.close-btn:hover {
|
|
1044
|
+
background-color: #f0f0f0;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.settings-body {
|
|
1048
|
+
flex: 1;
|
|
1049
|
+
padding: 2rem;
|
|
1050
|
+
overflow-y: auto;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.setting-group {
|
|
1054
|
+
margin-bottom: 2rem;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
.setting-group h3 {
|
|
1058
|
+
margin: 0 0 1rem 0;
|
|
1059
|
+
color: #333;
|
|
1060
|
+
font-size: 1.125rem;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.setting-item {
|
|
1064
|
+
display: flex;
|
|
1065
|
+
justify-content: space-between;
|
|
1066
|
+
align-items: center;
|
|
1067
|
+
padding: 1rem 0;
|
|
1068
|
+
border-bottom: 1px solid #f0f0f0;
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
.setting-info h4 {
|
|
1072
|
+
margin: 0 0 0.25rem 0;
|
|
1073
|
+
color: #333;
|
|
1074
|
+
font-size: 1rem;
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.setting-info p {
|
|
1078
|
+
margin: 0;
|
|
1079
|
+
color: #666;
|
|
1080
|
+
font-size: 0.875rem;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.toggle {
|
|
1084
|
+
position: relative;
|
|
1085
|
+
display: inline-block;
|
|
1086
|
+
width: 50px;
|
|
1087
|
+
height: 24px;
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
.toggle input {
|
|
1091
|
+
opacity: 0;
|
|
1092
|
+
width: 0;
|
|
1093
|
+
height: 0;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1096
|
+
.slider {
|
|
1097
|
+
position: absolute;
|
|
1098
|
+
cursor: pointer;
|
|
1099
|
+
top: 0;
|
|
1100
|
+
left: 0;
|
|
1101
|
+
right: 0;
|
|
1102
|
+
bottom: 0;
|
|
1103
|
+
background-color: #ccc;
|
|
1104
|
+
transition: 0.2s;
|
|
1105
|
+
border-radius: 24px;
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
.slider:before {
|
|
1109
|
+
position: absolute;
|
|
1110
|
+
content: "";
|
|
1111
|
+
height: 18px;
|
|
1112
|
+
width: 18px;
|
|
1113
|
+
left: 3px;
|
|
1114
|
+
bottom: 3px;
|
|
1115
|
+
background-color: white;
|
|
1116
|
+
transition: 0.2s;
|
|
1117
|
+
border-radius: 50%;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
input:checked + .slider {
|
|
1121
|
+
background-color: #007bff;
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
input:checked + .slider:before {
|
|
1125
|
+
transform: translateX(26px);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
.select {
|
|
1129
|
+
padding: 0.5rem;
|
|
1130
|
+
border: 1px solid #ddd;
|
|
1131
|
+
border-radius: 0.25rem;
|
|
1132
|
+
background-color: white;
|
|
1133
|
+
color: #333;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.settings-footer {
|
|
1137
|
+
display: flex;
|
|
1138
|
+
gap: 0.75rem;
|
|
1139
|
+
justify-content: flex-end;
|
|
1140
|
+
padding: 1.5rem 2rem;
|
|
1141
|
+
border-top: 1px solid #e0e0e0;
|
|
1142
|
+
}
|
|
1143
|
+
</style>
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
## Technical Notes
|
|
1147
|
+
|
|
1148
|
+
- Sheet provides a comprehensive modal system with smooth animations and flexible positioning
|
|
1149
|
+
- GSAP animations ensure smooth, performant transitions with hardware acceleration
|
|
1150
|
+
- Teleport usage ensures proper z-index layering and positioning outside component tree
|
|
1151
|
+
- Body scroll locking prevents background scrolling when sheet is open
|
|
1152
|
+
- Safe area support handles mobile device notches and home indicators
|
|
1153
|
+
- Custom scrollbar styling provides better visual consistency
|
|
1154
|
+
- Backdrop blur effects create modern, iOS-like appearance
|
|
1155
|
+
- Keyboard navigation includes Escape key support for accessibility
|
|
1156
|
+
- TypeScript interfaces ensure type safety for all props and events
|
|
1157
|
+
- CSS custom properties enable easy theming and customization
|
|
1158
|
+
- Responsive design adapts to different screen sizes and orientations
|
|
1159
|
+
- Animation cleanup prevents memory leaks and ensures smooth performance
|