diff --git a/src/components/ColorStand.module.css b/src/components/ColorStand.module.css new file mode 100644 index 0000000..2294075 --- /dev/null +++ b/src/components/ColorStand.module.css @@ -0,0 +1,60 @@ +@layer components { + .color_stand { + display: flex; + flex-direction: column; + font-size: var(--font-size-xs); + border: 1px solid var(--color-border); + border-radius: var(--border-radius-xxs); + min-width: 200px; + .preview_box { + position: relative; + .head_line { + position: absolute; + width: 100%; + display: flex; + flex-direction: row; + justify-content: flex-start; + gap: var(--spacing-xxs); + padding: var(--spacing-xxs) var(--spacing-xs); + h5 { + display: inline-block; + flex: 1; + font-size: var(--font-size-xs); + line-height: calc(var(--font-size-xs) * 1.2); + filter: drop-shadow(0 0 2px oklch(from var(--color-black) l c h / 30%)); + } + } + .color_box { + aspect-ratio: 3 / 2; + } + } + .color_describe { + display: flex; + flex-direction: column; + gap: var(--spacing-xs); + padding: var(--spacing-xs); + } + } + .color_value { + display: flex; + flex-direction: row; + justify-content: space-between; + gap: var(--spacing-xxs); + font-size: var(--font-size-xs); + line-height: var(--font-size-xs); + padding-inline: var(--spacing-xxs); + h6 { + font-size: var(--font-size-xs); + } + .na_value { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--spacing-xs); + color: var(--color-warn); + } + .value { + font-size: var(--font-size-xs); + } + } +} diff --git a/src/components/ColorStand.tsx b/src/components/ColorStand.tsx new file mode 100644 index 0000000..56c84b2 --- /dev/null +++ b/src/components/ColorStand.tsx @@ -0,0 +1,123 @@ +import { Icon } from '@iconify/react/dist/iconify.js'; +import { isNil } from 'lodash-es'; +import { useCallback, useEffect, useMemo } from 'react'; +import { useCopyToClipboard } from 'react-use'; +import NoColor from '../assets/NoColor.svg'; +import { useColorFunction } from '../ColorFunctionContext'; +import styles from './ColorStand.module.css'; +import { NotificationType, useNotification } from './Notifications'; + +type ColorValueProps = { + title: string; + value: string | null; +}; + +function ColorValue({ title, value }: ColorValueProps) { + const [cpState, copyToClipboard] = useCopyToClipboard(); + const { showToast } = useNotification(); + const handleCopy = useCallback(() => { + if (!isNil(value)) { + copyToClipboard(value); + } + }, [value]); + + useEffect(() => { + if (!isNil(cpState.error)) { + showToast(NotificationType.ERROR, 'Failed to copy to clipboard', 'tabler:alert-circle', 3000); + } else if (!isNil(cpState.value)) { + showToast( + NotificationType.SUCCESS, + `${cpState.value} has been copied to clipboard.`, + 'tabler:circle-check', + 3000, + ); + } + }, [cpState]); + + return ( +