Просмотр исходного кода

Fix My Profile layout under RTL with LTR subtree and width pins

Pin the profile page container with geometric left/right anchors so
constraints match the forced LTR subtree. Use leading stack alignment
with explicit arranged-subview widths, reapply LTR when the view
joins a window, and drop the redundant document width constraint so
the form fills the scroll view predictably.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 недель назад: 3
Родитель
Сommit
51ab8cf6de
2 измененных файлов с 69 добавлено и 26 удалено
  1. 2 2
      App for Indeed/Views/DashboardView.swift
  2. 67 24
      App for Indeed/Views/MyProfilePageView.swift

+ 2 - 2
App for Indeed/Views/DashboardView.swift

@@ -1219,8 +1219,8 @@ final class DashboardView: NSView, NSTextFieldDelegate {
1219
             cvMakerPageContainer.topAnchor.constraint(equalTo: nonHomeHost.topAnchor),
1219
             cvMakerPageContainer.topAnchor.constraint(equalTo: nonHomeHost.topAnchor),
1220
             cvMakerPageContainer.bottomAnchor.constraint(equalTo: nonHomeHost.bottomAnchor),
1220
             cvMakerPageContainer.bottomAnchor.constraint(equalTo: nonHomeHost.bottomAnchor),
1221
 
1221
 
1222
-            profilePageContainer.leadingAnchor.constraint(equalTo: nonHomeHost.leadingAnchor),
1223
-            profilePageContainer.trailingAnchor.constraint(equalTo: nonHomeHost.trailingAnchor),
1222
+            profilePageContainer.leftAnchor.constraint(equalTo: nonHomeHost.leftAnchor),
1223
+            profilePageContainer.rightAnchor.constraint(equalTo: nonHomeHost.rightAnchor),
1224
             profilePageContainer.topAnchor.constraint(equalTo: nonHomeHost.topAnchor),
1224
             profilePageContainer.topAnchor.constraint(equalTo: nonHomeHost.topAnchor),
1225
             profilePageContainer.bottomAnchor.constraint(equalTo: nonHomeHost.bottomAnchor)
1225
             profilePageContainer.bottomAnchor.constraint(equalTo: nonHomeHost.bottomAnchor)
1226
         ])
1226
         ])

+ 67 - 24
App for Indeed/Views/MyProfilePageView.swift

@@ -22,6 +22,14 @@ private enum ProfilePagePalette {
22
 
22
 
23
 /// Keeps profile text left-aligned and LTR so fields do not collapse to a narrow trailing strip under RTL / natural alignment.
23
 /// Keeps profile text left-aligned and LTR so fields do not collapse to a narrow trailing strip under RTL / natural alignment.
24
 private enum ProfileLayoutEnforcement {
24
 private enum ProfileLayoutEnforcement {
25
+    static func applyForcedLTRSubtree(from root: NSView) {
26
+        var stack: [NSView] = [root]
27
+        while let view = stack.popLast() {
28
+            applyForcedLTR(to: view)
29
+            stack.append(contentsOf: view.subviews)
30
+        }
31
+    }
32
+
25
     static func applyForcedLTR(to view: NSView) {
33
     static func applyForcedLTR(to view: NSView) {
26
         view.userInterfaceLayoutDirection = .leftToRight
34
         view.userInterfaceLayoutDirection = .leftToRight
27
     }
35
     }
@@ -44,6 +52,15 @@ private enum ProfileLayoutEnforcement {
44
     }
52
     }
45
 }
53
 }
46
 
54
 
55
+private extension NSStackView {
56
+    /// For vertical stacks using `.leading` alignment (geometric left under mixed RTL), pin each arranged subview’s width to the stack so labels/fields stay full-width.
57
+    func pinAllArrangedSubviewWidthsEqualToStackWidth() {
58
+        for subview in arrangedSubviews {
59
+            subview.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
60
+        }
61
+    }
62
+}
63
+
47
 /// 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.
64
 /// 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.
48
 private final class ProfileDualFieldRow: NSView {
65
 private final class ProfileDualFieldRow: NSView {
49
     private let leftView: NSView
66
     private let leftView: NSView
@@ -158,6 +175,13 @@ final class MyProfilePageView: NSView {
158
         setup()
175
         setup()
159
     }
176
     }
160
 
177
 
178
+    override func viewDidMoveToWindow() {
179
+        super.viewDidMoveToWindow()
180
+        guard window != nil else { return }
181
+        ProfileLayoutEnforcement.applyForcedLTRSubtree(from: self)
182
+        needsLayout = true
183
+    }
184
+
161
     override func layout() {
185
     override func layout() {
162
         super.layout()
186
         super.layout()
163
         if let layer = cardView.layer, layer.shadowOpacity > 0 {
187
         if let layer = cardView.layer, layer.shadowOpacity > 0 {
@@ -243,7 +267,7 @@ final class MyProfilePageView: NSView {
243
 
267
 
244
         formStack.translatesAutoresizingMaskIntoConstraints = false
268
         formStack.translatesAutoresizingMaskIntoConstraints = false
245
         formStack.orientation = .vertical
269
         formStack.orientation = .vertical
246
-        formStack.alignment = .width
270
+        formStack.alignment = .leading
247
         formStack.distribution = .fill
271
         formStack.distribution = .fill
248
         formStack.spacing = 24
272
         formStack.spacing = 24
249
         formStack.edgeInsets = NSEdgeInsets(top: 32, left: 28, bottom: 32, right: 28)
273
         formStack.edgeInsets = NSEdgeInsets(top: 32, left: 28, bottom: 32, right: 28)
@@ -266,7 +290,6 @@ final class MyProfilePageView: NSView {
266
             // Pin the document to the clip view’s geometric width so LTR/RTL semantics cannot slide the form.
290
             // Pin the document to the clip view’s geometric width so LTR/RTL semantics cannot slide the form.
267
             documentView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor),
291
             documentView.leftAnchor.constraint(equalTo: scrollView.contentView.leftAnchor),
268
             documentView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor),
292
             documentView.rightAnchor.constraint(equalTo: scrollView.contentView.rightAnchor),
269
-            documentView.widthAnchor.constraint(equalTo: scrollView.contentView.widthAnchor),
270
             documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
293
             documentView.topAnchor.constraint(equalTo: scrollView.contentView.topAnchor),
271
             documentView.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: Self.horizontalPageInset),
294
             documentView.bottomAnchor.constraint(equalTo: cardView.bottomAnchor, constant: Self.horizontalPageInset),
272
 
295
 
@@ -341,6 +364,8 @@ final class MyProfilePageView: NSView {
341
 
364
 
342
         appendWorkExperienceEntry()
365
         appendWorkExperienceEntry()
343
         appendEducationEntry()
366
         appendEducationEntry()
367
+
368
+        ProfileLayoutEnforcement.applyForcedLTRSubtree(from: self)
344
     }
369
     }
345
 
370
 
346
     private func applyResponsiveRowsIfNeeded() {
371
     private func applyResponsiveRowsIfNeeded() {
@@ -364,6 +389,7 @@ final class MyProfilePageView: NSView {
364
         formStack.addArrangedSubview(view)
389
         formStack.addArrangedSubview(view)
365
         view.setContentHuggingPriority(.defaultLow, for: .horizontal)
390
         view.setContentHuggingPriority(.defaultLow, for: .horizontal)
366
         view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
391
         view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
392
+        view.widthAnchor.constraint(equalTo: formStack.widthAnchor).isActive = true
367
     }
393
     }
368
 
394
 
369
     private func sectionHeading(_ text: String) -> NSView {
395
     private func sectionHeading(_ text: String) -> NSView {
@@ -398,7 +424,7 @@ final class MyProfilePageView: NSView {
398
         label.font = .systemFont(ofSize: 12, weight: .medium)
424
         label.font = .systemFont(ofSize: 12, weight: .medium)
399
         label.textColor = ProfilePagePalette.secondaryText
425
         label.textColor = ProfilePagePalette.secondaryText
400
         label.translatesAutoresizingMaskIntoConstraints = false
426
         label.translatesAutoresizingMaskIntoConstraints = false
401
-        label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
427
+        label.setContentHuggingPriority(.defaultLow, for: .horizontal)
402
         ProfileLayoutEnforcement.applyLeftAlignedTextField(label)
428
         ProfileLayoutEnforcement.applyLeftAlignedTextField(label)
403
 
429
 
404
         styleSingleLineField(field, placeholder: placeholder)
430
         styleSingleLineField(field, placeholder: placeholder)
@@ -407,8 +433,8 @@ final class MyProfilePageView: NSView {
407
         let stack = NSStackView(views: [label, wrap])
433
         let stack = NSStackView(views: [label, wrap])
408
         stack.orientation = .vertical
434
         stack.orientation = .vertical
409
         stack.spacing = 8
435
         stack.spacing = 8
410
-        // `.width` stretches label + field chrome to the row width; `.leading` collapses to intrinsic width and caused right-edge compression.
411
-        stack.alignment = .width
436
+        // `.leading` keeps rows on the geometric left; explicit widths keep labels/fields full-width (`.width` alone can still hug the trailing edge under RTL-style layout).
437
+        stack.alignment = .leading
412
         stack.translatesAutoresizingMaskIntoConstraints = false
438
         stack.translatesAutoresizingMaskIntoConstraints = false
413
         stack.userInterfaceLayoutDirection = .leftToRight
439
         stack.userInterfaceLayoutDirection = .leftToRight
414
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
440
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
@@ -416,8 +442,9 @@ final class MyProfilePageView: NSView {
416
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
442
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
417
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
443
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
418
         NSLayoutConstraint.activate([
444
         NSLayoutConstraint.activate([
419
-            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor),
420
-            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
445
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
446
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
447
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
421
         ])
448
         ])
422
         return stack
449
         return stack
423
     }
450
     }
@@ -523,14 +550,16 @@ final class MyProfilePageView: NSView {
523
         let stack = NSStackView(views: [label, wrap])
550
         let stack = NSStackView(views: [label, wrap])
524
         stack.orientation = .vertical
551
         stack.orientation = .vertical
525
         stack.spacing = 8
552
         stack.spacing = 8
526
-        stack.alignment = .width
553
+        stack.alignment = .leading
527
         stack.translatesAutoresizingMaskIntoConstraints = false
554
         stack.translatesAutoresizingMaskIntoConstraints = false
528
         stack.userInterfaceLayoutDirection = .leftToRight
555
         stack.userInterfaceLayoutDirection = .leftToRight
529
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
556
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
530
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
557
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
531
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
558
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
532
         NSLayoutConstraint.activate([
559
         NSLayoutConstraint.activate([
533
-            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
560
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
561
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
562
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
534
         ])
563
         ])
535
         return stack
564
         return stack
536
     }
565
     }
@@ -590,14 +619,16 @@ final class MyProfilePageView: NSView {
590
         let stack = NSStackView(views: [label, wrap])
619
         let stack = NSStackView(views: [label, wrap])
591
         stack.orientation = .vertical
620
         stack.orientation = .vertical
592
         stack.spacing = 8
621
         stack.spacing = 8
593
-        stack.alignment = .width
622
+        stack.alignment = .leading
594
         stack.translatesAutoresizingMaskIntoConstraints = false
623
         stack.translatesAutoresizingMaskIntoConstraints = false
595
         stack.userInterfaceLayoutDirection = .leftToRight
624
         stack.userInterfaceLayoutDirection = .leftToRight
596
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
625
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
597
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
626
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
598
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
627
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
599
         NSLayoutConstraint.activate([
628
         NSLayoutConstraint.activate([
600
-            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
629
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
630
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
631
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
601
         ])
632
         ])
602
         return stack
633
         return stack
603
     }
634
     }
@@ -622,7 +653,7 @@ final class MyProfilePageView: NSView {
622
         let stack = NSStackView(views: [label, wrap, helper])
653
         let stack = NSStackView(views: [label, wrap, helper])
623
         stack.orientation = .vertical
654
         stack.orientation = .vertical
624
         stack.spacing = 8
655
         stack.spacing = 8
625
-        stack.alignment = .width
656
+        stack.alignment = .leading
626
         stack.translatesAutoresizingMaskIntoConstraints = false
657
         stack.translatesAutoresizingMaskIntoConstraints = false
627
         stack.userInterfaceLayoutDirection = .leftToRight
658
         stack.userInterfaceLayoutDirection = .leftToRight
628
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
659
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
@@ -633,7 +664,10 @@ final class MyProfilePageView: NSView {
633
         }
664
         }
634
         NSLayoutConstraint.activate([
665
         NSLayoutConstraint.activate([
635
             label.leftAnchor.constraint(equalTo: stack.leftAnchor),
666
             label.leftAnchor.constraint(equalTo: stack.leftAnchor),
636
-            helper.leftAnchor.constraint(equalTo: stack.leftAnchor)
667
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
668
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor),
669
+            helper.leftAnchor.constraint(equalTo: stack.leftAnchor),
670
+            helper.widthAnchor.constraint(equalTo: stack.widthAnchor)
637
         ])
671
         ])
638
         return stack
672
         return stack
639
     }
673
     }
@@ -677,17 +711,18 @@ final class MyProfilePageView: NSView {
677
         workExperienceRowsStack.translatesAutoresizingMaskIntoConstraints = false
711
         workExperienceRowsStack.translatesAutoresizingMaskIntoConstraints = false
678
         workExperienceRowsStack.orientation = .vertical
712
         workExperienceRowsStack.orientation = .vertical
679
         workExperienceRowsStack.spacing = 20
713
         workExperienceRowsStack.spacing = 20
680
-        workExperienceRowsStack.alignment = .width
714
+        workExperienceRowsStack.alignment = .leading
681
         workExperienceRowsStack.userInterfaceLayoutDirection = .leftToRight
715
         workExperienceRowsStack.userInterfaceLayoutDirection = .leftToRight
682
         ProfileLayoutEnforcement.applyForcedLTR(to: workExperienceRowsStack)
716
         ProfileLayoutEnforcement.applyForcedLTR(to: workExperienceRowsStack)
683
 
717
 
684
         let outer = NSStackView(views: [headerRow, workExperienceRowsStack])
718
         let outer = NSStackView(views: [headerRow, workExperienceRowsStack])
685
         outer.orientation = .vertical
719
         outer.orientation = .vertical
686
         outer.spacing = 16
720
         outer.spacing = 16
687
-        outer.alignment = .width
721
+        outer.alignment = .leading
688
         outer.translatesAutoresizingMaskIntoConstraints = false
722
         outer.translatesAutoresizingMaskIntoConstraints = false
689
         outer.userInterfaceLayoutDirection = .leftToRight
723
         outer.userInterfaceLayoutDirection = .leftToRight
690
         ProfileLayoutEnforcement.applyForcedLTR(to: outer)
724
         ProfileLayoutEnforcement.applyForcedLTR(to: outer)
725
+        outer.pinAllArrangedSubviewWidthsEqualToStackWidth()
691
         return outer
726
         return outer
692
     }
727
     }
693
 
728
 
@@ -722,17 +757,18 @@ final class MyProfilePageView: NSView {
722
         educationRowsStack.translatesAutoresizingMaskIntoConstraints = false
757
         educationRowsStack.translatesAutoresizingMaskIntoConstraints = false
723
         educationRowsStack.orientation = .vertical
758
         educationRowsStack.orientation = .vertical
724
         educationRowsStack.spacing = 16
759
         educationRowsStack.spacing = 16
725
-        educationRowsStack.alignment = .width
760
+        educationRowsStack.alignment = .leading
726
         educationRowsStack.userInterfaceLayoutDirection = .leftToRight
761
         educationRowsStack.userInterfaceLayoutDirection = .leftToRight
727
         ProfileLayoutEnforcement.applyForcedLTR(to: educationRowsStack)
762
         ProfileLayoutEnforcement.applyForcedLTR(to: educationRowsStack)
728
 
763
 
729
         let outer = NSStackView(views: [headerRow, educationRowsStack])
764
         let outer = NSStackView(views: [headerRow, educationRowsStack])
730
         outer.orientation = .vertical
765
         outer.orientation = .vertical
731
         outer.spacing = 16
766
         outer.spacing = 16
732
-        outer.alignment = .width
767
+        outer.alignment = .leading
733
         outer.translatesAutoresizingMaskIntoConstraints = false
768
         outer.translatesAutoresizingMaskIntoConstraints = false
734
         outer.userInterfaceLayoutDirection = .leftToRight
769
         outer.userInterfaceLayoutDirection = .leftToRight
735
         ProfileLayoutEnforcement.applyForcedLTR(to: outer)
770
         ProfileLayoutEnforcement.applyForcedLTR(to: outer)
771
+        outer.pinAllArrangedSubviewWidthsEqualToStackWidth()
736
         return outer
772
         return outer
737
     }
773
     }
738
 
774
 
@@ -748,6 +784,7 @@ final class MyProfilePageView: NSView {
748
         }
784
         }
749
         workExperienceEntries.append(entry)
785
         workExperienceEntries.append(entry)
750
         workExperienceRowsStack.addArrangedSubview(entry)
786
         workExperienceRowsStack.addArrangedSubview(entry)
787
+        entry.widthAnchor.constraint(equalTo: workExperienceRowsStack.widthAnchor).isActive = true
751
         renumberWorkExperienceEntries()
788
         renumberWorkExperienceEntries()
752
         refreshWorkExperienceDeleteButtons()
789
         refreshWorkExperienceDeleteButtons()
753
     }
790
     }
@@ -786,6 +823,7 @@ final class MyProfilePageView: NSView {
786
         }
823
         }
787
         educationEntries.append(entry)
824
         educationEntries.append(entry)
788
         educationRowsStack.addArrangedSubview(entry)
825
         educationRowsStack.addArrangedSubview(entry)
826
+        entry.widthAnchor.constraint(equalTo: educationRowsStack.widthAnchor).isActive = true
789
         renumberEducationEntries()
827
         renumberEducationEntries()
790
         refreshEducationDeleteButtons()
828
         refreshEducationDeleteButtons()
791
     }
829
     }
@@ -940,11 +978,12 @@ private final class WorkExperienceEntryView: NSView {
940
         let inner = NSStackView(views: [headerRow, jobCompanyRow, durationGroup, descriptionGroup])
978
         let inner = NSStackView(views: [headerRow, jobCompanyRow, durationGroup, descriptionGroup])
941
         inner.orientation = .vertical
979
         inner.orientation = .vertical
942
         inner.spacing = 16
980
         inner.spacing = 16
943
-        inner.alignment = .width
981
+        inner.alignment = .leading
944
         inner.translatesAutoresizingMaskIntoConstraints = false
982
         inner.translatesAutoresizingMaskIntoConstraints = false
945
         inner.edgeInsets = NSEdgeInsets(top: 16, left: 18, bottom: 16, right: 18)
983
         inner.edgeInsets = NSEdgeInsets(top: 16, left: 18, bottom: 16, right: 18)
946
         inner.userInterfaceLayoutDirection = .leftToRight
984
         inner.userInterfaceLayoutDirection = .leftToRight
947
         ProfileLayoutEnforcement.applyForcedLTR(to: inner)
985
         ProfileLayoutEnforcement.applyForcedLTR(to: inner)
986
+        inner.pinAllArrangedSubviewWidthsEqualToStackWidth()
948
 
987
 
949
         addSubview(inner)
988
         addSubview(inner)
950
         NSLayoutConstraint.activate([
989
         NSLayoutConstraint.activate([
@@ -987,7 +1026,7 @@ private final class WorkExperienceEntryView: NSView {
987
         let stack = NSStackView(views: [label, wrap])
1026
         let stack = NSStackView(views: [label, wrap])
988
         stack.orientation = .vertical
1027
         stack.orientation = .vertical
989
         stack.spacing = 8
1028
         stack.spacing = 8
990
-        stack.alignment = .width
1029
+        stack.alignment = .leading
991
         stack.translatesAutoresizingMaskIntoConstraints = false
1030
         stack.translatesAutoresizingMaskIntoConstraints = false
992
         stack.userInterfaceLayoutDirection = .leftToRight
1031
         stack.userInterfaceLayoutDirection = .leftToRight
993
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
1032
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
@@ -995,8 +1034,9 @@ private final class WorkExperienceEntryView: NSView {
995
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
1034
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
996
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
1035
         wrap.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
997
         NSLayoutConstraint.activate([
1036
         NSLayoutConstraint.activate([
998
-            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor),
999
-            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
1037
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
1038
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
1039
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
1000
         ])
1040
         ])
1001
         return stack
1041
         return stack
1002
     }
1042
     }
@@ -1053,14 +1093,16 @@ private final class WorkExperienceEntryView: NSView {
1053
         let stack = NSStackView(views: [label, wrap])
1093
         let stack = NSStackView(views: [label, wrap])
1054
         stack.orientation = .vertical
1094
         stack.orientation = .vertical
1055
         stack.spacing = 8
1095
         stack.spacing = 8
1056
-        stack.alignment = .width
1096
+        stack.alignment = .leading
1057
         stack.translatesAutoresizingMaskIntoConstraints = false
1097
         stack.translatesAutoresizingMaskIntoConstraints = false
1058
         stack.userInterfaceLayoutDirection = .leftToRight
1098
         stack.userInterfaceLayoutDirection = .leftToRight
1059
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
1099
         ProfileLayoutEnforcement.applyForcedLTR(to: stack)
1060
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
1100
         stack.setContentHuggingPriority(.defaultLow, for: .horizontal)
1061
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
1101
         wrap.setContentHuggingPriority(.defaultLow, for: .horizontal)
1062
         NSLayoutConstraint.activate([
1102
         NSLayoutConstraint.activate([
1063
-            label.leftAnchor.constraint(equalTo: stack.leftAnchor)
1103
+            label.leftAnchor.constraint(equalTo: stack.leftAnchor),
1104
+            label.widthAnchor.constraint(equalTo: stack.widthAnchor),
1105
+            wrap.widthAnchor.constraint(equalTo: stack.widthAnchor)
1064
         ])
1106
         ])
1065
         return stack
1107
         return stack
1066
     }
1108
     }
@@ -1210,11 +1252,12 @@ private final class EducationEntryView: NSView {
1210
         let inner = NSStackView(views: [headerRow, degreeInstitutionRow, yearGroup])
1252
         let inner = NSStackView(views: [headerRow, degreeInstitutionRow, yearGroup])
1211
         inner.orientation = .vertical
1253
         inner.orientation = .vertical
1212
         inner.spacing = 14
1254
         inner.spacing = 14
1213
-        inner.alignment = .width
1255
+        inner.alignment = .leading
1214
         inner.translatesAutoresizingMaskIntoConstraints = false
1256
         inner.translatesAutoresizingMaskIntoConstraints = false
1215
         inner.edgeInsets = NSEdgeInsets(top: 14, left: 18, bottom: 14, right: 18)
1257
         inner.edgeInsets = NSEdgeInsets(top: 14, left: 18, bottom: 14, right: 18)
1216
         inner.userInterfaceLayoutDirection = .leftToRight
1258
         inner.userInterfaceLayoutDirection = .leftToRight
1217
         ProfileLayoutEnforcement.applyForcedLTR(to: inner)
1259
         ProfileLayoutEnforcement.applyForcedLTR(to: inner)
1260
+        inner.pinAllArrangedSubviewWidthsEqualToStackWidth()
1218
 
1261
 
1219
         addSubview(inner)
1262
         addSubview(inner)
1220
         NSLayoutConstraint.activate([
1263
         NSLayoutConstraint.activate([