Skip to content
Merged
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
1 change: 1 addition & 0 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"@mdx-js/react": "^3.1.1",
"@next/mdx": "^16.2.1",
"@tailwindcss/postcss": "^4.2.2",
"@uiw/react-color-chrome": "^2.9.6",
"framer-motion": "^12.38.0",
"is-lite": "^2.0.0",
"lucide-react": "^0.577.0",
Expand Down
163 changes: 163 additions & 0 deletions website/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion website/src/app/demos/modal/HeroModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ export default function HeroModal(props: HeroModalProps) {
backdrop: '!z-[80]',
wrapper: '!z-[90]',
}}
isDismissable={false}
isOpen={activeModal === 'heroui'}
onOpenChange={onOpenChange}
size="3xl"
Expand Down
2 changes: 2 additions & 0 deletions website/src/app/demos/modal/Modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ export default function Modal() {
<Container className="py-8 items-center justify-center">
<Joyride
onEvent={handleEvent}
portalElement="#joyride-portal"
run={run}
steps={steps}
{...mergeProps(baseProps, joyrideProps)}
Expand Down Expand Up @@ -303,6 +304,7 @@ export default function Modal() {

{/* React Modal — data table with toolbar */}
</Container>
<div data-react-aria-top-layer id="joyride-portal" />
</div>
);
}
78 changes: 43 additions & 35 deletions website/src/components/ColorPicker.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,57 @@
import { type ChangeEventHandler, useRef } from 'react';
import { Button, cn } from '@heroui/react';
import { Button, cn, Popover, PopoverContent, PopoverTrigger, useDisclosure } from '@heroui/react';
import Chrome, { ChromeInputType } from '@uiw/react-color-chrome';

interface ColorPickerProps {
export interface ColorPickerProps {
className?: string;
color: string;
isDisabled?: boolean;
onChange: ChangeEventHandler<HTMLInputElement>;
onChange: (value: string) => void;
showAlpha?: boolean;
size?: 'sm' | 'md' | 'lg';
}

export default function ColorPicker(props: ColorPickerProps) {
const { className, color, isDisabled, onChange, size = 'md', ...rest } = props;
const colorInputRef = useRef<HTMLInputElement>(null);

const left = {
sm: 'left-8',
md: 'left-10',
lg: 'left-12',
};
const { className, color, isDisabled, onChange, showAlpha = false, size = 'sm', ...rest } = props;
const { isOpen, onOpenChange } = useDisclosure();

return (
<div className="relative flex items-center">
<input
ref={colorInputRef}
aria-hidden="true"
className={cn('sr-only absolute top-1/2', left[size])}
onChange={onChange}
tabIndex={-1}
type="color"
value={color}
/>
<Button
aria-label="Color picker"
className={cn(
'shrink-0 text-foreground/10 disabled:text-foreground-200/10 rounded-full border-2 border-default disabled:cursor-not-allowed',
className,
)}
data-color={color}
isDisabled={isDisabled}
isIconOnly
onPress={() => colorInputRef.current?.click()}
size={size}
style={{ backgroundColor: color }}
{...rest}
/>
<Popover
backdrop="transparent"
classNames={{
trigger: 'aria-expanded:opacity-100 aria-expanded:scale-[1]',
}}
isOpen={isOpen}
onOpenChange={onOpenChange}
placement="bottom-start"
>
<PopoverTrigger>
<Button
aria-label="Color picker"
className={cn(
'shrink-0 text-foreground/10 disabled:text-foreground-200/10 rounded-full border-2 border-default disabled:cursor-not-allowed',
className,
)}
data-color={color}
isDisabled={isDisabled}
isIconOnly
size={size}
style={{ backgroundColor: color }}
{...rest}
/>
</PopoverTrigger>
<PopoverContent className="p-0 ">
<Chrome
color={color}
inputType={ChromeInputType.HEXA}
onChange={colorResult => {
onChange(showAlpha ? colorResult.hexa : colorResult.hex);
}}
showAlpha={showAlpha}
showTriangle={false}
/>
</PopoverContent>
</Popover>
</div>
);
}
36 changes: 36 additions & 0 deletions website/src/components/ColorSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { cn } from '@heroui/react';
import { CircleXIcon } from 'lucide-react';

import ColorPicker, { type ColorPickerProps } from '~/components/ColorPicker';

interface ColorSelectorProps extends ColorPickerProps {
fallback: string;
initialColor?: string;
label: string;
}

export default function ColorSelector(props: ColorSelectorProps) {
const { className, color, fallback, initialColor, label, onChange, ...rest } = props;

const isCustomized = initialColor && initialColor !== color;

return (
<div className={cn('flex flex-col gap-1', className)}>
<span className="text-small">{label}</span>
<div className="flex items-center gap-2">
<ColorPicker color={color || fallback} onChange={onChange} {...rest} />
{isCustomized && (
<button
aria-label="Reset color"
className="p-1"
onClick={() => onChange(initialColor)}
title="Reset Color"
type="button"
>
<CircleXIcon className="size-5" />
</button>
)}
</div>
</div>
);
}
Loading
Loading