{title}
{children} diff --git a/ApiCore-Frontend/src/components/hive/editor/editor-stack-list.tsx b/ApiCore-Frontend/src/components/hive/editor/editor-stack-list.tsx index 5212f00..2aa32a7 100644 --- a/ApiCore-Frontend/src/components/hive/editor/editor-stack-list.tsx +++ b/ApiCore-Frontend/src/components/hive/editor/editor-stack-list.tsx @@ -33,7 +33,7 @@ function Row({ part, name, isSelected, onSelect, moveUp, moveDown, remove }: Row type="button" onClick={onSelect} aria-current={isSelected ? "true" : undefined} - className="min-h-11 min-w-0 flex-1 truncate rounded-lg px-2 text-left text-sm focus-visible:outline-2 focus-visible:outline-holo-edge-strong aria-[current=true]:bg-holo-edge/25 aria-[current=true]:font-semibold" + className="min-h-11 min-w-0 flex-1 truncate rounded-lg px-2 text-left text-sm aria-[current=true]:bg-holo-edge/25 aria-[current=true]:font-semibold" data-part-id={part.id} > {name} diff --git a/ApiCore-Frontend/src/components/hive/editor/hive-editor.tsx b/ApiCore-Frontend/src/components/hive/editor/hive-editor.tsx index e76a981..1bda365 100644 --- a/ApiCore-Frontend/src/components/hive/editor/hive-editor.tsx +++ b/ApiCore-Frontend/src/components/hive/editor/hive-editor.tsx @@ -313,7 +313,7 @@ function HiveEditorBody({ colonyId, setup, catalog, canManageTemplates, onRefres } return ( -
+
Aufbau
{
expect(screen.getByText("1 Änderung wartet auf Netz")).toBeInTheDocument();
});
+ it("the stage is a .holo-stage and the outline panel on it takes the page focus ring back", async () => {
+ renderCard();
+ const toggle = await screen.findByRole("button", { name: "Aufbau als Liste" });
+
+ expect(screen.getByRole("img", { name: /Beute mit/ }).closest(".holo-stage")).not.toBeNull();
+ expect(toggle.closest(".holo-stage")).not.toBeNull();
+ await userEvent.click(toggle);
+ const panel = document.getElementById(toggle.getAttribute("aria-controls")!)!;
+ expect(panel).toHaveClass("stage-card");
+ });
+
+ it("the loading stage is a .holo-stage too", () => {
+ vi.mocked(fetchHive).mockReturnValue(new Promise(() => {}));
+ renderCard();
+
+ expect(screen.getByRole("status", { name: "Beute wird geladen" })).toHaveClass("holo-stage");
+ });
+
it("keeps the outline in the DOM but visually hidden until „Aufbau als Liste“", async () => {
renderCard();
const toggle = await screen.findByRole("button", { name: "Aufbau als Liste" });
diff --git a/ApiCore-Frontend/src/components/hive/hive-card.tsx b/ApiCore-Frontend/src/components/hive/hive-card.tsx
index ab8d2c1..a70d115 100644
--- a/ApiCore-Frontend/src/components/hive/hive-card.tsx
+++ b/ApiCore-Frontend/src/components/hive/hive-card.tsx
@@ -135,7 +135,7 @@ function HiveCardContent({ colonyId, colony, mode = "view", onOpsChange, initial
);
}
@@ -318,7 +318,7 @@ function HiveCardBody({ colonyId, setup, catalog, canEdit, mode, onOpsChange, in
return (
<>
-
+
diff --git a/ApiCore-Frontend/src/components/hive/hive-glass.ts b/ApiCore-Frontend/src/components/hive/hive-glass.ts
index 484cb10..7aafefa 100644
--- a/ApiCore-Frontend/src/components/hive/hive-glass.ts
+++ b/ApiCore-Frontend/src/components/hive/hive-glass.ts
@@ -1,11 +1,12 @@
// Frosted glass surfaces over the holo stage (mockups g2/h2). Text is
// --holo-label-fg on --holo-label-bg at 70 % over the midnight stage, well
-// above 4.5:1; focus rings use the strong edge colour.
+// above 4.5:1. The focus ring comes from the global rule; .holo-stage on the
+// stage root draws it in the strong edge colour (spec 17.8).
const GLASS_FILL = "bg-holo-label-bg/70 text-holo-label-fg backdrop-blur-md";
export const GLASS_SURFACE = `border border-white/15 shadow-[0_8px_24px_-12px_rgb(0_0_0/0.6)] ${GLASS_FILL}`;
-export const GLASS_BUTTON = `inline-flex h-11 shrink-0 items-center justify-center gap-1.5 rounded-xl px-3 text-sm sm:gap-2 sm:px-4 font-medium transition-colors hover:bg-holo-label-bg/90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-holo-edge-strong disabled:cursor-not-allowed disabled:opacity-60 aria-pressed:border-holo-edge/70 aria-pressed:bg-holo-edge/25 [&_svg]:size-5 border border-holo-edge/35 shadow-[0_0_18px_-8px_var(--holo-edge)] ${GLASS_FILL}`;
+export const GLASS_BUTTON = `inline-flex h-11 shrink-0 items-center justify-center gap-1.5 rounded-xl px-3 text-sm sm:gap-2 sm:px-4 font-medium transition-colors hover:bg-holo-label-bg/90 disabled:cursor-not-allowed disabled:opacity-60 aria-pressed:border-holo-edge/70 aria-pressed:bg-holo-edge/25 [&_svg]:size-5 border border-holo-edge/35 shadow-[0_0_18px_-8px_var(--holo-edge)] ${GLASS_FILL}`;
-export const GLASS_PILL = `inline-flex h-11 shrink-0 items-center gap-2 rounded-full px-4 text-sm font-medium transition-colors hover:bg-holo-label-bg/90 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-holo-edge-strong ${GLASS_SURFACE}`;
+export const GLASS_PILL = `inline-flex h-11 shrink-0 items-center gap-2 rounded-full px-4 text-sm font-medium transition-colors hover:bg-holo-label-bg/90 ${GLASS_SURFACE}`;
diff --git a/ApiCore-Frontend/src/components/hive/hive-history.tsx b/ApiCore-Frontend/src/components/hive/hive-history.tsx
index e254e86..03de12c 100644
--- a/ApiCore-Frontend/src/components/hive/hive-history.tsx
+++ b/ApiCore-Frontend/src/components/hive/hive-history.tsx
@@ -94,7 +94,7 @@ export function HiveHistory({ colonyId, state, catalog, onShowVersion }: HiveHis
type="button"
disabled={loadingId !== null}
onClick={() => void show(item)}
- className="flex min-h-11 w-full flex-col items-start justify-center rounded-lg px-3 py-1.5 text-start text-sm outline-none hover:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 disabled:opacity-60"
+ className="flex min-h-11 w-full flex-col items-start justify-center rounded-lg px-3 py-1.5 text-start text-sm hover:bg-muted disabled:opacity-60"
>
{shortGermanDay(item.occurredOn)} · {sourceLabel(item.source)}
diff --git a/ApiCore-Frontend/src/components/hive/hive-init.tsx b/ApiCore-Frontend/src/components/hive/hive-init.tsx
index 0ac0920..8446177 100644
--- a/ApiCore-Frontend/src/components/hive/hive-init.tsx
+++ b/ApiCore-Frontend/src/components/hive/hive-init.tsx
@@ -153,7 +153,7 @@ export function HiveInit({ colonyId, colony, canEdit }: HiveInitProps) {
{copying ? "Aufbau eines anderen Volks, ohne Namen und Füllstände." : "Startaufbau aus der Vorlage des Beutensystems."}
-
+
{proposal ? : null}
diff --git a/ApiCore-Frontend/src/components/hive/hive-outline.tsx b/ApiCore-Frontend/src/components/hive/hive-outline.tsx
index bc4860f..d1a0350 100644
--- a/ApiCore-Frontend/src/components/hive/hive-outline.tsx
+++ b/ApiCore-Frontend/src/components/hive/hive-outline.tsx
@@ -437,7 +437,7 @@ export function HiveOutline({ ref, state, catalog, canEdit, announcement, onEdit
activateNode(node);
}}
style={{ paddingInlineStart: `${0.75 + (node.level - 1) * 1.25}rem` }}
- className="flex min-h-11 cursor-pointer items-center gap-1 rounded-lg pe-3 text-sm outline-none hover:bg-muted focus-visible:ring-3 focus-visible:ring-ring/50 aria-[current=true]:bg-muted aria-[current=true]:font-medium"
+ className="flex min-h-11 cursor-pointer items-center gap-1 rounded-lg pe-3 text-sm hover:bg-muted aria-[current=true]:bg-muted aria-[current=true]:font-medium"
>
{node.hint ? `${node.name} · ${node.hint}` : node.name}
diff --git a/ApiCore-Frontend/src/components/hive/holo-stage.spec.ts b/ApiCore-Frontend/src/components/hive/holo-stage.spec.ts
new file mode 100644
index 0000000..7f6164d
--- /dev/null
+++ b/ApiCore-Frontend/src/components/hive/holo-stage.spec.ts
@@ -0,0 +1,28 @@
+import { readFileSync } from "node:fs";
+import { join } from "node:path";
+import { describe, expect, it } from "vitest";
+
+const SRC = join(__dirname, "..", "..");
+const read = (relative: string) => readFileSync(join(SRC, relative), "utf8");
+
+/**
+ * Spec 17.8: the page focus ring (--primary-ink) has less than 3:1 on --holo-bg, so every root
+ * that paints the stage carries .holo-stage, which sets --ring to --holo-edge-strong.
+ */
+describe("hive stage roots carry .holo-stage", () => {
+ it.each([
+ ["the editor", "components/hive/editor/hive-editor.tsx"],
+ ["the editor notice", "components/hive/editor/editor-notice.tsx"],
+ ["the loading fallback of the editor route", "app/(app)/colonies/[id]/hive/page.tsx"],
+ ["the setup preview", "components/hive/hive-init.tsx"],
+ ])("%s", (_name, file) => {
+ const roots = read(file).match(/className="[^"]*\bbg-holo-bg\b[^"]*"/g) ?? [];
+ expect(roots.length).toBeGreaterThan(0);
+ for (const root of roots) expect(root).toMatch(/\bholo-stage\b/);
+ });
+
+ it("no hive component draws its own stage ring any more", () => {
+ expect(read("components/hive/hive-glass.ts")).not.toMatch(/outline-holo-edge-strong/);
+ expect(read("components/hive/editor/editor-stack-list.tsx")).not.toMatch(/outline-holo-edge-strong/);
+ });
+});
diff --git a/ApiCore-Frontend/src/components/hive/part-sheet.tsx b/ApiCore-Frontend/src/components/hive/part-sheet.tsx
index 3dad97c..dbc4970 100644
--- a/ApiCore-Frontend/src/components/hive/part-sheet.tsx
+++ b/ApiCore-Frontend/src/components/hive/part-sheet.tsx
@@ -259,7 +259,7 @@ function PartForm({ located, type, catalog, startWithEvaporator, startWithFrameF
aria-labelledby={`part-${part.id}-confirm`}
className="flex flex-col gap-2 rounded-lg border border-destructive/40 p-3"
>
-
+
{removalNoun} wirklich entfernen?
diff --git a/ApiCore-Frontend/src/components/nav/nav-sheet.tsx b/ApiCore-Frontend/src/components/nav/nav-sheet.tsx
index c539440..95e682e 100644
--- a/ApiCore-Frontend/src/components/nav/nav-sheet.tsx
+++ b/ApiCore-Frontend/src/components/nav/nav-sheet.tsx
@@ -12,7 +12,7 @@ import {
/** A tappable row in a nav sheet: 56px high for gloved or hurried thumbs. */
export const NAV_SHEET_ROW_CLASS =
- "flex min-h-14 items-center gap-3 rounded-xl px-3 text-base font-medium focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-none";
+ "flex min-h-14 items-center gap-3 rounded-xl px-3 text-base font-medium";
interface NavSheetProps {
open: boolean;
diff --git a/ApiCore-Frontend/src/components/offline/offline-band.tsx b/ApiCore-Frontend/src/components/offline/offline-band.tsx
index 9dfdeca..6bd16cd 100644
--- a/ApiCore-Frontend/src/components/offline/offline-band.tsx
+++ b/ApiCore-Frontend/src/components/offline/offline-band.tsx
@@ -137,7 +137,6 @@ export function OfflineBand({ userId, pageContentRef, syncEnabled = true }: Offl
aria-live="polite"
tabIndex={-1}
className={cn(
- "outline-none focus-visible:ring-3 focus-visible:ring-ring/50",
hasContent &&
"flex flex-wrap items-center gap-x-3 gap-y-2 border-b border-border/60 px-4 py-2 text-sm sm:px-6",
hasContent && (isOffline ? "bg-warning/15" : "bg-muted/60"),
diff --git a/ApiCore-Frontend/src/components/offline/pending-queue-sheet.tsx b/ApiCore-Frontend/src/components/offline/pending-queue-sheet.tsx
index 6164ea5..0215e37 100644
--- a/ApiCore-Frontend/src/components/offline/pending-queue-sheet.tsx
+++ b/ApiCore-Frontend/src/components/offline/pending-queue-sheet.tsx
@@ -455,7 +455,7 @@ export function PendingQueueSheet({
id="queue-voice-heading"
ref={voiceHeadingRef}
tabIndex={-1}
- className="font-medium outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
+ className="font-medium"
>
Sprachnotizen
diff --git a/ApiCore-Frontend/src/components/phenology/phenology-report-sheet.tsx b/ApiCore-Frontend/src/components/phenology/phenology-report-sheet.tsx
index 3119d4f..14672b8 100644
--- a/ApiCore-Frontend/src/components/phenology/phenology-report-sheet.tsx
+++ b/ApiCore-Frontend/src/components/phenology/phenology-report-sheet.tsx
@@ -147,8 +147,8 @@ function ReportForm({
}
className={cn(
"flex min-h-14 w-full items-center gap-3 rounded-xl border border-border bg-background px-4",
- "text-left text-base font-medium outline-none transition-colors",
- "hover:bg-muted focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50",
+ "text-left text-base font-medium transition-colors",
+ "hover:bg-muted",
"disabled:pointer-events-none disabled:opacity-50",
)}
>
@@ -195,7 +195,7 @@ function ScopeChoice({
{options.map((option) => (
Meldungen dieses Jahres
diff --git a/ApiCore-Frontend/src/components/suggestions/due-date-sheet.tsx b/ApiCore-Frontend/src/components/suggestions/due-date-sheet.tsx
index be49302..96e18ed 100644
--- a/ApiCore-Frontend/src/components/suggestions/due-date-sheet.tsx
+++ b/ApiCore-Frontend/src/components/suggestions/due-date-sheet.tsx
@@ -63,7 +63,7 @@ function DueDateForm({ title, description, confirmLabel, initialDate, onConfirm
setDate(event.target.value)}
diff --git a/ApiCore-Frontend/src/components/suggestions/suggestion-card.tsx b/ApiCore-Frontend/src/components/suggestions/suggestion-card.tsx
index 3cb0822..41cc441 100644
--- a/ApiCore-Frontend/src/components/suggestions/suggestion-card.tsx
+++ b/ApiCore-Frontend/src/components/suggestions/suggestion-card.tsx
@@ -117,7 +117,7 @@ export function SuggestionCard(props: SuggestionCardProps) {
{suggestion.title}
diff --git a/ApiCore-Frontend/src/components/tab-switcher.spec.tsx b/ApiCore-Frontend/src/components/tab-switcher.spec.tsx
index 8165fb2..e238e87 100644
--- a/ApiCore-Frontend/src/components/tab-switcher.spec.tsx
+++ b/ApiCore-Frontend/src/components/tab-switcher.spec.tsx
@@ -15,7 +15,7 @@ describe("TabSwitcher", () => {
/>,
);
for (const tab of screen.getAllByRole("tab")) {
- expect(tab).toHaveClass("min-h-11", "sm:min-h-9");
+ expect(tab).toHaveClass("min-h-11", "pointer-fine:min-h-9");
}
});
});
diff --git a/ApiCore-Frontend/src/components/tab-switcher.tsx b/ApiCore-Frontend/src/components/tab-switcher.tsx
index bfbd2c7..7004d1c 100644
--- a/ApiCore-Frontend/src/components/tab-switcher.tsx
+++ b/ApiCore-Frontend/src/components/tab-switcher.tsx
@@ -20,7 +20,7 @@ export function TabSwitcher({ tabs, value, onChange }: TabSwit
aria-selected={value === tab.value}
onClick={() => onChange(tab.value)}
className={cn(
- "min-h-11 sm:min-h-9 rounded-lg px-4 py-1.5 text-sm font-medium transition-colors motion-reduce:transition-none",
+ "min-h-11 pointer-fine:min-h-9 rounded-lg px-4 py-1.5 text-sm font-medium transition-colors motion-reduce:transition-none",
value === tab.value
? "bg-card text-foreground shadow-[var(--shadow-soft)]"
: "text-muted-foreground hover:text-foreground",
diff --git a/ApiCore-Frontend/src/components/today/compliance-line.tsx b/ApiCore-Frontend/src/components/today/compliance-line.tsx
index 47ee136..0f1b014 100644
--- a/ApiCore-Frontend/src/components/today/compliance-line.tsx
+++ b/ApiCore-Frontend/src/components/today/compliance-line.tsx
@@ -35,7 +35,7 @@ export function ComplianceLine() {
return (
diff --git a/ApiCore-Frontend/src/components/today/today-panel.tsx b/ApiCore-Frontend/src/components/today/today-panel.tsx
index fbe6368..649d622 100644
--- a/ApiCore-Frontend/src/components/today/today-panel.tsx
+++ b/ApiCore-Frontend/src/components/today/today-panel.tsx
@@ -297,7 +297,7 @@ function AutopilotStepCard({ step, busy, ...handlers }: AutopilotStepCardProps)
Als Nächstes
@@ -359,7 +359,7 @@ function AutopilotChips({ autopilot }: { autopilot: AutopilotToday }) {
Vorschläge {autopilot.suggestionsOpen}
@@ -431,7 +431,7 @@ function TodayRow({ task, now, leaving, colonyCode, onComplete }: TodayRowProps)
diff --git a/ApiCore-Frontend/src/components/type-scale.spec.tsx b/ApiCore-Frontend/src/components/type-scale.spec.tsx
new file mode 100644
index 0000000..91ba519
--- /dev/null
+++ b/ApiCore-Frontend/src/components/type-scale.spec.tsx
@@ -0,0 +1,25 @@
+import { render, screen } from "@testing-library/react";
+import { Sprout } from "lucide-react";
+import { describe, expect, it } from "vitest";
+import { DetailHeader } from "./detail-header";
+import { EmptyState } from "./empty-state";
+import { EntityCard } from "./entity-card";
+
+const classesOf = (text: string) => screen.getByText(text).className.split(/\s+/);
+
+describe("content text is 16 px (spec 4.5)", () => {
+ it("EmptyState description", () => {
+ render( );
+ expect(classesOf("Lege das erste Volk an.")).toContain("text-base");
+ });
+
+ it("DetailHeader subtitle", () => {
+ render( );
+ expect(classesOf("Stand Waldrand")).toContain("text-base");
+ });
+
+ it("list title in EntityCard", () => {
+ render( );
+ expect(classesOf("V-01")).toContain("text-base");
+ });
+});
diff --git a/ApiCore-Frontend/src/components/ui/badge.tsx b/ApiCore-Frontend/src/components/ui/badge.tsx
index 11544b6..cf9b616 100644
--- a/ApiCore-Frontend/src/components/ui/badge.tsx
+++ b/ApiCore-Frontend/src/components/ui/badge.tsx
@@ -5,7 +5,7 @@ import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const badgeVariants = cva(
- "group/badge inline-flex h-5.5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2.5 py-0.5 text-xs font-semibold whitespace-nowrap transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 [&>svg]:pointer-events-none [&>svg]:size-3!",
+ "group/badge inline-flex h-5.5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2.5 py-0.5 text-xs font-semibold whitespace-nowrap transition-all has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive [&>svg]:pointer-events-none [&>svg]:size-3!",
{
variants: {
variant: {
@@ -13,9 +13,9 @@ const badgeVariants = cva(
secondary:
"bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
destructive:
- "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/20",
+ "bg-destructive/10 text-destructive [a]:hover:bg-destructive/20",
warning:
- "bg-warning/15 text-warning-ink focus-visible:ring-warning/30 [a]:hover:bg-warning/25",
+ "bg-warning/15 text-warning-ink [a]:hover:bg-warning/25",
outline:
"border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
ghost:
diff --git a/ApiCore-Frontend/src/components/ui/button.tsx b/ApiCore-Frontend/src/components/ui/button.tsx
index 78558cf..236e636 100644
--- a/ApiCore-Frontend/src/components/ui/button.tsx
+++ b/ApiCore-Frontend/src/components/ui/button.tsx
@@ -3,8 +3,13 @@ import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
+// Icon-only buttons get a 44 px hit area under a coarse pointer, centred and invisible, so they
+// stay small on screen but are easy to hit with a thumb or a glove (spec 4.5).
+const HIT_AREA =
+ "relative pointer-coarse:after:absolute pointer-coarse:after:top-1/2 pointer-coarse:after:left-1/2 pointer-coarse:after:size-11 pointer-coarse:after:-translate-1/2"
+
const buttonVariants = cva(
- "group/button inline-flex shrink-0 items-center justify-center rounded-xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ "group/button inline-flex shrink-0 items-center justify-center rounded-xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all select-none active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-inset aria-invalid:ring-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
{
variants: {
variant: {
@@ -17,24 +22,24 @@ const buttonVariants = cva(
ghost:
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground",
destructive:
- "bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20",
+ "bg-destructive/10 text-destructive hover:bg-destructive/20",
link: "text-primary-ink underline-offset-4 hover:underline",
},
size: {
- // Phones get at least 40 px: tapped with a thumb, often with gloves.
+ // 44 px for a thumb (often with gloves); compact only for a mouse or pen.
default:
- "h-10 sm:h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
+ "h-11 pointer-fine:h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
xs: "h-6 gap-1 rounded-[min(var(--radius-md),10px)] px-2 text-xs in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
- sm: "h-9 sm:h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
+ sm: "h-9 pointer-fine:h-7 gap-1 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] in-data-[slot=button-group]:rounded-lg has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
lg: "h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
// 44 px: reliable with gloves or sticky fingers at the apiary.
- touch: "h-11 gap-2 px-4 text-[0.95rem] [&_svg:not([class*='size-'])]:size-5",
- icon: "size-8",
+ touch: "h-11 gap-2 px-4 text-base [&_svg:not([class*='size-'])]:size-5",
+ icon: `size-8 ${HIT_AREA}`,
"icon-xs":
- "size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3",
+ `size-6 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-lg [&_svg:not([class*='size-'])]:size-3 ${HIT_AREA}`,
"icon-sm":
- "size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg",
- "icon-lg": "size-9",
+ `size-7 rounded-[min(var(--radius-md),12px)] in-data-[slot=button-group]:rounded-lg ${HIT_AREA}`,
+ "icon-lg": `size-9 ${HIT_AREA}`,
},
},
defaultVariants: {
diff --git a/ApiCore-Frontend/src/components/ui/checkbox.tsx b/ApiCore-Frontend/src/components/ui/checkbox.tsx
index 08ad1c7..f9aad72 100644
--- a/ApiCore-Frontend/src/components/ui/checkbox.tsx
+++ b/ApiCore-Frontend/src/components/ui/checkbox.tsx
@@ -8,7 +8,7 @@ function Checkbox({ className, ...props }: CheckboxPrimitive.Root.Props) {
diff --git a/ApiCore-Frontend/src/components/ui/input.tsx b/ApiCore-Frontend/src/components/ui/input.tsx
index 15c30a1..924a5f8 100644
--- a/ApiCore-Frontend/src/components/ui/input.tsx
+++ b/ApiCore-Frontend/src/components/ui/input.tsx
@@ -9,7 +9,7 @@ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
type={type}
data-slot="input"
className={cn(
- "h-11 w-full min-w-0 sm:h-9 rounded-xl border border-input bg-card px-3 py-1 text-base shadow-xs transition-all outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground hover:border-foreground/20 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm",
+ "h-11 w-full min-w-0 pointer-fine:h-9 rounded-xl border border-input bg-card px-3 py-1 text-base shadow-xs transition-all file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground hover:border-foreground/20 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-muted disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-inset aria-invalid:ring-destructive",
className
)}
{...props}
diff --git a/ApiCore-Frontend/src/components/ui/select.tsx b/ApiCore-Frontend/src/components/ui/select.tsx
index d93ad07..7d2d3eb 100644
--- a/ApiCore-Frontend/src/components/ui/select.tsx
+++ b/ApiCore-Frontend/src/components/ui/select.tsx
@@ -41,7 +41,7 @@ function SelectTrigger({
data-slot="select-trigger"
data-size={size}
className={cn(
- "flex w-fit items-center justify-between gap-1.5 rounded-xl border border-input bg-card py-2 pr-2.5 pl-3 text-sm whitespace-nowrap shadow-xs transition-all outline-none select-none hover:border-foreground/20 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-11 sm:data-[size=default]:h-9 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
+ "flex w-fit items-center justify-between gap-1.5 rounded-xl border border-input bg-card py-2 pr-2.5 pl-3 text-sm whitespace-nowrap shadow-xs transition-all select-none hover:border-foreground/20 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-inset aria-invalid:ring-destructive data-placeholder:text-muted-foreground data-[size=default]:h-11 pointer-fine:data-[size=default]:h-9 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
diff --git a/ApiCore-Frontend/src/components/ui/tabs.tsx b/ApiCore-Frontend/src/components/ui/tabs.tsx
index 285b745..e1ebccd 100644
--- a/ApiCore-Frontend/src/components/ui/tabs.tsx
+++ b/ApiCore-Frontend/src/components/ui/tabs.tsx
@@ -58,7 +58,7 @@ function TabsTrigger({ className, ...props }: TabsPrimitive.Tab.Props) {
)
diff --git a/ApiCore-Frontend/src/components/ui/textarea.tsx b/ApiCore-Frontend/src/components/ui/textarea.tsx
index 93dc3e7..7be5975 100644
--- a/ApiCore-Frontend/src/components/ui/textarea.tsx
+++ b/ApiCore-Frontend/src/components/ui/textarea.tsx
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
+
{removalNoun} wirklich entfernen?