style(ui): counters on labels sit right after the word
The counter hung at the label's right edge with a fixed 12 px gap, so two-digit numbers covered part of the last letter. It now follows the word in the text flow (position="text"): only its ring overlaps, the same for any number of digits, and wide numbers widen the tab. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8989321bdd
commit
92993c2dd2
6 files changed
+29
-19
No files matched your search
@@ -1198,9 +1198,9 @@ export const App: React.FC = () => {
|
|||||||
className={`tab-btn ${activeTab === 'triage' ? 'tab-btn-active' : ''}`}
|
className={`tab-btn ${activeTab === 'triage' ? 'tab-btn-active' : ''}`}
|
||||||
>
|
>
|
||||||
<Layers className="w-4 h-4" />
|
<Layers className="w-4 h-4" />
|
||||||
<span className={`relative inline-flex items-center ${stats.inboxCount > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
<span>Triage</span>
|
<span>Triage</span>
|
||||||
<CountBadge count={stats.inboxCount} variant="accent" position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={stats.inboxCount} variant="accent" position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -1223,9 +1223,9 @@ export const App: React.FC = () => {
|
|||||||
className={`tab-btn ${activeTab === 'tasks' ? 'tab-btn-active' : ''}`}
|
className={`tab-btn ${activeTab === 'tasks' ? 'tab-btn-active' : ''}`}
|
||||||
>
|
>
|
||||||
<CheckSquare className="w-4 h-4" />
|
<CheckSquare className="w-4 h-4" />
|
||||||
<span className={`relative inline-flex items-center ${stats.tasksOpenCount > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
<span>Aufgaben</span>
|
<span>Aufgaben</span>
|
||||||
<CountBadge count={stats.tasksOpenCount} variant="accent" position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={stats.tasksOpenCount} variant="accent" position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -1237,9 +1237,9 @@ export const App: React.FC = () => {
|
|||||||
className={`tab-btn ${activeTab === 'lists' ? 'tab-btn-active' : ''}`}
|
className={`tab-btn ${activeTab === 'lists' ? 'tab-btn-active' : ''}`}
|
||||||
>
|
>
|
||||||
<ShoppingCart className="w-4 h-4" />
|
<ShoppingCart className="w-4 h-4" />
|
||||||
<span className={`relative inline-flex items-center ${(stats.listItemsOpenCount ?? 0) > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
<span>Listen</span>
|
<span>Listen</span>
|
||||||
<CountBadge count={stats.listItemsOpenCount} variant="accent" position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={stats.listItemsOpenCount} variant="accent" position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,14 +4,16 @@ interface CountBadgeProps {
|
|||||||
count: number | undefined | null;
|
count: number | undefined | null;
|
||||||
// accent: something waits for you (nav bar); muted: plain amount (tabs, lists)
|
// accent: something waits for you (nav bar); muted: plain amount (tabs, lists)
|
||||||
variant?: 'accent' | 'muted';
|
variant?: 'accent' | 'muted';
|
||||||
// corner: notification badge on the top right of the nearest `relative` parent
|
// corner: notification badge on the top right of the nearest `relative` parent (icons);
|
||||||
position?: 'inline' | 'corner';
|
// text: right after a label, raised and hanging a little over its last letter (tabs, nav bar)
|
||||||
|
position?: 'inline' | 'corner' | 'text';
|
||||||
showZero?: boolean;
|
showZero?: boolean;
|
||||||
className?: string; // e.g. to fine-tune the corner offset
|
className?: string; // e.g. to fine-tune the corner offset
|
||||||
}
|
}
|
||||||
|
|
||||||
// Full class names: Tailwind drops component classes it cannot find literally in the source
|
// Full class names: Tailwind drops component classes it cannot find literally in the source
|
||||||
const VARIANT_CLASS = { accent: 'count-badge-accent', muted: 'count-badge-muted' };
|
const VARIANT_CLASS = { accent: 'count-badge-accent', muted: 'count-badge-muted' };
|
||||||
|
const POSITION_CLASS = { inline: '', corner: 'count-badge-corner', text: 'count-badge-text' };
|
||||||
|
|
||||||
// The one counter of the app (Doku/ui-patterns.md); hides itself at 0 unless showZero
|
// The one counter of the app (Doku/ui-patterns.md); hides itself at 0 unless showZero
|
||||||
export const CountBadge: React.FC<CountBadgeProps> = ({
|
export const CountBadge: React.FC<CountBadgeProps> = ({
|
||||||
@@ -25,7 +27,7 @@ export const CountBadge: React.FC<CountBadgeProps> = ({
|
|||||||
const label = count > 99 ? '99+' : String(count);
|
const label = count > 99 ? '99+' : String(count);
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
className={`count-badge ${VARIANT_CLASS[variant]} ${position === 'corner' ? 'count-badge-corner' : ''} ${className}`}
|
className={`count-badge ${VARIANT_CLASS[variant]} ${POSITION_CLASS[position]} ${className}`}
|
||||||
aria-label={String(count)}
|
aria-label={String(count)}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|||||||
@@ -1063,9 +1063,9 @@ export const SharedListsView: React.FC<SharedListsViewProps> = ({ onRefreshGloba
|
|||||||
>
|
>
|
||||||
<span>{lst.icon}</span>
|
<span>{lst.icon}</span>
|
||||||
{/* Counter on the label, like in the nav bar */}
|
{/* Counter on the label, like in the nav bar */}
|
||||||
<span className={`relative inline-flex items-center ${openCount > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
{lst.title}
|
{lst.title}
|
||||||
<CountBadge count={openCount} position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={openCount} position="text" />
|
||||||
</span>
|
</span>
|
||||||
<AvatarStack
|
<AvatarStack
|
||||||
people={otherMembers(lst)}
|
people={otherMembers(lst)}
|
||||||
|
|||||||
@@ -1796,9 +1796,9 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{/* Counter on the label, like in the nav bar */}
|
{/* Counter on the label, like in the nav bar */}
|
||||||
<span className={`relative inline-flex items-center ${openTasksCount ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
Alle Aufgaben
|
Alle Aufgaben
|
||||||
<CountBadge count={openTasksCount} position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={openTasksCount} position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -1825,9 +1825,9 @@ export const TasksView: React.FC<TasksViewProps> = ({
|
|||||||
className="h-full px-3 text-xs font-medium flex items-center gap-1.5 rounded-btn"
|
className="h-full px-3 text-xs font-medium flex items-center gap-1.5 rounded-btn"
|
||||||
>
|
>
|
||||||
<span>{tl.icon}</span>
|
<span>{tl.icon}</span>
|
||||||
<span className={`relative inline-flex items-center ${tl.tasksCount ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
{tl.title}
|
{tl.title}
|
||||||
<CountBadge count={tl.tasksCount} position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={tl.tasksCount} position="text" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{(() => {
|
{(() => {
|
||||||
|
|||||||
@@ -1623,9 +1623,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Check className="w-3.5 h-3.5 text-status-ok" />
|
<Check className="w-3.5 h-3.5 text-status-ok" />
|
||||||
<span className={`relative inline-flex items-center ${totalOpenTodos > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
To-Dos
|
To-Dos
|
||||||
<CountBadge count={totalOpenTodos} position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={totalOpenTodos} position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -1642,9 +1642,9 @@ export const WorkspaceView: React.FC<WorkspaceViewProps> = ({
|
|||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<Hash className="w-3.5 h-3.5 text-accent" />
|
<Hash className="w-3.5 h-3.5 text-accent" />
|
||||||
<span className={`relative inline-flex items-center ${tagsSummary.length > 0 ? 'pr-3' : ''}`}>
|
<span className="inline-flex items-center">
|
||||||
Hashtags
|
Hashtags
|
||||||
<CountBadge count={tagsSummary.length} position="corner" className="-top-0.5 -right-2" />
|
<CountBadge count={tagsSummary.length} position="text" />
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -339,6 +339,14 @@ body {
|
|||||||
/* ring in the page colour keeps the badge readable on top of borders */
|
/* ring in the page colour keeps the badge readable on top of borders */
|
||||||
box-shadow: 0 0 0 2px var(--bg-app);
|
box-shadow: 0 0 0 2px var(--bg-app);
|
||||||
}
|
}
|
||||||
|
/* In the text flow right after a label: only the ring hangs over the last letter (2 px), however many
|
||||||
|
digits; wider numbers make the tab wider instead of covering more of the word */
|
||||||
|
.count-badge-text {
|
||||||
|
position: relative;
|
||||||
|
top: -0.375rem;
|
||||||
|
z-index: 1;
|
||||||
|
box-shadow: 0 0 0 2px var(--bg-app);
|
||||||
|
}
|
||||||
|
|
||||||
.badge-ok {
|
.badge-ok {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
|
|||||||
Reference in new issue
Block a user