Add vendor certifications tab

Signed-off-by: Bryan Frimin <bryan@getprobo.com>
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
Jonathan
2025-06-01 12:08:27 +02:00
committed by Sacha Al Himdani
parent b94b58e2de
commit df23fd635f
37 changed files with 2266 additions and 199 deletions

View File

@@ -1,7 +1,9 @@
import type { HTMLAttributes } from "react";
import { tv } from "tailwind-variants";
import { Slot } from "../Slot";
type Props = {
asChild?: boolean;
variant?:
| "success"
| "warning"
@@ -11,10 +13,10 @@ type Props = {
| "outline"
| "highlight";
size?: "sm" | "md";
} & HTMLAttributes<HTMLDivElement>;
} & HTMLAttributes<HTMLElement>;
const badge = tv({
base: "font-medium rounded-lg w-max flex gap-1 items-center",
base: "font-medium rounded-lg w-max flex gap-1 items-center group whitespace-nowrap",
variants: {
variant: {
success: "bg-success text-txt-success",
@@ -37,5 +39,7 @@ const badge = tv({
});
export function Badge(props: Props) {
return <div {...props} className={badge(props)} />;
const Component = props.asChild ? Slot : "div";
const { asChild, size, variant, ...restProps } = props;
return <Component {...restProps} className={badge(props)} />;
}

View File

@@ -0,0 +1,12 @@
import { Dropzone } from "./Dropzone";
import type { Meta, StoryObj } from "@storybook/react";
export default {
title: "Atoms/Dropzone",
component: Dropzone,
argTypes: {},
} satisfies Meta<typeof Dropzone>;
type Story = StoryObj<typeof Dropzone>;
export const Default: Story = {};

View File

@@ -0,0 +1,24 @@
import { useCallback } from "react";
import { useDropzone } from "react-dropzone";
type Props = {};
export function Dropzone({}: Props) {
const onDrop = useCallback((acceptedFiles) => {
// Do something with the files
}, []);
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
});
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop the files here ...</p>
) : (
<p>Drag 'n' drop some files here, or click to select files</p>
)}
</div>
);
}

View File

@@ -83,7 +83,10 @@ export function Select({
return (
<Root onValueChange={onValueChange} value={value}>
<Trigger {...props} className={trigger()}>
<Trigger
{...props}
className={trigger({ className: props.className })}
>
<Value placeholder={placeholder} />
<Icon className={icon()}>
<IconChevronGrabberVertical size={16} />

View File

@@ -18,13 +18,34 @@ type Props = {
loading?: boolean;
onSearch: (query: string) => void;
placeholder?: string;
autoSelect?: boolean;
onSelect?: (value: string) => void;
resetValueOnHide?: boolean;
value?: string;
};
export function Combobox({ children, onSearch, placeholder }: Props) {
export function Combobox({
children,
onSearch,
placeholder,
autoSelect,
onSelect,
resetValueOnHide,
value,
}: Props) {
const showDropdown = !isEmpty(children);
return (
<ComboboxProvider setValue={onSearch}>
<AriaKitCombobox placeholder={placeholder} className={input()} />
<ComboboxProvider
value={value}
setValue={onSearch}
setSelectedValue={(v) => onSelect?.(v as string)}
resetValueOnHide={resetValueOnHide}
>
<AriaKitCombobox
autoSelect={autoSelect}
placeholder={placeholder}
className={input()}
/>
{showDropdown && (
<ComboboxPopover gutter={4} sameWidth className={dropdown()}>
{children}
@@ -39,7 +60,7 @@ export function ComboboxItem({
...props
}: PropsWithChildren<ComponentProps<typeof AriaKitComboboxItem>>) {
return (
<AriaKitComboboxItem className={dropdownItem()} {...props}>
<AriaKitComboboxItem hideOnClick className={dropdownItem()} {...props}>
{children}
</AriaKitComboboxItem>
);

View File

@@ -2,7 +2,7 @@ import { tv } from "tailwind-variants";
import { Label } from "../../Atoms/Label/Label";
import { Input } from "../../Atoms/Input/Input";
import { Textarea } from "../../Atoms/Textarea/Textarea";
import { type ComponentProps } from "react";
import { type ComponentProps, type ReactNode } from "react";
import { Select } from "../../Atoms/Select/Select";
type BaseProps<T extends string, P> = {
@@ -10,7 +10,8 @@ type BaseProps<T extends string, P> = {
help?: string;
error?: string;
onValueChange?: (s: string) => void;
type: T;
type?: T;
children?: ReactNode;
} & P;
type Props =
@@ -33,6 +34,7 @@ const { base: baseClass, label: labelClass, help: helpClass } = field();
export function Field(props: Props) {
const showHelp = props.help && !props.error;
const childrenAsInput = !props.type && props.children;
return (
<div className={baseClass()}>
{props.label && (
@@ -40,7 +42,7 @@ export function Field(props: Props) {
{props.label}
</Label>
)}
{getInput(props)}
{childrenAsInput ? props.children : getInput(props)}
{showHelp && <span className={helpClass()}>{props.help}</span>}
{props.error && (
<span className="text-txt-danger text-sm mt-1">

View File

@@ -249,6 +249,11 @@ button:focus-visible {
}
}
/* Allow interpolation : https://developer.chrome.com/docs/css-ui/animate-to-height-auto */
:root {
interpolate-size: allow-keywords;
}
::-webkit-scrollbar {
width: 7px;
height: 7px;