website refactor

This commit is contained in:
2026-01-18 16:18:18 +01:00
parent 0b301feb61
commit 13567d51af
329 changed files with 4701 additions and 4750 deletions

View File

@@ -2,9 +2,9 @@
import { ChevronDown, ChevronUp } from 'lucide-react';
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface AccordionProps {

View File

@@ -1,9 +1,9 @@
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Link } from './Link';
import { Text } from './Text';
import { Surface } from './Surface';
import { Surface } from './primitives/Surface';
interface ActivityItemProps {
headline: string;

View File

@@ -1,8 +1,8 @@
import { Box } from './Box';
import { Box } from './primitives/Box';
import { LoadingSpinner } from './LoadingSpinner';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface AuthLoadingProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Image } from './Image';
import { User } from 'lucide-react';
import { Icon } from './Icon';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react';
@@ -13,10 +13,11 @@ interface BadgeProps {
bg?: string;
color?: string;
borderColor?: string;
rounded?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
}
export function Badge({ children, className = '', variant = 'default', size = 'sm', icon, style, bg, color, borderColor }: BadgeProps) {
const baseClasses = 'flex items-center gap-1.5 rounded-none border font-bold uppercase tracking-widest';
export function Badge({ children, className = '', variant = 'default', size = 'sm', icon, style, bg, color, borderColor, rounded = 'none' }: BadgeProps) {
const baseClasses = 'flex items-center gap-1.5 border font-bold uppercase tracking-widest';
const sizeClasses = {
xs: 'px-1.5 py-0.5 text-[9px]',
@@ -24,6 +25,16 @@ export function Badge({ children, className = '', variant = 'default', size = 's
md: 'px-3 py-1 text-xs'
};
const roundedClasses = {
none: 'rounded-none',
sm: 'rounded-sm',
md: 'rounded-md',
lg: 'rounded-lg',
xl: 'rounded-xl',
'2xl': 'rounded-2xl',
full: 'rounded-full'
};
const variantClasses = {
default: 'bg-gray-500/10 border-gray-500/30 text-gray-400',
primary: 'bg-primary-accent/10 border-primary-accent/30 text-primary-accent',
@@ -36,6 +47,7 @@ export function Badge({ children, className = '', variant = 'default', size = 's
const classes = [
baseClasses,
sizeClasses[size],
roundedClasses[rounded],
!bg && !color && !borderColor ? variantClasses[variant] : '',
bg,
color,

View File

@@ -1,7 +1,7 @@
import { Badge } from './Badge';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface Tab {

View File

@@ -1,6 +1,6 @@
import React, { ReactNode, MouseEventHandler, ButtonHTMLAttributes, forwardRef } from 'react';
import { Stack } from './Stack';
import { Box, BoxProps } from './Box';
import { Stack } from './primitives/Stack';
import { Box, BoxProps } from './primitives/Box';
import { Loader2 } from 'lucide-react';
import { Icon } from './Icon';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode, MouseEventHandler } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { ProgressBar } from './ProgressBar';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Image } from './Image';
import { Tag } from 'lucide-react';
import { Icon } from './Icon';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface CheckboxProps {

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Heading } from './Heading';
import { Card } from './Card';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Heading } from './Heading';
import { Image } from './Image';
import { Text } from './Text';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Calendar } from 'lucide-react';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
import { Icon } from './Icon';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface DecorativeBlurProps {
color?: 'blue' | 'green' | 'purple' | 'yellow' | 'red';

View File

@@ -1,7 +1,7 @@
import { Box } from './Box';
import { Surface } from './Surface';
import { Box } from './primitives/Box';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
export interface ErrorBannerProps {

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Image } from './Image';

View File

@@ -1,8 +1,8 @@
import React from 'react';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface FilePickerProps {

View File

@@ -1,8 +1,8 @@
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Button } from './Button';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
interface FilterOption {
id: string;

View File

@@ -2,7 +2,7 @@
import React from 'react';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
import { LucideIcon } from 'lucide-react';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface FormSectionProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface GlowProps {
color?: 'primary' | 'aqua' | 'purple' | 'amber';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
import { Heading } from './Heading';
import { Card } from './Card';

View File

@@ -1,6 +1,6 @@
import React, { ReactNode, ElementType } from 'react';
import { Stack } from './Stack';
import { Box, BoxProps } from './Box';
import { Stack } from './primitives/Stack';
import { Box, BoxProps } from './primitives/Box';
interface ResponsiveFontSize {
base?: string;

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface HeroProps {
children: ReactNode;

View File

@@ -1,10 +1,10 @@
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Card } from './Card';
import { Stack } from './Stack';
import { Surface } from './Surface';
import { Stack } from './primitives/Stack';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
interface HorizontalStatCardProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface HorizontalStatItemProps {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
interface IconProps extends Omit<BoxProps<'svg'>, 'children' | 'as'> {
icon: LucideIcon;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Image as ImageIcon, AlertCircle, Loader2 } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { Text } from './Text';

View File

@@ -2,10 +2,10 @@
import { AlertTriangle, CheckCircle, Info, LucideIcon, XCircle } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Surface } from './Surface';
import { Stack } from './primitives/Stack';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
type BannerType = 'info' | 'warning' | 'success' | 'error';

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Surface } from './Surface';
import { Stack } from './Stack';
import { Box } from './Box';
import { Surface } from './primitives/Surface';
import { Stack } from './primitives/Stack';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { Text } from './Text';
import { LucideIcon } from 'lucide-react';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react';

View File

@@ -1,7 +1,7 @@
import React, { forwardRef, InputHTMLAttributes } from 'react';
import { Text } from './Text';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
variant?: 'default' | 'error';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface LeaderboardListProps {
children: ReactNode;

View File

@@ -1,10 +1,10 @@
import { Award, ChevronRight, LucideIcon } from 'lucide-react';
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Button } from './Button';
import { Heading } from './Heading';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface LeaderboardPreviewShellProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface LeaderboardTableShellProps {
columns: {

View File

@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
interface LinkProps extends Omit<BoxProps<'a'>, 'children' | 'className' | 'onClick'> {
href: string;

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Info, FileText, Maximize2, Type, Calendar, LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { ImagePlaceholder } from './ImagePlaceholder';
import { Image } from './Image';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface MiniStatProps {

View File

@@ -4,10 +4,10 @@ import React, {
type KeyboardEvent as ReactKeyboardEvent,
type ReactNode,
} from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Button } from './Button';
import { Heading } from './Heading';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface ModalProps {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
interface ModalIconProps {

View File

@@ -2,11 +2,11 @@
import { LucideIcon } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Heading } from './Heading';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Surface } from './Surface';
import { Stack } from './primitives/Stack';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
interface PageHeaderProps {

View File

@@ -2,8 +2,8 @@ import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Heading } from './Heading';
import { Button } from './Button';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
import { Icon } from './Icon';
import { ModalIcon } from './ModalIcon';

View File

@@ -1,10 +1,10 @@
import { ChevronLeft, ChevronRight } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Button } from './Button';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface PaginationProps {

View File

@@ -1,6 +1,6 @@
import React, { ReactNode } from 'react';
import { Surface } from './Surface';
import { Box, BoxProps } from './Box';
import { Surface } from './primitives/Surface';
import { Box, BoxProps } from './primitives/Box';
import { Text } from './Text';
interface PanelProps extends Omit<BoxProps<'div'>, 'variant' | 'padding'> {

View File

@@ -1,7 +1,7 @@
import React, { ComponentProps } from 'react';
import { Eye, EyeOff, Lock } from 'lucide-react';
import { Input } from './Input';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface PasswordFieldProps extends ComponentProps<typeof Input> {
showPassword?: boolean;

View File

@@ -1,7 +1,7 @@
import { User } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
export interface PlaceholderImageProps {

View File

@@ -2,10 +2,10 @@
import { Trophy } from 'lucide-react';
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Heading } from './Heading';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface PodiumProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
interface ProgressBarProps extends Omit<BoxProps<'div'>, 'children'> {
value: number;

View File

@@ -1,7 +1,7 @@
import { ChevronRight, LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Icon } from './Icon';
import { Link } from './Link';
import { Text } from './Text';

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Panel } from './Panel';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Button } from './Button';
import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react';

View File

@@ -1,7 +1,7 @@
import { ReactNode } from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Heading } from './Heading';
import { Text } from './Text';

View File

@@ -2,11 +2,11 @@
import { LucideIcon } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Heading } from './Heading';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Surface } from './Surface';
import { Stack } from './primitives/Stack';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
interface SectionHeaderProps {

View File

@@ -1,7 +1,7 @@
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface SegmentedControlOption {

View File

@@ -1,5 +1,5 @@
import React, { ChangeEvent, SelectHTMLAttributes } from 'react';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface SelectOption {

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { ChevronRight, LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { Link } from './Link';

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface CheckboxProps {
checked: boolean;

View File

@@ -1,10 +1,10 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Stack } from './Stack';
import { Box } from './Box';
import { Stack } from './primitives/Stack';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { Surface } from './Surface';
import { Surface } from './primitives/Surface';
interface StatBoxProps {
icon: LucideIcon;

View File

@@ -2,10 +2,10 @@
import { motion, useReducedMotion } from 'framer-motion';
import { ArrowDownRight, ArrowUpRight, LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Card } from './Card';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface StatCardProps {

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { Grid } from './Grid';
import { GridItem } from './GridItem';
import { Surface } from './Surface';
import { Grid } from './primitives/Grid';
import { GridItem } from './primitives/GridItem';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
type GridCols = 1 | 2 | 3 | 4 | 5 | 6 | 12;

View File

@@ -1,9 +1,9 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
interface StatGridItemProps {
label: string;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface StatItemProps {

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react';
import { Stack } from './Stack';
import { Stack } from './primitives/Stack';
interface StatusBadgeProps {
children: React.ReactNode;

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
interface StatusDotProps {
color?: string;

View File

@@ -2,7 +2,7 @@
import { LucideIcon } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';

View File

@@ -1,8 +1,8 @@
import { ReactNode } from 'react';
import { Box } from './Box';
import { Surface } from './Surface';
import { Box } from './primitives/Box';
import { Surface } from './primitives/Surface';
import { Text } from './Text';
interface SummaryItemProps {

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { LucideIcon } from 'lucide-react';

View File

@@ -1,5 +1,5 @@
import React, { ReactNode, HTMLAttributes } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
interface TableProps extends HTMLAttributes<HTMLTableElement> {
children: ReactNode;

View File

@@ -1,5 +1,5 @@
import React, { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps } from './primitives/Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;

View File

@@ -1,8 +1,8 @@
import React, { TextareaHTMLAttributes } from 'react';
import { Box } from './Box';
import { Stack } from './Stack';
import { Box } from './primitives/Box';
import { Stack } from './primitives/Stack';
import { Text } from './Text';
interface TextAreaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {

View File

@@ -1,5 +1,5 @@
import { motion } from 'framer-motion';
import { Box } from './Box';
import { Box } from './primitives/Box';
import { Text } from './Text';
interface ToggleProps {

View File

@@ -36,6 +36,8 @@ export interface BoxProps<T extends ElementType> {
flexWrap?: 'wrap' | 'nowrap' | 'wrap-reverse';
flexShrink?: number;
flexGrow?: number;
flex?: number | string;
alignSelf?: 'auto' | 'start' | 'end' | 'center' | 'stretch' | 'baseline';
gridCols?: number | string;
responsiveGridCols?: {
base?: number | string;
@@ -55,10 +57,10 @@ export interface BoxProps<T extends ElementType> {
left?: Spacing | string;
right?: Spacing | string;
overflow?: 'visible' | 'hidden' | 'scroll' | 'auto';
maxWidth?: string;
minWidth?: string;
maxHeight?: string;
minHeight?: string;
maxWidth?: string | ResponsiveValue<string>;
minWidth?: string | ResponsiveValue<string>;
maxHeight?: string | ResponsiveValue<string>;
minHeight?: string | ResponsiveValue<string>;
zIndex?: number;
w?: string | ResponsiveValue<string>;
h?: string | ResponsiveValue<string>;
@@ -75,14 +77,16 @@ export interface BoxProps<T extends ElementType> {
color?: string;
shadow?: string;
hoverBorderColor?: string;
transition?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
transition?: any;
cursor?: 'pointer' | 'default' | 'wait' | 'text' | 'move' | 'not-allowed';
lineClamp?: 1 | 2 | 3 | 4 | 5 | 6;
inset?: string;
bgOpacity?: number;
opacity?: number;
blur?: 'none' | 'sm' | 'md' | 'lg' | 'xl';
animate?: 'pulse' | 'bounce' | 'spin' | 'fade-in' | 'none';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
animate?: any;
translateX?: string;
textAlign?: 'left' | 'center' | 'right' | 'justify';
hoverScale?: boolean;
@@ -93,6 +97,7 @@ export interface BoxProps<T extends ElementType> {
groupHoverOpacity?: number;
groupHoverWidth?: 'full' | '0' | 'auto';
fontSize?: string;
fontWeight?: 'normal' | 'medium' | 'semibold' | 'bold';
transform?: string;
borderWidth?: string;
hoverTextColor?: string;
@@ -103,7 +108,16 @@ export interface BoxProps<T extends ElementType> {
aspectRatio?: string;
visibility?: 'visible' | 'hidden' | 'collapse';
pointerEvents?: 'auto' | 'none';
order?: number | string | ResponsiveValue<number | string>;
hideScrollbar?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
whileHover?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
whileTap?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
initial?: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
exit?: any;
onMouseEnter?: React.MouseEventHandler<T>;
onMouseLeave?: React.MouseEventHandler<T>;
onClick?: React.MouseEventHandler<T>;
@@ -121,7 +135,7 @@ export interface BoxProps<T extends ElementType> {
backgroundImage?: string;
}
type ResponsiveValue<T> = {
export type ResponsiveValue<T> = {
base?: T;
sm?: T;
md?: T;
@@ -175,8 +189,10 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
bg,
color,
shadow,
flex,
flexShrink,
flexGrow,
alignSelf,
hoverBorderColor,
transition,
cursor,
@@ -196,6 +212,7 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
groupHoverOpacity,
groupHoverWidth,
fontSize,
fontWeight,
transform,
borderWidth,
hoverTextColor,
@@ -206,7 +223,12 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
aspectRatio,
visibility,
pointerEvents,
order,
hideScrollbar,
whileHover,
whileTap,
initial,
exit,
onMouseEnter,
onMouseLeave,
onClick,
@@ -247,11 +269,11 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
return `${prefix}-${spacingMap[value]}`;
};
const getResponsiveClasses = (prefix: string, value: string | ResponsiveValue<string> | undefined) => {
const getResponsiveClasses = (prefix: string, value: string | number | ResponsiveValue<string | number> | undefined) => {
if (value === undefined) return '';
if (typeof value === 'object') {
const classes = [];
if (value.base !== undefined) classes.push(prefix ? `${prefix}-${value.base}` : value.base);
if (value.base !== undefined) classes.push(prefix ? `${prefix}-${value.base}` : String(value.base));
if (value.sm !== undefined) classes.push(prefix ? `sm:${prefix}-${value.sm}` : `sm:${value.sm}`);
if (value.md !== undefined) classes.push(prefix ? `md:${prefix}-${value.md}` : `md:${value.md}`);
if (value.lg !== undefined) classes.push(prefix ? `lg:${prefix}-${value.lg}` : `lg:${value.lg}`);
@@ -259,7 +281,7 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
if (value['2xl'] !== undefined) classes.push(prefix ? `2xl:${prefix}-${value['2xl']}` : `2xl:${value['2xl']}`);
return classes.join(' ');
}
return prefix ? `${prefix}-${value}` : value;
return prefix ? `${prefix}-${value}` : String(value);
};
const getFlexDirectionClass = (value: BoxProps<ElementType>['flexDirection']) => {
@@ -329,6 +351,10 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
getSpacingClass('py', py),
getResponsiveClasses('w', w),
getResponsiveClasses('h', h),
getResponsiveClasses('max-w', maxWidth),
getResponsiveClasses('min-w', minWidth),
getResponsiveClasses('max-h', maxHeight),
getResponsiveClasses('min-h', minHeight),
rounded ? `rounded-${rounded}` : '',
border ? 'border' : '',
borderStyle ? `border-${borderStyle}` : '',
@@ -342,8 +368,10 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
color ? color : '',
hoverColor ? `hover:${hoverColor}` : '',
shadow ? shadow : '',
flex !== undefined ? `flex-${flex}` : '',
flexShrink !== undefined ? `flex-shrink-${flexShrink}` : '',
flexGrow !== undefined ? `flex-grow-${flexGrow}` : '',
alignSelf !== undefined ? `self-${alignSelf}` : '',
flexWrap ? `flex-${flexWrap}` : '',
hoverBorderColor ? `hover:${hoverBorderColor}` : '',
hoverTextColor ? `hover:${hoverTextColor}` : '',
@@ -365,6 +393,8 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
groupHoverScale ? 'group-hover:scale-[1.02]' : '',
groupHoverOpacity !== undefined ? `group-hover:opacity-${groupHoverOpacity * 100}` : '',
groupHoverWidth ? `group-hover:w-${groupHoverWidth}` : '',
fontSize ? `text-${fontSize}` : '',
fontWeight ? `font-${fontWeight}` : '',
getResponsiveClasses('', display),
getFlexDirectionClass(flexDirection),
getAlignItemsClass(alignItems),
@@ -378,6 +408,7 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
responsiveColSpan?.md ? `md:col-span-${responsiveColSpan.md}` : '',
responsiveColSpan?.lg ? `lg:col-span-${responsiveColSpan.lg}` : '',
getSpacingClass('gap', gap),
getResponsiveClasses('order', order),
position ? position : '',
top !== undefined && spacingMap[top as string | number] ? `top-${spacingMap[top as string | number]}` : '',
bottom !== undefined && spacingMap[bottom as string | number] ? `bottom-${spacingMap[bottom as string | number]}` : '',
@@ -395,10 +426,10 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
const style: React.CSSProperties = {
...(width ? { width } : {}),
...(height ? { height } : {}),
...(maxWidth ? { maxWidth } : {}),
...(minWidth ? { minWidth } : {}),
...(maxHeight ? { maxHeight } : {}),
...(minHeight ? { minHeight } : {}),
...(typeof maxWidth === 'string' ? { maxWidth } : {}),
...(typeof minWidth === 'string' ? { minWidth } : {}),
...(typeof maxHeight === 'string' ? { maxHeight } : {}),
...(typeof minHeight === 'string' ? { minHeight } : {}),
...(fontSize ? { fontSize } : {}),
...(transform ? { transform } : {}),
...(borderWidth ? { borderWidth } : {}),
@@ -428,6 +459,11 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
onSubmit={onSubmit}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
whileHover={whileHover}
whileTap={whileTap}
initial={initial}
animate={animate}
exit={exit}
{...props}
style={style as React.CSSProperties}
>

View File

@@ -1,7 +1,7 @@
import React, { ReactNode } from 'react';
import { Box, BoxProps } from './Box';
interface GridProps extends Omit<BoxProps<'div'>, 'children' | 'display'> {
export interface GridProps extends Omit<BoxProps<'div'>, 'children' | 'display'> {
children: ReactNode;
cols?: 1 | 2 | 3 | 4 | 5 | 6 | 12;
mdCols?: 1 | 2 | 3 | 4 | 5 | 6 | 12;

View File

@@ -1,7 +1,7 @@
import React from 'react';
import { Box } from './Box';
interface GridItemProps {
export interface GridItemProps {
children: React.ReactNode;
colSpan?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
mdSpan?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;

View File

@@ -1,5 +1,5 @@
import React, { ReactNode, ElementType } from 'react';
import { Box, BoxProps } from './Box';
import { Box, BoxProps, ResponsiveValue } from './Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
@@ -20,13 +20,13 @@ interface ResponsiveSpacing {
'2xl'?: Spacing;
}
interface StackProps<T extends ElementType> extends Omit<BoxProps<T>, 'children' | 'className' | 'gap'> {
export interface StackProps<T extends ElementType> extends Omit<BoxProps<T>, 'children' | 'className' | 'gap'> {
children: ReactNode;
className?: string;
direction?: 'row' | 'col' | { base?: 'row' | 'col'; md?: 'row' | 'col'; lg?: 'row' | 'col' };
gap?: number | ResponsiveGap;
align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline';
justify?: 'start' | 'center' | 'end' | 'between' | 'around';
align?: 'start' | 'center' | 'end' | 'stretch' | 'baseline' | ResponsiveValue<'start' | 'center' | 'end' | 'stretch' | 'baseline'>;
justify?: 'start' | 'center' | 'end' | 'between' | 'around' | ResponsiveValue<'start' | 'center' | 'end' | 'between' | 'around'>;
wrap?: boolean;
center?: boolean;
m?: Spacing | ResponsiveSpacing;
@@ -53,8 +53,8 @@ export function Stack<T extends ElementType = 'div'>({
className = '',
direction = 'col',
gap = 4,
align = 'stretch',
justify = 'start',
align,
justify,
wrap = false,
center = false,
m, mt, mb, ml, mr,
@@ -133,7 +133,6 @@ export function Stack<T extends ElementType = 'div'>({
direction.lg === 'col' ? 'lg:flex-col' : (direction.lg === 'row' ? 'lg:flex-row' : ''),
].filter(Boolean).join(' '),
getGapClasses(gap) || 'gap-4',
center ? 'items-center justify-center' : `items-${align} justify-${justify}`,
wrap ? 'flex-wrap' : '',
getSpacingClass('m', m),
getSpacingClass('mt', mt),
@@ -151,5 +150,18 @@ export function Stack<T extends ElementType = 'div'>({
className
].filter(Boolean).join(' ');
return <Box as={as} className={classes} {...props}>{children}</Box>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { alignItems, justifyContent, ...restProps } = props as any;
return (
<Box
as={as}
className={classes}
alignItems={center ? 'center' : (align || alignItems)}
justifyContent={center ? 'center' : (justify || justifyContent)}
{...restProps}
>
{children}
</Box>
);
}

View File

@@ -1,7 +1,7 @@
import React, { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react';
import { Box, BoxProps } from './Box';
interface SurfaceProps<T extends ElementType = 'div'> extends Omit<BoxProps<T>, 'children' | 'className' | 'display'> {
export interface SurfaceProps<T extends ElementType = 'div'> extends Omit<BoxProps<T>, 'children' | 'className' | 'display'> {
as?: T;
children: ReactNode;
variant?: 'default' | 'muted' | 'dark' | 'glass' | 'gradient-blue' | 'gradient-gold' | 'gradient-purple' | 'gradient-green' | 'discord' | 'discord-inner';