Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions Demo/Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Demo/Demo.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 11;
CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -673,7 +673,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.9.1;
MARKETING_VERSION = 26.0;
PRODUCT_BUNDLE_IDENTIFIER = media.1998.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
Expand All @@ -695,7 +695,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Demo/Demo.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 11;
CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -715,7 +715,7 @@
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.9.1;
MARKETING_VERSION = 26.0;
PRODUCT_BUNDLE_IDENTIFIER = media.1998.Demo;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
Expand Down Expand Up @@ -822,7 +822,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -833,7 +833,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 26.0;
PRODUCT_BUNDLE_IDENTIFIER = media.1998.Demo.watchkitapp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
Expand All @@ -851,7 +851,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 10;
CURRENT_PROJECT_VERSION = 12;
DEVELOPMENT_TEAM = "";
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
Expand All @@ -862,7 +862,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.8.0;
MARKETING_VERSION = 26.0;
PRODUCT_BUNDLE_IDENTIFIER = media.1998.Demo.watchkitapp;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = watchos;
Expand Down
54 changes: 28 additions & 26 deletions Demo/Demo/Samples/Advanced/GlassFlower/GlassFlower.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,7 @@ struct GlassFlower: View {
// Flower petals: Eight capsules arranged in a circle pattern
// Each petal is a gradient-filled capsule with glass effect applied
ForEach(0..<8, id: \.self) { index in
Capsule()
.fill(
LinearGradient(
gradient: Gradient(stops: [
.init(color: colors[index % colors.count], location: 0),
.init(color: colors[index % colors.count].opacity(0.5), location: 1)
]),
startPoint: .bottom,
endPoint: .top
)
)

// Apply glass effect from SwiftGlass library to create translucent look
.glass(color: colors[index % colors.count], colorOpacity: 1, shadowColor: .white)

.frame(width: 55, height: 100) // Petal dimensions
.offset(x: 0, y: 0) // Position petals away from center
.rotationEffect(.degrees(Double(index) * 45), anchor: .bottom) // Distribute evenly in 360° (8×45°)
.offset(y: -50) // Adjust vertical position of entire flower
.scaleEffect(isPulsing ? 0.97 : 1.05) // Size animation range
.animation(
Animation.easeInOut(duration: 2.0)
.delay(Double(index) * 0.1) // Staggered animation for flowing effect
.repeatForever(autoreverses: true),
value: isPulsing
)
petalView(for: index)
}
}
.frame(width: 300, height: 300)
Expand All @@ -66,6 +41,33 @@ struct GlassFlower: View {
isPulsing.toggle()
}
}

@ViewBuilder
private func petalView(for index: Int) -> some View {
let color = colors[index % colors.count]
let gradient = LinearGradient(
gradient: Gradient(stops: [
.init(color: color, location: 0),
.init(color: color.opacity(0.5), location: 1)
]),
startPoint: .bottom,
endPoint: .top
)
let rotation = Double(index) * 45
let animation = Animation.easeInOut(duration: 2.0)
.delay(Double(index) * 0.1)
.repeatForever(autoreverses: true)

Capsule()
.fill(gradient)
.glass(color: color, colorOpacity: 1, shadowColor: .white)
.frame(width: 55, height: 100)
.offset(x: 0, y: 0)
.rotationEffect(.degrees(rotation), anchor: .bottom)
.offset(y: -50)
.scaleEffect(isPulsing ? 0.97 : 1.05)
.animation(animation, value: isPulsing)
}
}

// MARK: - Previews
Expand Down
95 changes: 49 additions & 46 deletions Demo/Demo/Samples/Advanced/GlassFlower/GlassFlowerRotate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,62 +34,65 @@ struct GlassFlowerRotate: View {
// Flower petals: Eight capsules arranged in a circle pattern
// Each petal is a gradient-filled capsule with glass effect applied
ForEach(0..<8, id: \.self) { index in
Capsule()
.fill(
LinearGradient(
gradient: Gradient(stops: [
.init(color: colors[index % colors.count], location: 0),
.init(color: colors[index % colors.count].opacity(0.5), location: 1)
]),
startPoint: .bottom,
endPoint: .top
)
)

// Apply glass effect from SwiftGlass library to create translucent look
.glass(color: colors[index % colors.count], colorOpacity: 1, shadowColor: .white)

.frame(width: 55, height: 100) // Petal dimensions
.offset(x: 0, y: 0) // Position petals away from center
.rotationEffect(.degrees(Double(index) * 45), anchor: .bottom) // Distribute evenly in 360° (8×45°)
.rotationEffect(rotateToCenter ? .degrees(720) : .degrees(0), anchor: .bottom) // Rotate petals to face center when activated
.offset(y: -50) // Adjust vertical position of entire flower
.scaleEffect(isPulsing ? 0.97 : 1.05) // Size animation range
.animation(
Animation.easeInOut(duration: 2.0)
.delay(Double(index) * 0.1) // Staggered animation for flowing effect
.repeatForever(autoreverses: true),
value: isPulsing
)
.animation(
Animation.easeInOut(duration: 3.5)
.delay(Double(index) * 0.15), // Slightly staggered rotation
value: rotateToCenter
)
petalView(for: index)
}

// Button to toggle rotation to center
Button(action: {
withAnimation {
rotateToCenter.toggle()
}
}) {
Text(rotateToCenter ? "Reset Rotation" : "Rotate to Center")
.foregroundColor(.white)
.padding(15)
}
.cornerRadius(8)

.glass(color: .blue, shadowColor: .blue)

.offset(y: 240) // Position button below the flower
rotationButton
}
.frame(width: 300, height: 300)
// Start the pulsing animation when view appears
.onAppear {
isPulsing.toggle()
}
}

@ViewBuilder
private func petalView(for index: Int) -> some View {
let color = colors[index % colors.count]
let gradient = LinearGradient(
gradient: Gradient(stops: [
.init(color: color, location: 0),
.init(color: color.opacity(0.5), location: 1)
]),
startPoint: .bottom,
endPoint: .top
)
let baseRotation = Double(index) * 45
let centerRotation = rotateToCenter ? 720.0 : 0.0
let pulseAnimation = Animation.easeInOut(duration: 2.0)
.delay(Double(index) * 0.1)
.repeatForever(autoreverses: true)
let rotateAnimation = Animation.easeInOut(duration: 3.5)
.delay(Double(index) * 0.15)

Capsule()
.fill(gradient)
.glass(color: color, colorOpacity: 1, shadowColor: .white)
.frame(width: 55, height: 100)
.offset(x: 0, y: 0)
.rotationEffect(.degrees(baseRotation), anchor: .bottom)
.rotationEffect(.degrees(centerRotation), anchor: .bottom)
.offset(y: -50)
.scaleEffect(isPulsing ? 0.97 : 1.05)
.animation(pulseAnimation, value: isPulsing)
.animation(rotateAnimation, value: rotateToCenter)
}

private var rotationButton: some View {
Button(action: {
withAnimation {
rotateToCenter.toggle()
}
}) {
Text(rotateToCenter ? "Reset Rotation" : "Rotate to Center")
.foregroundColor(.white)
.padding(15)
}
.cornerRadius(8)
.glass(color: .blue, shadowColor: .blue)
.offset(y: 240)
}
}

// MARK: - Previews
Expand Down
125 changes: 125 additions & 0 deletions Demo/Demo/Samples/Essential/Capsule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// Capsule.swift
// Demo
//
// Created by Ming on 22/4/2025.
//

import SwiftUI
import SwiftGlass

struct CapsuleGlass: View {
var body: some View {
ZStack {
#if !os(visionOS) && !os(watchOS) && !os(macOS)
background
#endif

VStack(spacing: 30) {
// Capsule shape example
HStack {
Image(systemName: "capsule.fill")
.font(.title2)
Text("Capsule Glass")
.font(.headline)
}
.foregroundStyle(.white)
.padding(.horizontal, 30)
.padding(.vertical, 15)
.glass(shape: .capsule, color: .purple, shadowColor: .purple)

// Multiple capsules with different styles
VStack(spacing: 20) {
Button(action: {}) {
HStack {
Image(systemName: "play.fill")
Text("Play Music")
}
.foregroundStyle(.white)
.padding(.horizontal, 25)
.padding(.vertical, 12)
}
.glass(shape: .capsule, color: .blue, shadowColor: .blue)

Button(action: {}) {
HStack {
Image(systemName: "pause.fill")
Text("Pause")
}
.foregroundStyle(.white)
.padding(.horizontal, 25)
.padding(.vertical, 12)
}
.glass(shape: .capsule, color: .orange, shadowColor: .orange)

Button(action: {}) {
HStack {
Image(systemName: "stop.fill")
Text("Stop")
}
.foregroundStyle(.white)
.padding(.horizontal, 25)
.padding(.vertical, 12)
}
.glass(shape: .capsule, color: .red, shadowColor: .red)
}

// Horizontal capsule badges
HStack(spacing: 15) {
Text("New")
.font(.caption.bold())
.foregroundStyle(.white)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.glass(shape: .capsule, color: .green, shadowColor: .green)

Text("Hot")
.font(.caption.bold())
.foregroundStyle(.white)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.glass(shape: .capsule, color: .red, shadowColor: .red)

Text("Sale")
.font(.caption.bold())
.foregroundStyle(.white)
.padding(.horizontal, 12)
.padding(.vertical, 6)
.glass(shape: .capsule, color: .yellow, shadowColor: .yellow)
}
}
#if !os(watchOS)
.padding(25)
#else
.padding(15)
#endif
}
}

// Add a background for better looking
var background: some View {
Group {
Color.black
.ignoresSafeArea()

AsyncImage(url: URL(string: "https://shareby.vercel.app/3vj7gk")) { image in
image
.resizable()
.scaledToFill()
} placeholder: {
ProgressView()
}.opacity(0.3)
.ignoresSafeArea()
}
}
}

#Preview("Light") {
CapsuleGlass()
}

#Preview("Dark") {
CapsuleGlass()
.preferredColorScheme(.dark)
}

Loading