fix(quick-260921-bi2): a11y - Dashboard-Widgets und Portal-Startseite
useButtonType: "Widget hinzufuegen"-, Bearbeiten-Modus- und Katalog-Buttons
(kein Formular in diesen Dateien) erhalten type="button".
noSvgWithoutTitle: Widget-Icons in der Katalog-Kachel (immer neben dem
Widget-Namen) und Buttons mit bestehendem aria-label/title werden dekorativ
(aria-hidden="true"); der bislang unbeschriftete Such-Button im Such-Widget
erhaelt aria-label={t('search.searchButton')} (neuer Schluessel, siehe
vorherige i18n-Festschreibung).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TPPB4ApQxzSU1rwV2Ffj9J
This commit is contained in:
@@ -81,10 +81,12 @@ export default function DashboardPage() {
|
|||||||
<div className="fixed bottom-6 right-6 z-20 flex items-center gap-2">
|
<div className="fixed bottom-6 right-6 z-20 flex items-center gap-2">
|
||||||
{isEditMode && (
|
{isEditMode && (
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => setCatalogOpen(true)}
|
onClick={() => setCatalogOpen(true)}
|
||||||
className="flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-lg hover:opacity-90 transition-opacity"
|
className="flex items-center gap-2 rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-lg hover:opacity-90 transition-opacity"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="16"
|
width="16"
|
||||||
height="16"
|
height="16"
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={onToggle}
|
onClick={onToggle}
|
||||||
className={`inline-flex items-center justify-center rounded-md p-2 shadow-lg transition-colors ${
|
className={`inline-flex items-center justify-center rounded-md p-2 shadow-lg transition-colors ${
|
||||||
isEditMode
|
isEditMode
|
||||||
@@ -32,6 +33,7 @@ export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
|
|||||||
{isEditMode ? (
|
{isEditMode ? (
|
||||||
// Checkmark icon
|
// Checkmark icon
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
@@ -47,6 +49,7 @@ export function EditModeToggle({ isEditMode, onToggle }: EditModeToggleProps) {
|
|||||||
) : (
|
) : (
|
||||||
// Pencil icon
|
// Pencil icon
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
|
|||||||
@@ -76,11 +76,13 @@ export function WidgetCatalogModal({
|
|||||||
{t('catalogTitle')}
|
{t('catalogTitle')}
|
||||||
</h2>
|
</h2>
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={onClose}
|
onClick={onClose}
|
||||||
className="rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
className="rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="20"
|
width="20"
|
||||||
height="20"
|
height="20"
|
||||||
@@ -105,6 +107,7 @@ export function WidgetCatalogModal({
|
|||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
key={type}
|
key={type}
|
||||||
|
type="button"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onAddWidget(type);
|
onAddWidget(type);
|
||||||
onClose();
|
onClose();
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ function PlaceholderWidget({ config }: WidgetProps) {
|
|||||||
function ClockIcon({ className }: { className?: string }) {
|
function ClockIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -110,6 +111,7 @@ function ClockIcon({ className }: { className?: string }) {
|
|||||||
function SearchIcon({ className }: { className?: string }) {
|
function SearchIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -130,6 +132,7 @@ function SearchIcon({ className }: { className?: string }) {
|
|||||||
function CalendarIcon({ className }: { className?: string }) {
|
function CalendarIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -152,6 +155,7 @@ function CalendarIcon({ className }: { className?: string }) {
|
|||||||
function NoteIcon({ className }: { className?: string }) {
|
function NoteIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -175,6 +179,7 @@ function NoteIcon({ className }: { className?: string }) {
|
|||||||
function CalculatorIcon({ className }: { className?: string }) {
|
function CalculatorIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -203,6 +208,7 @@ function CalculatorIcon({ className }: { className?: string }) {
|
|||||||
function FavoritesIcon({ className }: { className?: string }) {
|
function FavoritesIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
@@ -222,6 +228,7 @@ function FavoritesIcon({ className }: { className?: string }) {
|
|||||||
function StopwatchIcon({ className }: { className?: string }) {
|
function StopwatchIcon({ className }: { className?: string }) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
|
|||||||
@@ -157,11 +157,13 @@ export function NoteWidget({ instanceId, config }: WidgetProps) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
|
type="button"
|
||||||
onClick={() => setIsEditing((v) => !v)}
|
onClick={() => setIsEditing((v) => !v)}
|
||||||
className={`flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors hover:bg-muted ${isEditing ? 'text-destructive' : 'text-muted-foreground'}`}
|
className={`flex h-6 w-6 shrink-0 items-center justify-center rounded transition-colors hover:bg-muted ${isEditing ? 'text-destructive' : 'text-muted-foreground'}`}
|
||||||
title={isEditing ? t('note.viewMode') : t('note.editMode')}
|
title={isEditing ? t('note.viewMode') : t('note.editMode')}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="14"
|
width="14"
|
||||||
height="14"
|
height="14"
|
||||||
|
|||||||
@@ -116,8 +116,10 @@ export function SearchWidget({ instanceId, config }: WidgetProps) {
|
|||||||
type="button"
|
type="button"
|
||||||
className="flex h-8 shrink-0 items-center justify-center rounded bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90"
|
className="flex h-8 shrink-0 items-center justify-center rounded bg-primary px-3 text-sm font-medium text-primary-foreground transition-colors hover:bg-primary/90"
|
||||||
onClick={handleSearch}
|
onClick={handleSearch}
|
||||||
|
aria-label={t('search.searchButton')}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="16"
|
width="16"
|
||||||
height="16"
|
height="16"
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ export function WidgetWrapper({ widget, isEditMode, onRemove }: WidgetWrapperPro
|
|||||||
data-no-drag=""
|
data-no-drag=""
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="12"
|
width="12"
|
||||||
height="12"
|
height="12"
|
||||||
|
|||||||
Reference in New Issue
Block a user