Files
spoolman2/client/src/components/spoolIcon.tsx
tonym 267fadfc54
Some checks failed
CI / style (push) Has been cancelled
CI / build-client (push) Has been cancelled
CI / build-amd64 (push) Has been cancelled
CI / build-tester (push) Has been cancelled
CI / test (cockroachdb) (push) Has been cancelled
CI / test (mariadb) (push) Has been cancelled
CI / test (postgres) (push) Has been cancelled
CI / test (sqlite) (push) Has been cancelled
CI / build-arm64 (push) Has been cancelled
CI / build-armv7 (push) Has been cancelled
CI / publish-images (push) Has been cancelled
CI / publish-release (push) Has been cancelled
feat(color): add hex code display and click-to-copy functionality
Enhances SpoolIcon component with optional showHex prop:
- Displays hex color code next to swatch when enabled
- Click to copy hex code to clipboard
- Shows tooltip with copy hint
- Supports both single and multi-color filaments

Enabled on detail pages:
- Filament show page
- Spool show page

Added translation keys for copy feedback messages.

Closes #33

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 23:33:21 -06:00

73 lines
2.1 KiB
TypeScript

import { CopyOutlined } from "@ant-design/icons";
import { message, Tooltip } from "antd";
import { useTranslate } from "@refinedev/core";
import "./spoolIcon.css";
interface Props {
color: string | { colors: string[]; vertical: boolean };
size?: "small" | "large";
no_margin?: boolean;
showHex?: boolean;
}
export default function SpoolIcon(props: Readonly<Props>) {
const t = useTranslate();
let dirClass = "vertical";
let cols: string[] = [];
const size = props.size ? props.size : "small";
const no_margin = props.no_margin ? "no-margin" : "";
if (typeof props.color === "string") {
cols = [props.color];
} else {
dirClass = props.color.vertical ? "vertical" : "horizontal";
cols = props.color.colors;
}
// Normalize hex codes (remove # if present, uppercase)
const normalizedCols = cols.map((col) => col.replace("#", "").toUpperCase());
const hexDisplay = normalizedCols.length === 1 ? `#${normalizedCols[0]}` : normalizedCols.map((c) => `#${c}`).join(", ");
const copyToClipboard = async () => {
try {
await navigator.clipboard.writeText(hexDisplay);
message.success(t("color.copied", { color: hexDisplay }));
} catch {
message.error(t("color.copy_failed"));
}
};
const swatchContent = (
<div className={"spool-icon " + dirClass + " " + size + " " + no_margin}>
{normalizedCols.map((col) => (
<div
key={col}
style={{
backgroundColor: "#" + col,
}}
></div>
))}
</div>
);
if (props.showHex) {
return (
<Tooltip title={`${t("color.click_to_copy")}: ${hexDisplay}`}>
<div
className="spool-icon-with-hex"
onClick={copyToClipboard}
style={{ cursor: "pointer", display: "inline-flex", alignItems: "center", gap: 8 }}
>
{swatchContent}
<span className="hex-code" style={{ fontFamily: "monospace", fontSize: "0.85em", opacity: 0.8 }}>
{hexDisplay}
<CopyOutlined style={{ marginLeft: 4, fontSize: "0.9em" }} />
</span>
</div>
</Tooltip>
);
}
return swatchContent;
}