Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions apps/web/vibes/soul/docs/modal.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ import { useState } from 'react';
import { Modal } from '@/vibes/soul/primitives/modal';

function Usage() {
const [isOpen, setIsOpen] = useState(true);
const [isOpen, setIsOpen] = useState(true);

return (
<Modal
isOpen={isOpen}
setOpen={setIsOpen}
title="Example modal"
trigger={<button>Open Modal</button>}
>
<p>Put your content here!</p>
</Modal>
<Modal
isOpen={isOpen}
setOpen={setIsOpen}
title="Example modal"
trigger={<button>Open Modal</button>}
>
<p>Put your content here!</p>
</Modal>
);
}
`}
Expand All @@ -40,13 +40,16 @@ This component uses the Dialog component from Radix UI. Refer to the [Radix UI D

### ModalProps

| Prop | Type | Default |
| ----------- | ------------------------- | ------- |
| `isOpen*` | `boolean` | |
| `setOpen*` | `(open: boolean) => void` | |
| `title*` | `string` | |
| `trigger*` | `ReactNode` | |
| `children*` | `ReactNode` | |
| Prop | Type | Default |
| ------------ | ------------------------- | ------- |
| `className` | `string` | |
| `isOpen` | `boolean` | |
| `setOpen` | `(open: boolean) => void` | |
| `required` | `boolean` | `false` |
| `hideHeader` | `boolean` | `false` |
| `title*` | `string` | |
| `trigger*` | `ReactNode` | |
| `children*` | `ReactNode` | |

### CSS Variables

Expand Down
7 changes: 4 additions & 3 deletions apps/web/vibes/soul/examples/form/checkbox-group/index.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
'use client';

import { CheckboxGroup } from '@/vibes/soul/form/checkbox-group';
import { useState } from 'react';

import { CheckboxGroup } from '@/vibes/soul/form/checkbox-group';

export default function Preview() {
const [value, setValue] = useState<string[]>([]);

return (
<div className="p-10">
<CheckboxGroup
label="Options"
onValueChange={setValue}
options={[
{ label: 'Option 1', value: 'option-1' },
{ label: 'Option 2', value: 'option-2' },
{ label: 'Option 3', value: 'option-3' },
]}
label="Options"
value={value}
onValueChange={setValue}
/>
</div>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/form/number-input/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { NumberInput } from '@/vibes/soul/form/number-input';
export default function Preview() {
return (
<div className="p-10">
<NumberInput errors={['Please select a quantity.']} min={0} max={5} label="Quantity" />
<NumberInput errors={['Please select a quantity.']} label="Quantity" max={5} min={0} />
</div>
);
}
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/form/select/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export default function Preview() {
return (
<div className="p-10">
<Select
name="options"
label="Option"
name="options"
options={[
{ value: 'option-1', label: 'Option 1' },
{ value: 'option-2', label: 'Option 2' },
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/blog/post/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import { posts } from '@/vibes/soul/examples/sections/blog-post-list/electric';
Expand All @@ -8,6 +7,7 @@ import {
copyright,
footerLinks,
} from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { BlogPost, BlogPostContent } from '@/vibes/soul/sections/blog-post-content';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/blog/post/luxury.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/luxury';
import { posts } from '@/vibes/soul/examples/sections/blog-post-list/luxury';
Expand All @@ -8,6 +7,7 @@ import {
copyright,
footerLinks,
} from '@/vibes/soul/examples/sections/footer/luxury';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { BlogPost, BlogPostContent } from '@/vibes/soul/sections/blog-post-content';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/blog/post/warm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/warm';
import { posts } from '@/vibes/soul/examples/sections/blog-post-list/warm';
Expand All @@ -8,6 +7,7 @@ import {
copyright,
footerLinks,
} from '@/vibes/soul/examples/sections/footer/warm';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { BlogPost, BlogPostContent } from '@/vibes/soul/sections/blog-post-content';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/cart/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getLineItems } from '@/vibes/soul/data/line-items';
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import {
Expand All @@ -9,6 +8,7 @@ import {
lineItemAction,
} from '@/vibes/soul/examples/sections/cart/actions';
import { copyright, footerLinks } from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { Cart } from '@/vibes/soul/sections/cart';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/cart/luxury.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getLineItems } from '@/vibes/soul/data/line-items';
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import {
Expand All @@ -9,6 +8,7 @@ import {
lineItemAction,
} from '@/vibes/soul/examples/sections/cart/actions';
import { copyright, footerLinks } from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { Cart } from '@/vibes/soul/sections/cart';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/cart/warm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { getLineItems } from '@/vibes/soul/data/line-items';
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import {
Expand All @@ -9,6 +8,7 @@ import {
lineItemAction,
} from '@/vibes/soul/examples/sections/cart/actions';
import { copyright, footerLinks } from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { Cart } from '@/vibes/soul/sections/cart';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/error/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import { copyright, footerLinks } from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { Error } from '@/vibes/soul/sections/error';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/not-found/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { locales } from '@/vibes/soul/data/locales';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { logo, navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import { copyright, footerLinks } from '@/vibes/soul/examples/sections/footer/electric';
import { action } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
import { type Product } from '@/vibes/soul/primitives/product-card';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/product/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getProducts } from '@/vibes/soul/data';
import { locales } from '@/vibes/soul/data/locales';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import { footerLinks, logo } from '@/vibes/soul/examples/sections/footer/electric';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { action, fields } from '@/vibes/soul/examples/sections/product-detail/action';
import { product } from '@/vibes/soul/examples/sections/product-detail/electric';
import { reviews } from '@/vibes/soul/examples/sections/reviews';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/product/luxury.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getProducts } from '@/vibes/soul/data';
import { locales } from '@/vibes/soul/data/locales';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { navigationLinks } from '@/vibes/soul/examples/primitives/navigation/luxury';
import { footerLinks, logo } from '@/vibes/soul/examples/sections/footer/luxury';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { action, fields } from '@/vibes/soul/examples/sections/product-detail/action';
import { product } from '@/vibes/soul/examples/sections/product-detail/luxury';
import { reviews } from '@/vibes/soul/examples/sections/reviews';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/product/warm.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { getProducts } from '@/vibes/soul/data';
import { locales } from '@/vibes/soul/data/locales';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { navigationLinks } from '@/vibes/soul/examples/primitives/navigation/warm';
import { footerLinks, logo } from '@/vibes/soul/examples/sections/footer/warm';
import { action as subscribeAction } from '@/vibes/soul/examples/sections/inline-email-form/actions';
import { action, fields } from '@/vibes/soul/examples/sections/product-detail/action';
import { product } from '@/vibes/soul/examples/sections/product-detail/warm';
import { reviews } from '@/vibes/soul/examples/sections/reviews';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/products/electric.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getFilters, getProducts, getSortOptions } from '@/vibes/soul/data';
import { locales } from '@/vibes/soul/data/locales';
import { breadcrumbs } from '@/vibes/soul/examples/sections/breadcrumbs/electric';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { navigationLinks } from '@/vibes/soul/examples/primitives/navigation/electric';
import { breadcrumbs } from '@/vibes/soul/examples/sections/breadcrumbs/electric';
import { copyright, footerLinks, logo } from '@/vibes/soul/examples/sections/footer/electric';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
Expand Down
2 changes: 1 addition & 1 deletion apps/web/vibes/soul/examples/pages/products/luxury.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { getFilters, getProducts, getSortOptions } from '@/vibes/soul/data';
import { locales } from '@/vibes/soul/data/locales';
import { breadcrumbs } from '@/vibes/soul/examples/sections/breadcrumbs/luxury';
import { localeAction } from '@/vibes/soul/examples/primitives/navigation/actions';
import { navigationLinks } from '@/vibes/soul/examples/primitives/navigation/luxury';
import { breadcrumbs } from '@/vibes/soul/examples/sections/breadcrumbs/luxury';
import { copyright, footerLinks, logo } from '@/vibes/soul/examples/sections/footer/luxury';
import { Banner } from '@/vibes/soul/primitives/banner';
import { Navigation } from '@/vibes/soul/primitives/navigation';
Expand Down
1 change: 1 addition & 0 deletions apps/web/vibes/soul/examples/primitives/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Modal } from '@/vibes/soul/primitives/modal';

export default function Preview() {
const [isOpen, setIsOpen] = useState(true);

return (
<div>
<div className="bg-background p-8 @container">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { ForgotPassword } from '@/vibes/soul/sections/forgot-password';
import { schema } from '@/vibes/soul/sections/forgot-password/schema';
import { SubmissionResult } from '@conform-to/react';
import { parseWithZod } from '@conform-to/zod';

import { ForgotPassword } from '@/vibes/soul/sections/forgot-password';
import { schema } from '@/vibes/soul/sections/forgot-password/schema';

export default function Preview() {
return <ForgotPassword action={forgotPasswordAction} />;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ResetPassword } from '@/vibes/soul/sections/reset-password';

import { SubmissionResult } from '@conform-to/react';
import { parseWithZod } from '@conform-to/zod';

import { ResetPassword } from '@/vibes/soul/sections/reset-password';
import { schema } from '@/vibes/soul/sections/reset-password/schema';

export default function Preview() {
Expand Down
5 changes: 3 additions & 2 deletions apps/web/vibes/soul/examples/sections/sign-in/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { SignIn } from '@/vibes/soul/sections/sign-in';
import { schema } from '@/vibes/soul/sections/sign-in/schema';
import { SubmissionResult } from '@conform-to/react';
import { parseWithZod } from '@conform-to/zod';

import { SignIn } from '@/vibes/soul/sections/sign-in';
import { schema } from '@/vibes/soul/sections/sign-in/schema';

export default function Preview() {
return <SignIn action={signInAction} forgotPasswordHref="#" />;
}
Expand Down
64 changes: 52 additions & 12 deletions apps/web/vibes/soul/primitives/modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import * as Dialog from '@radix-ui/react-dialog';
import { clsx } from 'clsx';
import { ReactNode } from 'react';
import { XIcon } from 'lucide-react';

export interface ModalProps {
isOpen: boolean;
setOpen: (open: boolean) => void;
import { Button } from '@/vibes/soul/primitives/button';

export interface ModalProps extends React.PropsWithChildren {
className?: string;
isOpen?: boolean;
setOpen?: (open: boolean) => void;
/** Title should always be given for screen reader support. */
title: string;
trigger: ReactNode;
children: ReactNode;
/** Element to trigger the modal. Not required if the modal is being controlled manually. */
trigger?: React.ReactNode;
/** If `true`, a user will be required to make a choice by clicking on one of the provided actions. Defaults to `false`. */
required?: boolean;
/** Hides the header / top of the modal. */
hideHeader?: boolean;
}

/**
Expand All @@ -21,23 +29,55 @@ export interface ModalProps {
* }
* ```
*/
export const Modal = function Modal({ isOpen, setOpen, title, trigger, children }: ModalProps) {
export const Modal = ({
className = '',
isOpen,
setOpen,
title,
trigger,
children,
required = false,
hideHeader = false,
}: ModalProps) => {
return (
<Dialog.Root onOpenChange={setOpen} open={isOpen}>
<Dialog.Trigger asChild>{trigger}</Dialog.Trigger>
{trigger != null && <Dialog.Trigger asChild>{trigger}</Dialog.Trigger>}
<Dialog.Portal>
<Dialog.Overlay className="fixed inset-0 z-30 flex items-center justify-center bg-[var(--modal-overlay-background,hsl(var(--foreground)/50%))] @container">
<Dialog.Content
className={clsx(
'mx-3 my-10 max-h-[90%] max-w-3xl overflow-y-auto rounded-xl bg-[var(--modal-background,hsl(var(--background)))] px-3 py-5 @sm:px-6 @sm:py-8 @5xl:px-20 @5xl:py-10',
'mx-3 my-10 max-h-[90%] max-w-3xl overflow-y-auto rounded-2xl bg-[var(--modal-background,hsl(var(--background)))]',
'transition ease-out',
'data-[state=closed]:duration-200 data-[state=open]:duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out',
'focus:outline-none data-[state=closed]:slide-out-to-bottom-16 data-[state=open]:slide-in-from-bottom-16',
className,
)}
onOpenAutoFocus={(e) => e.preventDefault()}
onEscapeKeyDown={required ? (event) => event.preventDefault() : undefined}
onInteractOutside={required ? (event) => event.preventDefault() : undefined}
onPointerDownOutside={required ? (event) => event.preventDefault() : undefined}
>
<Dialog.Title className="sr-only">{title}</Dialog.Title>
{children}
<div className="flex flex-col">
<div
className={clsx(
'mb-5 flex min-h-10 flex-row items-center border-b border-b-contrast-200 py-3 pl-5',
hideHeader ? 'sr-only' : '',
)}
>
<Dialog.Title asChild>
<h1 className="flex-1 pr-4 text-base font-semibold leading-none">{title}</h1>
</Dialog.Title>
{!(required || hideHeader) && (
<div className="flex items-center justify-center pr-3">
<Dialog.Close asChild>
<Button shape="circle" size="x-small" variant="ghost">
<XIcon size={20} />
</Button>
</Dialog.Close>
</div>
)}
</div>
<div className={clsx('mb-5 flex-1 px-5', hideHeader ? 'mt-5' : '')}>{children}</div>
</div>
</Dialog.Content>
</Dialog.Overlay>
</Dialog.Portal>
Expand Down
Loading
Loading