Add PDF editor toolbar with navigation and zoom controls

Introduced a `SenderPdfImageEditorToolbar` component to enhance the PDF editor with navigation, zoom, and action controls. Updated `SenderPdfImageEditor.razor` to display the toolbar when `PageCount > 0`.

Added parameters (`CurrentPage`, `TotalPages`, `ZoomPercent`) and computed properties to manage and display toolbar state dynamically.

Styled the toolbar in `envelope-viewer.css` with grid-based layout, responsive design, and hover/disabled states for buttons. Adjusted styles for smaller screens to improve usability.
This commit is contained in:
2026-09-30 15:25:29 +02:00
parent 7a126050cf
commit db613358d5
3 changed files with 192 additions and 1 deletions

View File

@@ -5,13 +5,20 @@
@inject IStringLocalizer<Resource> UiLocalizer
@inject IJSRuntime JSRuntime
@if (PageCount > 0)
{
<SenderPdfImageEditorToolbar CurrentPage="1"
TotalPages="@PageCount"
ZoomPercent="112" />
}
<div class="pdf-editor-wrapper sender-image-editor sender-editor-pdf-viewer"
style="cursor: @(IsPlacementMode ? "crosshair" : (_isDragging ? "grabbing" : "default"));"
@onclick="HandleClickAsync"
@onmousemove="OnEditorMouseMoveAsync"
@onmouseup="OnEditorMouseUp"
@onmouseleave="OnEditorMouseUp">
@if (PageCount <= 0)
@if (PageCount <= 0)
{
<div class="sender-image-editor__empty">@L("SenderEditor_NoPagesToDisplay", "Keine Seiten zur Anzeige verfügbar.")</div>
}

View File

@@ -0,0 +1,97 @@
<div class="sender-image-toolbar" @onclick:stopPropagation="true">
<div class="sender-image-toolbar__group sender-image-toolbar__group--nav" role="group" aria-label="Page navigation">
<button type="button" class="sender-image-toolbar__icon-btn" title="First page" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M8 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<path d="M16 7L11 12L16 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Previous page" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M15 7L10 12L15 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<div class="sender-image-toolbar__value-box" aria-hidden="true">
<span>@CurrentPageDisplay of @TotalPagesDisplay</span>
</div>
<button type="button" class="sender-image-toolbar__icon-btn sender-image-toolbar__icon-btn--caret" title="Page selector" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Next page" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M9 7L14 12L9 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Last page" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M16 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<path d="M8 7L13 12L8 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
</div>
<div class="sender-image-toolbar__group sender-image-toolbar__group--zoom" role="group" aria-label="Zoom controls">
<button type="button" class="sender-image-toolbar__icon-btn" title="Zoom out" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M6 12H18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
<div class="sender-image-toolbar__value-box" aria-hidden="true">
<span>@ZoomPercentDisplay%</span>
</div>
<button type="button" class="sender-image-toolbar__icon-btn sender-image-toolbar__icon-btn--caret" title="Zoom presets" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M6 9L12 15L18 9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Zoom in" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 6V18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<path d="M6 12H18" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
</div>
<div class="sender-image-toolbar__group sender-image-toolbar__group--actions" role="group" aria-label="Document actions">
<button type="button" class="sender-image-toolbar__icon-btn" title="Print" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M7 9V4H17V9" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<rect x="5" y="9" width="14" height="8" rx="2" stroke="currentColor" stroke-width="2" />
<path d="M7 14H17V20H7V14Z" stroke="currentColor" stroke-width="2" stroke-linejoin="round" />
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Download PDF" disabled>
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 4V14" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<path d="M8 10L12 14L16 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
<path d="M5 18H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
</svg>
</button>
</div>
</div>
@code {
[Parameter]
public int CurrentPage { get; set; }
[Parameter]
public int TotalPages { get; set; }
[Parameter]
public int ZoomPercent { get; set; } = 112;
private int CurrentPageDisplay => CurrentPage > 0 ? CurrentPage : 0;
private int TotalPagesDisplay => TotalPages > 0 ? TotalPages : 0;
private int ZoomPercentDisplay => ZoomPercent > 0 ? ZoomPercent : 100;
}

View File

@@ -61,6 +61,80 @@
padding: 1rem;
}
.sender-image-toolbar {
max-width: 980px;
margin: 0 auto 1rem;
display: grid;
grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr) auto;
gap: 0.75rem;
align-items: center;
}
.sender-image-toolbar__group {
min-height: 4.8rem;
background: #ffffff;
border: 1px solid #d6deef;
border-radius: 0.5rem;
padding: 0.6rem;
display: flex;
align-items: center;
justify-content: center;
gap: 0.3rem;
box-shadow: 0 6px 16px rgba(15, 23, 42, 0.08);
}
.sender-image-toolbar__group--nav {
justify-content: flex-start;
}
.sender-image-toolbar__group--zoom {
justify-content: center;
}
.sender-image-toolbar__group--actions {
justify-content: center;
gap: 0.45rem;
padding-inline: 0.75rem;
}
.sender-image-toolbar__icon-btn {
width: 2.5rem;
height: 2.5rem;
border: 0;
border-radius: 0.45rem;
background: transparent;
color: #1f2a44;
display: inline-flex;
align-items: center;
justify-content: center;
transition: background-color 0.2s ease;
}
.sender-image-toolbar__icon-btn:disabled {
opacity: 0.42;
cursor: not-allowed;
}
.sender-image-toolbar__icon-btn--caret {
width: 2.1rem;
}
.sender-image-toolbar__value-box {
min-width: 9rem;
height: 2.5rem;
border: 1px solid #d5dceb;
border-radius: 0.45rem;
background: #f8fafc;
display: inline-flex;
align-items: center;
justify-content: flex-start;
padding: 0 0.8rem;
color: #233252;
font-size: 1.1rem;
font-weight: 500;
letter-spacing: 0.01em;
}
.sender-image-editor__pages {
max-width: 980px;
margin: 0 auto;
@@ -1174,6 +1248,19 @@ body.resizing {
padding: 0.75rem;
}
.sender-image-toolbar {
grid-template-columns: 1fr;
}
.sender-image-toolbar__group {
min-height: 3.9rem;
}
.sender-image-toolbar__value-box {
min-width: 7.5rem;
font-size: 1rem;
}
.pdf-thumbnails {
width: 180px;
border-radius: 0 0 0 16px;