Files
gridpilot.gg/apps/website/ui/Surface.tsx
2026-01-20 17:49:54 +01:00

104 lines
3.7 KiB
TypeScript

import React, { ElementType, ForwardedRef, forwardRef, ReactNode } from 'react';
import { Box, BoxProps } from './Box';
import { ThemeRadii, ThemeShadows } from './theme/Theme';
/**
* WARNING: DO NOT VIOLATE THE PURPOSE OF THIS PRIMITIVE.
*
* Surface is a styled container with background, border, and shadow.
*
* - DO NOT add layout props (flex, grid, gap) - use Stack or Grid instead.
* - DO NOT add positioning props (absolute, top, zIndex).
*
* If you need a more specific layout, create a new component in apps/website/components.
*/
export interface SurfaceProps<T extends ElementType = 'div'> extends BoxProps<T> {
as?: T;
children?: ReactNode;
variant?: 'default' | 'dark' | 'muted' | 'glass' | 'discord' | 'gradient-blue' | 'gradient-gold' | 'gradient-purple' | 'gradient-green' | 'discord-inner' | 'outline' | 'rarity-common' | 'rarity-rare' | 'rarity-epic' | 'rarity-legendary' | 'precision';
rounded?: keyof ThemeRadii | 'none' | '2xl' | string | boolean;
shadow?: keyof ThemeShadows | 'none' | string;
}
export const Surface = forwardRef(<T extends ElementType = 'div'>(
{
as,
children,
variant = 'default',
rounded = 'none',
shadow = 'none',
...props
}: SurfaceProps<T>,
ref: ForwardedRef<HTMLElement>
) => {
const variantStyles: Record<string, React.CSSProperties> = {
default: { backgroundColor: 'var(--ui-color-bg-surface)' },
dark: { backgroundColor: 'var(--ui-color-bg-base)' },
muted: { backgroundColor: 'var(--ui-color-bg-surface-muted)' },
precision: {
backgroundColor: 'var(--ui-color-bg-surface)',
border: '1px solid var(--ui-color-border-default)',
boxShadow: 'inset 0 1px 0 0 rgba(255, 255, 255, 0.02)'
},
glass: {
backgroundColor: 'rgba(20, 22, 25, 0.6)',
backdropFilter: 'blur(12px)',
WebkitBackdropFilter: 'blur(12px)'
},
discord: {
background: 'linear-gradient(to bottom, var(--ui-color-bg-base), var(--ui-color-bg-surface))'
},
'discord-inner': {
background: 'linear-gradient(to br, var(--ui-color-bg-surface), var(--ui-color-bg-base), var(--ui-color-bg-surface))'
},
'gradient-blue': {
background: 'linear-gradient(to br, rgba(25, 140, 255, 0.1), var(--ui-color-bg-surface), var(--ui-color-bg-base))'
},
'gradient-gold': {
background: 'linear-gradient(to br, rgba(255, 190, 77, 0.1), var(--ui-color-bg-surface), var(--ui-color-bg-base))'
},
'gradient-purple': {
background: 'linear-gradient(to br, rgba(147, 51, 234, 0.1), var(--ui-color-bg-surface), var(--ui-color-bg-base))'
},
'gradient-green': {
background: 'linear-gradient(to br, rgba(111, 227, 122, 0.1), var(--ui-color-bg-surface), var(--ui-color-bg-base))'
},
outline: {
backgroundColor: 'transparent',
border: '1px solid var(--ui-color-border-default)'
},
'rarity-common': {
backgroundColor: 'rgba(107, 114, 128, 0.1)',
border: '1px solid rgba(107, 114, 128, 0.5)'
},
'rarity-rare': {
backgroundColor: 'rgba(96, 165, 250, 0.1)',
border: '1px solid rgba(96, 165, 250, 0.5)'
},
'rarity-epic': {
backgroundColor: 'rgba(192, 132, 252, 0.1)',
border: '1px solid rgba(192, 132, 252, 0.5)'
},
'rarity-legendary': {
backgroundColor: 'rgba(255, 190, 77, 0.1)',
border: '1px solid rgba(255, 190, 77, 0.5)'
}
};
const style: React.CSSProperties = {
...(props.style || {}),
...variantStyles[variant],
borderRadius: rounded !== 'none' ? `var(--ui-radius-${String(rounded)})` : undefined,
boxShadow: shadow !== 'none' ? `var(--ui-shadow-${String(shadow)})` : undefined,
};
return (
<Box as={as} ref={ref} {...(props as any)} style={style}>
{children}
</Box>
);
});
Surface.displayName = 'Surface';