Skip to content

Commit

Permalink
chore(): customize border radius per components (#2550)
Browse files Browse the repository at this point in the history
  • Loading branch information
didd authored Feb 17, 2025
1 parent 09f4ad0 commit dd57101
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 192 deletions.
2 changes: 1 addition & 1 deletion libs/ui/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"config": "",
"css": "main.css",
"baseColor": "zinc",
"cssVariables": true
Expand Down
47 changes: 45 additions & 2 deletions libs/ui/main.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,29 @@
@import 'tailwindcss' source(none);
@import 'tailwindcss';
@source "../ui";

@theme inline {
--animate-accordion-down: accordion-down 0.2s ease-out;
--animate-accordion-up: accordion-up 0.2s ease-out;

@keyframes accordion-down {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}

@keyframes accordion-up {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
}

@layer base {
html {
font-family: Inter, sans-serif;
Expand Down Expand Up @@ -62,7 +85,9 @@
--success-foreground: 97.9% 0.021 166.1;
--warning: 86% 0.173 91.8;
--warning-foreground: 98.7% 0.026 102.2;
--radius: 1.5rem;
--nested-card: 98.5% 0 0;

--radius: 0.5rem;
}

.dark {
Expand Down Expand Up @@ -91,6 +116,24 @@
--success-foreground: 37.8% 0.073 168.9;
--warning: 97.3% 0.07 103.2;
--warning-foreground: 55.4% 0.121 66.4;
--nested-card: 37% 0.012 285.8;
}
}

@layer component {
[data-slot='card'] {
--radius: 1.25rem;
}
[data-slot='card'] * {
--radius: 0.5rem;
}
[data-slot='card'] [data-slot='card'] {
--radius: 0.625rem;
}

[data-slot='button'],
[data-slot='badge'] {
--radius: 1.5rem;
}
}

Expand Down
76 changes: 34 additions & 42 deletions libs/ui/src/akasha-components/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cn } from '@/library/utils';
import { typographyVariants } from '@/akasha-components/typography';

const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-bold 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 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 cursor-pointer',
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md font-bold transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 ring-ring/10 dark:ring-ring/20 dark:outline-ring/40 outline-ring/50 focus-visible:ring-4 focus-visible:outline-1 aria-invalid:focus-visible:ring-0 cursor-pointer",
{
variants: {
variant: {
Expand All @@ -33,47 +33,39 @@ const buttonVariants = cva(
},
);

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
loading?: boolean;
asChild?: boolean;
}
function Button({
className,
variant,
size = 'default',
loading,
asChild = false,
disabled,
children,
...props
}: React.ComponentProps<'button'> &
VariantProps<typeof buttonVariants> & {
loading?: boolean;
asChild?: boolean;
}) {
const Comp = asChild ? Slot : 'button';

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(
{
className,
variant,
size = 'default',
loading,
asChild = false,
disabled,
children,
...props
},
ref,
) => {
const Comp = asChild ? Slot : 'button';
return (
<Comp
className={cn(
{
[typographyVariants({ variant: 'sm' })]: size === 'default',
[typographyVariants({ variant: 'xs' })]: size === 'sm',
},
buttonVariants({ variant, size, className }),
{ 'p-0': variant === 'link' || asChild },
)}
ref={ref}
disabled={loading || disabled}
{...props}
>
{loading ? <Loader2 className="animate-spin" /> : children}
</Comp>
);
},
);
Button.displayName = 'Button';
return (
<Comp
data-slot="button"
className={cn(
{
[typographyVariants({ variant: 'sm' })]: size === 'default',
[typographyVariants({ variant: 'xs' })]: size === 'sm',
},
buttonVariants({ variant, size, className }),
{ 'p-0': variant === 'link' || asChild },
)}
disabled={loading || disabled}
{...props}
>
{loading ? <Loader2 className="animate-spin" /> : children}
</Comp>
);
}

export { Button, buttonVariants };
85 changes: 41 additions & 44 deletions libs/ui/src/akasha-components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,66 +3,63 @@ import * as React from 'react';
import { cn } from '@/library/utils';
import { typographyVariants } from '@/akasha-components/typography';

const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
function Card({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
ref={ref}
className={cn('rounded-lg border bg-card text-card-foreground shadow-sm', className)}
data-slot="card"
className={cn(
'bg-card text-card-foreground rounded-lg border overflow-hidden p-6',
className,
)}
{...props}
/>
),
);
Card.displayName = 'Card';
);
}

const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('flex flex-col space-y-1.5 p-6', className)} {...props} />
),
);
CardHeader.displayName = 'CardHeader';
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-header"
className={cn('flex flex-col space-y-1.5 pb-6', className)}
{...props}
/>
);
}

const CardTitle = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
ref={ref}
className={cn(
'text-center font-bold leading-none tracking-tight',
typographyVariants({ variant: 'h5' }),
className,
)}
data-slot="card-title"
className={cn('text-center font-bold', typographyVariants({ variant: 'h5' }), className)}
{...props}
/>
),
);
CardTitle.displayName = 'CardTitle';
);
}

const CardDescription = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
ref={ref}
className={cn('text-sm text-center text-muted-foreground', className)}
data-slot="card-description"
className={cn('text-muted-foreground text-sm text-center ', className)}
{...props}
/>
),
);
CardDescription.displayName = 'CardDescription';
);
}

const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn('p-6 pt-0', className)} {...props} />
),
);
CardContent.displayName = 'CardContent';
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div data-slot="card-content" className={cn('flex justify-center', className)} {...props} />
);
}

const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
ref={ref}
className={cn('flex items-center justify-end w-full gap-2 p-6 pt-0', className)}
data-slot="card-footer"
className={cn('flex items-center justify-end w-full gap-2 pt-6', className)}
{...props}
/>
),
);
CardFooter.displayName = 'CardFooter';
);
}

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
94 changes: 49 additions & 45 deletions libs/ui/src/akasha-components/duplex-button.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
import * as React from 'react';

import { Button, ButtonProps } from '@/akasha-components/button';

interface DuplexButtonProps {
active: boolean;
children: React.ReactNode;
}

interface DuplexButtonProps extends React.HTMLAttributes<HTMLDivElement> {
active: boolean;
children: React.ReactNode;
}
import { Button } from '@/akasha-components/button';

const DuplexButtonContext = React.createContext<{
active: boolean;
Expand All @@ -26,44 +16,58 @@ const useDuplexButtonContext = () => {
return context;
};

const DuplexButton = React.forwardRef<HTMLDivElement, DuplexButtonProps>(
({ children, active, ...props }, ref) => {
const [hovered, setHovered] = React.useState(false);
return (
<DuplexButtonContext.Provider
value={{
active,
hovered,
onHovered: hovered => setHovered(hovered),
}}
>
<div ref={ref} {...props}>
{children}
</div>
</DuplexButtonContext.Provider>
);
},
);
DuplexButton.displayName = 'DuplexButton';
const DuplexButton = ({
children,
active,
...props
}: React.ComponentProps<'div'> & {
active: boolean;
children: React.ReactNode;
}) => {
const [hovered, setHovered] = React.useState(false);
return (
<DuplexButtonContext.Provider
data-slot="duplex-button"
value={{
active,
hovered,
onHovered: hovered => setHovered(hovered),
}}
>
<div {...props}>{children}</div>
</DuplexButtonContext.Provider>
);
};

const DuplexButtonActive = React.forwardRef<HTMLButtonElement, ButtonProps>(({ ...props }, ref) => {
const DuplexButtonActive = ({
...props
}: React.ComponentProps<'button'> & React.ComponentProps<typeof Button>) => {
const { active, hovered, onHovered } = useDuplexButtonContext();
return active && !hovered && <Button ref={ref} onMouseEnter={() => onHovered(true)} {...props} />;
});
DuplexButtonActive.displayName = 'DuplexButtonActive';
return (
active &&
!hovered && (
<Button data-slot="duplex-button-active" onMouseEnter={() => onHovered(true)} {...props} />
)
);
};

const DuplexButtonHover = React.forwardRef<HTMLButtonElement, ButtonProps>(({ ...props }, ref) => {
const DuplexButtonHover = ({
...props
}: React.ComponentProps<'button'> & React.ComponentProps<typeof Button>) => {
const { active, hovered, onHovered } = useDuplexButtonContext();
return active && hovered && <Button ref={ref} onMouseLeave={() => onHovered(false)} {...props} />;
});
DuplexButtonHover.displayName = 'DuplexButtonHover';
return (
active &&
hovered && (
<Button data-slot="duplex-button-hover" onMouseLeave={() => onHovered(false)} {...props} />
)
);
};

const DuplexButtonInactive = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ ...props }, ref) => {
const { active } = useDuplexButtonContext();
return !active && <Button ref={ref} {...props} />;
},
);
DuplexButtonInactive.displayName = 'DuplexButtonInactive';
const DuplexButtonInactive = ({
...props
}: React.ComponentProps<'button'> & React.ComponentProps<typeof Button>) => {
const { active } = useDuplexButtonContext();
return !active && <Button data-slot="duplex-button-inactive" {...props} />;
};

export { DuplexButton, DuplexButtonActive, DuplexButtonHover, DuplexButtonInactive };
Loading

0 comments on commit dd57101

Please sign in to comment.