I’m a beginner and i’ve been trying to build a safari app extension as my first project.
I’m trying to customize the look of NavigationLink rows inside a list when pressed.
Right now, pressing each row looks like this:
It gets that dark gray highlight, and i want to change it to something smoother.
The code for that view is divided in two files, the HomeView and the FolderRowView. I’ll add both for context:
// HomeView snippet
var body: some View {
NavigationStack {
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("Explore")
.font(.title2)
Spacer()
SortButton(isAscending: $isAscending) // Now properly updates sorting
}
SearchBar(text: $searchText)
.padding(.vertical, 2)
//below is the list with the NavigationLink
List(filteredFolders) { folder in
NavigationLink(destination: DummyFolderDetailView(folder: folder)) {
FolderRowView(folder: folder)
}
}
.clipShape(RoundedRectangle(cornerRadius: 8))
.navigationTitle("Folders")
}
}
}
// Component FolderRowView
struct FolderRowView: View {
let folder: Folder
@State private var isHovering = false
var body: some View {
HStack {
// Folder Icon
Image(systemName: "folder.fill")
.resizable()
.scaledToFit()
.frame(width: 18, height: 18)
.foregroundStyle(.gray)
Spacer()
// Folder Name
Text(folder.name)
.font(.body)
.frame(maxWidth: .infinity, alignment: .leading)
// Chevron Icon
Image(systemName: "chevron.right")
.foregroundColor(.gray)
}
.padding(.vertical, 6)
.padding(.horizontal, 10) // Added horizontal padding for space around content
.background(isHovering ? Color.gray.opacity(0.1) : Color.clear) // Optional background change on hover
.scaleEffect(isHovering ? 1.05 : 1.0) // Zoom-in effect
.cornerRadius(8)
.animation(.easeInOut(duration: 0.2), value: isHovering) // Smooth animation
.onHover { hovering in
isHovering = hovering
}
.contextMenu { //(...)
So as you can see i already successfully added on hover styling and animation to the rows by working inside the component file.
I realize that customizing the on press style is a bit more complicated than that!
I tried:
-
.onTapGesture
with@State private var isPressed = false
in the component file, which showed up on press correctly, but interfered with theNavigationLink
click in a way the action was no longer actioning 🙂 -
Made a third component file
CustomStyle
containingview struct PressableStyle: ButtonStyle
that was then added as a modifier to theNavigationLink
as.buttonStyle(PressableStyle())
but it didn’t really do anything.. -
ChatGPT suggested i try creating a component view
FolderRowLink
that calls theFolderRowView
, nests it inside a button, and embeds a hiddenNavigationLink
triggered by the button. Then in theHomeView
i’d only have to call thatFolderRowLink
view in the list. I tried this but it has the same result as the first approach, where the new on press style shows up but clicking doesn’t action.
I understand the highlight color applied by default in the on press is the accentColor, but i’ve ran into some issues with it where .foregroundStyle(.accent)
calls my Assets.xcassets
AccentColor, but .foregroundStyle(Color.accentColor)
calls a dark gray (the one showing on press by default) and adding style modifiers to the NavigationLink doesn’t work either.
Overall i guess i just want to know whether styling this is possible, and how do you guys do it?