Skip to content

Add zIndex API #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 5, 2025
Merged

Add zIndex API #243

merged 1 commit into from
Apr 5, 2025

Conversation

Kyle-Ye
Copy link
Member

@Kyle-Ye Kyle-Ye commented Apr 5, 2025

Summary by CodeRabbit

  • New Features

    • Introduced new functionality allowing developers to control the layering order of overlapping views using a customizable display order.
  • Tests

    • Added automated tests to validate that the view layering control works as intended.

Copy link

coderabbitai bot commented Apr 5, 2025

Walkthrough

This pull request introduces a new view layer ordering feature into the OpenSwiftUICore framework. A new file extends the View protocol with a zIndex(_:) method to control the display order of overlapping views. The implementation uses a package-level trait key (ZIndexTraitKey) to manage a default z-index value and integrates this property into the view’s trait collection. Additionally, tests are added to validate the new API, ensuring that the z-index functionality works as expected by simulating view rendering behavior.

Changes

File Change Summary
Sources/…/ZIndex.swift Introduces a new file that extends View with a nonisolated public func zIndex(_:) -> some View method. Adds a package-level ZIndexTraitKey with a default value of 0.0 and extends ViewTraitCollection with a z-index property. Marks the trait key as unavailable for Sendable.
Tests/…/ZIndexTests.swift Adds a new test file with a ZIndexTests structure annotated with @MainActor, including the test method indexOrder() that verifies the z-index functionality in a sample view.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant V as View Extension
    participant TC as ViewTraitCollection
    participant TK as ZIndexTraitKey

    Dev->>V: call zIndex(value)
    V->>TC: update trait (using TK)
    TC-->>V: trait updated
    V-->>Dev: return modified view with new z-index
Loading

Poem

Hop along, dear coder friend,
With z-index layers now on trend,
Views stack up with a graceful twist,
A trait key dance you can’t resist,
Carrots and code in one blissful blend!

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai plan to trigger planning for file edits and PR creation.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfea6f1 and 1f9f8d6.

📒 Files selected for processing (2)
  • Sources/OpenSwiftUICore/Layout/ZIndex.swift (1 hunks)
  • Tests/OpenSwiftUICoreTests/Layout/ZIndexTests.swift (1 hunks)
🧰 Additional context used
🧬 Code Definitions (1)
Tests/OpenSwiftUICoreTests/Layout/ZIndexTests.swift (1)
Sources/OpenSwiftUICore/Layout/ZIndex.swift (1)
  • zIndex (36-39)
🪛 SwiftLint (0.57.0)
Tests/OpenSwiftUICoreTests/Layout/ZIndexTests.swift

[Warning] 19-19: TODOs should be resolved (Add a test helper to hook into...)

(todo)

⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: Execute tests on Ubuntu (6.0.1)
  • GitHub Check: Execute tests on iOS (macos-15, 16.0, 2021, 18.0)
  • GitHub Check: Execute tests on iOS (macos-15, 16.0, 2024, 18.0)
  • GitHub Check: Execute compatibility tests for iOS (macos-15, 16.0, 2024, 18.0)
  • GitHub Check: Execute tests on macOS (macos-15, 16.0, 2021)
  • GitHub Check: Execute compatibility tests for macOS (macos-15, 16.0, 2024)
🔇 Additional comments (6)
Sources/OpenSwiftUICore/Layout/ZIndex.swift (6)

8-41: Clean, well-documented implementation of zIndex API.

The View extension and its documentation are excellent. The documentation clearly explains the purpose, provides a practical example with visual reference, and specifies the default value. The implementation follows the trait pattern used elsewhere in the framework.


36-39: Implementation uses trait system correctly.

The zIndex implementation properly uses the trait system to store the value, with appropriate annotations for inlining and actor isolation.


42-46: Trait key implementation is appropriate.

The ZIndexTraitKey implementation provides the correct default value (0.0) matching the documented behavior.


48-49: Correctly marked as unavailable for Sendable.

This prevents potential concurrent access issues with the trait key.


51-56: ViewTraitCollection extension provides clean accessor.

The computed property offers a convenient way to access the zIndex value in the trait collection.


36-39: Consider validating the zIndex implementation with comprehensive tests.

While the implementation looks solid, the associated test file (ZIndexTests.swift) doesn't yet verify the behavior of this API. Consider implementing the test helper mentioned in the TODO to ensure the functionality works as expected.

Comment on lines +12 to +20
func indexOrder() {
struct ContentView: View {
var body: some View {
Color.red
.zIndex(0.5)
}
}
// TODO: Add a test helper to hook into makeViewList and retrieve the zIndex value to verify it
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Incomplete test implementation.

The test defines a view with a zIndex modifier but doesn't include any assertions to verify the functionality. This means the test isn't actually testing anything yet.

Consider implementing the test helper mentioned in the TODO comment or using a different approach to verify that the zIndex value is correctly applied to the view. Without assertions, this test doesn't provide any validation of the functionality.

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 19-19: TODOs should be resolved (Add a test helper to hook into...)

(todo)

.zIndex(0.5)
}
}
// TODO: Add a test helper to hook into makeViewList and retrieve the zIndex value to verify it
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Address TODO comment before merging.

TODOs in committed code can lead to forgotten tasks and technical debt.

Either implement the test helper mentioned in the TODO, create a tracked issue to address it later, or add more context about why it can't be implemented yet.


🌐 Web query:

What are best practices for testing SwiftUI view modifiers?

💡 Result:

To ensure SwiftUI view modifiers are thoroughly tested and maintainable, follow these best practices:

Leverage ViewInspector for Hierarchy Inspection

Use ViewInspector to verify modifiers are applied correctly by inspecting the view hierarchy:

func testButtonStyle() throws {
    let view = Button("Test", action: {})
        .buttonStyle(PrimaryButtonStyle())
    
    let button = try view.inspect().button()
    XCTAssertEqual(try button.label().text().string(), "Test")
    XCTAssertTrue(try button.actualButtonStyle() is PrimaryButtonStyle) [1][5]
}

This validates both the presence of the modifier and its concrete type.

Test Modifier Side Effects

Verify visual and behavioral impacts through:

  1. State changes: Check if modifiers alter @State/@binding
    XCTAssertTrue(viewModel.items.first!.isCompleted) [1]
  2. View updates: Confirm layout changes after modifiers
    XCTAssertEqual(try list.count, 1) [1]

Structure Modifiers for Testability

  1. Isolate pure modifiers without external dependencies
  2. Create test targets specifically for modifier validation [5]
  3. Use @testable imports to access internal components
    @testable import YourAppModule [5]

Validate Custom ViewModifier Conformance

Test custom modifiers by:

  1. Checking protocol conformance
  2. Verifying modifier composition
struct TitleModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .font(.largeTitle)
            .foregroundColor(.blue)
}

Performance and Safety

  1. Profile with Instruments to detect rendering bottlenecks from complex modifiers [8]
  2. Prevent recursion using safety attributes:
    @warn_unqualified_access
    func customModifier() -> some View [10]

Test Modifier Combinations

Validate interactions between multiple modifiers:

Text("Hello")
    .titleStyle()
    .watermarked("TEST")
// Verify both modifiers apply correctly [4][7]

Asynchronous Testing

Handle modifiers with async operations using XCTest expectations:

let expectation = self.expectation(description: "Async modifier")
// Test async code
waitForExpectations(timeout: 1) [5]

By combining these strategies, you can create a robust testing suite that ensures view modifiers behave as expected across different states and configurations.

Citations:


Action Required: Implement or Track the Z‑Index Test Helper

Before merging, please address the pending TODO in Tests/OpenSwiftUICoreTests/Layout/ZIndexTests.swift at line 19. The file currently contains this placeholder:

        // TODO: Add a test helper to hook into makeViewList and retrieve the zIndex value to verify it

To align with SwiftUI testing best practices, consider the following options:

  • Implement the Test Helper: Use a solution such as ViewInspector to inspect the view hierarchy and verify that the expected zIndex is applied.
  • Document and Track: If implementing this helper immediately isn’t feasible, add more context in the code explaining the limitation and create a tracked issue to ensure this task is addressed later.

Taking one of these actions will help prevent technical debt by ensuring that all view modifiers are properly tested.

🧰 Tools
🪛 SwiftLint (0.57.0)

[Warning] 19-19: TODOs should be resolved (Add a test helper to hook into...)

(todo)

Copy link

codecov bot commented Apr 5, 2025

Codecov Report

Attention: Patch coverage is 0% with 5 lines in your changes missing coverage. Please review.

Project coverage is 20.03%. Comparing base (bfea6f1) to head (1f9f8d6).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
Sources/OpenSwiftUICore/Layout/ZIndex.swift 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #243      +/-   ##
==========================================
+ Coverage   20.00%   20.03%   +0.02%     
==========================================
  Files         325      326       +1     
  Lines       14583    14588       +5     
==========================================
+ Hits         2918     2922       +4     
- Misses      11665    11666       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Kyle-Ye Kyle-Ye linked an issue Apr 5, 2025 that may be closed by this pull request
@Kyle-Ye Kyle-Ye merged commit 8d39851 into main Apr 5, 2025
10 checks passed
@Kyle-Ye Kyle-Ye deleted the feature/zindex branch April 5, 2025 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add ZIndex implementation
1 participant