Browse Source

Fix profile form layout: pin card edges instead of fixed width

The profile card used an explicit width plus a trailing inequality, which could conflict with the scroll clip and shift content to the right. Pin the card leading and trailing to the document view so the form always spans the available width.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 2 tháng trước cách đây
mục cha
commit
3d968e7bfa
1 tập tin đã thay đổi với 143 bổ sung145 xóa
  1. 143 145
      App for Indeed/Views/MyProfilePageView.swift

+ 143 - 145
App for Indeed/Views/MyProfilePageView.swift

@@ -44,16 +44,77 @@ private enum ProfileLayoutEnforcement {
     }
 }
 
+/// Two fields side‑by‑side with a true 50/50 split, or stacked full‑width when compact. Avoids `NSStackView` collapsing paired columns to a narrow strip on the trailing edge.
+private final class ProfileDualFieldRow: NSView {
+    private let leftView: NSView
+    private let rightView: NSView
+    private let spacing: CGFloat
+    private var horizontalConstraints: [NSLayoutConstraint] = []
+    private var verticalConstraints: [NSLayoutConstraint] = []
+    private var isCompact = false
+
+    init(left: NSView, right: NSView, spacing: CGFloat = 12) {
+        self.leftView = left
+        self.rightView = right
+        self.spacing = spacing
+        super.init(frame: .zero)
+        translatesAutoresizingMaskIntoConstraints = false
+        ProfileLayoutEnforcement.applyForcedLTR(to: self)
+        addSubview(leftView)
+        addSubview(rightView)
+        leftView.translatesAutoresizingMaskIntoConstraints = false
+        rightView.translatesAutoresizingMaskIntoConstraints = false
+        leftView.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        rightView.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        leftView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        rightView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        horizontalConstraints = [
+            leftView.leftAnchor.constraint(equalTo: leftAnchor),
+            leftView.topAnchor.constraint(equalTo: topAnchor),
+            leftView.bottomAnchor.constraint(equalTo: bottomAnchor),
+            rightView.rightAnchor.constraint(equalTo: rightAnchor),
+            rightView.topAnchor.constraint(equalTo: topAnchor),
+            rightView.bottomAnchor.constraint(equalTo: bottomAnchor),
+            leftView.rightAnchor.constraint(equalTo: rightView.leftAnchor, constant: -spacing),
+            leftView.widthAnchor.constraint(equalTo: rightView.widthAnchor)
+        ]
+        verticalConstraints = [
+            leftView.leftAnchor.constraint(equalTo: leftAnchor),
+            leftView.rightAnchor.constraint(equalTo: rightAnchor),
+            leftView.topAnchor.constraint(equalTo: topAnchor),
+            rightView.leftAnchor.constraint(equalTo: leftAnchor),
+            rightView.rightAnchor.constraint(equalTo: rightAnchor),
+            rightView.topAnchor.constraint(equalTo: leftView.bottomAnchor, constant: spacing),
+            rightView.bottomAnchor.constraint(equalTo: bottomAnchor)
+        ]
+        NSLayoutConstraint.activate(horizontalConstraints)
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    func setCompact(_ compact: Bool) {
+        guard compact != isCompact else { return }
+        isCompact = compact
+        if compact {
+            NSLayoutConstraint.deactivate(horizontalConstraints)
+            NSLayoutConstraint.activate(verticalConstraints)
+        } else {
+            NSLayoutConstraint.deactivate(verticalConstraints)
+            NSLayoutConstraint.activate(horizontalConstraints)
+        }
+    }
+}
+
 final class MyProfilePageView: NSView {
     /// Below this form content width, two-column rows stack vertically.
     private static let compactFormWidth: CGFloat = 640
-    private static let readableFormMaxWidth: CGFloat = 880
     private static let horizontalPageInset: CGFloat = 24
 
     private let scrollView = NSScrollView()
     private let documentView = NSView()
     private let cardView = NSView()
-    private var readableFormWidthConstraint: NSLayoutConstraint!
     private let formStack = NSStackView()
 
     private let profileNameField = NSTextField()
@@ -69,8 +130,8 @@ final class MyProfilePageView: NSView {
     private let referralField = NSTextField()
     private let saveButton = ProfilePrimaryButton(title: "Save Profile  →", target: nil, action: nil)
 
-    private let nameEmailRow = NSStackView()
-    private let phoneJobRow = NSStackView()
+    private var nameEmailRow: ProfileDualFieldRow!
+    private var phoneJobRow: ProfileDualFieldRow!
 
     private let workExperienceRowsStack = NSStackView()
     private var workExperienceEntries: [WorkExperienceEntryView] = []
@@ -97,16 +158,6 @@ final class MyProfilePageView: NSView {
         setup()
     }
 
-    override func updateConstraints() {
-        updateReadableFormCardWidthConstraint()
-        super.updateConstraints()
-    }
-
-    override func viewDidMoveToWindow() {
-        super.viewDidMoveToWindow()
-        needsUpdateConstraints = true
-    }
-
     override func layout() {
         super.layout()
         if let layer = cardView.layer, layer.shadowOpacity > 0 {
@@ -117,18 +168,6 @@ final class MyProfilePageView: NSView {
         applyResponsiveRowsIfNeeded()
     }
 
-    /// Keeps the card width at `min(readable max, clip − horizontal insets)` before constraint passes. If the constant is ever wider than the clip, Auto Layout can slide the card to the trailing edge and the form looks compressed / right‑aligned.
-    private func updateReadableFormCardWidthConstraint() {
-        let clipW = max(bounds.width, scrollView.bounds.width, scrollView.contentView.bounds.width)
-        guard clipW > 1 else { return }
-        let horizontalCardInset = Self.horizontalPageInset * 2
-        let maxUsable = clipW - horizontalCardInset
-        let target = min(Self.readableFormMaxWidth, max(1, maxUsable))
-        if abs(readableFormWidthConstraint.constant - target) > 0.5 {
-            readableFormWidthConstraint.constant = target
-        }
-    }
-
     /// Wrapping `NSTextField`s report a tiny intrinsic width until `preferredMaxLayoutWidth` tracks the chrome width, which otherwise collapses the stack to a narrow trailing column.
     private func updateMultilinePreferredLayoutWidths() {
         let horizontalInset: CGFloat = 24
@@ -202,9 +241,6 @@ final class MyProfilePageView: NSView {
             cardView.layer?.cornerCurve = .continuous
         }
 
-        // Start narrow so the first constraint pass cannot exceed a small host; `updateConstraints` sets the real width.
-        readableFormWidthConstraint = cardView.widthAnchor.constraint(equalToConstant: 200)
-
         formStack.translatesAutoresizingMaskIntoConstraints = false
         formStack.orientation = .vertical
         formStack.alignment = .width
@@ -234,44 +270,43 @@ final class MyProfilePageView: NSView {
             documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
             documentView.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: Self.horizontalPageInset),
 
-            cardView.leadingAnchor.constraint(equalTo: documentView.leadingAnchor, constant: Self.horizontalPageInset),
-            cardView.trailingAnchor.constraint(lessThanOrEqualTo: documentView.trailingAnchor, constant: -Self.horizontalPageInset),
+            // Pin both edges so the card always spans the clip width minus insets; a separate width equal to a large constant can conflict with the clip and slide the card to the trailing edge.
+            cardView.leftAnchor.constraint(equalTo: documentView.leftAnchor, constant: Self.horizontalPageInset),
+            cardView.rightAnchor.constraint(equalTo: documentView.rightAnchor, constant: -Self.horizontalPageInset),
             cardView.topAnchor.constraint(equalTo: documentView.topAnchor, constant: Self.horizontalPageInset),
-            readableFormWidthConstraint,
 
-            formStack.leadingAnchor.constraint(equalTo: cardView.leadingAnchor),
-            formStack.trailingAnchor.constraint(equalTo: cardView.trailingAnchor),
+            formStack.leftAnchor.constraint(equalTo: cardView.leftAnchor),
+            formStack.rightAnchor.constraint(equalTo: cardView.rightAnchor),
             formStack.widthAnchor.constraint(equalTo: cardView.widthAnchor),
             formStack.topAnchor.constraint(equalTo: cardView.topAnchor),
             formStack.bottomAnchor.constraint(equalTo: cardView.bottomAnchor)
         ])
 
-        formStack.addArrangedSubview(labeledGroup(title: "Profile Name *", field: profileNameField, placeholder: "Marketing Director Profile"))
-        formStack.addArrangedSubview(sectionHeading("Personal Information"))
+        addFullWidthArrangedSubview(
+            labeledGroup(title: "Profile Name *", field: profileNameField, placeholder: "Marketing Director Profile")
+        )
+        addFullWidthArrangedSubview(sectionHeading("Personal Information"))
 
         let nameGroup = labeledGroup(title: "Full Name *", field: fullNameField, placeholder: "John Doe")
         let emailGroup = labeledGroup(title: "Email *", field: emailField, placeholder: "john@example.com")
-        configureTwoColumnRow(nameEmailRow, left: nameGroup, right: emailGroup)
-        pinEqualColumnWidths(in: nameEmailRow)
-        formStack.addArrangedSubview(nameEmailRow)
+        nameEmailRow = ProfileDualFieldRow(left: nameGroup, right: emailGroup, spacing: 12)
+        addFullWidthArrangedSubview(nameEmailRow)
 
         let phoneGroup = labeledGroup(title: "Phone", field: phoneField, placeholder: "+1 (555) 123-4567")
         let jobGroup = labeledGroup(title: "Job Title *", field: jobTitleField, placeholder: "Software Engineer")
-        configureTwoColumnRow(phoneJobRow, left: phoneGroup, right: jobGroup)
-        pinEqualColumnWidths(in: phoneJobRow)
-        formStack.addArrangedSubview(phoneJobRow)
-
-        ProfileLayoutEnforcement.applyForcedLTR(to: nameEmailRow)
-        ProfileLayoutEnforcement.applyForcedLTR(to: phoneJobRow)
-
-        formStack.addArrangedSubview(labeledGroup(title: "Address", field: addressField, placeholder: "123 Main St, City, State, ZIP"))
-        formStack.addArrangedSubview(careerSummaryBlock())
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(workExperienceSection())
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(educationSection())
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(
+        phoneJobRow = ProfileDualFieldRow(left: phoneGroup, right: jobGroup, spacing: 12)
+        addFullWidthArrangedSubview(phoneJobRow)
+
+        addFullWidthArrangedSubview(
+            labeledGroup(title: "Address", field: addressField, placeholder: "123 Main St, City, State, ZIP")
+        )
+        addFullWidthArrangedSubview(careerSummaryBlock())
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(workExperienceSection())
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(educationSection())
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(
             multilineProfileBlock(
                 title: "Certificates / Rewards",
                 placeholder: "List your certificates and awards...",
@@ -279,8 +314,8 @@ final class MyProfilePageView: NSView {
                 minHeight: 100
             )
         )
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(
             multilineProfileBlock(
                 title: "Interests",
                 placeholder: "List your interests and hobbies...",
@@ -288,8 +323,8 @@ final class MyProfilePageView: NSView {
                 minHeight: 100
             )
         )
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(
             multilineProfileBlock(
                 title: "Languages",
                 placeholder: "List languages you speak (e.g., English - Native, Spanish - Fluent)...",
@@ -297,9 +332,9 @@ final class MyProfilePageView: NSView {
                 minHeight: 100
             )
         )
-        formStack.addArrangedSubview(horizontalSeparator())
-        formStack.addArrangedSubview(referralBlock())
-        formStack.addArrangedSubview(saveButtonHost())
+        addFullWidthArrangedSubview(horizontalSeparator())
+        addFullWidthArrangedSubview(referralBlock())
+        addFullWidthArrangedSubview(saveButtonHost())
 
         saveButton.target = self
         saveButton.action = #selector(didTapSave)
@@ -315,14 +350,8 @@ final class MyProfilePageView: NSView {
         let compact = formWidth < Self.compactFormWidth
         guard compact != lastCompactLayout else { return }
         lastCompactLayout = compact
-        let orientation: NSUserInterfaceLayoutOrientation = compact ? .vertical : .horizontal
-        let rowSpacing: CGFloat = compact ? 16 : 12
-        nameEmailRow.orientation = orientation
-        nameEmailRow.spacing = rowSpacing
-        phoneJobRow.orientation = orientation
-        phoneJobRow.spacing = rowSpacing
-        nameEmailRow.distribution = compact ? .fill : .fillEqually
-        phoneJobRow.distribution = compact ? .fill : .fillEqually
+        nameEmailRow.setCompact(compact)
+        phoneJobRow.setCompact(compact)
         for entry in workExperienceEntries {
             entry.applyCompactLayout(compact)
         }
@@ -331,26 +360,10 @@ final class MyProfilePageView: NSView {
         }
     }
 
-    /// Keeps two columns the same width when the row is horizontal; avoids NSTextField intrinsic width fighting the stack.
-    private func pinEqualColumnWidths(in row: NSStackView) {
-        guard row.arrangedSubviews.count == 2 else { return }
-        let left = row.arrangedSubviews[0]
-        let right = row.arrangedSubviews[1]
-        left.widthAnchor.constraint(equalTo: right.widthAnchor).isActive = true
-    }
-
-    private func configureTwoColumnRow(_ row: NSStackView, left: NSView, right: NSView) {
-        row.translatesAutoresizingMaskIntoConstraints = false
-        row.orientation = .horizontal
-        row.spacing = 12
-        row.distribution = .fillEqually
-        row.alignment = .top
-        row.userInterfaceLayoutDirection = .leftToRight
-        ProfileLayoutEnforcement.applyForcedLTR(to: row)
-        row.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        row.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-        row.addArrangedSubview(left)
-        row.addArrangedSubview(right)
+    private func addFullWidthArrangedSubview(_ view: NSView) {
+        formStack.addArrangedSubview(view)
+        view.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
     }
 
     private func sectionHeading(_ text: String) -> NSView {
@@ -374,6 +387,9 @@ final class MyProfilePageView: NSView {
         row.userInterfaceLayoutDirection = .leftToRight
         ProfileLayoutEnforcement.applyForcedLTR(to: row)
         row.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([
+            label.leftAnchor.constraint(equalTo: row.leftAnchor)
+        ])
         return row
     }
 
@@ -400,7 +416,8 @@ final class MyProfilePageView: NSView {
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
         NSLayoutConstraint.activate([
-            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor),
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
         ])
         return stack
     }
@@ -512,6 +529,9 @@ final class MyProfilePageView: NSView {
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        NSLayoutConstraint.activate([
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
+        ])
         return stack
     }
 
@@ -576,6 +596,9 @@ final class MyProfilePageView: NSView {
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        NSLayoutConstraint.activate([
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
+        ])
         return stack
     }
 
@@ -608,6 +631,10 @@ final class MyProfilePageView: NSView {
         if #available(macOS 10.11, *) {
             stack.setCustomSpacing(6, after: wrap)
         }
+        NSLayoutConstraint.activate([
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
+            helper.leftAnchor.constraint(equalTo: stack.leftAnchor)
+        ])
         return stack
     }
 
@@ -826,7 +853,7 @@ private final class WorkExperienceEntryView: NSView {
     private let companyField = NSTextField()
     private let durationField = NSTextField()
     private let descriptionField = NSTextField()
-    private let jobCompanyRow = NSStackView()
+    private var jobCompanyRow: ProfileDualFieldRow!
 
     override init(frame frameRect: NSRect) {
         super.init(frame: frameRect)
@@ -846,9 +873,7 @@ private final class WorkExperienceEntryView: NSView {
     }
 
     func applyCompactLayout(_ compact: Bool) {
-        jobCompanyRow.orientation = compact ? .vertical : .horizontal
-        jobCompanyRow.spacing = compact ? 12 : 12
-        jobCompanyRow.distribution = compact ? .fill : .fillEqually
+        jobCompanyRow.setCompact(compact)
     }
 
     private func configure() {
@@ -902,8 +927,7 @@ private final class WorkExperienceEntryView: NSView {
 
         let jobGroup = Self.labeledFieldStack(title: "Job Title *", field: jobTitleField, placeholder: "e.g., Software Engineer")
         let companyGroup = Self.labeledFieldStack(title: "Company Name *", field: companyField, placeholder: "e.g., Google")
-        configureTwoColumnRow(jobCompanyRow, left: jobGroup, right: companyGroup)
-        pinEqualColumnWidths(in: jobCompanyRow)
+        jobCompanyRow = ProfileDualFieldRow(left: jobGroup, right: companyGroup, spacing: 12)
 
         let durationGroup = Self.labeledFieldStack(title: "Duration *", field: durationField, placeholder: "e.g., Jan 2020 - Present")
         let descriptionGroup = Self.multilineLabeledStack(
@@ -931,20 +955,6 @@ private final class WorkExperienceEntryView: NSView {
         ])
     }
 
-    private func configureTwoColumnRow(_ row: NSStackView, left: NSView, right: NSView) {
-        row.translatesAutoresizingMaskIntoConstraints = false
-        row.orientation = .horizontal
-        row.spacing = 12
-        row.distribution = .fillEqually
-        row.alignment = .top
-        row.userInterfaceLayoutDirection = .leftToRight
-        ProfileLayoutEnforcement.applyForcedLTR(to: row)
-        row.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        row.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-        row.addArrangedSubview(left)
-        row.addArrangedSubview(right)
-    }
-
     override func layout() {
         super.layout()
         for field in [jobTitleField, companyField, durationField, descriptionField] {
@@ -960,13 +970,6 @@ private final class WorkExperienceEntryView: NSView {
         layer.shadowPath = CGPath(roundedRect: bounds, cornerWidth: r, cornerHeight: r, transform: nil)
     }
 
-    private func pinEqualColumnWidths(in row: NSStackView) {
-        guard row.arrangedSubviews.count == 2 else { return }
-        let left = row.arrangedSubviews[0]
-        let right = row.arrangedSubviews[1]
-        left.widthAnchor.constraint(equalTo: right.widthAnchor).isActive = true
-    }
-
     @objc private func didTapDelete() {
         onDelete?()
     }
@@ -988,7 +991,13 @@ private final class WorkExperienceEntryView: NSView {
         stack.translatesAutoresizingMaskIntoConstraints = false
         stack.userInterfaceLayoutDirection = .leftToRight
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
-        NSLayoutConstraint.activate([wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)])
+        stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+        NSLayoutConstraint.activate([
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor),
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
+        ])
         return stack
     }
 
@@ -1048,6 +1057,11 @@ private final class WorkExperienceEntryView: NSView {
         stack.translatesAutoresizingMaskIntoConstraints = false
         stack.userInterfaceLayoutDirection = .leftToRight
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
+        stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
+        NSLayoutConstraint.activate([
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
+        ])
         return stack
     }
 
@@ -1103,7 +1117,7 @@ private final class EducationEntryView: NSView {
     private let degreeField = NSTextField()
     private let institutionField = NSTextField()
     private let yearField = NSTextField()
-    private let degreeInstitutionRow = NSStackView()
+    private var degreeInstitutionRow: ProfileDualFieldRow!
 
     override init(frame frameRect: NSRect) {
         super.init(frame: frameRect)
@@ -1123,9 +1137,7 @@ private final class EducationEntryView: NSView {
     }
 
     func applyCompactLayout(_ compact: Bool) {
-        degreeInstitutionRow.orientation = compact ? .vertical : .horizontal
-        degreeInstitutionRow.spacing = 12
-        degreeInstitutionRow.distribution = compact ? .fill : .fillEqually
+        degreeInstitutionRow.setCompact(compact)
     }
 
     private func configure() {
@@ -1187,8 +1199,7 @@ private final class EducationEntryView: NSView {
             field: institutionField,
             placeholder: "e.g., MIT"
         )
-        configureTwoColumnRow(degreeInstitutionRow, left: degreeGroup, right: institutionGroup)
-        pinEqualColumnWidths(in: degreeInstitutionRow)
+        degreeInstitutionRow = ProfileDualFieldRow(left: degreeGroup, right: institutionGroup, spacing: 12)
 
         let yearGroup = WorkExperienceEntryView.labeledFieldStack(
             title: "Year *",
@@ -1214,34 +1225,21 @@ private final class EducationEntryView: NSView {
         ])
     }
 
-    private func configureTwoColumnRow(_ row: NSStackView, left: NSView, right: NSView) {
-        row.translatesAutoresizingMaskIntoConstraints = false
-        row.orientation = .horizontal
-        row.spacing = 12
-        row.distribution = .fillEqually
-        row.alignment = .top
-        row.userInterfaceLayoutDirection = .leftToRight
-        ProfileLayoutEnforcement.applyForcedLTR(to: row)
-        row.setContentHuggingPriority(.defaultLow, for: .horizontal)
-        row.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-        row.addArrangedSubview(left)
-        row.addArrangedSubview(right)
-    }
-
     override func layout() {
         super.layout()
+        for field in [degreeField, institutionField, yearField] {
+            if let wrap = field.superview, wrap.bounds.width > 2 {
+                let w = max(1, wrap.bounds.width - 24)
+                if abs(field.preferredMaxLayoutWidth - w) > 0.5 {
+                    field.preferredMaxLayoutWidth = w
+                }
+            }
+        }
         guard let layer = layer, layer.shadowOpacity > 0 else { return }
         let r = layer.cornerRadius
         layer.shadowPath = CGPath(roundedRect: bounds, cornerWidth: r, cornerHeight: r, transform: nil)
     }
 
-    private func pinEqualColumnWidths(in row: NSStackView) {
-        guard row.arrangedSubviews.count == 2 else { return }
-        let left = row.arrangedSubviews[0]
-        let right = row.arrangedSubviews[1]
-        left.widthAnchor.constraint(equalTo: right.widthAnchor).isActive = true
-    }
-
     @objc private func didTapDelete() {
         onDelete?()
     }