feat(board/promoted_attributes): improve rendering for color badge

This commit is contained in:
Elian Doran
2025-11-13 09:14:13 +02:00
parent 5dbe9e7da6
commit 3036d18df5
2 changed files with 30 additions and 24 deletions

View File

@@ -76,6 +76,11 @@ function getHue(color: ColorInstance) {
} }
} }
export function getReadableTextColor(bgColor: string) {
const colorInstance = Color(bgColor);
return colorInstance.isLight() ? "#000" : "#fff";
}
export default { export default {
createClassForColor createClassForColor
}; };

View File

@@ -5,9 +5,10 @@ import { useTriliumEvent } from "../react/hooks";
import attributes from "../../services/attributes"; import attributes from "../../services/attributes";
import { DefinitionObject } from "../../services/promoted_attribute_definition_parser"; import { DefinitionObject } from "../../services/promoted_attribute_definition_parser";
import { formatDateTime } from "../../utils/formatters"; import { formatDateTime } from "../../utils/formatters";
import { ComponentChildren } from "preact"; import { ComponentChildren, CSSProperties } from "preact";
import Icon from "../react/Icon"; import Icon from "../react/Icon";
import NoteLink from "../react/NoteLink"; import NoteLink from "../react/NoteLink";
import { getReadableTextColor } from "../../services/css_class_manager";
interface PromotedAttributesDisplayProps { interface PromotedAttributesDisplayProps {
note: FNote; note: FNote;
@@ -26,15 +27,7 @@ export default function PromotedAttributesDisplay({ note, ignoredAttributes }: P
const promotedDefinitionAttributes = useNoteAttributesWithDefinitions(note, ignoredAttributes); const promotedDefinitionAttributes = useNoteAttributesWithDefinitions(note, ignoredAttributes);
return promotedDefinitionAttributes?.length > 0 && ( return promotedDefinitionAttributes?.length > 0 && (
<div className="promoted-attributes"> <div className="promoted-attributes">
{promotedDefinitionAttributes?.map((attr) => { {promotedDefinitionAttributes?.map(attr => buildPromotedAttribute(attr))}
const className = `${attr.type === "label" ? "label" + " " + attr.def.labelType : "relation"}`;
return (
<span key={attr.friendlyName} className={`promoted-attribute type-${className}`}>
{attr.type === "relation" ? formatRelation(attr) : formatLabelValue(attr)}
</span>
);
}
)}
</div> </div>
) )
@@ -52,7 +45,21 @@ function useNoteAttributesWithDefinitions(note: FNote, attributesToIgnore: stri
return promotedDefinitionAttributes; return promotedDefinitionAttributes;
} }
function formatLabelValue(attr: AttributeWithDefinitions): ComponentChildren { function PromotedAttribute({ attr, children, style }: { attr: AttributeWithDefinitions, children: ComponentChildren, style?: CSSProperties }) {
const className = `${attr.type === "label" ? "label" + " " + attr.def.labelType : "relation"}`;
return (
<span key={attr.friendlyName} className={`promoted-attribute type-${className}`} style={style}>
{children}
</span>
)
}
function buildPromotedAttribute(attr: AttributeWithDefinitions): ComponentChildren {
if (attr.type === "relation") {
return <PromotedAttribute attr={attr}><strong>{attr.friendlyName}:</strong> <NoteLink notePath={attr.value} showNoteIcon /></PromotedAttribute>
}
let value = attr.value; let value = attr.value;
switch (attr.def.labelType) { switch (attr.def.labelType) {
case "number": case "number":
@@ -61,35 +68,29 @@ function formatLabelValue(attr: AttributeWithDefinitions): ComponentChildren {
if (attr.def.numberPrecision) { if (attr.def.numberPrecision) {
formattedValue = numberValue.toFixed(attr.def.numberPrecision); formattedValue = numberValue.toFixed(attr.def.numberPrecision);
} }
return <><strong>{attr.friendlyName}:</strong> {formattedValue}</>; return <PromotedAttribute attr={attr}><strong>{attr.friendlyName}:</strong> {formattedValue}</PromotedAttribute>;
case "date": case "date":
case "datetime": { case "datetime": {
const date = new Date(value); const date = new Date(value);
const timeFormat = attr.def.labelType !== "date" ? "short" : "none"; const timeFormat = attr.def.labelType !== "date" ? "short" : "none";
return <><strong>{attr.friendlyName}:</strong> {formatDateTime(date, "short", timeFormat)}</>; return <PromotedAttribute attr={attr}><strong>{attr.friendlyName}:</strong> {formatDateTime(date, "short", timeFormat)}</PromotedAttribute>;
} }
case "time": { case "time": {
const date = new Date(`1970-01-01T${value}Z`); const date = new Date(`1970-01-01T${value}Z`);
return <><strong>{attr.friendlyName}:</strong> {formatDateTime(date, "none", "short")}</>; return <PromotedAttribute attr={attr}><strong>{attr.friendlyName}:</strong> {formatDateTime(date, "none", "short")}</PromotedAttribute>;
} }
case "boolean": case "boolean":
return <><Icon icon={value === "true" ? "bx bx-check-square" : "bx bx-square"} /> <strong>{attr.friendlyName}</strong></>; return <PromotedAttribute attr={attr}><Icon icon={value === "true" ? "bx bx-check-square" : "bx bx-square"} /> <strong>{attr.friendlyName}</strong></PromotedAttribute>;
case "url": case "url":
return <><a href={value} target="_blank" rel="noopener noreferrer">{attr.friendlyName}</a></>; return <PromotedAttribute attr={attr}><a href={value} target="_blank" rel="noopener noreferrer">{attr.friendlyName}</a></PromotedAttribute>;
case "color": case "color":
return <><span style={{ color: value }}>{attr.friendlyName}</span></>; return <PromotedAttribute attr={attr} style={{ backgroundColor: value, color: getReadableTextColor(value) }}>{attr.friendlyName}</PromotedAttribute>;
case "text": case "text":
default: default:
return <><strong>{attr.friendlyName}:</strong> {value}</>; return <PromotedAttribute attr={attr}><strong>{attr.friendlyName}:</strong> {value}</PromotedAttribute>;
} }
} }
function formatRelation(attr: AttributeWithDefinitions): ComponentChildren {
return (
<><strong>{attr.friendlyName}:</strong> <NoteLink notePath={attr.value} showNoteIcon /></>
)
}
function getAttributesWithDefinitions(note: FNote, attributesToIgnore: string[] = []): AttributeWithDefinitions[] { function getAttributesWithDefinitions(note: FNote, attributesToIgnore: string[] = []): AttributeWithDefinitions[] {
const promotedDefinitionAttributes = note.getAttributeDefinitions(); const promotedDefinitionAttributes = note.getAttributeDefinitions();
const result: AttributeWithDefinitions[] = []; const result: AttributeWithDefinitions[] = [];