增加一个悬浮Color Picker组件
This commit is contained in:
parent
7b26c95a9a
commit
a9ad4dea5d
38
src/components/FloatColorPicker.module.css
Normal file
38
src/components/FloatColorPicker.module.css
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
src/components/FloatColorPicker.tsx
Normal file
54
src/components/FloatColorPicker.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user