# Creating custom buttons in SwiftUI

When we want to develop applications with SwiftUI, the reuse of components is key to have a clean, well structured, efficient and easy to maintain code. Next we are going to see an example of creating a reusable component, a custom button that we can incorporate to different views in our application.

## Reusable components in SwiftUI
SwiftUI facilitates the use of components that can be reused in different parts or views of our application. On the one hand, this reduces code duplication. On the other hand, it facilitates the maintenance and scalability of our applications or projects.

## Benefits of using reusable components in our applications
- Efficiency:** Saves time by avoiding having to rewrite code that may be identical or very similar.
- Consistency:** Maintains a uniform appearance and behavior throughout the application.
- Maintenance:** Facilitates the upgrade or update process since everything is in one place.

## Creating a custom button
We start by creating a custom button in a new Swift file. We will name this view `CustomButton`. This button will have a specific style that will make it stand out and will be easily reusable in any other view that needs it.

```swift
struct CustomButton: View {
    
    var text: String
    var action: () -> Void
    
    var body: some View {
        Button(action: action) {
            Text(text)
        }
        .frame(width: 400, height: 80)
        .foregroundStyle(.blue)
        .font(.title)
        .overlay(
            Capsule().stroke(
                LinearGradient(
                    colors: [.cyan, .purple, .cyan],
                    startPoint: .leading,
                    endPoint: .trailing
                ),
                lineWidth: 5
            )
        )
    }
}
```

``CustomButton`` is a structure that conforms to the `View` protocol and receives two parameters: `text` and ``action`.
- `text` is a String that will display the text that appears on the button.
- action` is a closure that defines the action to perform when the button is clicked. In this case an `empty function`.

As the goal is to reuse the button style in different screens of our application, we need to be able to adjust its text and action according to the needs of each of those screens and what we want to happen when the user interacts with that button.

Now we only have to go to the view where we want to incorporate the `struct` `CustomButton` and incorporate it, passing the `text` and `action` parameters as we want.

```swift
struct BookCardView: View {

    @State private var books = Books()
    @State private var title: String = ""
    @State private var var author: String = ""
    @State private var pages: String = "" @State private var pages: String = ""
    @State private var status: Bool = false
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Library 📚").font(.largeTitle.bold())
            
            TextField("Title of book", text: $title)
            TextField("Author", text: $author)
            TextField("Number of pages", text: $pages)
            
            Toggle(isOn: $status) {
                Text("Finished")
            }
            
            CustomButton(text: "Add book", action: {
                books.addBook(title: title, author: author, pages: pages, status: status)
                title = ""
                author = ""
                pages = ""
                status = false
                })


            List {
                ForEach(books.bookList.indices, id: \.self) { index in
                    let book = books.bookList[index]
                    VStack {
                        HStack {
                            Text("Title:").font(.subheadline)
                            Text(book.title).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Author:").font(.subheadline)
                            Text(book.author).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Pages:").font(.subheadline)
                            Text(book.pages).font(.subheadline.bold())
                        }
                        HStack {
                            Text("Status:").font(.subheadline)
                            Text(book.status ? "Read" : "Not started")
                                .font(.subheadline.bold())
                        }
                    }
                }
                .onDelete(perform: { indexSet in
                    indexSet.forEach { index in
                        books.deleteBook(at: index)
                    }
                })
            }
            .frame(height: 200)
            .clipShape(RoundedRectangle(cornerRadius: 10))
        }
        .textFieldStyle(RoundedBorderTextFieldStyle())
        .padding()
        .background(
            LinearGradient(gradient: Gradient(colors: [Color.blue, Color.purple]), startPoint: .top, endPoint: .bottom)
                .opacity(0.4)
        )
        .clipShape(RoundedRectangle(cornerRadius: 20))
        .frame(width: 400)
    }
}
```

In this simple way, we can reuse components in different views of the same application without having to repeat code.
