This commit is contained in:
@@ -5,14 +5,14 @@ import { Card } from "@/components/ui/card";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const appCardVariants = cva(
|
||||
"rounded-surface border transition-all duration-200",
|
||||
"rounded-lg transition-colors",
|
||||
{
|
||||
variants: {
|
||||
level: {
|
||||
1: "border-border bg-surface-1 text-foreground shadow-card",
|
||||
2: "border-border bg-surface-2 text-foreground shadow-sm",
|
||||
3: "border-border/90 bg-surface-3 text-foreground shadow-panel",
|
||||
inverse: "border-transparent bg-surface-inverse text-surface-inverse-foreground shadow-lg",
|
||||
1: "border bg-card text-card-foreground shadow-sm",
|
||||
2: "border bg-card text-card-foreground shadow-sm",
|
||||
3: "border bg-card text-card-foreground shadow-md",
|
||||
inverse: "border-transparent bg-foreground text-background shadow-sm",
|
||||
},
|
||||
padding: {
|
||||
none: "",
|
||||
@@ -21,7 +21,7 @@ const appCardVariants = cva(
|
||||
lg: "p-8",
|
||||
},
|
||||
interactive: {
|
||||
true: "hover:-translate-y-0.5 hover:border-border-strong hover:shadow-md",
|
||||
true: "hover:bg-accent/30 hover:text-accent-foreground",
|
||||
false: "",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ const badgeVariants = cva(
|
||||
variant: {
|
||||
default: "border-transparent bg-primary text-primary-foreground",
|
||||
secondary: "border-transparent bg-secondary text-secondary-foreground",
|
||||
outline: "border-border bg-surface-1 text-foreground",
|
||||
outline: "border-input bg-background text-foreground",
|
||||
success: "border-transparent bg-status-success-soft text-status-success",
|
||||
warning: "border-transparent bg-status-warning-soft text-status-warning",
|
||||
},
|
||||
|
||||
@@ -5,16 +5,16 @@ import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-nested text-sm font-medium ring-offset-background transition-all duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-primary text-primary-foreground shadow-xs hover:brightness-95",
|
||||
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
||||
outline: "border border-border bg-surface-1 text-foreground shadow-xs hover:border-border-strong hover:bg-surface-2",
|
||||
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
||||
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
||||
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||
ghost: "text-muted-foreground hover:bg-muted hover:text-foreground",
|
||||
link: "rounded-none text-primary underline-offset-4 hover:underline",
|
||||
destructive: "bg-destructive text-destructive-foreground shadow-xs hover:brightness-95",
|
||||
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
||||
},
|
||||
size: {
|
||||
default: "h-10 px-4 py-2",
|
||||
|
||||
@@ -7,7 +7,7 @@ const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElemen
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"rounded-surface border border-border bg-surface-1 text-card-foreground shadow-card",
|
||||
"rounded-lg border bg-card text-card-foreground shadow-sm",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
||||
import { Check } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type CheckboxProps = React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root> & {
|
||||
name?: string;
|
||||
};
|
||||
|
||||
const Checkbox = React.forwardRef<
|
||||
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
||||
CheckboxProps
|
||||
>(({ className, name, checked, defaultChecked, onCheckedChange, ...props }, ref) => {
|
||||
const [internalChecked, setInternalChecked] = React.useState(defaultChecked === true);
|
||||
const isControlled = checked !== undefined;
|
||||
const currentChecked = isControlled ? checked === true : internalChecked;
|
||||
|
||||
return (
|
||||
<>
|
||||
{name ? <input type="hidden" name={name} value={currentChecked ? "on" : "false"} /> : null}
|
||||
<CheckboxPrimitive.Root
|
||||
ref={ref}
|
||||
checked={checked}
|
||||
defaultChecked={defaultChecked}
|
||||
onCheckedChange={(nextChecked) => {
|
||||
if (!isControlled) {
|
||||
setInternalChecked(nextChecked === true);
|
||||
}
|
||||
onCheckedChange?.(nextChecked);
|
||||
}}
|
||||
className={cn(
|
||||
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<CheckboxPrimitive.Indicator className="flex items-center justify-center text-current">
|
||||
<Check className="h-3.5 w-3.5" />
|
||||
</CheckboxPrimitive.Indicator>
|
||||
</CheckboxPrimitive.Root>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
||||
|
||||
export { Checkbox };
|
||||
@@ -7,7 +7,7 @@ const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
|
||||
<input
|
||||
type={type}
|
||||
className={cn(
|
||||
"flex h-10 w-full rounded-nested border border-input bg-surface-1 px-3 py-2 text-sm text-foreground ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base text-foreground ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
||||
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type SelectProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {
|
||||
name?: string;
|
||||
required?: boolean;
|
||||
};
|
||||
|
||||
function Select({
|
||||
name,
|
||||
required,
|
||||
value,
|
||||
defaultValue,
|
||||
onValueChange,
|
||||
children,
|
||||
...props
|
||||
}: SelectProps) {
|
||||
const [internalValue, setInternalValue] = React.useState(defaultValue ?? "");
|
||||
const isControlled = value !== undefined;
|
||||
const currentValue = (isControlled ? value : internalValue) as string;
|
||||
|
||||
return (
|
||||
<>
|
||||
{name ? <input type="hidden" name={name} value={currentValue} required={required} /> : null}
|
||||
<SelectPrimitive.Root
|
||||
value={value}
|
||||
defaultValue={defaultValue}
|
||||
onValueChange={(nextValue) => {
|
||||
if (!isControlled) {
|
||||
setInternalValue(nextValue);
|
||||
}
|
||||
onValueChange?.(nextValue);
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Root>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const SelectGroup = SelectPrimitive.Group;
|
||||
|
||||
const SelectValue = SelectPrimitive.Value;
|
||||
|
||||
const SelectTrigger = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<SelectPrimitive.Trigger
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<SelectPrimitive.Icon asChild>
|
||||
<ChevronDown className="h-4 w-4 opacity-50" />
|
||||
</SelectPrimitive.Icon>
|
||||
</SelectPrimitive.Trigger>
|
||||
));
|
||||
|
||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
||||
|
||||
const SelectScrollUpButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollUpButton
|
||||
ref={ref}
|
||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronUp className="h-4 w-4" />
|
||||
</SelectPrimitive.ScrollUpButton>
|
||||
));
|
||||
|
||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
||||
|
||||
const SelectScrollDownButton = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.ScrollDownButton
|
||||
ref={ref}
|
||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
||||
{...props}
|
||||
>
|
||||
<ChevronUp className="h-4 w-4 rotate-180" />
|
||||
</SelectPrimitive.ScrollDownButton>
|
||||
));
|
||||
|
||||
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
||||
|
||||
const SelectContent = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
||||
<SelectPrimitive.Portal>
|
||||
<SelectPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||
position === "popper" &&
|
||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
||||
className,
|
||||
)}
|
||||
position={position}
|
||||
{...props}
|
||||
>
|
||||
<SelectScrollUpButton />
|
||||
<SelectPrimitive.Viewport
|
||||
className={cn(
|
||||
"p-1",
|
||||
position === "popper" &&
|
||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</SelectPrimitive.Viewport>
|
||||
<SelectScrollDownButton />
|
||||
</SelectPrimitive.Content>
|
||||
</SelectPrimitive.Portal>
|
||||
));
|
||||
|
||||
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
||||
|
||||
const SelectLabel = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Label
|
||||
ref={ref}
|
||||
className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
||||
|
||||
const SelectItem = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<SelectPrimitive.Item
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
||||
<SelectPrimitive.ItemIndicator>
|
||||
<Check className="h-4 w-4" />
|
||||
</SelectPrimitive.ItemIndicator>
|
||||
</span>
|
||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
||||
</SelectPrimitive.Item>
|
||||
));
|
||||
|
||||
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
||||
|
||||
const SelectSeparator = React.forwardRef<
|
||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<SelectPrimitive.Separator
|
||||
ref={ref}
|
||||
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
|
||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
||||
|
||||
export {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectGroup,
|
||||
SelectItem,
|
||||
SelectLabel,
|
||||
SelectScrollDownButton,
|
||||
SelectScrollUpButton,
|
||||
SelectSeparator,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
};
|
||||
@@ -44,7 +44,7 @@ function TabsList({
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"inline-flex h-auto flex-wrap items-center gap-2 rounded-surface border border-border bg-surface-2 p-1.5",
|
||||
"inline-flex h-auto flex-wrap items-center gap-2 rounded-lg border bg-muted/40 p-1.5",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
@@ -69,8 +69,8 @@ function TabsTrigger({
|
||||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
"inline-flex items-center justify-center rounded-nested px-3 py-2 text-sm font-medium text-muted-foreground transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
isActive && "bg-surface-1 text-foreground shadow-xs",
|
||||
"inline-flex items-center justify-center rounded-md px-3 py-2 text-sm font-medium text-muted-foreground transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
|
||||
isActive && "bg-background text-foreground shadow-sm",
|
||||
className,
|
||||
)}
|
||||
onClick={(event) => {
|
||||
|
||||
@@ -6,7 +6,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<"tex
|
||||
({ className, ...props }, ref) => (
|
||||
<textarea
|
||||
className={cn(
|
||||
"flex min-h-[112px] w-full rounded-nested border border-input bg-surface-1 px-3 py-2 text-sm text-foreground ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
||||
"flex min-h-[80px] w-full rounded-md border border-input bg-background px-3 py-2 text-base text-foreground ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||
className,
|
||||
)}
|
||||
ref={ref}
|
||||
|
||||
@@ -224,7 +224,7 @@ export function UiKitShowcase({ localeKey }: UiKitShowcaseProps) {
|
||||
<div className="flex flex-col gap-section">
|
||||
<AppCard level={3}>
|
||||
<CardContent className="flex flex-col gap-4 p-6 lg:p-10">
|
||||
<div className="inline-flex w-fit items-center gap-2 rounded-pill border border-border bg-surface-1 px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
|
||||
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-input bg-background px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
|
||||
<Layers3 className="h-3.5 w-3.5 text-brand-secondary" />
|
||||
{copy.title}
|
||||
</div>
|
||||
@@ -292,10 +292,10 @@ export function UiKitShowcase({ localeKey }: UiKitShowcaseProps) {
|
||||
</AppCard>
|
||||
<AppCard level="inverse">
|
||||
<CardContent className="p-5">
|
||||
<p className="text-sm font-medium text-surface-inverse-foreground/80">
|
||||
<p className="text-sm font-medium text-background/80">
|
||||
{copy.inverseOuterCard}
|
||||
</p>
|
||||
<p className="mt-2 text-sm text-surface-inverse-foreground/88">
|
||||
<p className="mt-2 text-sm text-background/88">
|
||||
{copy.inverseOuterCardText}
|
||||
</p>
|
||||
</CardContent>
|
||||
@@ -452,8 +452,8 @@ export function UiKitShowcase({ localeKey }: UiKitShowcaseProps) {
|
||||
</AppCard>
|
||||
<AppCard level="inverse">
|
||||
<CardContent className="p-5">
|
||||
<p className="font-medium text-surface-inverse-foreground">{copy.inverse}</p>
|
||||
<p className="mt-2 text-sm text-surface-inverse-foreground/88">{copy.inverseText}</p>
|
||||
<p className="font-medium text-background">{copy.inverse}</p>
|
||||
<p className="mt-2 text-sm text-background/88">{copy.inverseText}</p>
|
||||
</CardContent>
|
||||
</AppCard>
|
||||
</div>
|
||||
@@ -492,7 +492,7 @@ export function UiKitShowcase({ localeKey }: UiKitShowcaseProps) {
|
||||
<div className="grid gap-6">
|
||||
<AppCard level={3}>
|
||||
<CardContent className="space-y-3 p-6">
|
||||
<div className="inline-flex w-fit items-center gap-2 rounded-pill border border-border bg-surface-1 px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
|
||||
<div className="inline-flex w-fit items-center gap-2 rounded-full border border-input bg-background px-3 py-1 text-xs font-semibold uppercase tracking-[0.14em] text-foreground/80">
|
||||
<Type className="h-3.5 w-3.5 text-brand-primary" />
|
||||
{copy.pageHeader}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user