From swiftui
Enforces SwiftUI best practices: extract subviews to separate files, separate logic/actions from bodies, prefer modern APIs for buttons, previews, animations, and TabViews.
npx claudepluginhub fradser/dotclaude --plugin swiftuiswiftui-review/references/# SwiftUI Views - Strongly prefer to avoid breaking up view bodies using computed properties or methods that return `some View`, even if `@ViewBuilder` is used. Extract them into separate `View` structs instead, placing each into its own file. - Flag `body` properties that are excessively long; they should be broken into extracted subviews. - Button actions should be extracted from view bodies into separate methods, to avoid mixing layout and logic. - Similarly, general business logic should not live inline in `task()`, `onAppear()` or elsewhere in `body`. - Prefer to place view logic into...
/create-viewGenerates a SwiftUI view file with MVVM architecture, property wrappers, layouts, navigation elements, states, accessibility, dark mode support, previews, and documentation.
/convertConvert Claude-generated HTML design from URL or tarball path into SwiftUI View file in active Xcode workspace, with build, error fix, and preview diff.
Share bugs, ideas, or general feedback.
some View, even if @ViewBuilder is used. Extract them into separate View structs instead, placing each into its own file.body properties that are excessively long; they should be broken into extracted subviews.task(), onAppear() or elsewhere in body.TextField with axis: .vertical to using TextEditor, because it allows placeholder text. If a specific minimum height is required for TextField, use something like lineLimit(5...).action parameter, do so. For example: Button("Label", systemImage: "plus", action: myAction) is preferred over Button("Label", systemImage: "plus") { action() }.ImageRenderer over UIGraphicsImageRenderer.#Preview should be used for previews, not the legacy PreviewProvider protocol.TabView(selection:), use a binding to a property that stores an enum rather than an integer or string. For example, Tab("Home", systemImage: "house", value: .home) is better than Tab("Home", systemImage: "house", value: 0).some View, even if @ViewBuilder is used. Extract them into separate View structs instead, placing each into its own file. (Yes, this is repeated, but it’s so important it needs to be mentioned twice.)@Animatable macro over creating animatableData manually – the macro automatically adds conformance to the Animatable protocol and creates the correct animatableData property. If some properties should not or cannot be animated (e.g. Booleans, integers, etc), mark them @AnimatableIgnored.animation(_ animation: Animation?); always provide a value to watch, such as .animation(.bouncy, value: score).completion closure passed to withAnimation(), rather than trying to execute multiple withAnimation() calls using delays.For example:
Button("Animate Me") {
withAnimation {
scale = 2
} completion: {
withAnimation {
scale = 1
}
}
}