Skip to content

Commit a13d492

Browse files
authored
Merge pull request #557 from Lemoncode/feature/#554-move-zoom-buttons-to-footer
Feature/#554 move zoom buttons to footer
2 parents 00e3bd5 + a347ed0 commit a13d492

37 files changed

Lines changed: 547 additions & 411 deletions

src/App.css

Lines changed: 268 additions & 262 deletions
Large diffs are not rendered by default.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
.button {
2+
background: none;
3+
display: flex;
4+
flex-direction: column;
5+
align-items: center;
6+
gap: 10px;
7+
fill: var(--text-color);
8+
}
9+
10+
@media screen and (max-device-width: 1090px) {
11+
.button {
12+
padding: 6px;
13+
font-size: var(--fs-s);
14+
}
15+
}
16+
17+
.tooltip {
18+
-moz-border-radius: 3px;
19+
-webkit-border-radius: 3px;
20+
background-color: hsla(0, 0%, 20%, 0.7);
21+
border-radius: 3px;
22+
color: var(--text-color);
23+
font-size: 14px;
24+
line-height: 14px;
25+
padding: 7px 14px;
26+
position: absolute;
27+
transform: translate(0%, 90px);
28+
visibility: hidden;
29+
z-index: 2;
30+
}
31+
32+
.tooltipBottom {
33+
transform: translate(0%, 90px);
34+
}
35+
36+
.tooltipTop {
37+
transform: translate(0%, -90px);
38+
}
39+
40+
.tooltipTopLeft {
41+
transform: translate(-50%, -90px);
42+
}
43+
44+
@media (hover: hover) {
45+
.button:hover .tooltip {
46+
animation: fadeIn 1s linear;
47+
animation-fill-mode: forwards;
48+
}
49+
}
50+
51+
@media screen and (max-device-width: 1090px) {
52+
.tooltip {
53+
display: none;
54+
}
55+
}
56+
57+
@keyframes fadeIn {
58+
0% {
59+
opacity: 0;
60+
}
61+
75% {
62+
opacity: 0;
63+
}
64+
100% {
65+
opacity: 1;
66+
visibility: visible;
67+
}
68+
}

src/pods/toolbar/components/toolbar-button/toolbarButton.component.spec.tsx renamed to src/common/components/action-button/action-button.component.spec.tsx

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { fireEvent, render, screen } from '@testing-library/react';
2-
import { ToolbarButton } from './toolbarButton.component';
32
import { vi } from 'vitest';
4-
import { ShortcutOptions } from '../../shortcut/shortcut.model';
3+
import { ActionButton } from './action-button.component';
4+
import { ShortcutOptions } from '@/common/shortcut';
55

6-
describe('ToolbarButton', () => {
6+
describe('ActionButton', () => {
77
let onClick: () => void;
88
let shortcutOptions: ShortcutOptions;
99

@@ -25,7 +25,7 @@ describe('ToolbarButton', () => {
2525

2626
it('should render the button with the provided label and icon', () => {
2727
render(
28-
<ToolbarButton
28+
<ActionButton
2929
icon={<span>Icon</span>}
3030
label="Label"
3131
onClick={onClick}
@@ -39,7 +39,7 @@ describe('ToolbarButton', () => {
3939

4040
it('should call the onClick callback when the button is clicked', () => {
4141
const { getByText } = render(
42-
<ToolbarButton
42+
<ActionButton
4343
icon={<span>Icon</span>}
4444
label="Label"
4545
onClick={onClick}
@@ -54,7 +54,7 @@ describe('ToolbarButton', () => {
5454

5555
it('should render the tooltip with the correct shortcut key', () => {
5656
const { getByRole } = render(
57-
<ToolbarButton
57+
<ActionButton
5858
icon={<span>Icon</span>}
5959
label="Label"
6060
onClick={onClick}
@@ -69,7 +69,7 @@ describe('ToolbarButton', () => {
6969

7070
it('should disable the button if the disabled prop is true', () => {
7171
const { getByText } = render(
72-
<ToolbarButton
72+
<ActionButton
7373
icon={<span>Icon</span>}
7474
label="Label"
7575
onClick={onClick}
@@ -82,4 +82,47 @@ describe('ToolbarButton', () => {
8282

8383
expect(button).toHaveProperty('disabled', true);
8484
});
85+
86+
it('should hide the label when showLabel is false', () => {
87+
render(
88+
<ActionButton
89+
icon={<span>Icon</span>}
90+
label="Label"
91+
onClick={onClick}
92+
showLabel={false}
93+
shortcutOptions={shortcutOptions}
94+
/>
95+
);
96+
97+
expect(screen.queryByText('Label')).toBeNull();
98+
});
99+
100+
it('should apply tooltipBottom by default when tooltipPosition is not provided', () => {
101+
const { getByRole } = render(
102+
<ActionButton
103+
icon={<span>Icon</span>}
104+
label="Label"
105+
onClick={onClick}
106+
shortcutOptions={shortcutOptions}
107+
/>
108+
);
109+
110+
const tooltip = getByRole('tooltip');
111+
expect(tooltip.className).toContain('tooltipBottom');
112+
});
113+
114+
it('should apply tooltipTop class when tooltipPosition is top', () => {
115+
const { getByRole } = render(
116+
<ActionButton
117+
icon={<span>Icon</span>}
118+
label="Label"
119+
onClick={onClick}
120+
tooltipPosition="top"
121+
shortcutOptions={shortcutOptions}
122+
/>
123+
);
124+
125+
const tooltip = getByRole('tooltip');
126+
expect(tooltip.className).toContain('tooltipTop');
127+
});
85128
});

src/pods/toolbar/components/toolbar-button/toolbarButton.component.tsx renamed to src/common/components/action-button/action-button.component.tsx

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React from 'react';
2-
import useShortcut from '../../shortcut/shortcut.hook';
32
import { isMacOS } from '@/common/helpers/platform.helpers';
4-
import { ShortcutOptions } from '../../shortcut/shortcut.model';
3+
import classes from './action-button.component.module.css';
4+
import { ShortcutOptions } from '@/common/shortcut';
5+
import useShortcut from '@/common/shortcut/shortcut.hook';
56

67
interface Props {
78
icon?: React.ReactNode;
@@ -10,20 +11,33 @@ interface Props {
1011
className?: string;
1112
disabled?: boolean;
1213
shortcutOptions?: ShortcutOptions;
14+
showLabel?: boolean;
15+
tooltipPosition?: 'top' | 'bottom';
1316
}
1417

15-
export const ToolbarButton: React.FC<Props> = ({
18+
export const ActionButton: React.FC<Props> = ({
1619
disabled,
1720
icon,
1821
onClick = () => {},
1922
className,
2023
label,
2124
shortcutOptions,
25+
showLabel = true,
26+
tooltipPosition = 'bottom',
2227
}) => {
2328
const shortcutCommand = isMacOS() ? 'Ctrl' : 'Alt';
2429
const showTooltip = shortcutOptions && !disabled;
2530
const tooltipText = `(${shortcutCommand} + ${shortcutOptions?.targetKeyLabel})`;
2631

32+
const tooltipPositionClass =
33+
tooltipPosition === 'top' ? classes.tooltipTop : classes.tooltipBottom;
34+
35+
const tooltipClasses = `${classes.tooltip} ${tooltipPositionClass}`;
36+
37+
const buttonClasses = className
38+
? `${classes.button} ${className}`.trim()
39+
: classes.button;
40+
2741
useShortcut({
2842
...shortcutOptions,
2943
targetKey: shortcutOptions?.targetKey || [],
@@ -32,15 +46,19 @@ export const ToolbarButton: React.FC<Props> = ({
3246

3347
return (
3448
<button
35-
className={className}
49+
className={buttonClasses}
3650
onClick={onClick}
3751
disabled={disabled === true}
3852
aria-describedby={shortcutOptions?.id}
3953
>
4054
<span aria-hidden={true}>{icon}</span>
41-
<span>{label}</span>
55+
{showLabel && <span>{label}</span>}
4256
{showTooltip && (
43-
<span role="tooltip" id={shortcutOptions?.id}>
57+
<span
58+
className={tooltipClasses}
59+
role="tooltip"
60+
id={shortcutOptions?.id}
61+
>
4462
{tooltipText}
4563
</span>
4664
)}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './action-button.component';

src/common/shortcut/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './shortcut.const';
2+
export * from './shortcut.hook';
3+
export * from './shortcut.model';
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)