Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions apps/www/src/content/docs/components/button/props.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { ButtonHTMLAttributes } from 'react';

export type ButtonProps = {
/**
* Visual style variant
Expand Down Expand Up @@ -41,8 +43,27 @@ export type ButtonProps = {
/** Custom width for the button */
width?: string | number;

/** Boolean to merge props onto child element */
asChild?: boolean;
/**
* Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (e.g. <div>).
* Defaults to false when render prop is provided.
*/
nativeButton?: boolean;

/**
* Whether the button should be focusable when disabled.
* Defaults to true when loading is true.
*/
focusableWhenDisabled?: boolean;

/**
* Allows rendering the button as a different element.
* Accepts a React element or a function that receives props and returns an element.
*
* @remarks `ReactElement | function`
*/
render?:
| React.ReactElement<ButtonHTMLAttributes<HTMLButtonElement>>
| ((props: ButtonHTMLAttributes<HTMLButtonElement>) => React.ReactElement);

/** Additional CSS class names */
className?: string;
Expand Down
15 changes: 15 additions & 0 deletions apps/www/src/content/docs/components/flex/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ export interface FlexProps {
/** Sets how flex items are placed in the flex container defining the main axis and the direction (normal or reversed) */
direction?: 'row' | 'rowReverse' | 'column' | 'columnReverse';

/**
* Sets the width of the flex container.
*/
width?: 'full';

/**
* Allows rendering the flex container as a different element.
* Accepts a React element or a function that receives props and returns an element.
*
* @remarks `ReactElement | function`
*/
render?:
| React.ReactElement
| ((props: React.HTMLAttributes<HTMLDivElement>) => React.ReactElement);

/** Custom CSS class names */
className?: string;
}
20 changes: 14 additions & 6 deletions apps/www/src/content/docs/components/grid/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,14 @@ export interface GridProps {
inline?: boolean;

/**
* Merges the grid's props with its child component.
* Useful for composition with other components.
* Allows rendering the grid as a different element.
* Accepts a React element or a function that receives props and returns an element.
*
* @remarks `ReactElement | function`
*/
asChild?: boolean;
render?:
| React.ReactElement
| ((props: React.HTMLAttributes<HTMLDivElement>) => React.ReactElement);
}

export interface GridItemProps {
Expand Down Expand Up @@ -149,8 +153,12 @@ export interface GridItemProps {
alignSelf?: 'start' | 'end' | 'center' | 'stretch';

/**
* Merges the grid item's props with its child component.
* Useful for composition with other components.
* Allows rendering the grid item as a different element.
* Accepts a React element or a function that receives props and returns an element.
*
* @remarks `ReactElement | function`
*/
asChild?: boolean;
render?:
| React.ReactElement
| ((props: React.HTMLAttributes<HTMLDivElement>) => React.ReactElement);
}
1 change: 1 addition & 0 deletions packages/raystack/components/button/button.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
.button-disabled {
opacity: 0.5;
cursor: not-allowed;
pointer-events: initial;
}

.button:disabled:hover,
Expand Down
29 changes: 14 additions & 15 deletions packages/raystack/components/button/button.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { type VariantProps, cva } from 'class-variance-authority';
import { Slot } from 'radix-ui';
import {
ButtonHTMLAttributes,
PropsWithChildren,
ReactNode,
forwardRef
} from 'react';
import { Button as ButtonPrimitive } from '@base-ui/react';
import { cva, type VariantProps } from 'class-variance-authority';
import { ElementRef, forwardRef, PropsWithChildren, ReactNode } from 'react';

import { Spinner } from '../spinner';
import styles from './button.module.css';
Expand Down Expand Up @@ -130,8 +125,7 @@ const getLoaderOnlyClass = (size: 'small' | 'normal' | null) =>
: styles['loader-only-button-normal'];

type ButtonProps = PropsWithChildren<VariantProps<typeof button>> &
ButtonHTMLAttributes<HTMLButtonElement> & {
asChild?: boolean;
ButtonPrimitive.Props & {
loading?: boolean;
loaderText?: ReactNode;
leadingIcon?: ReactNode;
Expand All @@ -141,14 +135,16 @@ type ButtonProps = PropsWithChildren<VariantProps<typeof button>> &
style?: React.CSSProperties;
};

export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
export const Button = forwardRef<
ElementRef<typeof ButtonPrimitive>,
ButtonProps
>(
(
{
className,
variant = 'solid',
color = 'accent',
size = 'normal',
asChild = false,
disabled,
loading,
loaderText,
Expand All @@ -158,21 +154,24 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
width,
style = {},
children,
render,
...props
},
ref
) => {
const Comp = asChild ? Slot.Root : 'button';
const isLoaderOnly = loading && !loaderText;
const widthStyle = { maxWidth, width };
const buttonStyle = { ...widthStyle, ...style };

return (
<Comp
<ButtonPrimitive
className={`${button({ variant, size, color, disabled, loading, className })} ${isLoaderOnly ? getLoaderOnlyClass(size) : ''}`}
ref={ref}
disabled={disabled}
style={buttonStyle}
render={render}
nativeButton={!render}
focusableWhenDisabled={loading}
{...props}
>
{loading ? (
Expand All @@ -197,7 +196,7 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
)}
</>
)}
</Comp>
</ButtonPrimitive>
);
}
);
Expand Down
48 changes: 25 additions & 23 deletions packages/raystack/components/flex/flex.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { VariantProps, cva } from 'class-variance-authority';
import { HTMLAttributes, PropsWithChildren, forwardRef } from 'react';

import { mergeProps, useRender } from '@base-ui/react';
import { cva, VariantProps } from 'class-variance-authority';
import { forwardRef } from 'react';
import styles from './flex.module.css';

const flex = cva(styles.flex, {
Expand Down Expand Up @@ -57,40 +57,42 @@ const flex = cva(styles.flex, {
}
});

type BoxProps = PropsWithChildren<VariantProps<typeof flex>> &
HTMLAttributes<HTMLDivElement>;
type BoxProps = VariantProps<typeof flex> & useRender.ComponentProps<'div'>;

export const Flex = forwardRef<HTMLDivElement, BoxProps>(
(
{
children,
direction,
align,
justify,
wrap,
gap,
className,
width,
render,
...props
},
ref
) => {
return (
<div
className={flex({
direction,
align,
justify,
wrap,
gap,
className,
width
})}
{...props}
ref={ref}
>
{children}
</div>
);
const flexProps = {
className: flex({
direction,
align,
justify,
wrap,
gap,
className,
width
})
};

const element = useRender({
defaultTagName: 'div',
ref,
render,
props: mergeProps<'div'>(flexProps, props)
});

return element;
}
);
48 changes: 24 additions & 24 deletions packages/raystack/components/grid/grid-item.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Slot } from 'radix-ui';
import { HTMLAttributes, forwardRef } from 'react';
import { mergeProps, useRender } from '@base-ui/react';
import { forwardRef } from 'react';
import { AlignType } from './types';

type GridItemProps = HTMLAttributes<HTMLDivElement> & {
type GridItemProps = useRender.ComponentProps<'div'> & {
area?: string;
colStart?: number | string;
colEnd?: number | string;
Expand All @@ -12,7 +12,6 @@ type GridItemProps = HTMLAttributes<HTMLDivElement> & {
rowSpan?: number | string;
justifySelf?: AlignType;
alignSelf?: AlignType;
asChild?: boolean;
};

export const GridItem = forwardRef<HTMLDivElement, GridItemProps>(
Expand All @@ -28,31 +27,32 @@ export const GridItem = forwardRef<HTMLDivElement, GridItemProps>(
justifySelf,
alignSelf,
style,
asChild,
render,
...props
},
ref
) => {
const Comp = asChild ? Slot.Root : 'div';
const gridItemStyle = {
gridArea: area,
gridColumnStart: colStart,
gridColumnEnd: colEnd,
gridRowStart: rowStart,
gridRowEnd: rowEnd,
gridColumn: colSpan ? `span ${colSpan}` : undefined,
gridRow: rowSpan ? `span ${rowSpan}` : undefined,
justifySelf,
alignSelf,
...style
};

const element = useRender({
defaultTagName: 'div',
ref,
render,
props: mergeProps<'div'>({ style: gridItemStyle }, props)
});

return (
<Comp
ref={ref}
style={{
gridArea: area,
gridColumnStart: colStart,
gridColumnEnd: colEnd,
gridRowStart: rowStart,
gridRowEnd: rowEnd,
gridColumn: colSpan ? `span ${colSpan}` : undefined,
gridRow: rowSpan ? `span ${rowSpan}` : undefined,
justifySelf,
alignSelf,
...style
}}
{...props}
/>
);
return element;
}
);

Expand Down
Loading