Skip to content

Commit ef33f3c

Browse files
committed
style: share tooltip styles for diff action buttons
1 parent 7febba8 commit ef33f3c

5 files changed

Lines changed: 132 additions & 100 deletions

File tree

‎src/App.tsx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import "./styles/ds-toast.css";
77
import "./styles/ds-panel.css";
88
import "./styles/ds-diff.css";
99
import "./styles/ds-popover.css";
10+
import "./styles/ds-tooltip.css";
1011
import "./styles/buttons.css";
1112
import "./styles/sidebar.css";
1213
import "./styles/home.css";

‎src/features/git/components/GitDiffPanelModeContent.tsx‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ export function GitDiffModeContent({
540540
/>
541541
<button
542542
type="button"
543-
className="commit-message-generate-button diff-row-action"
543+
className="commit-message-generate-button diff-row-action ds-tooltip-trigger"
544544
onClick={() => {
545545
if (!canGenerateCommitMessage) {
546546
return;
@@ -551,6 +551,7 @@ export function GitDiffModeContent({
551551
title={generateCommitMessageTooltip}
552552
data-tooltip={generateCommitMessageTooltip}
553553
data-tooltip-placement="bottom"
554+
data-tooltip-align="end"
554555
aria-label="Generate commit message"
555556
>
556557
{commitMessageLoading ? (

‎src/features/git/components/GitDiffPanelShared.tsx‎

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -207,12 +207,13 @@ function DiffFileRow({
207207
{showStage && (
208208
<button
209209
type="button"
210-
className="diff-row-action diff-row-action--stage"
210+
className="diff-row-action diff-row-action--stage ds-tooltip-trigger"
211211
onClick={(event) => {
212212
event.stopPropagation();
213213
void onStageFile?.(file.path);
214214
}}
215215
data-tooltip="Stage Changes"
216+
data-tooltip-align="end"
216217
aria-label="Stage file"
217218
>
218219
<Plus size={12} aria-hidden />
@@ -221,12 +222,13 @@ function DiffFileRow({
221222
{showUnstage && (
222223
<button
223224
type="button"
224-
className="diff-row-action diff-row-action--unstage"
225+
className="diff-row-action diff-row-action--unstage ds-tooltip-trigger"
225226
onClick={(event) => {
226227
event.stopPropagation();
227228
void onUnstageFile?.(file.path);
228229
}}
229230
data-tooltip="Unstage Changes"
231+
data-tooltip-align="end"
230232
aria-label="Unstage file"
231233
>
232234
<Minus size={12} aria-hidden />
@@ -235,12 +237,13 @@ function DiffFileRow({
235237
{showDiscard && (
236238
<button
237239
type="button"
238-
className="diff-row-action diff-row-action--discard"
240+
className="diff-row-action diff-row-action--discard ds-tooltip-trigger"
239241
onClick={(event) => {
240242
event.stopPropagation();
241243
void onDiscardFile?.(file.path);
242244
}}
243245
data-tooltip="Discard Changes"
246+
data-tooltip-align="end"
244247
aria-label="Discard changes"
245248
>
246249
<RotateCcw size={12} aria-hidden />
@@ -330,12 +333,13 @@ export function DiffSection({
330333
{canApplyWorktree && (
331334
<button
332335
type="button"
333-
className="diff-row-action diff-row-action--apply"
336+
className="diff-row-action diff-row-action--apply ds-tooltip-trigger"
334337
onClick={() => {
335338
void onApplyWorktreeChanges?.();
336339
}}
337340
disabled={worktreeApplyLoading || worktreeApplySuccess}
338341
data-tooltip={worktreeApplyTitle ?? "Apply changes to parent workspace"}
342+
data-tooltip-align="end"
339343
aria-label="Apply worktree changes"
340344
>
341345
<WorktreeApplyIcon success={worktreeApplySuccess} />
@@ -344,11 +348,12 @@ export function DiffSection({
344348
{canReviewUncommitted && (
345349
<button
346350
type="button"
347-
className="diff-row-action diff-row-action--review"
351+
className="diff-row-action diff-row-action--review ds-tooltip-trigger"
348352
onClick={() => {
349353
void onReviewUncommittedChanges?.();
350354
}}
351355
data-tooltip="Review Uncommitted Changes"
356+
data-tooltip-align="end"
352357
aria-label="Review uncommitted changes"
353358
>
354359
<MagicSparkleIcon size={12} />
@@ -357,7 +362,7 @@ export function DiffSection({
357362
{canStageAll && (
358363
<button
359364
type="button"
360-
className="diff-row-action diff-row-action--stage"
365+
className="diff-row-action diff-row-action--stage ds-tooltip-trigger"
361366
onClick={() => {
362367
if (onStageAllChanges) {
363368
void onStageAllChanges();
@@ -370,6 +375,7 @@ export function DiffSection({
370375
})();
371376
}}
372377
data-tooltip="Stage All Changes"
378+
data-tooltip-align="end"
373379
aria-label="Stage all changes"
374380
>
375381
<Plus size={12} aria-hidden />
@@ -378,7 +384,7 @@ export function DiffSection({
378384
{canUnstageAll && (
379385
<button
380386
type="button"
381-
className="diff-row-action diff-row-action--unstage"
387+
className="diff-row-action diff-row-action--unstage ds-tooltip-trigger"
382388
onClick={() => {
383389
void (async () => {
384390
for (const path of filePaths) {
@@ -387,6 +393,7 @@ export function DiffSection({
387393
})();
388394
}}
389395
data-tooltip="Unstage All Changes"
396+
data-tooltip-align="end"
390397
aria-label="Unstage all changes"
391398
>
392399
<Minus size={12} aria-hidden />
@@ -395,11 +402,12 @@ export function DiffSection({
395402
{canDiscardAll && (
396403
<button
397404
type="button"
398-
className="diff-row-action diff-row-action--discard"
405+
className="diff-row-action diff-row-action--discard ds-tooltip-trigger"
399406
onClick={() => {
400407
void onDiscardFiles?.(filePaths);
401408
}}
402409
data-tooltip="Discard All Changes"
410+
data-tooltip-align="end"
403411
aria-label="Discard all changes"
404412
>
405413
<RotateCcw size={12} aria-hidden />

‎src/styles/diff.css‎

Lines changed: 0 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -634,97 +634,6 @@
634634
color: #5aa9ff;
635635
}
636636

637-
.diff-row-action[data-tooltip]::before,
638-
.diff-row-action[data-tooltip]::after {
639-
opacity: 0;
640-
pointer-events: none;
641-
transition: opacity 150ms ease, transform 150ms ease;
642-
transform: translateY(4px);
643-
z-index: 10;
644-
}
645-
646-
.diff-row-action[data-tooltip]::after {
647-
content: attr(data-tooltip);
648-
position: absolute;
649-
left: 50%;
650-
bottom: calc(100% + 8px);
651-
transform: translateX(-50%) translateY(4px);
652-
padding: 4px 8px;
653-
border-radius: 8px;
654-
background: var(--surface-command);
655-
color: var(--text-emphasis);
656-
font-size: 10px;
657-
line-height: 1.2;
658-
white-space: nowrap;
659-
border: 1px solid var(--border-subtle);
660-
box-shadow: 0 14px 24px rgba(0, 0, 0, 0.22);
661-
}
662-
663-
.diff-row-action[data-tooltip]::before {
664-
content: "";
665-
position: absolute;
666-
left: 50%;
667-
bottom: calc(100% + 4px);
668-
transform: translateX(-50%) translateY(4px) rotate(45deg);
669-
width: 8px;
670-
height: 8px;
671-
background: var(--surface-command);
672-
border-left: 1px solid var(--border-subtle);
673-
border-top: 1px solid var(--border-subtle);
674-
}
675-
676-
.diff-row-action:last-child[data-tooltip]:not([data-tooltip-placement="bottom"])::after {
677-
left: auto;
678-
right: 0;
679-
transform: translateX(0) translateY(4px);
680-
}
681-
682-
.diff-row-action:last-child[data-tooltip]:not([data-tooltip-placement="bottom"])::before {
683-
left: auto;
684-
right: 8px;
685-
transform: translateX(0) translateY(4px) rotate(45deg);
686-
}
687-
688-
.diff-row-action[data-tooltip][data-tooltip-placement="bottom"]::after {
689-
top: calc(100% + 8px);
690-
bottom: auto;
691-
left: auto;
692-
right: 0;
693-
transform: translateY(-4px);
694-
}
695-
696-
.diff-row-action[data-tooltip][data-tooltip-placement="bottom"]::before {
697-
display: none;
698-
}
699-
700-
.diff-row-action:hover::before,
701-
.diff-row-action:hover::after,
702-
.diff-row-action:focus-visible::before,
703-
.diff-row-action:focus-visible::after {
704-
opacity: 1;
705-
transform: translateX(-50%) translateY(0);
706-
}
707-
708-
.diff-row-action:hover::before,
709-
.diff-row-action:focus-visible::before {
710-
transform: translateX(-50%) translateY(0) rotate(45deg);
711-
}
712-
713-
.diff-row-action[data-tooltip][data-tooltip-placement="bottom"]:hover::after,
714-
.diff-row-action[data-tooltip][data-tooltip-placement="bottom"]:focus-visible::after {
715-
transform: translateY(0);
716-
}
717-
718-
.diff-row-action:last-child:hover:not([data-tooltip-placement="bottom"])::after,
719-
.diff-row-action:last-child:focus-visible:not([data-tooltip-placement="bottom"])::after {
720-
transform: translateX(0) translateY(0);
721-
}
722-
723-
.diff-row-action:last-child:hover:not([data-tooltip-placement="bottom"])::before,
724-
.diff-row-action:last-child:focus-visible:not([data-tooltip-placement="bottom"])::before {
725-
transform: translateX(0) translateY(0) rotate(45deg);
726-
}
727-
728637
.diff-icon {
729638
width: 16px;
730639
height: 16px;

‎src/styles/ds-tooltip.css‎

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
.ds-tooltip-trigger {
2+
position: relative;
3+
}
4+
5+
.ds-tooltip-trigger[data-tooltip]::before,
6+
.ds-tooltip-trigger[data-tooltip]::after {
7+
opacity: 0;
8+
pointer-events: none;
9+
transition: opacity 150ms ease, transform 150ms ease;
10+
z-index: 20;
11+
}
12+
13+
.ds-tooltip-trigger[data-tooltip]::after {
14+
content: attr(data-tooltip);
15+
position: absolute;
16+
left: 50%;
17+
bottom: calc(100% + 8px);
18+
transform: translateX(-50%) translateY(4px);
19+
padding: 4px 8px;
20+
border-radius: 8px;
21+
background: var(--surface-command);
22+
color: var(--text-emphasis);
23+
font-size: 10px;
24+
line-height: 1.2;
25+
white-space: nowrap;
26+
border: 1px solid var(--border-subtle);
27+
box-shadow: 0 14px 24px rgba(0, 0, 0, 0.22);
28+
}
29+
30+
.ds-tooltip-trigger[data-tooltip]::before {
31+
content: "";
32+
position: absolute;
33+
left: 50%;
34+
bottom: calc(100% + 4px);
35+
transform: translateX(-50%) translateY(4px) rotate(45deg);
36+
width: 8px;
37+
height: 8px;
38+
background: var(--surface-command);
39+
border-left: 1px solid var(--border-subtle);
40+
border-top: 1px solid var(--border-subtle);
41+
}
42+
43+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]::after {
44+
left: 0;
45+
transform: translateY(4px);
46+
}
47+
48+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]::before {
49+
left: 8px;
50+
transform: translateY(4px) rotate(45deg);
51+
}
52+
53+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]::after {
54+
left: auto;
55+
right: 0;
56+
transform: translateY(4px);
57+
}
58+
59+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]::before {
60+
left: auto;
61+
right: 8px;
62+
transform: translateY(4px) rotate(45deg);
63+
}
64+
65+
.ds-tooltip-trigger[data-tooltip][data-tooltip-placement="bottom"]::after {
66+
top: calc(100% + 8px);
67+
bottom: auto;
68+
transform: translateX(-50%) translateY(-4px);
69+
}
70+
71+
.ds-tooltip-trigger[data-tooltip][data-tooltip-placement="bottom"]::before {
72+
display: none;
73+
}
74+
75+
.ds-tooltip-trigger[data-tooltip][data-tooltip-placement="bottom"][data-tooltip-align="start"]::after {
76+
transform: translateY(-4px);
77+
}
78+
79+
.ds-tooltip-trigger[data-tooltip][data-tooltip-placement="bottom"][data-tooltip-align="end"]::after {
80+
transform: translateY(-4px);
81+
}
82+
83+
.ds-tooltip-trigger[data-tooltip]:hover::after,
84+
.ds-tooltip-trigger[data-tooltip]:focus-visible::after {
85+
opacity: 1;
86+
transform: translateX(-50%) translateY(0);
87+
}
88+
89+
.ds-tooltip-trigger[data-tooltip]:hover::before,
90+
.ds-tooltip-trigger[data-tooltip]:focus-visible::before {
91+
opacity: 1;
92+
transform: translateX(-50%) translateY(0) rotate(45deg);
93+
}
94+
95+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]:hover::after,
96+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]:focus-visible::after {
97+
transform: translateY(0);
98+
}
99+
100+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]:hover::before,
101+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="start"]:focus-visible::before {
102+
transform: translateY(0) rotate(45deg);
103+
}
104+
105+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]:hover::after,
106+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]:focus-visible::after {
107+
transform: translateY(0);
108+
}
109+
110+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]:hover::before,
111+
.ds-tooltip-trigger[data-tooltip][data-tooltip-align="end"]:focus-visible::before {
112+
transform: translateY(0) rotate(45deg);
113+
}

0 commit comments

Comments
 (0)