增加一个悬浮Color Picker组件

This commit is contained in:
徐涛 2025-01-27 07:48:21 +08:00
parent 7b26c95a9a
commit a9ad4dea5d
2 changed files with 92 additions and 0 deletions

View File

@ -0,0 +1,38 @@
@layer components {
.float_color_picker {
position: relative;
height: 32px;
.preview {
height: 100%;
display: flex;
flex-direction: row;
align-items: center;
gap: var(--spacing-xs);
.preview_block {
height: 100%;
aspect-ratio: 16 / 9;
border-radius: var(--border-radius-xxs);
border: 1px solid var(--color-border);
cursor: pointer;
}
}
.picker {
position: absolute;
top: calc(100% + 4px);
padding: var(--spacing-s) var(--spacing-s);
border-radius: var(--border-radius-xxs);
border: 1px solid var(--color-border);
background-color: var(--color-bg);
box-shadow: 2px 0 8px oklch(from var(--color-black) l c h / 65%);
display: flex;
flex-direction: column;
align-items: stretch;
gap: var(--spacing-s);
.btns {
display: flex;
flex-direction: row-reverse;
gap: var(--spacing-xs);
}
}
}
}

View File

@ -0,0 +1,54 @@
import { isEqual, isNil } from 'lodash-es';
import { useCallback, useEffect, useState } from 'react';
import { ActionIcon } from './ActionIcon';
import { ColorPicker } from './ColorPicker';
import styles from './FloatColorPicker.module.css';
type FloatColorPickerProps = {
name?: string;
color?: string;
onPick?: (color: string) => void;
};
export function FloatColorPicker({ name, color, onPick }: FloatColorPickerProps) {
const [pickedColor, setPicked] = useState<string | null>(color ?? null);
const [showPicker, setPickerShow] = useState(false);
const handlePickAction = useCallback(
(value: string | null) => {
setPicked(value);
onPick?.(value);
},
[onPick],
);
useEffect(() => {
if (!isEqual(pickedColor, color)) {
setPicked(color);
}
}, [color]);
return (
<div className={styles.float_color_picker}>
<div className={styles.preview}>
<div
className={styles.preview_block}
onClick={() => setPickerShow(true)}
style={{
backgroundColor: isNil(pickedColor) ? 'rgba(0, 0, 0, 0)' : `#${pickedColor}`,
}}></div>
<ActionIcon icon="tabler:x" onClick={() => handlePickAction(null)} />
</div>
{showPicker && (
<div className={styles.picker}>
<ColorPicker color={pickedColor} onSelect={handlePickAction} />
<div className={styles.btns}>
<button type="button" className="primary" onClick={() => setPickerShow(false)}>
Done
</button>
</div>
</div>
)}
{!isNil(name) && <input type="hidden" name={name} value={pickedColor} />}
</div>
);
}