mana-swift-ui/Sources/ManaComponentsUI/ManaPinnedGlyph.swift
Till JS fc8a8d4702 ManaComponentsUI: ManaSectionHeader + ManaPinnedGlyph, ManaScreenHeader fett
Geteilte Listen-Bausteine, drift-sicher als Pendant zur Compose-Lib:
- ManaSectionHeader: großer (.title2/SemiBold) Abschnitts-Header für
  scrollende Listen, optional einklappbar (Chevron).
- ManaPinnedGlyph: gezeichneter Fünfzack-Stern (geteilte Geometrie via
  ManaStarShape), kein SF-Symbol → pixelgleich zum Android-Pendant.
- ManaScreenHeader: Titel jetzt fett (.title.bold).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-10 17:08:02 +02:00

64 lines
2.4 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import ManaTokens
import SwiftUI
/// Fünfzackiger Stern als **gezeichneter** Glyph — natives Pendant zur
/// Android-`ManaPinnedGlyph` (mana-kotlin-ui). Beide Plattformen zeichnen
/// **dieselbe Geometrie** (5 Außen-/5 Innenzacken, Innenradius = 0,40 · Außen-
/// radius, erste Spitze nach oben), damit der „Angepinnt"-Marker pixelgleich
/// aussieht und nicht auseinanderdriftet — wie bei `SparklesGlyph`/`CopyGlyph`.
///
/// Bewusst KEIN SF-Symbol (`star.fill`): das System-Symbol weicht in Strich-
/// stärke/Proportion vom Material-Pendant ab. Eine geteilte Pfad-Definition ist
/// die einzige Quelle der Wahrheit.
public struct ManaPinnedGlyph: View {
@Environment(\.manaTheme) private var theme
private let size: CGFloat
private let color: Color?
/// - Parameters:
/// - size: Kantenlänge des quadratischen Glyphen. Default 16.
/// - color: Füllfarbe. `nil` → Theme-`primary`.
public init(size: CGFloat = 16, color: Color? = nil) {
self.size = size
self.color = color
}
public var body: some View {
ManaStarShape()
.fill(color ?? theme.colors.primary)
.frame(width: size, height: size)
.accessibilityLabel("Angepinnt")
}
}
/// Pfad eines fünfzackigen Sterns, zentriert in `rect`. Geteilte Geometrie mit
/// der Android-Canvas-Variante: Außenradius = halbe Kantenlänge, Innenradius =
/// 0,40 davon, 10 Stützpunkte, Start an der oberen Spitze (−90°).
public struct ManaStarShape: Shape {
/// Verhältnis Innen- zu Außenradius. Geteilt mit Android.
public static let innerRatio: CGFloat = 0.40
/// Anzahl der Zacken.
public static let points = 5
public init() {}
public func path(in rect: CGRect) -> Path {
let center = CGPoint(x: rect.midX, y: rect.midY)
let outer = min(rect.width, rect.height) / 2
let inner = outer * Self.innerRatio
var path = Path()
let step = Double.pi / Double(Self.points) // halbe Zacken-Teilung
for i in 0 ..< (Self.points * 2) {
let radius = i.isMultiple(of: 2) ? outer : inner
let angle = -Double.pi / 2 + Double(i) * step
let point = CGPoint(
x: center.x + CGFloat(cos(angle)) * radius,
y: center.y + CGFloat(sin(angle)) * radius
)
if i == 0 { path.move(to: point) } else { path.addLine(to: point) }
}
path.closeSubpath()
return path
}
}