Tailwind CSS 4 Migration (#100)
* Updated to TailwindCSS v4 * Moved CSS module to its own CSS file because of lightingcss strict validation * Respect next parameter in middleware * Updated all packages. * Split CSSs for better organization. * Redesigned theme and auth pages * Improved pill and header design * Formatted files using Prettier * Better footer layout * Better auth layout * Bump version of the repository to 2.0.0
This commit is contained in:
committed by
GitHub
parent
d799f54ede
commit
4e91f267e0
@@ -5,8 +5,6 @@ import Link from 'next/link';
|
||||
|
||||
import type { User } from '@supabase/supabase-js';
|
||||
|
||||
import { ArrowRightIcon } from 'lucide-react';
|
||||
|
||||
import { PersonalAccountDropdown } from '@kit/accounts/personal-account-dropdown';
|
||||
import { useSignOut } from '@kit/supabase/hooks/use-sign-out';
|
||||
import { useUser } from '@kit/supabase/hooks/use-user';
|
||||
@@ -65,30 +63,26 @@ function SuspendedPersonalAccountDropdown(props: { user: User | null }) {
|
||||
|
||||
function AuthButtons() {
|
||||
return (
|
||||
<div className={'flex space-x-2'}>
|
||||
<div className={'hidden space-x-0.5 md:flex'}>
|
||||
<div className={'flex gap-x-2.5'}>
|
||||
<div className={'hidden md:flex'}>
|
||||
<If condition={features.enableThemeToggle}>
|
||||
<ModeToggle />
|
||||
</If>
|
||||
</div>
|
||||
|
||||
<Button asChild variant={'ghost'}>
|
||||
<div className={'flex gap-x-2.5'}>
|
||||
<Button className={'hidden md:block'} asChild variant={'ghost'}>
|
||||
<Link href={pathsConfig.auth.signIn}>
|
||||
<Trans i18nKey={'auth:signIn'} />
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
<Button asChild className="group" variant={'default'}>
|
||||
<Link href={pathsConfig.auth.signUp}>
|
||||
<Trans i18nKey={'auth:signUp'} />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button asChild className="group" variant={'default'}>
|
||||
<Link href={pathsConfig.auth.signUp}>
|
||||
<Trans i18nKey={'auth:signUp'} />
|
||||
|
||||
<ArrowRightIcon
|
||||
className={
|
||||
'ml-1 hidden h-4 w-4 transition-transform duration-500 group-hover:translate-x-1 lg:block'
|
||||
}
|
||||
/>
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ export function SiteNavigation() {
|
||||
return (
|
||||
<>
|
||||
<div className={'hidden items-center justify-center md:flex'}>
|
||||
<NavigationMenu className={'px-4 py-2'}>
|
||||
<NavigationMenuList className={'space-x-5'}>
|
||||
<NavigationMenu>
|
||||
<NavigationMenuList className={'gap-x-2.5'}>
|
||||
{NavItems}
|
||||
</NavigationMenuList>
|
||||
</NavigationMenu>
|
||||
|
||||
@@ -15,12 +15,10 @@ export function SitePageHeader({
|
||||
|
||||
return (
|
||||
<div className={cn('border-b py-8 xl:py-10 2xl:py-12', className)}>
|
||||
<div
|
||||
className={cn('flex flex-col space-y-2 lg:space-y-4', containerClass)}
|
||||
>
|
||||
<div className={cn('flex flex-col gap-y-3 lg:gap-y-4', containerClass)}>
|
||||
<h1
|
||||
className={
|
||||
'font-heading text-3xl font-medium tracking-tighter dark:text-white xl:text-5xl'
|
||||
'font-heading text-3xl font-medium tracking-tighter xl:text-5xl dark:text-white'
|
||||
}
|
||||
>
|
||||
{title}
|
||||
@@ -28,7 +26,7 @@ export function SitePageHeader({
|
||||
|
||||
<h2
|
||||
className={
|
||||
'text-lg tracking-tight text-muted-foreground 2xl:text-2xl'
|
||||
'text-muted-foreground text-lg tracking-tight 2xl:text-2xl'
|
||||
}
|
||||
>
|
||||
{subtitle}
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
.HTML {
|
||||
@apply text-secondary-foreground;
|
||||
}
|
||||
|
||||
.HTML h1 {
|
||||
@apply mt-14 text-4xl font-semibold font-heading tracking-tight;
|
||||
}
|
||||
|
||||
.HTML h2 {
|
||||
@apply mb-6 mt-12 font-semibold text-2xl font-heading tracking-tight;
|
||||
}
|
||||
|
||||
.HTML h3 {
|
||||
@apply mt-12 text-xl font-semibold font-heading tracking-tight;
|
||||
}
|
||||
|
||||
.HTML h4 {
|
||||
@apply mt-8 text-lg font-medium tracking-tight;
|
||||
}
|
||||
|
||||
.HTML h5 {
|
||||
@apply mt-6 text-base font-medium tracking-tight;
|
||||
}
|
||||
|
||||
.HTML h6 {
|
||||
@apply mt-2 text-sm font-normal tracking-tight;
|
||||
}
|
||||
|
||||
/**
|
||||
Tailwind "dark" variants do not work with CSS Modules
|
||||
We work it around using :global(.dark)
|
||||
For more info: https://github.com/tailwindlabs/tailwindcss/issues/3258#issuecomment-770215347
|
||||
*/
|
||||
:global(.dark) .HTML h1,
|
||||
:global(.dark) .HTML h2,
|
||||
:global(.dark) .HTML h3,
|
||||
:global(.dark) .HTML h4,
|
||||
:global(.dark) .HTML h5,
|
||||
:global(.dark) .HTML h6 {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.HTML p {
|
||||
@apply mb-6 mt-4 text-base leading-7 text-muted-foreground;
|
||||
}
|
||||
|
||||
.HTML li {
|
||||
@apply relative my-1.5 text-base leading-7 text-muted-foreground;
|
||||
}
|
||||
|
||||
.HTML ul > li:before {
|
||||
content: '-';
|
||||
|
||||
@apply mr-2;
|
||||
}
|
||||
|
||||
.HTML ol > li:before {
|
||||
@apply inline-flex font-medium text-muted-foreground;
|
||||
|
||||
content: counters(counts, '.') '. ';
|
||||
font-feature-settings: 'tnum';
|
||||
}
|
||||
|
||||
.HTML b,
|
||||
.HTML strong {
|
||||
@apply font-semibold text-secondary-foreground;
|
||||
}
|
||||
|
||||
:global(.dark) .HTML b,
|
||||
:global(.dark) .HTML strong {
|
||||
@apply text-white;
|
||||
}
|
||||
|
||||
.HTML img,
|
||||
.HTML video {
|
||||
@apply rounded-md;
|
||||
}
|
||||
|
||||
.HTML ul,
|
||||
.HTML ol {
|
||||
@apply pl-1;
|
||||
}
|
||||
|
||||
.HTML ol > li {
|
||||
counter-increment: counts;
|
||||
}
|
||||
|
||||
.HTML ol > li:before {
|
||||
@apply mr-2 inline-flex font-semibold;
|
||||
|
||||
content: counters(counts, '.') '. ';
|
||||
font-feature-settings: 'tnum';
|
||||
}
|
||||
|
||||
.HTML p > code, .HTML li > code {
|
||||
@apply p-0.5 text-sm font-semibold bg-muted/50 border font-mono text-secondary-foreground;
|
||||
}
|
||||
|
||||
.HTML blockquote {
|
||||
@apply my-4 border-l-8 border border-primary px-6 py-4 text-lg font-medium text-muted-foreground;
|
||||
}
|
||||
|
||||
.HTML a {
|
||||
@apply border-b-black border-b hover:border-b-2 pb-0.5 text-secondary-foreground font-semibold;
|
||||
}
|
||||
|
||||
:global(.dark) .HTML a {
|
||||
@apply border-yellow-300;
|
||||
}
|
||||
|
||||
.HTML hr {
|
||||
@apply mt-8 mb-6 border-border;
|
||||
}
|
||||
|
||||
.HTML [role='alert'] {
|
||||
@apply py-4 m-0 my-8;
|
||||
}
|
||||
|
||||
.HTML [role='alert'] * {
|
||||
color: inherit;
|
||||
@apply m-0 p-0 text-sm;
|
||||
}
|
||||
|
||||
.HTML [role='alert'] h5 {
|
||||
color: inherit;
|
||||
}
|
||||
@@ -25,7 +25,7 @@ export function PostPreview({
|
||||
const slug = `/blog/${post.slug}`;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col space-y-4 rounded-lg transition-shadow duration-500">
|
||||
<div className="transition-shadow-sm flex flex-col gap-y-4 rounded-lg duration-500">
|
||||
<If condition={image}>
|
||||
{(imageUrl) => (
|
||||
<div className="relative mb-2 w-full" style={{ height }}>
|
||||
@@ -42,13 +42,13 @@ export function PostPreview({
|
||||
|
||||
<div className={'flex flex-col space-y-4 px-1'}>
|
||||
<div className={'flex flex-col space-y-2'}>
|
||||
<h2 className="text-2xl font-semibold leading-snug tracking-tight">
|
||||
<h2 className="text-xl leading-snug font-semibold tracking-tight">
|
||||
<Link href={slug} className="hover:underline">
|
||||
{title}
|
||||
</Link>
|
||||
</h2>
|
||||
|
||||
<div className="flex flex-row items-center space-x-2 text-sm">
|
||||
<div className="flex flex-row items-center gap-x-3 text-sm">
|
||||
<div className="text-muted-foreground">
|
||||
<DateFormatter dateString={publishedAt} />
|
||||
</div>
|
||||
@@ -56,7 +56,7 @@ export function PostPreview({
|
||||
</div>
|
||||
|
||||
<p
|
||||
className="mb-4 text-sm leading-relaxed text-muted-foreground"
|
||||
className="text-muted-foreground mb-4 text-sm leading-relaxed"
|
||||
dangerouslySetInnerHTML={{ __html: description ?? '' }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Cms } from '@kit/cms';
|
||||
import { ContentRenderer } from '@kit/cms';
|
||||
|
||||
import styles from './html-renderer.module.css';
|
||||
import { PostHeader } from './post-header';
|
||||
|
||||
export function Post({
|
||||
@@ -16,7 +15,7 @@ export function Post({
|
||||
<PostHeader post={post} />
|
||||
|
||||
<div className={'mx-auto flex max-w-3xl flex-col space-y-6 py-8'}>
|
||||
<article className={styles.HTML}>
|
||||
<article className="markdoc">
|
||||
<ContentRenderer content={content} />
|
||||
</article>
|
||||
</div>
|
||||
|
||||
@@ -9,8 +9,6 @@ import { cn } from '@kit/ui/utils';
|
||||
|
||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||
|
||||
// styles
|
||||
import styles from '../../blog/_components/html-renderer.module.css';
|
||||
// local imports
|
||||
import { DocsCards } from '../_components/docs-cards';
|
||||
import { DocsTableOfContents } from '../_components/docs-table-of-contents';
|
||||
@@ -61,20 +59,18 @@ async function DocumentationPage({ params }: DocumentationPageProps) {
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={'flex flex-1 flex-col space-y-4 overflow-y-hidden'}>
|
||||
<div className={'flex flex-1 flex-col gap-y-4 overflow-y-hidden py-5'}>
|
||||
<div className={'flex overflow-y-hidden'}>
|
||||
<article
|
||||
className={cn(styles.HTML, 'container space-y-12 overflow-y-auto')}
|
||||
>
|
||||
<section className={'flex flex-col space-y-4 pt-6'}>
|
||||
<h1 className={'!my-0'}>{page.title}</h1>
|
||||
<article className={cn('gap-y-12 overflow-y-auto px-6')}>
|
||||
<section className={'flex flex-col gap-y-2.5'}>
|
||||
<h1 className={'text-3xl font-semibold text-foreground'}>{page.title}</h1>
|
||||
|
||||
<h2 className={'!mb-0 !font-normal !text-muted-foreground'}>
|
||||
{description}
|
||||
</h2>
|
||||
<h2 className={'text-muted-foreground text-lg'}>{description}</h2>
|
||||
</section>
|
||||
|
||||
<ContentRenderer content={page.content} />
|
||||
<div className={'markdoc'}>
|
||||
<ContentRenderer content={page.content} />
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<DocsTableOfContents data={headings} />
|
||||
|
||||
@@ -17,14 +17,14 @@ export function DocsCard({
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div
|
||||
className={`flex grow flex-col space-y-2.5 border bg-background p-6 ${link ? 'rounded-t-2xl border-b-0' : 'rounded-2xl'}`}
|
||||
className={`bg-background flex grow flex-col gap-y-2 border p-6 ${link ? 'rounded-t-lg border-b-0' : 'rounded-lg'}`}
|
||||
>
|
||||
<h3 className="mt-0 text-lg font-semibold hover:underline dark:text-white">
|
||||
<Link href={link.url}>{title}</Link>
|
||||
</h3>
|
||||
|
||||
{subtitle && (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<div className="text-muted-foreground text-sm">
|
||||
<p dangerouslySetInnerHTML={{ __html: subtitle }}></p>
|
||||
</div>
|
||||
)}
|
||||
@@ -33,17 +33,19 @@ export function DocsCard({
|
||||
</div>
|
||||
|
||||
{link && (
|
||||
<div className="rounded-b-2xl border bg-muted p-6 py-4 dark:bg-background">
|
||||
<span className={'flex items-center space-x-2'}>
|
||||
<Link
|
||||
className={'text-sm font-medium hover:underline'}
|
||||
href={link.url}
|
||||
>
|
||||
<div className="bg-muted/50 rounded-b-lg border p-6 py-4">
|
||||
<Link
|
||||
className={
|
||||
'flex items-center space-x-2 text-sm font-medium hover:underline'
|
||||
}
|
||||
href={link.url}
|
||||
>
|
||||
<span>
|
||||
{link.label ?? <Trans i18nKey={'marketing:readMore'} />}
|
||||
</Link>
|
||||
</span>
|
||||
|
||||
<ChevronRight className={'h-4'} />
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -22,8 +22,8 @@ export function DocsNavLink({
|
||||
<SidebarMenuButton
|
||||
asChild
|
||||
isActive={isCurrent}
|
||||
className={cn('border-l-3 transition-background !font-normal', {
|
||||
'font-bold text-secondary-foreground': isCurrent,
|
||||
className={cn('transition-background font-normal!', {
|
||||
'text-secondary-foreground font-bold': isCurrent,
|
||||
})}
|
||||
>
|
||||
<Link href={url}>
|
||||
|
||||
@@ -116,7 +116,7 @@ export function DocsNavigation({
|
||||
<>
|
||||
<Sidebar
|
||||
variant={'ghost'}
|
||||
className={'z-1 sticky max-h-full overflow-y-auto'}
|
||||
className={'sticky z-1 mt-4 max-h-full overflow-y-auto'}
|
||||
>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
|
||||
@@ -13,7 +13,7 @@ export function DocsTableOfContents(props: { data: NavItem[] }) {
|
||||
const navData = props.data;
|
||||
|
||||
return (
|
||||
<div className="sticky inset-y-0 hidden h-svh max-h-full min-w-[14em] border-l bg-background p-4 lg:block">
|
||||
<div className="bg-background sticky inset-y-0 hidden h-svh max-h-full min-w-[14em] border-l p-4 lg:block">
|
||||
<ol
|
||||
role="list"
|
||||
className="relative text-sm text-gray-600 dark:text-gray-400"
|
||||
@@ -22,7 +22,7 @@ export function DocsTableOfContents(props: { data: NavItem[] }) {
|
||||
<li key={item.href} className="group/item relative mt-3 first:mt-0">
|
||||
<a
|
||||
href={item.href}
|
||||
className="block transition-colors hover:text-gray-950 dark:hover:text-white [&_*]:[font:inherit]"
|
||||
className="block transition-colors **:[font:inherit] hover:text-gray-950 dark:hover:text-white"
|
||||
>
|
||||
{item.text}
|
||||
</a>
|
||||
@@ -35,7 +35,7 @@ export function DocsTableOfContents(props: { data: NavItem[] }) {
|
||||
>
|
||||
<Link
|
||||
href={child.href}
|
||||
className="block transition-colors hover:text-gray-950 dark:hover:text-white [&_*]:[font:inherit]"
|
||||
className="block transition-colors **:[font:inherit] hover:text-gray-950 dark:hover:text-white"
|
||||
>
|
||||
{child.text}
|
||||
</Link>
|
||||
|
||||
@@ -14,7 +14,7 @@ async function DocsLayout({ children }: React.PropsWithChildren) {
|
||||
|
||||
return (
|
||||
<SidebarProvider
|
||||
style={{ '--sidebar-width': '20em' } as React.CSSProperties}
|
||||
style={{ '--sidebar-width': '18em' } as React.CSSProperties}
|
||||
className={'h-[calc(100vh-72px)] overflow-y-hidden lg:container'}
|
||||
>
|
||||
<DocsNavigation pages={tree} />
|
||||
|
||||
@@ -21,7 +21,7 @@ async function DocsPage() {
|
||||
const cards = items.filter((item) => !item.parentId);
|
||||
|
||||
return (
|
||||
<div className={'flex flex-col space-y-6 xl:space-y-10'}>
|
||||
<div className={'flex flex-col gap-y-6 xl:gap-y-10'}>
|
||||
<SitePageHeader
|
||||
title={t('marketing:documentation')}
|
||||
subtitle={t('marketing:documentationSubtitle')}
|
||||
|
||||
@@ -135,7 +135,7 @@ function FaqItem({
|
||||
</div>
|
||||
</summary>
|
||||
|
||||
<div className={'flex flex-col space-y-2 py-1 text-muted-foreground'}>
|
||||
<div className={'text-muted-foreground flex flex-col gap-y-3 py-1'}>
|
||||
<Trans i18nKey={item.answer} defaults={item.answer} />
|
||||
</div>
|
||||
</details>
|
||||
|
||||
@@ -2,7 +2,6 @@ import { getSupabaseServerClient } from '@kit/supabase/server-client';
|
||||
|
||||
import { SiteFooter } from '~/(marketing)/_components/site-footer';
|
||||
import { SiteHeader } from '~/(marketing)/_components/site-header';
|
||||
import { BackgroundHue } from '~/components/background-hue';
|
||||
import { withI18n } from '~/lib/i18n/with-i18n';
|
||||
|
||||
async function SiteLayout(props: React.PropsWithChildren) {
|
||||
@@ -18,7 +17,6 @@ async function SiteLayout(props: React.PropsWithChildren) {
|
||||
|
||||
{props.children}
|
||||
|
||||
<BackgroundHue />
|
||||
<SiteFooter />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
FeatureShowcaseIconContainer,
|
||||
Hero,
|
||||
Pill,
|
||||
PillActionButton,
|
||||
SecondaryHero,
|
||||
} from '@kit/ui/marketing';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
@@ -27,7 +28,12 @@ function Home() {
|
||||
<Hero
|
||||
pill={
|
||||
<Pill label={'New'}>
|
||||
<span>The leading SaaS Starter Kit for ambitious developers</span>
|
||||
<span>The SaaS Starter Kit for ambitious developers</span>
|
||||
<PillActionButton asChild>
|
||||
<Link href={'/auth/sign-up'}>
|
||||
<ArrowRightIcon className={'h-4 w-4'} />
|
||||
</Link>
|
||||
</PillActionButton>
|
||||
</Pill>
|
||||
}
|
||||
title={
|
||||
@@ -47,7 +53,7 @@ function Home() {
|
||||
<Image
|
||||
priority
|
||||
className={
|
||||
'rounded-2xl border border-gray-200 dark:border-primary/10'
|
||||
'dark:border-primary/10 rounded-xl border border-gray-200'
|
||||
}
|
||||
width={3558}
|
||||
height={2222}
|
||||
@@ -65,11 +71,11 @@ function Home() {
|
||||
<FeatureShowcase
|
||||
heading={
|
||||
<>
|
||||
<b className="font-semibold dark:text-white">
|
||||
<b className="font-medium tracking-tighter dark:text-white">
|
||||
The ultimate SaaS Starter Kit
|
||||
</b>
|
||||
.{' '}
|
||||
<span className="font-normal text-muted-foreground">
|
||||
<span className="text-muted-foreground font-normal tracking-tighter">
|
||||
Unleash your creativity and build your SaaS faster than ever
|
||||
with Makerkit.
|
||||
</span>
|
||||
@@ -84,64 +90,36 @@ function Home() {
|
||||
>
|
||||
<FeatureGrid>
|
||||
<FeatureCard
|
||||
className={'relative col-span-2 overflow-hidden lg:h-96'}
|
||||
className={'relative col-span-1 overflow-hidden'}
|
||||
label={'Beautiful Dashboard'}
|
||||
description={`Makerkit provides a beautiful dashboard to manage your SaaS business.`}
|
||||
>
|
||||
<Image
|
||||
className="absolute right-0 top-0 hidden h-full w-full rounded-tl-2xl border border-border lg:top-36 lg:flex lg:h-auto lg:w-10/12"
|
||||
src={'/images/dashboard-header.webp'}
|
||||
width={'2061'}
|
||||
height={'800'}
|
||||
alt={'Dashboard Header'}
|
||||
/>
|
||||
</FeatureCard>
|
||||
></FeatureCard>
|
||||
|
||||
<FeatureCard
|
||||
className={
|
||||
'relative col-span-2 w-full overflow-hidden lg:col-span-1'
|
||||
'relative col-span-1 w-full overflow-hidden lg:col-span-1'
|
||||
}
|
||||
label={'Authentication'}
|
||||
description={`Makerkit provides a variety of providers to allow your users to sign in.`}
|
||||
>
|
||||
<Image
|
||||
className="absolute left-16 top-32 hidden h-auto w-8/12 rounded-l-2xl lg:flex"
|
||||
src={'/images/sign-in.webp'}
|
||||
width={'1760'}
|
||||
height={'1680'}
|
||||
alt={'Sign In'}
|
||||
/>
|
||||
</FeatureCard>
|
||||
></FeatureCard>
|
||||
|
||||
<FeatureCard
|
||||
className={
|
||||
'relative col-span-2 overflow-hidden lg:col-span-1 lg:h-96'
|
||||
}
|
||||
className={'relative col-span-2 overflow-hidden lg:col-span-1'}
|
||||
label={'Multi Tenancy'}
|
||||
description={`Multi tenant memberships for your SaaS business.`}
|
||||
>
|
||||
<Image
|
||||
className="absolute right-0 top-0 hidden h-full w-full rounded-tl-2xl border lg:top-28 lg:flex lg:h-auto lg:w-8/12"
|
||||
src={'/images/multi-tenancy.webp'}
|
||||
width={'2061'}
|
||||
height={'800'}
|
||||
alt={'Multi Tenancy'}
|
||||
/>
|
||||
</FeatureCard>
|
||||
/>
|
||||
|
||||
<FeatureCard
|
||||
className={'relative col-span-2 overflow-hidden lg:h-96'}
|
||||
className={'relative col-span-1 overflow-hidden lg:col-span-2'}
|
||||
label={'Billing'}
|
||||
description={`Makerkit supports multiple payment gateways to charge your customers.`}
|
||||
>
|
||||
<Image
|
||||
className="absolute right-0 top-0 hidden h-full w-full rounded-tl-2xl border border-border lg:top-36 lg:flex lg:h-auto lg:w-11/12"
|
||||
src={'/images/billing.webp'}
|
||||
width={'2061'}
|
||||
height={'800'}
|
||||
alt={'Billing'}
|
||||
/>
|
||||
</FeatureCard>
|
||||
/>
|
||||
|
||||
<FeatureCard
|
||||
className={'relative col-span-1 overflow-hidden'}
|
||||
label={'Plugins'}
|
||||
description={`Extend your SaaS with plugins that you can install using the CLI.`}
|
||||
/>
|
||||
</FeatureGrid>
|
||||
</FeatureShowcase>
|
||||
</div>
|
||||
@@ -188,8 +166,8 @@ function MainCallToActionButton() {
|
||||
|
||||
<ArrowRightIcon
|
||||
className={
|
||||
'h-4 animate-in fade-in slide-in-from-left-8' +
|
||||
' delay-1000 duration-1000 zoom-in fill-mode-both'
|
||||
'animate-in fade-in slide-in-from-left-8 h-4' +
|
||||
' zoom-in fill-mode-both delay-1000 duration-1000'
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import { AuthLayoutShell } from '@kit/auth/shared';
|
||||
|
||||
import { AppLogo } from '~/components/app-logo';
|
||||
import { BackgroundHue } from '~/components/background-hue';
|
||||
|
||||
function AuthLayout({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<AuthLayoutShell Logo={AppLogo}>
|
||||
{children}
|
||||
|
||||
<BackgroundHue />
|
||||
</AuthLayoutShell>
|
||||
);
|
||||
return <AuthLayoutShell Logo={AppLogo}>{children}</AuthLayoutShell>;
|
||||
}
|
||||
|
||||
export default AuthLayout;
|
||||
|
||||
@@ -23,9 +23,15 @@ const redirectPath = `${callback}?next=${passwordUpdate}`;
|
||||
function PasswordResetPage() {
|
||||
return (
|
||||
<>
|
||||
<Heading level={5} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:passwordResetLabel'} />
|
||||
</Heading>
|
||||
<div className={'flex flex-col items-center gap-1'}>
|
||||
<Heading level={4} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:passwordResetLabel'} />
|
||||
</Heading>
|
||||
|
||||
<p className={'text-muted-foreground text-sm'}>
|
||||
<Trans i18nKey={'auth:passwordResetSubheading'} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<PasswordResetRequestContainer redirectPath={redirectPath} />
|
||||
|
||||
@@ -39,9 +39,15 @@ async function SignInPage({ searchParams }: SignInPageProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Heading level={5} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:signInHeading'} />
|
||||
</Heading>
|
||||
<div className={'flex flex-col items-center gap-1'}>
|
||||
<Heading level={4} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:signInHeading'} />
|
||||
</Heading>
|
||||
|
||||
<p className={'text-muted-foreground text-sm'}>
|
||||
<Trans i18nKey={'auth:signInSubheading'} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<SignInMethodsContainer
|
||||
inviteToken={inviteToken}
|
||||
|
||||
@@ -38,9 +38,15 @@ async function SignUpPage({ searchParams }: Props) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Heading level={5} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:signUpHeading'} />
|
||||
</Heading>
|
||||
<div className={'flex flex-col items-center gap-1'}>
|
||||
<Heading level={4} className={'tracking-tight'}>
|
||||
<Trans i18nKey={'auth:signUpHeading'} />
|
||||
</Heading>
|
||||
|
||||
<p className={'text-muted-foreground text-sm'}>
|
||||
<Trans i18nKey={'auth:signUpSubheading'} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<SignUpMethodsContainer
|
||||
providers={authConfig.providers}
|
||||
@@ -49,7 +55,7 @@ async function SignUpPage({ searchParams }: Props) {
|
||||
paths={paths}
|
||||
/>
|
||||
|
||||
<div className={'justify-centers flex'}>
|
||||
<div className={'flex justify-center'}>
|
||||
<Button asChild variant={'link'} size={'sm'}>
|
||||
<Link href={signInPath}>
|
||||
<Trans i18nKey={'auth:alreadyHaveAnAccount'} />
|
||||
|
||||
@@ -39,7 +39,7 @@ const ErrorPage = ({
|
||||
<div className={'flex flex-col items-center space-y-8'}>
|
||||
<div
|
||||
className={
|
||||
'flex max-w-xl flex-col items-center space-y-1 text-center'
|
||||
'flex max-w-xl flex-col items-center gap-y-2 text-center'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
@@ -48,7 +48,7 @@ const ErrorPage = ({
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
<p className={'text-lg text-muted-foreground'}>
|
||||
<p className={'text-muted-foreground text-lg'}>
|
||||
<Trans i18nKey={'common:genericErrorSubHeading'} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ const GlobalErrorPage = ({
|
||||
<div className={'flex flex-col items-center space-y-8'}>
|
||||
<div
|
||||
className={
|
||||
'flex max-w-xl flex-col items-center space-y-1 text-center'
|
||||
'flex max-w-xl flex-col items-center gap-y-2 text-center'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
@@ -50,7 +50,7 @@ const GlobalErrorPage = ({
|
||||
</Heading>
|
||||
</div>
|
||||
|
||||
<p className={'text-lg text-muted-foreground'}>
|
||||
<p className={'text-muted-foreground text-lg'}>
|
||||
<Trans i18nKey={'common:genericErrorSubHeading'} />
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,7 @@ export function HomeSidebar(props: HomeSidebarProps) {
|
||||
return (
|
||||
<Sidebar>
|
||||
<SidebarHeader className={'h-16 justify-center'}>
|
||||
<div className={'flex items-center justify-between space-x-2'}>
|
||||
<div className={'flex items-center justify-between gap-x-3'}>
|
||||
<If
|
||||
condition={featuresFlagConfig.enableTeamAccounts}
|
||||
fallback={
|
||||
|
||||
@@ -47,7 +47,7 @@ export default function DashboardDemo() {
|
||||
return (
|
||||
<div
|
||||
className={
|
||||
'flex flex-col space-y-4 pb-36 duration-500 animate-in fade-in'
|
||||
'animate-in fade-in flex flex-col space-y-4 pb-36 duration-500'
|
||||
}
|
||||
>
|
||||
<div
|
||||
@@ -189,11 +189,11 @@ function Chart(
|
||||
const chartConfig = {
|
||||
desktop: {
|
||||
label: 'Desktop',
|
||||
color: 'hsl(var(--chart-1))',
|
||||
color: 'var(--chart-1)',
|
||||
},
|
||||
mobile: {
|
||||
label: 'Mobile',
|
||||
color: 'hsl(var(--chart-2))',
|
||||
color: 'var(--chart-2)',
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
@@ -423,7 +423,7 @@ function CustomersTable() {
|
||||
<TableRow key={customer.name}>
|
||||
<TableCell className={'flex flex-col'}>
|
||||
<span>{customer.name}</span>
|
||||
<span className={'text-sm text-muted-foreground'}>
|
||||
<span className={'text-muted-foreground text-sm'}>
|
||||
{customer.email}
|
||||
</span>
|
||||
</TableCell>
|
||||
@@ -482,7 +482,7 @@ function Trend(
|
||||
case 'up':
|
||||
return <ArrowUp className={'h-3 w-3 text-green-500'} />;
|
||||
case 'down':
|
||||
return <ArrowDown className={'h-3 w-3 text-destructive'} />;
|
||||
return <ArrowDown className={'text-destructive h-3 w-3'} />;
|
||||
case 'stale':
|
||||
return <Menu className={'h-3 w-3 text-orange-500'} />;
|
||||
}
|
||||
@@ -604,11 +604,11 @@ export function VisitorsChart() {
|
||||
},
|
||||
desktop: {
|
||||
label: 'Desktop',
|
||||
color: 'hsl(var(--chart-1))',
|
||||
color: 'var(--chart-1)',
|
||||
},
|
||||
mobile: {
|
||||
label: 'Mobile',
|
||||
color: 'hsl(var(--chart-2))',
|
||||
color: 'var(--chart-2)',
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
@@ -685,10 +685,10 @@ export function VisitorsChart() {
|
||||
<CardFooter>
|
||||
<div className="flex w-full items-start gap-2 text-sm">
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center gap-2 font-medium leading-none">
|
||||
<div className="flex items-center gap-2 leading-none font-medium">
|
||||
Trending up by 5.2% this month <TrendingUp className="h-4 w-4" />
|
||||
</div>
|
||||
<div className="flex items-center gap-2 leading-none text-muted-foreground">
|
||||
<div className="text-muted-foreground flex items-center gap-2 leading-none">
|
||||
January - June 2024
|
||||
</div>
|
||||
</div>
|
||||
@@ -802,11 +802,11 @@ export function PageViewsChart() {
|
||||
},
|
||||
desktop: {
|
||||
label: 'Desktop',
|
||||
color: 'hsl(var(--chart-1))',
|
||||
color: 'var(--chart-1)',
|
||||
},
|
||||
mobile: {
|
||||
label: 'Mobile',
|
||||
color: 'hsl(var(--chart-2))',
|
||||
color: 'var(--chart-2)',
|
||||
},
|
||||
} satisfies ChartConfig;
|
||||
|
||||
@@ -836,13 +836,13 @@ export function PageViewsChart() {
|
||||
<button
|
||||
key={chart}
|
||||
data-active={activeChart === chart}
|
||||
className="relative z-30 flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l data-[active=true]:bg-muted/50 sm:border-l sm:border-t-0 sm:px-8 sm:py-6"
|
||||
className="data-[active=true]:bg-muted/50 relative z-30 flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l sm:border-t-0 sm:border-l sm:px-8 sm:py-6"
|
||||
onClick={() => setActiveChart(chart)}
|
||||
>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
<span className="text-muted-foreground text-xs">
|
||||
{chartConfig[chart].label}
|
||||
</span>
|
||||
<span className="text-lg font-bold leading-none sm:text-3xl">
|
||||
<span className="text-lg leading-none font-bold sm:text-3xl">
|
||||
{total[key as keyof typeof total].toLocaleString()}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
@@ -98,7 +98,7 @@ function DropdownLink(
|
||||
<DropdownMenuItem asChild>
|
||||
<Link
|
||||
href={props.path}
|
||||
className={'flex h-12 w-full items-center space-x-2 px-3'}
|
||||
className={'flex h-12 w-full items-center gap-x-3 px-3'}
|
||||
>
|
||||
{props.Icon}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user