增加一个悬浮Color Picker组件
This commit is contained in:
		
							
								
								
									
										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> | ||||||
|  |   ); | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user