chore: improve UI

This commit is contained in:
Aleix Soler 2025-08-07 20:02:23 +02:00
parent 7dcac0a704
commit 1629944738
2 changed files with 36 additions and 166 deletions

View file

@ -1,4 +1,4 @@
import React, { FC, memo, useEffect, useState } from "react";
import React, { FC, memo } from "react";
import { GroupedStatuses } from "@/types/noteStatus";
import { StatusesInfoPopup } from "@/integrations/popups/statusesInfoPopupIntegration";
@ -13,20 +13,12 @@ interface EditorToolbarButtonProps {
export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
({ statuses, onClick, unknownStatusConfig }) => {
const [statusChanged, setStatusChanged] = useState(false);
const statusEntries = Object.entries(statuses);
const allStatuses = statusEntries.flatMap(
([_, statusList]) => statusList,
);
const totalStatuses = allStatuses.length;
// Animate when status changes
useEffect(() => {
setStatusChanged(true);
const timer = setTimeout(() => setStatusChanged(false), 600);
return () => clearTimeout(timer);
}, [statusEntries.length, allStatuses.map((s) => s.name).join(",")]);
const handleMouseEnter = () => {
StatusesInfoPopup.open(statuses);
};
@ -37,27 +29,15 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
const getPrimaryStatus = () => allStatuses[0];
const containerClasses = [
"editor-toolbar-button",
totalStatuses === 0
? "editor-toolbar-button--no-status"
: "editor-toolbar-button--has-status",
totalStatuses > 1 ? "editor-toolbar-button--multiple" : "",
statusChanged ? "editor-toolbar-button--status-changed" : "",
]
.filter(Boolean)
.join(" ");
// No status state
if (totalStatuses === 0) {
return (
<button
type="button"
className={containerClasses}
className="clickable-icon"
onClick={onClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
title="No status assigned - click to add"
aria-label="Add status to note"
>
<span
@ -66,9 +46,6 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
>
{unknownStatusConfig.icon}
</span>
<span className="editor-toolbar-button__text">
Add Status
</span>
</button>
);
}
@ -80,22 +57,14 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
return (
<button
type="button"
className={containerClasses}
className="clickable-icon"
onClick={onClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
title={`Status: ${primaryStatus.name} - click to change`}
aria-label={`Current status: ${primaryStatus.name}. Click to change.`}
style={
{
"--status-color":
primaryStatus.color ||
"var(--interactive-accent)",
} as React.CSSProperties
}
>
<span
className="editor-toolbar-button__icon"
className="editor-toolbar-button__icon editor-toolbar-button__icon--has-status"
style={{
color:
primaryStatus.color ||
@ -104,9 +73,6 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
>
{primaryStatus.icon || "📝"}
</span>
<span className="editor-toolbar-button__text">
{primaryStatus.name}
</span>
</button>
);
}
@ -115,22 +81,15 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
return (
<button
type="button"
className={containerClasses}
className="clickable-icon"
onClick={onClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
title={`${totalStatuses} statuses: ${allStatuses.map((s) => s.name).join(", ")} - click to change`}
aria-label={`${totalStatuses} statuses assigned. Click to change.`}
style={
{
"--status-color":
primaryStatus.color || "var(--interactive-accent)",
} as React.CSSProperties
}
>
<span className="editor-toolbar-button__icon-stack">
<div className="editor-toolbar-button__icon-container">
<span
className="editor-toolbar-button__icon"
className="editor-toolbar-button__icon editor-toolbar-button__icon--has-status"
style={{
color:
primaryStatus.color ||
@ -142,10 +101,7 @@ export const EditorToolbarButton: FC<EditorToolbarButtonProps> = memo(
<span className="editor-toolbar-button__counter">
{totalStatuses}
</span>
</span>
<span className="editor-toolbar-button__text">
{totalStatuses} Status{totalStatuses === 1 ? "" : "es"}
</span>
</div>
</button>
);
},

View file

@ -1,75 +1,46 @@
/* Editor Toolbar Button - Obsidian-integrated icon button */
.editor-toolbar-button {
/* Editor Toolbar Button - Using Obsidian's native clickable-icon styling */
/* Container styling for proper integration */
.note-status-editor-toolbar-badge {
display: inline-flex;
align-items: center;
justify-content: center;
gap: var(--size-2-1);
padding: var(--size-2-1);
background: transparent;
border: 1px solid transparent;
border-radius: var(--radius-s);
font-size: var(--font-ui-smaller);
font-weight: var(--font-medium);
color: var(--icon-color, var(--text-muted));
cursor: pointer;
transition: all var(--anim-duration-fast) ease;
position: relative;
min-width: 24px;
min-height: 24px;
opacity: var(--icon-opacity);
outline: none;
margin: 0 var(--size-2-1);
}
.editor-toolbar-button:hover {
background: transparent;
border-color: var(--background-modifier-border);
opacity: var(--icon-opacity-hover);
color: var(--icon-color-hover, var(--text-normal));
}
.editor-toolbar-button:active {
background: var(--background-modifier-hover);
border-color: var(--background-modifier-border-hover);
opacity: var(--icon-opacity-active);
}
.editor-toolbar-button:focus-visible {
outline: 2px solid var(--interactive-accent);
outline-offset: 1px;
}
/* Icon styling */
.editor-toolbar-button__icon {
font-size: 14px;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
min-width: 14px;
}
/* Text styling - Hidden by default, shown on hover */
.editor-toolbar-button__text {
/* Hidden state */
.note-status-editor-toolbar-badge--hidden {
display: none;
white-space: nowrap;
line-height: 1.2;
font-size: var(--font-ui-smaller);
font-weight: var(--font-medium);
margin-left: var(--size-2-1);
}
/* Icon stack for multiple statuses */
.editor-toolbar-button__icon-stack {
/* BEM-based styles for toolbar button components */
/* Status icon styling */
.editor-toolbar-button__icon {
font-size: 16px;
display: flex;
align-items: center;
justify-content: center;
color: var(--text-muted);
}
/* Icon with status color */
.editor-toolbar-button__icon--has-status {
color: var(--interactive-accent);
}
/* Multiple statuses container */
.editor-toolbar-button__icon-container {
position: relative;
display: flex;
align-items: center;
justify-content: center;
}
/* Status counter badge */
.editor-toolbar-button__counter {
position: absolute;
top: -2px;
right: -2px;
top: -4px;
right: -6px;
min-width: 12px;
height: 12px;
padding: 0 2px;
@ -84,60 +55,3 @@
line-height: 1;
border: 1px solid var(--background-primary);
}
/* Status variants */
.editor-toolbar-button--has-status {
color: var(--status-color, var(--interactive-accent));
}
.editor-toolbar-button--has-status:hover {
color: var(--status-color, var(--interactive-accent));
}
.editor-toolbar-button--no-status {
color: var(--text-muted);
}
.editor-toolbar-button--no-status:hover {
color: var(--text-normal);
}
/* Multiple statuses styling */
.editor-toolbar-button--multiple {
color: var(--status-color, var(--interactive-accent));
position: relative;
}
/* Status change animation */
@keyframes status-change-pulse {
0% {
opacity: var(--icon-opacity);
}
50% {
opacity: 1;
}
100% {
opacity: var(--icon-opacity);
}
}
.editor-toolbar-button--status-changed {
animation: status-change-pulse 0.6s ease-out;
}
/* Show text on hover for better UX */
.editor-toolbar-button:hover .editor-toolbar-button__text {
display: inline;
}
/* Container styling for proper integration */
.note-status-editor-toolbar-badge {
display: inline-flex;
align-items: center;
margin: 0 var(--size-2-1);
}
/* Hidden state */
.note-status-editor-toolbar-badge--hidden {
display: none;
}