| 672 | // MARK: - Square Icon Button Style (no horizontal padding, fixed square) |
| 673 | |
| 674 | struct SquareIconButtonStyle: ButtonStyle { |
| 675 | var foreground: Color? = nil |
| 676 | var borderColor: Color? = nil |
| 677 | |
| 678 | func makeBody(configuration: Configuration) -> some View { |
| 679 | SquareIconButton( |
| 680 | configuration: configuration, |
| 681 | foreground: self.foreground, |
| 682 | borderColor: self.borderColor |
| 683 | ) |
| 684 | } |
| 685 | |
| 686 | private struct SquareIconButton: View { |
| 687 | @Environment(\.theme) private var theme |
| 688 | @State private var isHovered = false |
| 689 | let configuration: ButtonStyle.Configuration |
| 690 | let foreground: Color? |
| 691 | let borderColor: Color? |
| 692 | |
| 693 | private var shape: RoundedRectangle { |
| 694 | RoundedRectangle(cornerRadius: self.theme.metrics.corners.sm, style: .continuous) |
| 695 | } |
| 696 | |
| 697 | var body: some View { |
| 698 | let border = self.borderColor ?? self.theme.palette.cardBorder |
| 699 | let borderOpacity = self.borderColor == nil |
| 700 | ? (self.isHovered ? 0.8 : 0.6) |
| 701 | : (self.isHovered ? 0.84 : 0.68) |
| 702 | let foregroundColor = self.foreground ?? self.theme.palette.primaryText |
| 703 | |
| 704 | self.configuration.label |
| 705 | .foregroundStyle(foregroundColor) |
| 706 | .background(self.theme.materials.card, in: self.shape) |
| 707 | .background( |
| 708 | self.shape |
| 709 | .fill(self.theme.palette.cardBackground) |
| 710 | .overlay( |
| 711 | self.shape.stroke( |
| 712 | border.opacity(borderOpacity), |
| 713 | lineWidth: 1 |
| 714 | ) |
| 715 | ) |
| 716 | ) |
| 717 | .shadow( |
| 718 | color: border.opacity(self.isHovered ? 0.18 : 0.06), |
| 719 | radius: self.isHovered ? 4 : 1.5, |
| 720 | x: 0, |
| 721 | y: self.isHovered ? 1 : 0.5 |
| 722 | ) |
| 723 | .scaleEffect(FluidInteractionVisuals.scale(isPressed: self.configuration.isPressed, isHovered: self.isHovered)) |
| 724 | .animation(FluidInteractionVisuals.hoverAnimation, value: self.isHovered) |
| 725 | .animation(FluidInteractionVisuals.pressedAnimation, value: self.configuration.isPressed) |
| 726 | .onHover { self.isHovered = $0 } |
| 727 | } |
| 728 | } |
| 729 | } |
no outgoing calls
no test coverage detected