sprintify-ui 0.0.18 → 0.0.20
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/sprintify-ui.es.js +5552 -4491
- package/dist/types/src/components/BaseActionItem.vue.d.ts +121 -0
- package/dist/types/src/components/BaseAlert.vue.d.ts +3 -3
- package/dist/types/src/components/BaseAppDialogs.vue.d.ts +1 -1
- package/dist/types/src/components/BaseBoolean.vue.d.ts +2 -2
- package/dist/types/src/components/BaseCounter.vue.d.ts +3 -3
- package/dist/types/src/components/BaseDialog.vue.d.ts +4 -4
- package/dist/types/src/components/BaseInput.vue.d.ts +1 -1
- package/dist/types/src/components/BaseLayoutSidebar.vue.d.ts +114 -0
- package/dist/types/src/components/BaseLayoutSidebarConfigurable.vue.d.ts +163 -0
- package/dist/types/src/components/BaseLayoutStacked.vue.d.ts +76 -0
- package/dist/types/src/components/BaseLayoutStackedConfigurable.vue.d.ts +163 -0
- package/dist/types/src/components/BaseMenuItem.vue.d.ts +5 -5
- package/dist/types/src/components/BaseNavbar.vue.d.ts +20 -1
- package/dist/types/src/components/BaseNavbarItem.vue.d.ts +17 -71
- package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +11 -2
- package/dist/types/src/components/BaseNavbarSideItem.vue.d.ts +26 -0
- package/dist/types/src/components/BaseNavbarSideItemContent.vue.d.ts +50 -0
- package/dist/types/src/components/BaseSwitch.vue.d.ts +3 -3
- package/dist/types/src/components/BaseSystemAlert.vue.d.ts +8 -8
- package/dist/types/src/components/BaseTableColumn.vue.d.ts +1 -1
- package/dist/types/src/components/index.d.ts +5 -1
- package/package.json +1 -1
- package/src/components/BaseActionItem.vue +68 -0
- package/src/components/BaseBreadcrumbs.vue +1 -1
- package/src/components/{HasMany.stories.js → BaseHasMany.stories.js} +0 -0
- package/src/components/BaseLayoutSidebar.vue +199 -0
- package/src/components/BaseLayoutSidebarConfigurable.stories.js +111 -0
- package/src/components/BaseLayoutSidebarConfigurable.vue +115 -0
- package/src/components/BaseLayoutStacked.vue +52 -0
- package/src/components/BaseLayoutStackedConfigurable.stories.js +92 -0
- package/src/components/BaseLayoutStackedConfigurable.vue +124 -0
- package/src/components/BaseMediaItem.vue +7 -7
- package/src/components/BaseMediaLibrary.vue +3 -3
- package/src/components/BaseMediaPreview.vue +1 -1
- package/src/components/BaseNavbar.stories.js +18 -14
- package/src/components/BaseNavbar.vue +19 -3
- package/src/components/BaseNavbarItem.vue +17 -43
- package/src/components/BaseNavbarItemContent.vue +36 -16
- package/src/components/BaseNavbarSideItem.vue +42 -0
- package/src/components/BaseNavbarSideItemContent.vue +77 -0
- package/src/components/index.ts +9 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="min-h-full">
|
|
3
|
+
<TransitionRoot as="template" :show="showMobileMenu">
|
|
4
|
+
<Dialog
|
|
5
|
+
as="div"
|
|
6
|
+
class="relative z-40 xl:hidden"
|
|
7
|
+
@close="showMobileMenu = false"
|
|
8
|
+
>
|
|
9
|
+
<TransitionChild
|
|
10
|
+
as="template"
|
|
11
|
+
enter="transition-opacity ease-linear duration-300"
|
|
12
|
+
enter-from="opacity-0"
|
|
13
|
+
enter-to="opacity-100"
|
|
14
|
+
leave="transition-opacity ease-linear duration-300"
|
|
15
|
+
leave-from="opacity-100"
|
|
16
|
+
leave-to="opacity-0"
|
|
17
|
+
>
|
|
18
|
+
<div class="fixed inset-0 bg-slate-600 bg-opacity-75" />
|
|
19
|
+
</TransitionChild>
|
|
20
|
+
|
|
21
|
+
<div class="fixed inset-0 z-40 flex">
|
|
22
|
+
<TransitionChild
|
|
23
|
+
as="template"
|
|
24
|
+
enter="transition ease-in-out duration-300 transform"
|
|
25
|
+
enter-from="-translate-x-full"
|
|
26
|
+
enter-to="translate-x-0"
|
|
27
|
+
leave="transition ease-in-out duration-300 transform"
|
|
28
|
+
leave-from="translate-x-0"
|
|
29
|
+
leave-to="-translate-x-full"
|
|
30
|
+
>
|
|
31
|
+
<DialogPanel
|
|
32
|
+
class="relative flex w-full max-w-xs flex-1 flex-col pt-5 pb-4"
|
|
33
|
+
:class="[dark ? 'bg-slate-800' : 'bg-white']"
|
|
34
|
+
>
|
|
35
|
+
<TransitionChild
|
|
36
|
+
as="template"
|
|
37
|
+
enter="ease-in-out duration-300"
|
|
38
|
+
enter-from="opacity-0"
|
|
39
|
+
enter-to="opacity-100"
|
|
40
|
+
leave="ease-in-out duration-300"
|
|
41
|
+
leave-from="opacity-100"
|
|
42
|
+
leave-to="opacity-0"
|
|
43
|
+
>
|
|
44
|
+
<div class="absolute top-0 right-0 -mr-12 pt-2">
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
class="ml-1 flex h-10 w-10 items-center justify-center rounded-full"
|
|
48
|
+
@click="showMobileMenu = false"
|
|
49
|
+
>
|
|
50
|
+
<span class="sr-only">Close sidebar</span>
|
|
51
|
+
<BaseIcon
|
|
52
|
+
icon="heroicons:x-mark"
|
|
53
|
+
class="h-6 w-6 text-white"
|
|
54
|
+
aria-hidden="true"
|
|
55
|
+
/>
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</TransitionChild>
|
|
59
|
+
<div class="flex flex-shrink-0 items-center px-4">
|
|
60
|
+
<img class="block h-8 w-auto" :src="logoUrl" :alt="appName" />
|
|
61
|
+
</div>
|
|
62
|
+
<div class="mt-5 h-0 flex-1 overflow-y-auto">
|
|
63
|
+
<nav>
|
|
64
|
+
<slot name="menu" />
|
|
65
|
+
</nav>
|
|
66
|
+
</div>
|
|
67
|
+
</DialogPanel>
|
|
68
|
+
</TransitionChild>
|
|
69
|
+
<div class="w-14 flex-shrink-0" aria-hidden="true">
|
|
70
|
+
<!-- Dummy element to force sidebar to shrink to fit close icon -->
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
</Dialog>
|
|
74
|
+
</TransitionRoot>
|
|
75
|
+
|
|
76
|
+
<div class="flex min-h-full flex-col xl:pl-64">
|
|
77
|
+
<div class="sticky top-0 left-0 z-10 shrink-0 shadow">
|
|
78
|
+
<BaseSystemAlert
|
|
79
|
+
v-for="systemAlert in systemAlerts"
|
|
80
|
+
:key="systemAlert.id"
|
|
81
|
+
:color="systemAlert.color"
|
|
82
|
+
:to="systemAlert.to"
|
|
83
|
+
:action="systemAlert.action"
|
|
84
|
+
:closable="systemAlert.closable"
|
|
85
|
+
@close="systemAlertStore.remove(systemAlert)"
|
|
86
|
+
>
|
|
87
|
+
{{ systemAlert.message }}
|
|
88
|
+
</BaseSystemAlert>
|
|
89
|
+
|
|
90
|
+
<div class="flex h-16 bg-white">
|
|
91
|
+
<button
|
|
92
|
+
type="button"
|
|
93
|
+
class="border-r border-slate-200 px-4 text-slate-500 xl:hidden"
|
|
94
|
+
@click="showMobileMenu = true"
|
|
95
|
+
>
|
|
96
|
+
<span class="sr-only">Open sidebar</span>
|
|
97
|
+
<BaseIcon
|
|
98
|
+
icon="heroicons:bars-3-bottom-left"
|
|
99
|
+
class="h-6 w-6"
|
|
100
|
+
aria-hidden="true"
|
|
101
|
+
/>
|
|
102
|
+
</button>
|
|
103
|
+
|
|
104
|
+
<!-- Navbar -->
|
|
105
|
+
<div class="flex flex-1">
|
|
106
|
+
<slot name="navbar" />
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<!-- Position: relative to contain Loading Covers -->
|
|
112
|
+
<main class="relative min-h-full flex-1">
|
|
113
|
+
<slot />
|
|
114
|
+
</main>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<!-- Static sidebar for desktop -->
|
|
118
|
+
<div class="z-10 hidden xl:fixed xl:inset-y-0 xl:flex xl:w-64 xl:flex-col">
|
|
119
|
+
<!-- Sidebar component, swap this element with another sidebar if you like -->
|
|
120
|
+
<div
|
|
121
|
+
class="flex min-h-0 flex-1 flex-col"
|
|
122
|
+
:class="[dark ? 'bg-slate-800' : 'bg-white shadow']"
|
|
123
|
+
>
|
|
124
|
+
<div
|
|
125
|
+
class="flex h-16 flex-shrink-0 items-center px-4"
|
|
126
|
+
:class="[dark ? 'bg-slate-900' : 'bg-white']"
|
|
127
|
+
>
|
|
128
|
+
<img class="block h-8 w-auto" :src="logoUrl" :alt="appName" />
|
|
129
|
+
</div>
|
|
130
|
+
<div class="flex flex-1">
|
|
131
|
+
<nav class="flex-1">
|
|
132
|
+
<slot name="menu" />
|
|
133
|
+
</nav>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</div>
|
|
138
|
+
</template>
|
|
139
|
+
|
|
140
|
+
<script setup lang="ts">
|
|
141
|
+
import { ref } from 'vue';
|
|
142
|
+
import {
|
|
143
|
+
Dialog,
|
|
144
|
+
DialogPanel,
|
|
145
|
+
TransitionChild,
|
|
146
|
+
TransitionRoot,
|
|
147
|
+
} from '@headlessui/vue';
|
|
148
|
+
|
|
149
|
+
import { useSystemAlertStore } from '../stores/systemAlerts';
|
|
150
|
+
import { BaseIcon } from '.';
|
|
151
|
+
import BaseSystemAlert from './BaseSystemAlert.vue';
|
|
152
|
+
|
|
153
|
+
const props = defineProps({
|
|
154
|
+
appName: {
|
|
155
|
+
default: '',
|
|
156
|
+
type: String,
|
|
157
|
+
},
|
|
158
|
+
logoUrl: {
|
|
159
|
+
default: 'https://sprintify.witify.io/img/logo/logo-side-dark.svg',
|
|
160
|
+
type: String,
|
|
161
|
+
},
|
|
162
|
+
dark: {
|
|
163
|
+
default: false,
|
|
164
|
+
type: Boolean,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* System Alert And Navigation size
|
|
170
|
+
*/
|
|
171
|
+
|
|
172
|
+
const systemAlertStore = useSystemAlertStore();
|
|
173
|
+
|
|
174
|
+
const systemAlerts = computed(() => {
|
|
175
|
+
return systemAlertStore.systemAlerts;
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Show/Hide sidebar
|
|
180
|
+
*/
|
|
181
|
+
|
|
182
|
+
const showMobileMenu = ref(false);
|
|
183
|
+
|
|
184
|
+
function toggleMenu() {
|
|
185
|
+
showMobileMenu.value = !showMobileMenu.value;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function openMenu() {
|
|
189
|
+
showMobileMenu.value = true;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function closeMenu() {
|
|
193
|
+
showMobileMenu.value = false;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
provide('toggleMenu', toggleMenu);
|
|
197
|
+
provide('openMenu', openMenu);
|
|
198
|
+
provide('closeMenu', closeMenu);
|
|
199
|
+
</script>
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import BaseContainer from './BaseContainer.vue';
|
|
2
|
+
import BaseLayoutSidebarConfigurable from './BaseLayoutSidebarConfigurable.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Layout/BaseLayoutSidebarConfigurable',
|
|
6
|
+
component: BaseLayoutSidebarConfigurable,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'fullscreen',
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
user: {
|
|
12
|
+
email: 'jane@witify.io',
|
|
13
|
+
first_name: 'Jane',
|
|
14
|
+
last_name: 'Doe',
|
|
15
|
+
full_name: 'Jane Doe',
|
|
16
|
+
avatar_url:
|
|
17
|
+
'https://images.unsplash.com/photo-1494790108377-be9c29b29330??auto=format&fit=crop&w=200&h=200&q=80&g=face',
|
|
18
|
+
},
|
|
19
|
+
menu: [
|
|
20
|
+
{
|
|
21
|
+
title: 'General',
|
|
22
|
+
actions: [
|
|
23
|
+
{
|
|
24
|
+
label: 'Dashboard',
|
|
25
|
+
to: '/',
|
|
26
|
+
icon: 'heroicons-home',
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
label: 'Articles',
|
|
30
|
+
to: '/articles',
|
|
31
|
+
icon: 'heroicons:document-text',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
label: 'Users',
|
|
35
|
+
to: '/users',
|
|
36
|
+
icon: 'heroicons:users',
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
title: 'Settings',
|
|
42
|
+
actions: [
|
|
43
|
+
{
|
|
44
|
+
label: 'Account',
|
|
45
|
+
to: '/account',
|
|
46
|
+
icon: 'heroicons:cog',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'Logout',
|
|
50
|
+
action: logout,
|
|
51
|
+
icon: 'heroicons:arrow-left-on-rectangle',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
userMenu: [
|
|
57
|
+
{
|
|
58
|
+
label: 'Dashboard',
|
|
59
|
+
to: '/',
|
|
60
|
+
icon: 'heroicons-home',
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
label: 'Settings',
|
|
64
|
+
to: '/account',
|
|
65
|
+
icon: 'heroicons:cog',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
label: 'Logout',
|
|
69
|
+
action: logout,
|
|
70
|
+
icon: 'heroicons:arrow-left-on-rectangle',
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
async function logout() {
|
|
77
|
+
alert('logout');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const Template = (args) => ({
|
|
81
|
+
components: {
|
|
82
|
+
BaseContainer,
|
|
83
|
+
BaseLayoutSidebarConfigurable,
|
|
84
|
+
},
|
|
85
|
+
setup() {
|
|
86
|
+
return { args };
|
|
87
|
+
},
|
|
88
|
+
template: `
|
|
89
|
+
<BaseLayoutSidebarConfigurable v-bind="args">
|
|
90
|
+
<div class="py-16">
|
|
91
|
+
<BaseContainer size="3xl">
|
|
92
|
+
<p v-for="i in 20" class="mb-1">
|
|
93
|
+
Amet occaecat enim pariatur incididunt enim laborum enim. Duis cillum in in excepteur sit excepteur laboris consectetur magna. Commodo proident labore commodo duis veniam do nisi irure ipsum officia excepteur non. Nisi cillum mollit tempor ut.
|
|
94
|
+
</p>
|
|
95
|
+
</BaseContainer>
|
|
96
|
+
</div>
|
|
97
|
+
</BaseLayoutSidebarConfigurable>
|
|
98
|
+
`,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const Light = Template.bind({});
|
|
102
|
+
Light.args = {
|
|
103
|
+
dark: false,
|
|
104
|
+
logoUrl: 'https://sprintify.witify.io/img/logo/logo-side.svg',
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
export const Dark = Template.bind({});
|
|
108
|
+
Dark.args = {
|
|
109
|
+
dark: true,
|
|
110
|
+
logoUrl: 'https://sprintify.witify.io/img/logo/logo-side-dark.svg',
|
|
111
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<BaseLayoutSidebar :app-name="appName" :logo-url="logoUrl" :dark="dark">
|
|
3
|
+
<template #menu>
|
|
4
|
+
<div class="px-3 py-6">
|
|
5
|
+
<div class="space-y-8">
|
|
6
|
+
<div v-for="section in actionSections" :key="section.title">
|
|
7
|
+
<h2
|
|
8
|
+
v-if="section.title"
|
|
9
|
+
class="mb-3 pl-3 text-xs font-semibold uppercase tracking-widest"
|
|
10
|
+
:class="dark ? 'text-slate-400' : 'text-slate-500'"
|
|
11
|
+
>
|
|
12
|
+
{{ section.title }}
|
|
13
|
+
</h2>
|
|
14
|
+
<div>
|
|
15
|
+
<div class="space-y-1">
|
|
16
|
+
<BaseNavbarSideItem
|
|
17
|
+
v-for="item in section.actions"
|
|
18
|
+
:key="item.label"
|
|
19
|
+
:item="item"
|
|
20
|
+
:dark="dark"
|
|
21
|
+
/>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
|
|
29
|
+
<template #navbar>
|
|
30
|
+
<div class="flex flex-1 justify-between px-4">
|
|
31
|
+
<div class="flex flex-1">
|
|
32
|
+
<!-- Good spot for search bar... -->
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<div class="ml-4 flex items-center md:ml-6">
|
|
36
|
+
<!-- Good spot for notification button... -->
|
|
37
|
+
|
|
38
|
+
<!-- Profile dropdown -->
|
|
39
|
+
<div class="relative ml-3 mr-3">
|
|
40
|
+
<BaseMenu :items="userMenu">
|
|
41
|
+
<template #button="{ open }">
|
|
42
|
+
<div
|
|
43
|
+
class="flex"
|
|
44
|
+
:class="[
|
|
45
|
+
open
|
|
46
|
+
? 'ring-2 ring-blue-500 ring-offset-2 ring-offset-white'
|
|
47
|
+
: '',
|
|
48
|
+
]"
|
|
49
|
+
>
|
|
50
|
+
<BaseAvatar :user="user" show-details />
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
</BaseMenu>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
59
|
+
<template #default>
|
|
60
|
+
<slot />
|
|
61
|
+
</template>
|
|
62
|
+
</BaseLayoutSidebar>
|
|
63
|
+
</template>
|
|
64
|
+
|
|
65
|
+
<script setup lang="ts">
|
|
66
|
+
import { User } from '@/types/User';
|
|
67
|
+
import { PropType } from 'vue';
|
|
68
|
+
import { ActionItem, ActionSection } from '../types/types';
|
|
69
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
70
|
+
import BaseLayoutSidebar from './BaseLayoutSidebar.vue';
|
|
71
|
+
import BaseMenu from './BaseMenu.vue';
|
|
72
|
+
import BaseNavbarSideItem from './BaseNavbarSideItem.vue';
|
|
73
|
+
|
|
74
|
+
const props = defineProps({
|
|
75
|
+
appName: {
|
|
76
|
+
default: '',
|
|
77
|
+
type: String,
|
|
78
|
+
},
|
|
79
|
+
logoUrl: {
|
|
80
|
+
default: 'https://sprintify.witify.io/img/logo/logo-side-dark.svg',
|
|
81
|
+
type: String,
|
|
82
|
+
},
|
|
83
|
+
menu: {
|
|
84
|
+
required: true,
|
|
85
|
+
type: Array as PropType<ActionItem[] | ActionSection[]>,
|
|
86
|
+
},
|
|
87
|
+
userMenu: {
|
|
88
|
+
required: true,
|
|
89
|
+
type: Array as PropType<ActionItem[]>,
|
|
90
|
+
},
|
|
91
|
+
user: {
|
|
92
|
+
required: true,
|
|
93
|
+
type: Object as PropType<User>,
|
|
94
|
+
},
|
|
95
|
+
dark: {
|
|
96
|
+
default: false,
|
|
97
|
+
type: Boolean,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const actionSections = computed((): ActionSection[] => {
|
|
102
|
+
const isActionSections = props.menu.length > 0 && 'actions' in props.menu[0];
|
|
103
|
+
|
|
104
|
+
if (isActionSections) {
|
|
105
|
+
return props.menu as ActionSection[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return [
|
|
109
|
+
{
|
|
110
|
+
title: '',
|
|
111
|
+
actions: props.menu as ActionItem[],
|
|
112
|
+
},
|
|
113
|
+
];
|
|
114
|
+
});
|
|
115
|
+
</script>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="sticky top-0 z-20 w-full shadow-sm">
|
|
3
|
+
<BaseSystemAlert
|
|
4
|
+
v-for="systemAlert in systemAlerts"
|
|
5
|
+
:key="systemAlert.id"
|
|
6
|
+
:color="systemAlert.color"
|
|
7
|
+
:to="systemAlert.to"
|
|
8
|
+
:action="systemAlert.action"
|
|
9
|
+
:closable="systemAlert.closable"
|
|
10
|
+
@close="systemAlertStore.remove(systemAlert)"
|
|
11
|
+
>
|
|
12
|
+
{{ systemAlert.message }}
|
|
13
|
+
</BaseSystemAlert>
|
|
14
|
+
|
|
15
|
+
<BaseNavbar :dark="dark">
|
|
16
|
+
<template #navbar>
|
|
17
|
+
<slot name="navbar" />
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<template #mobile>
|
|
21
|
+
<slot name="mobile" />
|
|
22
|
+
</template>
|
|
23
|
+
</BaseNavbar>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div>
|
|
27
|
+
<slot />
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script lang="ts" setup>
|
|
32
|
+
import { useSystemAlertStore } from '../stores/systemAlerts';
|
|
33
|
+
import BaseNavbar from './BaseNavbar.vue';
|
|
34
|
+
import BaseSystemAlert from './BaseSystemAlert.vue';
|
|
35
|
+
|
|
36
|
+
defineProps({
|
|
37
|
+
dark: {
|
|
38
|
+
default: false,
|
|
39
|
+
type: Boolean,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* System Alerts
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
const systemAlertStore = useSystemAlertStore();
|
|
48
|
+
|
|
49
|
+
const systemAlerts = computed(() => {
|
|
50
|
+
return systemAlertStore.systemAlerts;
|
|
51
|
+
});
|
|
52
|
+
</script>
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import BaseContainer from './BaseContainer.vue';
|
|
2
|
+
import BaseLayoutStackedConfigurable from './BaseLayoutStackedConfigurable.vue';
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
title: 'Layout/BaseLayoutStackedConfigurable',
|
|
6
|
+
component: BaseLayoutStackedConfigurable,
|
|
7
|
+
parameters: {
|
|
8
|
+
layout: 'fullscreen',
|
|
9
|
+
},
|
|
10
|
+
args: {
|
|
11
|
+
appName: 'Sprintify',
|
|
12
|
+
user: {
|
|
13
|
+
email: 'jane@witify.io',
|
|
14
|
+
first_name: 'Jane',
|
|
15
|
+
last_name: 'Doe',
|
|
16
|
+
full_name: 'Jane Doe',
|
|
17
|
+
avatar_url:
|
|
18
|
+
'https://images.unsplash.com/photo-1494790108377-be9c29b29330??auto=format&fit=crop&w=200&h=200&q=80&g=face',
|
|
19
|
+
},
|
|
20
|
+
menu: [
|
|
21
|
+
{
|
|
22
|
+
label: 'Products',
|
|
23
|
+
to: '/',
|
|
24
|
+
count: 234,
|
|
25
|
+
type: 'RouterLink',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
label: 'Users',
|
|
29
|
+
to: '/setup',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: 'Account',
|
|
33
|
+
to: '/settings',
|
|
34
|
+
icon: 'heroicons:cog',
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
userMenu: [
|
|
38
|
+
{
|
|
39
|
+
label: 'Dashboard',
|
|
40
|
+
to: '/',
|
|
41
|
+
icon: 'heroicons-home',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
label: 'Settings',
|
|
45
|
+
to: '/account',
|
|
46
|
+
icon: 'heroicons:cog',
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
label: 'Logout',
|
|
50
|
+
action: logout,
|
|
51
|
+
icon: 'heroicons:arrow-left-on-rectangle',
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
async function logout() {
|
|
58
|
+
alert('logout');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const Template = (args) => ({
|
|
62
|
+
components: {
|
|
63
|
+
BaseLayoutStackedConfigurable,
|
|
64
|
+
BaseContainer,
|
|
65
|
+
},
|
|
66
|
+
setup() {
|
|
67
|
+
return { args };
|
|
68
|
+
},
|
|
69
|
+
template: `
|
|
70
|
+
<BaseLayoutStackedConfigurable v-bind="args">
|
|
71
|
+
<div class="py-16">
|
|
72
|
+
<BaseContainer size="3xl">
|
|
73
|
+
<p v-for="i in 20" class="mb-1">
|
|
74
|
+
Amet occaecat enim pariatur incididunt enim laborum enim. Duis cillum in in excepteur sit excepteur laboris consectetur magna. Commodo proident labore commodo duis veniam do nisi irure ipsum officia excepteur non. Nisi cillum mollit tempor ut.
|
|
75
|
+
</p>
|
|
76
|
+
</BaseContainer>
|
|
77
|
+
</div>
|
|
78
|
+
</BaseLayoutStackedConfigurable>
|
|
79
|
+
`,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
export const Light = Template.bind({});
|
|
83
|
+
Light.args = {
|
|
84
|
+
dark: false,
|
|
85
|
+
logoUrl: 'https://sprintify.witify.io/img/logo/logo-side.svg',
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
export const Dark = Template.bind({});
|
|
89
|
+
Dark.args = {
|
|
90
|
+
dark: true,
|
|
91
|
+
logoUrl: 'https://sprintify.witify.io/img/logo/logo-side-dark.svg',
|
|
92
|
+
};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<BaseLayoutStacked :dark="dark">
|
|
3
|
+
<template #navbar>
|
|
4
|
+
<div class="flex h-16 justify-between">
|
|
5
|
+
<!-- Left -->
|
|
6
|
+
|
|
7
|
+
<div class="flex justify-center">
|
|
8
|
+
<!-- Logo -->
|
|
9
|
+
<router-link to="/" class="flex flex-shrink-0 items-center p-2 pl-0">
|
|
10
|
+
<img class="block h-8 w-auto" :src="logoUrl" :alt="appName" />
|
|
11
|
+
</router-link>
|
|
12
|
+
|
|
13
|
+
<!-- Links (desktop) -->
|
|
14
|
+
<div class="ml-10 hidden space-x-4 md:flex">
|
|
15
|
+
<BaseNavbarItem
|
|
16
|
+
v-for="item in menu"
|
|
17
|
+
:key="item.label"
|
|
18
|
+
:item="item"
|
|
19
|
+
:dark="dark"
|
|
20
|
+
/>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<!-- Right -->
|
|
25
|
+
|
|
26
|
+
<div class="hidden md:ml-6 md:flex md:items-center">
|
|
27
|
+
<!-- Profile dropdown -->
|
|
28
|
+
<BaseMenu menu-class="w-52" :items="userMenu">
|
|
29
|
+
<template #button="{ open }">
|
|
30
|
+
<div
|
|
31
|
+
class="flex rounded-full"
|
|
32
|
+
:class="[
|
|
33
|
+
open
|
|
34
|
+
? 'bg-slate-700 ring-2 ring-blue-500 ring-offset-2 ring-offset-slate-700'
|
|
35
|
+
: '',
|
|
36
|
+
]"
|
|
37
|
+
>
|
|
38
|
+
<BaseAvatar :class="dark ? 'text-white' : ''" :user="user" />
|
|
39
|
+
</div>
|
|
40
|
+
</template>
|
|
41
|
+
</BaseMenu>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<template #mobile>
|
|
47
|
+
<!-- Links mobile -->
|
|
48
|
+
<div class="space-y-1 p-2 pt-0">
|
|
49
|
+
<BaseNavbarSideItem
|
|
50
|
+
v-for="item in menu"
|
|
51
|
+
:key="item.label"
|
|
52
|
+
:item="item"
|
|
53
|
+
:dark="dark"
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<hr
|
|
58
|
+
class="mb-4 mt-2"
|
|
59
|
+
:class="[dark ? 'border-slate-700' : 'border-slate-200']"
|
|
60
|
+
/>
|
|
61
|
+
|
|
62
|
+
<!-- Profile links -->
|
|
63
|
+
<div class="p-2 pb-6">
|
|
64
|
+
<BaseAvatar
|
|
65
|
+
:user="user"
|
|
66
|
+
show-details
|
|
67
|
+
size="base"
|
|
68
|
+
class="px-3"
|
|
69
|
+
:class="dark ? 'text-white' : ''"
|
|
70
|
+
/>
|
|
71
|
+
<div class="mt-4 space-y-1">
|
|
72
|
+
<BaseNavbarSideItem
|
|
73
|
+
v-for="item in userMenu"
|
|
74
|
+
:key="item.label"
|
|
75
|
+
:item="item"
|
|
76
|
+
:dark="dark"
|
|
77
|
+
/>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<template #default>
|
|
83
|
+
<slot name="default" />
|
|
84
|
+
</template>
|
|
85
|
+
</BaseLayoutStacked>
|
|
86
|
+
</template>
|
|
87
|
+
|
|
88
|
+
<script lang="ts" setup>
|
|
89
|
+
import { User } from '@/types/User';
|
|
90
|
+
import { PropType } from 'vue';
|
|
91
|
+
import { ActionItem } from '../types/types';
|
|
92
|
+
import BaseAvatar from './BaseAvatar.vue';
|
|
93
|
+
import BaseLayoutStacked from './BaseLayoutStacked.vue';
|
|
94
|
+
import BaseMenu from './BaseMenu.vue';
|
|
95
|
+
import BaseNavbarItem from './BaseNavbarItem.vue';
|
|
96
|
+
import BaseNavbarSideItem from './BaseNavbarSideItem.vue';
|
|
97
|
+
|
|
98
|
+
defineProps({
|
|
99
|
+
appName: {
|
|
100
|
+
default: '',
|
|
101
|
+
type: String,
|
|
102
|
+
},
|
|
103
|
+
logoUrl: {
|
|
104
|
+
default: 'https://sprintify.witify.io/img/logo/logo-side.svg',
|
|
105
|
+
type: String,
|
|
106
|
+
},
|
|
107
|
+
menu: {
|
|
108
|
+
required: true,
|
|
109
|
+
type: Array as PropType<ActionItem[]>,
|
|
110
|
+
},
|
|
111
|
+
userMenu: {
|
|
112
|
+
required: true,
|
|
113
|
+
type: Array as PropType<ActionItem[]>,
|
|
114
|
+
},
|
|
115
|
+
user: {
|
|
116
|
+
required: true,
|
|
117
|
+
type: Object as PropType<User>,
|
|
118
|
+
},
|
|
119
|
+
dark: {
|
|
120
|
+
default: false,
|
|
121
|
+
type: Boolean,
|
|
122
|
+
},
|
|
123
|
+
});
|
|
124
|
+
</script>
|