diff --git a/.changeset/healthy-houses-remember.md b/.changeset/healthy-houses-remember.md new file mode 100644 index 00000000..2da9731c --- /dev/null +++ b/.changeset/healthy-houses-remember.md @@ -0,0 +1,7 @@ +--- +"enspire": minor +--- +
+**Welcome to Enspire v1.3.0!** + +This version introduces redesign of the sidebar. diff --git a/app/app.vue b/app/app.vue index c24669dc..1ff62919 100644 --- a/app/app.vue +++ b/app/app.vue @@ -1,8 +1,15 @@ - + + diff --git a/app/components/custom/sidebar.vue b/app/components/custom/sidebar.vue index 16bf0d32..07cd4c83 100644 --- a/app/components/custom/sidebar.vue +++ b/app/components/custom/sidebar.vue @@ -1,9 +1,19 @@ diff --git a/app/components/ui/breadcrumb/Breadcrumb.vue b/app/components/ui/breadcrumb/Breadcrumb.vue new file mode 100644 index 00000000..72ca1437 --- /dev/null +++ b/app/components/ui/breadcrumb/Breadcrumb.vue @@ -0,0 +1,13 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbEllipsis.vue b/app/components/ui/breadcrumb/BreadcrumbEllipsis.vue new file mode 100644 index 00000000..cfccf9fe --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbEllipsis.vue @@ -0,0 +1,22 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbItem.vue b/app/components/ui/breadcrumb/BreadcrumbItem.vue new file mode 100644 index 00000000..42e721cd --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbItem.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbLink.vue b/app/components/ui/breadcrumb/BreadcrumbLink.vue new file mode 100644 index 00000000..dbb1014a --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbLink.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbList.vue b/app/components/ui/breadcrumb/BreadcrumbList.vue new file mode 100644 index 00000000..60856cc4 --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbList.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbPage.vue b/app/components/ui/breadcrumb/BreadcrumbPage.vue new file mode 100644 index 00000000..fe43bda6 --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbPage.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/ui/breadcrumb/BreadcrumbSeparator.vue b/app/components/ui/breadcrumb/BreadcrumbSeparator.vue new file mode 100644 index 00000000..a9c47fea --- /dev/null +++ b/app/components/ui/breadcrumb/BreadcrumbSeparator.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/breadcrumb/index.ts b/app/components/ui/breadcrumb/index.ts new file mode 100644 index 00000000..05909832 --- /dev/null +++ b/app/components/ui/breadcrumb/index.ts @@ -0,0 +1,7 @@ +export { default as Breadcrumb } from './Breadcrumb.vue' +export { default as BreadcrumbEllipsis } from './BreadcrumbEllipsis.vue' +export { default as BreadcrumbItem } from './BreadcrumbItem.vue' +export { default as BreadcrumbLink } from './BreadcrumbLink.vue' +export { default as BreadcrumbList } from './BreadcrumbList.vue' +export { default as BreadcrumbPage } from './BreadcrumbPage.vue' +export { default as BreadcrumbSeparator } from './BreadcrumbSeparator.vue' diff --git a/app/components/ui/collapsible/Collapsible.vue b/app/components/ui/collapsible/Collapsible.vue new file mode 100644 index 00000000..fae7919c --- /dev/null +++ b/app/components/ui/collapsible/Collapsible.vue @@ -0,0 +1,15 @@ + + + diff --git a/app/components/ui/collapsible/CollapsibleContent.vue b/app/components/ui/collapsible/CollapsibleContent.vue new file mode 100644 index 00000000..9f30898b --- /dev/null +++ b/app/components/ui/collapsible/CollapsibleContent.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/collapsible/CollapsibleTrigger.vue b/app/components/ui/collapsible/CollapsibleTrigger.vue new file mode 100644 index 00000000..4a434639 --- /dev/null +++ b/app/components/ui/collapsible/CollapsibleTrigger.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/collapsible/index.ts b/app/components/ui/collapsible/index.ts new file mode 100644 index 00000000..abab9567 --- /dev/null +++ b/app/components/ui/collapsible/index.ts @@ -0,0 +1,3 @@ +export { default as Collapsible } from './Collapsible.vue' +export { default as CollapsibleContent } from './CollapsibleContent.vue' +export { default as CollapsibleTrigger } from './CollapsibleTrigger.vue' diff --git a/app/components/ui/form/index.ts b/app/components/ui/form/index.ts index 676da1dc..fca299e7 100644 --- a/app/components/ui/form/index.ts +++ b/app/components/ui/form/index.ts @@ -1,7 +1,7 @@ -export { default as FormControl } from '@/components/ui/form/FormControl.vue' -export { default as FormDescription } from '@/components/ui/form/FormDescription.vue' -export { default as FormItem } from '@/components/ui/form/FormItem.vue' -export { default as FormLabel } from '@/components/ui/form/FormLabel.vue' -export { default as FormMessage } from '@/components/ui/form/FormMessage.vue' +export { default as FormControl } from './FormControl.vue' +export { default as FormDescription } from './FormDescription.vue' +export { default as FormItem } from './FormItem.vue' +export { default as FormLabel } from './FormLabel.vue' +export { default as FormMessage } from './FormMessage.vue' export { FORM_ITEM_INJECTION_KEY } from './injectionKeys' export { Field as FormField, Form } from 'vee-validate' diff --git a/app/components/ui/sheet/Sheet.vue b/app/components/ui/sheet/Sheet.vue new file mode 100644 index 00000000..a04c0262 --- /dev/null +++ b/app/components/ui/sheet/Sheet.vue @@ -0,0 +1,14 @@ + + + diff --git a/app/components/ui/sheet/SheetClose.vue b/app/components/ui/sheet/SheetClose.vue new file mode 100644 index 00000000..a64703e5 --- /dev/null +++ b/app/components/ui/sheet/SheetClose.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/sheet/SheetContent.vue b/app/components/ui/sheet/SheetContent.vue new file mode 100644 index 00000000..a3606186 --- /dev/null +++ b/app/components/ui/sheet/SheetContent.vue @@ -0,0 +1,56 @@ + + + diff --git a/app/components/ui/sheet/SheetDescription.vue b/app/components/ui/sheet/SheetDescription.vue new file mode 100644 index 00000000..b515e42a --- /dev/null +++ b/app/components/ui/sheet/SheetDescription.vue @@ -0,0 +1,22 @@ + + + diff --git a/app/components/ui/sheet/SheetFooter.vue b/app/components/ui/sheet/SheetFooter.vue new file mode 100644 index 00000000..ac2d0c18 --- /dev/null +++ b/app/components/ui/sheet/SheetFooter.vue @@ -0,0 +1,19 @@ + + + diff --git a/app/components/ui/sheet/SheetHeader.vue b/app/components/ui/sheet/SheetHeader.vue new file mode 100644 index 00000000..541f48f5 --- /dev/null +++ b/app/components/ui/sheet/SheetHeader.vue @@ -0,0 +1,16 @@ + + + diff --git a/app/components/ui/sheet/SheetTitle.vue b/app/components/ui/sheet/SheetTitle.vue new file mode 100644 index 00000000..b1029593 --- /dev/null +++ b/app/components/ui/sheet/SheetTitle.vue @@ -0,0 +1,22 @@ + + + diff --git a/app/components/ui/sheet/SheetTrigger.vue b/app/components/ui/sheet/SheetTrigger.vue new file mode 100644 index 00000000..ee0c12ff --- /dev/null +++ b/app/components/ui/sheet/SheetTrigger.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/sheet/index.ts b/app/components/ui/sheet/index.ts new file mode 100644 index 00000000..b6949d4e --- /dev/null +++ b/app/components/ui/sheet/index.ts @@ -0,0 +1,31 @@ +import { cva, type VariantProps } from 'class-variance-authority' + +export { default as Sheet } from './Sheet.vue' +export { default as SheetClose } from './SheetClose.vue' +export { default as SheetContent } from './SheetContent.vue' +export { default as SheetDescription } from './SheetDescription.vue' +export { default as SheetFooter } from './SheetFooter.vue' +export { default as SheetHeader } from './SheetHeader.vue' +export { default as SheetTitle } from './SheetTitle.vue' +export { default as SheetTrigger } from './SheetTrigger.vue' + +export const sheetVariants = cva( + 'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500 backdrop-blur-md', + { + variants: { + side: { + top: 'inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top', + bottom: + 'inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom', + left: 'inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm', + right: + 'inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm', + }, + }, + defaultVariants: { + side: 'right', + }, + }, +) + +export type SheetVariants = VariantProps diff --git a/app/components/ui/sidebar/Sidebar.vue b/app/components/ui/sidebar/Sidebar.vue new file mode 100644 index 00000000..2dfb4867 --- /dev/null +++ b/app/components/ui/sidebar/Sidebar.vue @@ -0,0 +1,85 @@ + + + diff --git a/app/components/ui/sidebar/SidebarContent.vue b/app/components/ui/sidebar/SidebarContent.vue new file mode 100644 index 00000000..4b6244a4 --- /dev/null +++ b/app/components/ui/sidebar/SidebarContent.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarFooter.vue b/app/components/ui/sidebar/SidebarFooter.vue new file mode 100644 index 00000000..9d145c05 --- /dev/null +++ b/app/components/ui/sidebar/SidebarFooter.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarGroup.vue b/app/components/ui/sidebar/SidebarGroup.vue new file mode 100644 index 00000000..adc6843c --- /dev/null +++ b/app/components/ui/sidebar/SidebarGroup.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarGroupAction.vue b/app/components/ui/sidebar/SidebarGroupAction.vue new file mode 100644 index 00000000..74cac4ea --- /dev/null +++ b/app/components/ui/sidebar/SidebarGroupAction.vue @@ -0,0 +1,27 @@ + + + diff --git a/app/components/ui/sidebar/SidebarGroupContent.vue b/app/components/ui/sidebar/SidebarGroupContent.vue new file mode 100644 index 00000000..37390c93 --- /dev/null +++ b/app/components/ui/sidebar/SidebarGroupContent.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarGroupLabel.vue b/app/components/ui/sidebar/SidebarGroupLabel.vue new file mode 100644 index 00000000..83826c3e --- /dev/null +++ b/app/components/ui/sidebar/SidebarGroupLabel.vue @@ -0,0 +1,24 @@ + + + diff --git a/app/components/ui/sidebar/SidebarHeader.vue b/app/components/ui/sidebar/SidebarHeader.vue new file mode 100644 index 00000000..eecaddb2 --- /dev/null +++ b/app/components/ui/sidebar/SidebarHeader.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarInput.vue b/app/components/ui/sidebar/SidebarInput.vue new file mode 100644 index 00000000..adf11f97 --- /dev/null +++ b/app/components/ui/sidebar/SidebarInput.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/sidebar/SidebarInset.vue b/app/components/ui/sidebar/SidebarInset.vue new file mode 100644 index 00000000..30ad2928 --- /dev/null +++ b/app/components/ui/sidebar/SidebarInset.vue @@ -0,0 +1,20 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenu.vue b/app/components/ui/sidebar/SidebarMenu.vue new file mode 100644 index 00000000..3bfd73e6 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenu.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuAction.vue b/app/components/ui/sidebar/SidebarMenuAction.vue new file mode 100644 index 00000000..c91295e6 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuAction.vue @@ -0,0 +1,34 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuBadge.vue b/app/components/ui/sidebar/SidebarMenuBadge.vue new file mode 100644 index 00000000..f8789687 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuBadge.vue @@ -0,0 +1,25 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuButton.vue b/app/components/ui/sidebar/SidebarMenuButton.vue new file mode 100644 index 00000000..ac6926bf --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuButton.vue @@ -0,0 +1,49 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuButtonChild.vue b/app/components/ui/sidebar/SidebarMenuButtonChild.vue new file mode 100644 index 00000000..1d438667 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuButtonChild.vue @@ -0,0 +1,33 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuItem.vue b/app/components/ui/sidebar/SidebarMenuItem.vue new file mode 100644 index 00000000..b6000734 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuItem.vue @@ -0,0 +1,17 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuSkeleton.vue b/app/components/ui/sidebar/SidebarMenuSkeleton.vue new file mode 100644 index 00000000..76053a12 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuSkeleton.vue @@ -0,0 +1,33 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuSub.vue b/app/components/ui/sidebar/SidebarMenuSub.vue new file mode 100644 index 00000000..0bb5af79 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuSub.vue @@ -0,0 +1,21 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuSubButton.vue b/app/components/ui/sidebar/SidebarMenuSubButton.vue new file mode 100644 index 00000000..0c63da14 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuSubButton.vue @@ -0,0 +1,35 @@ + + + diff --git a/app/components/ui/sidebar/SidebarMenuSubItem.vue b/app/components/ui/sidebar/SidebarMenuSubItem.vue new file mode 100644 index 00000000..b04030b0 --- /dev/null +++ b/app/components/ui/sidebar/SidebarMenuSubItem.vue @@ -0,0 +1,9 @@ + + + diff --git a/app/components/ui/sidebar/SidebarProvider.vue b/app/components/ui/sidebar/SidebarProvider.vue new file mode 100644 index 00000000..4fc3aae0 --- /dev/null +++ b/app/components/ui/sidebar/SidebarProvider.vue @@ -0,0 +1,80 @@ + + + diff --git a/app/components/ui/sidebar/SidebarRail.vue b/app/components/ui/sidebar/SidebarRail.vue new file mode 100644 index 00000000..ec1db266 --- /dev/null +++ b/app/components/ui/sidebar/SidebarRail.vue @@ -0,0 +1,32 @@ + + + diff --git a/app/components/ui/sidebar/SidebarSeparator.vue b/app/components/ui/sidebar/SidebarSeparator.vue new file mode 100644 index 00000000..dc7e93cb --- /dev/null +++ b/app/components/ui/sidebar/SidebarSeparator.vue @@ -0,0 +1,18 @@ + + + diff --git a/app/components/ui/sidebar/SidebarTrigger.vue b/app/components/ui/sidebar/SidebarTrigger.vue new file mode 100644 index 00000000..db5964a9 --- /dev/null +++ b/app/components/ui/sidebar/SidebarTrigger.vue @@ -0,0 +1,26 @@ + + + diff --git a/app/components/ui/sidebar/index.ts b/app/components/ui/sidebar/index.ts new file mode 100644 index 00000000..6c28e312 --- /dev/null +++ b/app/components/ui/sidebar/index.ts @@ -0,0 +1,59 @@ +import type { HTMLAttributes } from 'vue' +import { cva, type VariantProps } from 'class-variance-authority' + +export interface SidebarProps { + side?: 'left' | 'right' + variant?: 'sidebar' | 'floating' | 'inset' + collapsible?: 'offcanvas' | 'icon' | 'none' + class?: HTMLAttributes['class'] +} + +export { default as Sidebar } from './Sidebar.vue' +export { default as SidebarContent } from './SidebarContent.vue' +export { default as SidebarFooter } from './SidebarFooter.vue' +export { default as SidebarGroup } from './SidebarGroup.vue' +export { default as SidebarGroupAction } from './SidebarGroupAction.vue' +export { default as SidebarGroupContent } from './SidebarGroupContent.vue' +export { default as SidebarGroupLabel } from './SidebarGroupLabel.vue' +export { default as SidebarHeader } from './SidebarHeader.vue' +export { default as SidebarInput } from './SidebarInput.vue' +export { default as SidebarInset } from './SidebarInset.vue' +export { default as SidebarMenu } from './SidebarMenu.vue' +export { default as SidebarMenuAction } from './SidebarMenuAction.vue' +export { default as SidebarMenuBadge } from './SidebarMenuBadge.vue' +export { default as SidebarMenuButton } from './SidebarMenuButton.vue' +export { default as SidebarMenuItem } from './SidebarMenuItem.vue' +export { default as SidebarMenuSkeleton } from './SidebarMenuSkeleton.vue' +export { default as SidebarMenuSub } from './SidebarMenuSub.vue' +export { default as SidebarMenuSubButton } from './SidebarMenuSubButton.vue' +export { default as SidebarMenuSubItem } from './SidebarMenuSubItem.vue' +export { default as SidebarProvider } from './SidebarProvider.vue' +export { default as SidebarRail } from './SidebarRail.vue' +export { default as SidebarSeparator } from './SidebarSeparator.vue' +export { default as SidebarTrigger } from './SidebarTrigger.vue' + +export { useSidebar } from './utils' + +export const sidebarMenuButtonVariants = cva( + 'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0', + { + variants: { + variant: { + default: 'hover:bg-primary/10 hover:text-sidebar-accent-foreground bg-transparent', + outline: + 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]', + }, + size: { + default: 'h-8 text-sm', + sm: 'h-7 text-xs', + lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0', + }, + }, + defaultVariants: { + variant: 'default', + size: 'default', + }, + }, +) + +export type SidebarMenuButtonVariants = VariantProps diff --git a/app/components/ui/sidebar/utils.ts b/app/components/ui/sidebar/utils.ts new file mode 100644 index 00000000..3ded66c4 --- /dev/null +++ b/app/components/ui/sidebar/utils.ts @@ -0,0 +1,19 @@ +import type { ComputedRef, Ref } from 'vue' +import { createContext } from 'radix-vue' + +export const SIDEBAR_COOKIE_NAME = 'sidebar:state' +export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 +export const SIDEBAR_WIDTH = '16rem' +export const SIDEBAR_WIDTH_MOBILE = '18rem' +export const SIDEBAR_WIDTH_ICON = '3rem' +export const SIDEBAR_KEYBOARD_SHORTCUT = 'b' + +export const [useSidebar, provideSidebarContext] = createContext<{ + state: ComputedRef<'expanded' | 'collapsed'> + open: Ref + setOpen: (value: boolean) => void + isMobile: Ref + openMobile: Ref + setOpenMobile: (value: boolean) => void + toggleSidebar: () => void +}>('Sidebar') diff --git a/app/components/ui/tooltip/Tooltip.vue b/app/components/ui/tooltip/Tooltip.vue new file mode 100644 index 00000000..b421f0fe --- /dev/null +++ b/app/components/ui/tooltip/Tooltip.vue @@ -0,0 +1,14 @@ + + + diff --git a/app/components/ui/tooltip/TooltipContent.vue b/app/components/ui/tooltip/TooltipContent.vue new file mode 100644 index 00000000..c583a984 --- /dev/null +++ b/app/components/ui/tooltip/TooltipContent.vue @@ -0,0 +1,31 @@ + + + diff --git a/app/components/ui/tooltip/TooltipProvider.vue b/app/components/ui/tooltip/TooltipProvider.vue new file mode 100644 index 00000000..816505d6 --- /dev/null +++ b/app/components/ui/tooltip/TooltipProvider.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/tooltip/TooltipTrigger.vue b/app/components/ui/tooltip/TooltipTrigger.vue new file mode 100644 index 00000000..f5b0e57f --- /dev/null +++ b/app/components/ui/tooltip/TooltipTrigger.vue @@ -0,0 +1,11 @@ + + + diff --git a/app/components/ui/tooltip/index.ts b/app/components/ui/tooltip/index.ts new file mode 100644 index 00000000..5ab96536 --- /dev/null +++ b/app/components/ui/tooltip/index.ts @@ -0,0 +1,4 @@ +export { default as Tooltip } from './Tooltip.vue' +export { default as TooltipContent } from './TooltipContent.vue' +export { default as TooltipProvider } from './TooltipProvider.vue' +export { default as TooltipTrigger } from './TooltipTrigger.vue' diff --git a/app/error.vue b/app/error.vue index f36585eb..9dd31d65 100644 --- a/app/error.vue +++ b/app/error.vue @@ -6,12 +6,14 @@ const props = defineProps({ }) const handleError = () => reloadNuxtApp({ path: '/' }) + +console.error(props.error)