refactor: change to use iframe
feat: add more blocks
This commit is contained in:
parent
cb962888ab
commit
6c66e974e5
12
apps/www/.vitepress/theme/components/BlockPage.vue
Normal file
12
apps/www/.vitepress/theme/components/BlockPage.vue
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<script setup lang="ts">
|
||||
import { useUrlSearchParams } from '@vueuse/core'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
|
||||
const params = useUrlSearchParams('hash-params')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="params.containerClass">
|
||||
<ComponentLoader :name="params.name.toString()" :type-name="'block'" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -7,7 +7,6 @@ import MagicString from 'magic-string'
|
|||
import { cssVariables } from '../config/shiki'
|
||||
import StyleSwitcher from './StyleSwitcher.vue'
|
||||
import Spinner from './Spinner.vue'
|
||||
import ComponentLoader from './ComponentLoader.vue'
|
||||
import { useConfigStore } from '@/stores/config'
|
||||
|
||||
// import { BlockCopyCodeButton } from '@/components/block-copy-code-button'
|
||||
|
|
@ -26,7 +25,10 @@ const props = defineProps<{
|
|||
|
||||
const { style, codeConfig } = useConfigStore()
|
||||
|
||||
const isLoading = ref(true)
|
||||
const tabValue = ref('preview')
|
||||
const resizableRef = ref<InstanceType<typeof ResizablePanel>>()
|
||||
|
||||
const rawString = ref('')
|
||||
const codeHtml = ref('')
|
||||
const metadata = reactive({
|
||||
|
|
@ -90,10 +92,10 @@ watch([style, codeConfig], async () => {
|
|||
<template>
|
||||
<Tabs
|
||||
:id="name"
|
||||
default-value="preview"
|
||||
v-model="tabValue"
|
||||
class="relative grid w-full scroll-m-20 gap-4"
|
||||
:style=" {
|
||||
'--container-height': metadata.iframeHeight,
|
||||
'--container-height': metadata.iframeHeight ?? '600px',
|
||||
}"
|
||||
>
|
||||
<div class="flex flex-col items-center gap-4 sm:flex-row">
|
||||
|
|
@ -205,6 +207,8 @@ watch([style, codeConfig], async () => {
|
|||
</div>
|
||||
</div>
|
||||
<TabsContent
|
||||
v-show="tabValue === 'preview'"
|
||||
force-mount
|
||||
value="preview"
|
||||
class="relative after:absolute after:inset-0 after:right-3 after:z-0 after:rounded-lg after:bg-muted h-[--container-height] px-0"
|
||||
>
|
||||
|
|
@ -216,9 +220,15 @@ watch([style, codeConfig], async () => {
|
|||
:default-size="100"
|
||||
:min-size="25"
|
||||
>
|
||||
<div :class="metadata.containerClass">
|
||||
<ComponentLoader :key="style" :name="name" :type-name="'block'" />
|
||||
<div v-if="isLoading" class="flex items-center justify-center h-full">
|
||||
<Spinner />
|
||||
</div>
|
||||
<iframe
|
||||
v-show="!isLoading"
|
||||
:src="`/blocks/renderer#name=${name}&style=${style}&containerClass=${encodeURIComponent(metadata.containerClass ?? '')}`"
|
||||
class="relative z-20 w-full bg-background h-[--container-height]"
|
||||
@load="isLoading = false"
|
||||
/>
|
||||
</ResizablePanel>
|
||||
<ResizableHandle id="block-resizable-handle" class="relative hidden w-3 bg-transparent p-0 after:absolute after:right-0 after:top-1/2 after:h-8 after:w-[6px] after:-translate-y-1/2 after:translate-x-[-1px] after:rounded-full after:bg-border after:transition-all after:hover:h-10 sm:block" />
|
||||
<ResizablePanel id="block-resizable-panel-2" :default-size="0" :min-size="0" />
|
||||
|
|
@ -226,7 +236,7 @@ watch([style, codeConfig], async () => {
|
|||
</TabsContent>
|
||||
<TabsContent value="code" class="h-[--container-height]">
|
||||
<div
|
||||
class="language-vue !h-full !mt-0"
|
||||
class="language-vue !h-full !max-h-[none] !mt-0"
|
||||
v-html="codeHtml"
|
||||
/>
|
||||
</TabsContent>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ import('../../../__registry__/index').then((res) => {
|
|||
</PageAction>
|
||||
</PageHeader>
|
||||
|
||||
<section>
|
||||
<section class="grid scroll-mt-24 gap-24 lg:gap-48">
|
||||
<BlockPreview v-for="block in blocks" :key="block" :name="block" />
|
||||
</section>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -84,7 +84,10 @@ watch(() => $route.path, (n) => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
|
||||
<div v-if="$route.data.frontmatter.layout === false">
|
||||
<Content :key="$route.path" />
|
||||
</div>
|
||||
<div v-else vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
|
||||
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
|
||||
<div
|
||||
class="container flex h-14 max-w-screen-2xl items-center"
|
||||
|
|
@ -298,4 +301,4 @@ watch(() => $route.path, (n) => {
|
|||
<NewYorkSonner :theme="'system'" />
|
||||
<NewYorkToaster />
|
||||
</div>
|
||||
</template>../components/CodeConfigCustomizer.vue
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1109,6 +1109,27 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/default/block/Authentication01.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Authentication01.vue"],
|
||||
},
|
||||
"Authentication02": {
|
||||
name: "Authentication02",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
component: () => import("../src/lib/registry/default/block/Authentication02.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Authentication02.vue"],
|
||||
},
|
||||
"Authentication03": {
|
||||
name: "Authentication03",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
component: () => import("../src/lib/registry/default/block/Authentication03.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Authentication03.vue"],
|
||||
},
|
||||
"Authentication04": {
|
||||
name: "Authentication04",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","input","label"],
|
||||
component: () => import("../src/lib/registry/default/block/Authentication04.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/default/block/Authentication04.vue"],
|
||||
},
|
||||
}, "new-york": {
|
||||
"AccordionDemo": {
|
||||
name: "AccordionDemo",
|
||||
|
|
@ -2216,5 +2237,26 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/new-york/block/Authentication01.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Authentication01.vue"],
|
||||
},
|
||||
"Authentication02": {
|
||||
name: "Authentication02",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
component: () => import("../src/lib/registry/new-york/block/Authentication02.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Authentication02.vue"],
|
||||
},
|
||||
"Authentication03": {
|
||||
name: "Authentication03",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","card","input","label"],
|
||||
component: () => import("../src/lib/registry/new-york/block/Authentication03.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Authentication03.vue"],
|
||||
},
|
||||
"Authentication04": {
|
||||
name: "Authentication04",
|
||||
type: "components:block",
|
||||
registryDependencies: ["button","input","label"],
|
||||
component: () => import("../src/lib/registry/new-york/block/Authentication04.vue").then((m) => m.default),
|
||||
files: ["../src/lib/registry/new-york/block/Authentication04.vue"],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
10
apps/www/src/content/blocks/renderer.md
Normal file
10
apps/www/src/content/blocks/renderer.md
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
title: Blocks - shadcn-vue
|
||||
layout: false
|
||||
---
|
||||
|
||||
<script setup>
|
||||
import BlockPage from "../../../.vitepress/theme/components/BlockPage.vue"
|
||||
</script>
|
||||
|
||||
<BlockPage />
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
export const description
|
||||
= 'A simple login form with email and password. The submit button says \'Sign in\'.'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-full flex items-center justify-center px-4'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
|||
60
apps/www/src/lib/registry/default/block/Authentication02.vue
Normal file
60
apps/www/src/lib/registry/default/block/Authentication02.vue
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A login form with email and password. There\'s an option to login with Google and a link to sign up if you don\'t have an account.'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/lib/registry/default/ui/card'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mx-auto max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-2xl">
|
||||
Login
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<div class="flex items-center">
|
||||
<Label for="password">Password</Label>
|
||||
<a href="#" class="ml-auto inline-block text-sm underline">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Don't have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</template>
|
||||
65
apps/www/src/lib/registry/default/block/Authentication03.vue
Normal file
65
apps/www/src/lib/registry/default/block/Authentication03.vue
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A sign up form with first name, last name, email and password inside a card. There\'s an option to sign up with GitHub and a link to login if you already have an account'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/lib/registry/default/ui/card'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mx-auto max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-xl">
|
||||
Sign Up
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your information to create an account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="first-name">First name</Label>
|
||||
<Input id="first-name" placeholder="Max" required />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="last-name">Last name</Label>
|
||||
<Input id="last-name" placeholder="Robinson" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="password">Password</Label>
|
||||
<Input id="password" type="password" />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Create an account
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Sign up with GitHub
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Already have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign in
|
||||
</a>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</template>
|
||||
73
apps/www/src/lib/registry/default/block/Authentication04.vue
Normal file
73
apps/www/src/lib/registry/default/block/Authentication04.vue
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A login page with two columns. The first column has the login form with email and password. There\'s a Forgot your passwork link and a link to sign up if you do not have an account. The second column has a cover image.'
|
||||
export const iframeHeight = '800px'
|
||||
export const containerClass = 'w-full h-full p-4 lg:p-0'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/default/ui/button'
|
||||
import { Input } from '@/lib/registry/default/ui/input'
|
||||
import { Label } from '@/lib/registry/default/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full lg:grid lg:min-h-[600px] lg:grid-cols-2 xl:min-h-[800px]">
|
||||
<div class="flex items-center justify-center py-12">
|
||||
<div class="mx-auto grid w-[350px] gap-6">
|
||||
<div class="grid gap-2 text-center">
|
||||
<h1 class="text-3xl font-bold">
|
||||
Login
|
||||
</h1>
|
||||
<p class="text-balance text-muted-foreground">
|
||||
Enter your email below to login to your account
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<div class="flex items-center">
|
||||
<Label for="password">Password</Label>
|
||||
<a
|
||||
href="/forgot-password"
|
||||
class="ml-auto inline-block text-sm underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Don't have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden bg-muted lg:block">
|
||||
<img
|
||||
src="/placeholder.svg"
|
||||
alt="Image"
|
||||
width="1920"
|
||||
height="1080"
|
||||
class="h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
export const description
|
||||
= 'A simple login form with email and password. The submit button says \'Sign in\'.'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-full flex items-center justify-center px-4'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,60 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A login form with email and password. There\'s an option to login with Google and a link to sign up if you don\'t have an account.'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/lib/registry/new-york/ui/card'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mx-auto max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-2xl">
|
||||
Login
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your email below to login to your account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<div class="flex items-center">
|
||||
<Label for="password">Password</Label>
|
||||
<a href="#" class="ml-auto inline-block text-sm underline">
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Don't have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A sign up form with first name, last name, email and password inside a card. There\'s an option to sign up with GitHub and a link to login if you already have an account'
|
||||
export const iframeHeight = '600px'
|
||||
export const containerClass = 'w-full h-screen flex items-center justify-center px-4'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/lib/registry/new-york/ui/card'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card class="mx-auto max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle class="text-xl">
|
||||
Sign Up
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
Enter your information to create an account
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid grid-cols-2 gap-4">
|
||||
<div class="space-y-2">
|
||||
<Label for="first-name">First name</Label>
|
||||
<Input id="first-name" placeholder="Max" required />
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="last-name">Last name</Label>
|
||||
<Input id="last-name" placeholder="Robinson" required />
|
||||
</div>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<Label for="password">Password</Label>
|
||||
<Input id="password" type="password" />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Create an account
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Sign up with GitHub
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Already have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign in
|
||||
</a>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<script lang="ts">
|
||||
export const description
|
||||
= 'A login page with two columns. The first column has the login form with email and password. There\'s a Forgot your passwork link and a link to sign up if you do not have an account. The second column has a cover image.'
|
||||
export const iframeHeight = '800px'
|
||||
export const containerClass = 'w-full h-full p-4 lg:p-0'
|
||||
</script>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button } from '@/lib/registry/new-york/ui/button'
|
||||
import { Input } from '@/lib/registry/new-york/ui/input'
|
||||
import { Label } from '@/lib/registry/new-york/ui/label'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-full lg:grid lg:min-h-[600px] lg:grid-cols-2 xl:min-h-[800px]">
|
||||
<div class="flex items-center justify-center py-12">
|
||||
<div class="mx-auto grid w-[350px] gap-6">
|
||||
<div class="grid gap-2 text-center">
|
||||
<h1 class="text-3xl font-bold">
|
||||
Login
|
||||
</h1>
|
||||
<p class="text-balance text-muted-foreground">
|
||||
Enter your email below to login to your account
|
||||
</p>
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
<div class="grid gap-2">
|
||||
<Label for="email">Email</Label>
|
||||
<Input
|
||||
id="email"
|
||||
type="email"
|
||||
placeholder="m@example.com"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div class="grid gap-2">
|
||||
<div class="flex items-center">
|
||||
<Label for="password">Password</Label>
|
||||
<a
|
||||
href="/forgot-password"
|
||||
class="ml-auto inline-block text-sm underline"
|
||||
>
|
||||
Forgot your password?
|
||||
</a>
|
||||
</div>
|
||||
<Input id="password" type="password" required />
|
||||
</div>
|
||||
<Button type="submit" class="w-full">
|
||||
Login
|
||||
</Button>
|
||||
<Button variant="outline" class="w-full">
|
||||
Login with Google
|
||||
</Button>
|
||||
</div>
|
||||
<div class="mt-4 text-center text-sm">
|
||||
Don't have an account?
|
||||
<a href="#" class="underline">
|
||||
Sign up
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hidden bg-muted lg:block">
|
||||
<img
|
||||
src="/placeholder.svg"
|
||||
alt="Image"
|
||||
width="1920"
|
||||
height="1080"
|
||||
class="h-full w-full object-cover dark:brightness-[0.2] dark:grayscale"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
1
apps/www/src/public/placeholder.svg
Normal file
1
apps/www/src/public/placeholder.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1200" fill="none"><rect width="1200" height="1200" fill="#EAEAEA" rx="3"/><g opacity=".5"><g opacity=".5"><path fill="#FAFAFA" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 736.5c-75.454 0-136.621-61.167-136.621-136.62 0-75.454 61.167-136.621 136.621-136.621 75.453 0 136.62 61.167 136.62 136.621 0 75.453-61.167 136.62-136.62 136.62Z"/></g><path stroke="url(#a)" stroke-width="2.418" d="M0-1.209h553.581" transform="scale(1 -1) rotate(45 1163.11 91.165)"/><path stroke="url(#b)" stroke-width="2.418" d="M404.846 598.671h391.726"/><path stroke="url(#c)" stroke-width="2.418" d="M599.5 795.742V404.017"/><path stroke="url(#d)" stroke-width="2.418" d="m795.717 796.597-391.441-391.44"/><path fill="#fff" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/><g clip-path="url(#e)"><path fill="#666" fill-rule="evenodd" d="M616.426 586.58h-31.434v16.176l3.553-3.554.531-.531h9.068l.074-.074 8.463-8.463h2.565l7.18 7.181V586.58Zm-15.715 14.654 3.698 3.699 1.283 1.282-2.565 2.565-1.282-1.283-5.2-5.199h-6.066l-5.514 5.514-.073.073v2.876a2.418 2.418 0 0 0 2.418 2.418h26.598a2.418 2.418 0 0 0 2.418-2.418v-8.317l-8.463-8.463-7.181 7.181-.071.072Zm-19.347 5.442v4.085a6.045 6.045 0 0 0 6.046 6.045h26.598a6.044 6.044 0 0 0 6.045-6.045v-7.108l1.356-1.355-1.282-1.283-.074-.073v-17.989h-38.689v23.43l-.146.146.146.147Z" clip-rule="evenodd"/></g><path stroke="#C9C9C9" stroke-width="2.418" d="M600.709 656.704c-31.384 0-56.825-25.441-56.825-56.824 0-31.384 25.441-56.825 56.825-56.825 31.383 0 56.824 25.441 56.824 56.825 0 31.383-25.441 56.824-56.824 56.824Z"/></g><defs><linearGradient id="a" x1="554.061" x2="-.48" y1=".083" y2=".087" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="b" x1="796.912" x2="404.507" y1="599.963" y2="599.965" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="c" x1="600.792" x2="600.794" y1="403.677" y2="796.082" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><linearGradient id="d" x1="404.85" x2="796.972" y1="403.903" y2="796.02" gradientUnits="userSpaceOnUse"><stop stop-color="#C9C9C9" stop-opacity="0"/><stop offset=".208" stop-color="#C9C9C9"/><stop offset=".792" stop-color="#C9C9C9"/><stop offset="1" stop-color="#C9C9C9" stop-opacity="0"/></linearGradient><clipPath id="e"><path fill="#fff" d="M581.364 580.535h38.689v38.689h-38.689z"/></clipPath></defs></svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
Loading…
Reference in New Issue
Block a user