chore: icon selection field added

This commit is contained in:
Aleix Soler 2025-11-21 09:13:22 +01:00
parent e5233f6f0e
commit 2e7c3ad66c
4 changed files with 137 additions and 46 deletions

View file

@ -2,7 +2,7 @@ import { NoteStatus } from "@/types/noteStatus";
import React from "react";
import { Input } from "@/components/atoms/Input";
import { StatusIcon } from "@/components/atoms/StatusIcon";
import { LucideIconPicker } from "./LucideIconPicker";
import { IconSelectionField } from "./IconSelectionField";
export type Props = {
status: NoteStatus;
@ -32,44 +32,23 @@ export const CustomStatusItem: React.FC<Props> = ({
const isValid = status.name.trim().length > 0;
return (
<div className="custom-status-item">
<div className="custom-status-item__row custom-status-item__row--icons">
<div className="custom-status-item__field custom-status-item__field--icon">
<label className="custom-status-item__label">
Emoji icon
</label>
<Input
variant="text"
value={status.icon}
onChange={(value) =>
onCustomStatusChange(index, "icon", value || "")
}
placeholder="Example: ✅ or 🚧"
className="custom-status-item__input custom-status-item__input--icon"
/>
<p className="custom-status-item__hint">
This fallback icon is shown anywhere Lucide is not
available.
</p>
</div>
<div className="custom-status-item__field custom-status-item__field--lucide">
<label className="custom-status-item__label">
Lucide icon (optional)
</label>
<LucideIconPicker
value={status.lucideIcon || ""}
onChange={(value) =>
onCustomStatusChange(index, "lucideIcon", value)
}
placeholder="Browse Lucide icons"
allowClear
/>
<p className="custom-status-item__hint">
Matches Obsidian&apos;s toolbar icons so your status
button blends in.
</p>
</div>
</div>
<IconSelectionField
className="custom-status-item__icon-fields"
emojiValue={status.icon}
onEmojiChange={(value) =>
onCustomStatusChange(index, "icon", value || "")
}
emojiLabel="Emoji icon"
emojiPlaceholder="Example: ✅ or 🚧"
emojiHint="Shown anywhere Lucide is not available."
lucideValue={status.lucideIcon || ""}
onLucideChange={(value) =>
onCustomStatusChange(index, "lucideIcon", value)
}
lucideLabel="Lucide icon (optional)"
lucidePlaceholder="Browse Lucide icons"
lucideHint="Matches Obsidian's toolbar icons so your status button blends in."
/>
{/* Simple horizontal layout with remaining inputs */}
<div className="custom-status-item__row">

View file

@ -0,0 +1,75 @@
import React from "react";
import { Input } from "@/components/atoms/Input";
import { LucideIconPicker } from "./LucideIconPicker";
export interface IconSelectionFieldProps {
className?: string;
emojiValue: string;
onEmojiChange: (value: string) => void;
emojiLabel?: string;
emojiPlaceholder?: string;
emojiHint?: string;
lucideValue?: string;
onLucideChange?: (value: string) => void;
lucideLabel?: string;
lucidePlaceholder?: string;
lucideHint?: string;
lucideAllowClear?: boolean;
}
export const IconSelectionField: React.FC<IconSelectionFieldProps> = ({
className = "",
emojiValue,
onEmojiChange,
emojiLabel = "Emoji fallback",
emojiPlaceholder = "Example: ✅",
emojiHint,
lucideValue,
onLucideChange,
lucideLabel = "Lucide icon",
lucidePlaceholder = "Choose Lucide icon",
lucideHint,
lucideAllowClear = true,
}) => {
const containerClass = ["icon-selection-field", className]
.filter(Boolean)
.join(" ");
return (
<div className={containerClass}>
<div className="icon-selection-field__column">
<label className="icon-selection-field__label">
{emojiLabel}
</label>
<Input
variant="text"
value={emojiValue}
onChange={onEmojiChange}
placeholder={emojiPlaceholder}
className="icon-selection-field__emoji-input"
/>
{emojiHint && (
<p className="icon-selection-field__hint">{emojiHint}</p>
)}
</div>
{onLucideChange && (
<div className="icon-selection-field__column">
<label className="icon-selection-field__label">
{lucideLabel}
</label>
<LucideIconPicker
value={lucideValue}
onChange={onLucideChange}
placeholder={lucidePlaceholder}
allowClear={lucideAllowClear}
/>
{lucideHint && (
<p className="icon-selection-field__hint">
{lucideHint}
</p>
)}
</div>
)}
</div>
);
};

View file

@ -3,7 +3,7 @@ import React from "react";
import { Input } from "../atoms/Input";
import { Select } from "../atoms/Select";
import { SettingItem } from "./SettingItem";
import { LucideIconPicker } from "./LucideIconPicker";
import { IconSelectionField } from "./IconSelectionField";
export type Props = {
settings: PluginSettings;
@ -270,13 +270,21 @@ export const UISettings: React.FC<Props> = ({ settings, onChange }) => {
<SettingItem
name="Icon for unknown status"
description="Emoji or Lucide icon name displayed whenever a note does not have a status."
vertical
>
<LucideIconPicker
value={settings.unknownStatusIcon}
onChange={(value) => onChange("unknownStatusIcon", value)}
placeholder="Emoji or Lucide icon"
allowTextInput
allowClear
<IconSelectionField
emojiValue={settings.unknownStatusIcon}
onEmojiChange={(value) =>
onChange("unknownStatusIcon", value)
}
emojiPlaceholder="❓"
emojiHint="Type any emoji or text fallback."
lucideValue={settings.unknownStatusIcon}
onLucideChange={(value) =>
onChange("unknownStatusIcon", value)
}
lucidePlaceholder="Choose Lucide icon"
lucideHint="Matches the Obsidian toolbar style."
/>
</SettingItem>

View file

@ -155,3 +155,32 @@
color: var(--text-muted);
padding: var(--size-4-2);
}
.icon-selection-field {
display: flex;
flex-wrap: wrap;
gap: var(--size-4-2);
}
.icon-selection-field__column {
flex: 1;
min-width: 220px;
}
.icon-selection-field__label {
display: block;
font-size: var(--font-ui-smaller);
font-weight: var(--font-medium);
color: var(--text-muted);
margin-bottom: var(--size-2-1);
}
.icon-selection-field__emoji-input {
max-width: 260px;
}
.icon-selection-field__hint {
margin-top: var(--size-2-1);
font-size: var(--font-ui-smaller);
color: var(--text-muted);
}