基本形成色卡页面功能。

This commit is contained in:
徐涛
2025-01-10 14:24:18 +08:00
parent 6708c40ffb
commit 9fec4a31e9
11 changed files with 356 additions and 1 deletions

View File

@@ -0,0 +1,42 @@
@layer pages {
.card {
width: 100%;
display: flex;
flex-direction: column;
gap: var(--spacing-n);
font-size: var(--font-size-xxs);
line-height: var(--font-size-xxs);
border: 1px solid var(--color-border);
border-radius: var(--border-radius-xs);
cursor: pointer;
}
.color_block {
width: 100%;
height: 5em;
}
.description_line {
display: flex;
flex-direction: row;
align-items: center;
padding: var(--spacing-xs) var(--spacing-s);
}
.title {
display: flex;
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-xxs);
flex: 1;
.name {
font-size: var(--font-size-xs);
line-height: var(--font-size-xs);
font-weight: bold;
}
.en_name {
font-style: italic;
color: var(--color-neutral-focus);
}
}
.color_value {
text-transform: uppercase;
}
}

View File

@@ -0,0 +1,74 @@
import { capitalize } from 'lodash-es';
import { useCallback, useMemo } from 'react';
import { useColorFunction } from '../../ColorFunctionContext';
import { useCopyColor } from '../../hooks/useCopyColor';
import { ColorDescription } from '../../models';
import styles from './ColorCard.module.css';
type ColorCardProps = {
color: ColorDescription;
copyMode?: 'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch';
};
export function ColorCard({ color, copyMode }: ColorCardProps) {
const { colorFn } = useColorFunction();
const copytToClipboard = useCopyColor();
const colorHex = useMemo(() => {
const [r, g, b] = color.rgb;
if (colorFn) {
try {
const hex = colorFn.rgb_to_hex(r, g, b);
return hex;
} catch (e) {
console.error('[Convert RGB]', e);
}
}
return `${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
}, [colorFn, color]);
const handleCopy = useCallback(() => {
switch (copyMode) {
case 'rgb':
copytToClipboard(`rgb(${color.rgb[0]}, ${color.rgb[1]}, ${color.rgb[2]})`);
break;
case 'hsl':
copytToClipboard(
`hsl(${color.hsl[0].toFixed(1)}, ${(color.hsl[1] * 100).toFixed(2)}%, ${(
color.hsl[2] * 100
).toFixed(2)}%)`,
);
break;
case 'lab':
copytToClipboard(
`lab(${color.lab[0].toFixed(1)}, ${color.lab[1].toFixed(2)}, ${color.lab[2].toFixed(2)})`,
);
break;
case 'oklch':
copytToClipboard(
`oklch(${(color.oklch[0] * 100).toFixed(2)}%, ${color.oklch[1].toFixed(
4,
)}, ${color.oklch[2].toFixed(1)})`,
);
break;
case 'hex':
default:
copytToClipboard(`#${colorHex}`);
break;
}
}, [copytToClipboard, color, copyMode, colorHex]);
return (
<div className={styles.card} onClick={handleCopy}>
<div
className={styles.color_block}
style={{ backgroundColor: `rgb(${color.rgb[0]}, ${color.rgb[1]}, ${color.rgb[2]})` }}
/>
<div className={styles.description_line}>
<div className={styles.title}>
<span className={styles.name}>{color.name}</span>
<span className={styles.en_name}>{color.pinyin.map(capitalize).join(' ')}</span>
</div>
<div className={styles.color_value}>#{colorHex}</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import cx from 'clsx';
import { NavLink } from 'react-router-dom';
import styles from './CardsNavigation.module.css';
export function CardsNavigation() {
return (
<div className={styles.cards_list}>
<menu className={styles.nav_menu}>
<li>
<NavLink
to="chinese"
className={({ isActive }) => cx(styles.nav_link, isActive && styles.active)}>
Chinese Traditional
</NavLink>
</li>
<li>
<NavLink
to="japanese"
className={({ isActive }) => cx(styles.nav_link, isActive && styles.active)}>
Japanese Traditional
</NavLink>
</li>
</menu>
</div>
);
}

View File

@@ -0,0 +1,33 @@
@layer pages {
.cards_list {
max-width: calc(var(--spacing) * 125);
flex: 1 1 calc(var(--spacing) * 125);
padding: calc(var(--spacing) * 4) 0;
box-shadow: 2px 0 8px oklch(from var(--color-black) l c h / 65%);
z-index: 40;
}
.nav_menu {
flex: 1 0;
padding: var(--spacing-n);
padding-block-start: var(--spacing-s);
display: flex;
flex-direction: column;
align-items: stretch;
gap: var(--spacing-xs);
li {
list-style: none;
a.nav_link {
display: inline-block;
width: 100%;
padding-inline: var(--spacing-l);
padding-block: var(--spacing-s);
&.active {
background-color: var(--color-primary-active);
}
&:hover {
background-color: var(--color-primary-hover);
}
}
}
}
}