fix(checkbox): align checkbox properly in item using start alignment (#29850)
Issue number: resolves #29837 --------- ## What is the current behavior? The checkbox is not aligned properly to the top when using a long label with `alignment="start"` inside of an `ion-item`: ```html <ion-item> <ion-checkbox justify="start" alignment="start"> <ion-label class="ion-text-wrap"> Enable Notifications Enable Notifications Enable Notifications </ion-label> </ion-checkbox> </ion-item> ``` ## What is the new behavior? - Applies the same margin to the `.native-wrapper` (checkbox) as the label. - Adds a screenshot test to verify the alignment ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information | Before | After | | --- | --- | |  |  | |  |  | - [Label Preview](https://ionic-framework-git-rou-11163-ionic1.vercel.app/src/components/checkbox/test/label) - [Item Preview](https://ionic-framework-git-rou-11163-ionic1.vercel.app/src/components/checkbox/test/item) > [!NOTE] > The alignment on the Material Design checkbox is still slightly off. I could add margin directly to its checkbox but then it would change the margin of the checkbox in all use cases.
@ -87,7 +87,10 @@
 | 
				
			|||||||
  overflow: hidden;
 | 
					  overflow: hidden;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:host(.in-item) .label-text-wrapper {
 | 
					// Checkboxes that are not slotted inside an item and are not used with a
 | 
				
			||||||
 | 
					// stacked label should have margins equal to those of the label.
 | 
				
			||||||
 | 
					:host(.in-item) .label-text-wrapper,
 | 
				
			||||||
 | 
					:host(.in-item:not(.checkbox-label-placement-stacked):not([slot])) .native-wrapper {
 | 
				
			||||||
  @include margin($checkbox-item-label-margin-top, null, $checkbox-item-label-margin-bottom, null);
 | 
					  @include margin($checkbox-item-label-margin-top, null, $checkbox-item-label-margin-bottom, null);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -51,7 +51,7 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
 | 
				
			|||||||
  });
 | 
					  });
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, config }) => {
 | 
					configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
 | 
				
			||||||
  test.describe(title('checkbox: long label in item'), () => {
 | 
					  test.describe(title('checkbox: long label in item'), () => {
 | 
				
			||||||
    test('should render margins correctly when using long label in item', async ({ page }) => {
 | 
					    test('should render margins correctly when using long label in item', async ({ page }) => {
 | 
				
			||||||
      await page.setContent(
 | 
					      await page.setContent(
 | 
				
			||||||
@ -69,6 +69,28 @@ configs({ directions: ['ltr'], modes: ['md'] }).forEach(({ title, screenshot, co
 | 
				
			|||||||
      const list = page.locator('ion-list');
 | 
					      const list = page.locator('ion-list');
 | 
				
			||||||
      await expect(list).toHaveScreenshot(screenshot(`checkbox-long-label-in-item`));
 | 
					      await expect(list).toHaveScreenshot(screenshot(`checkbox-long-label-in-item`));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    test('should render margins correctly when using long label in item with start alignment', async ({
 | 
				
			||||||
 | 
					      page,
 | 
				
			||||||
 | 
					    }, testInfo) => {
 | 
				
			||||||
 | 
					      testInfo.annotations.push({
 | 
				
			||||||
 | 
					        type: 'issue',
 | 
				
			||||||
 | 
					        description: 'https://github.com/ionic-team/ionic-framework/issues/29837',
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					      await page.setContent(
 | 
				
			||||||
 | 
					        `
 | 
				
			||||||
 | 
					          <ion-list>
 | 
				
			||||||
 | 
					            <ion-item>
 | 
				
			||||||
 | 
					              <ion-checkbox justify="start" alignment="start">
 | 
				
			||||||
 | 
					                <ion-label class="ion-text-wrap">Enable Notifications Enable Notifications Enable Notifications</ion-label>
 | 
				
			||||||
 | 
					              </ion-checkbox>
 | 
				
			||||||
 | 
					            </ion-item>
 | 
				
			||||||
 | 
					          </ion-list>
 | 
				
			||||||
 | 
					        `,
 | 
				
			||||||
 | 
					        config
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      const list = page.locator('ion-list');
 | 
				
			||||||
 | 
					      await expect(list).toHaveScreenshot(screenshot(`checkbox-long-label-in-item-align-start`));
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  test.describe(title('checkbox: stacked label in item'), () => {
 | 
					  test.describe(title('checkbox: stacked label in item'), () => {
 | 
				
			||||||
 | 
				
			|||||||
| 
		 After Width: | Height: | Size: 3.3 KiB  | 
| 
		 After Width: | Height: | Size: 5.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.3 KiB  | 
| 
		 After Width: | Height: | Size: 2.9 KiB  | 
| 
		 After Width: | Height: | Size: 6.5 KiB  | 
| 
		 After Width: | Height: | Size: 2.6 KiB  | 
| 
		 After Width: | Height: | Size: 3.4 KiB  | 
| 
		 After Width: | Height: | Size: 5.7 KiB  | 
| 
		 After Width: | Height: | Size: 3.4 KiB  | 
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
| 
		 After Width: | Height: | Size: 3.5 KiB  | 
| 
		 After Width: | Height: | Size: 2.4 KiB  | 
@ -181,6 +181,15 @@
 | 
				
			|||||||
              </ion-checkbox>
 | 
					              </ion-checkbox>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="grid-item">
 | 
				
			||||||
 | 
					            <ion-item>
 | 
				
			||||||
 | 
					              <ion-checkbox justify="start" alignment="start">
 | 
				
			||||||
 | 
					                <ion-label class="ion-text-wrap">
 | 
				
			||||||
 | 
					                  Enable Notifications Enable Notifications Enable Notifications
 | 
				
			||||||
 | 
					                </ion-label>
 | 
				
			||||||
 | 
					              </ion-checkbox>
 | 
				
			||||||
 | 
					            </ion-item>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
      </ion-content>
 | 
					      </ion-content>
 | 
				
			||||||
    </ion-app>
 | 
					    </ion-app>
 | 
				
			||||||
 | 
				
			|||||||
@ -113,6 +113,24 @@
 | 
				
			|||||||
            <ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
 | 
					            <ion-checkbox label-placement="stacked" alignment="center">Enable Notifications</ion-checkbox>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        <h1>Multiline Label</h1>
 | 
				
			||||||
 | 
					        <div class="grid">
 | 
				
			||||||
 | 
					          <div class="grid-item">
 | 
				
			||||||
 | 
					            <ion-checkbox justify="start">
 | 
				
			||||||
 | 
					              <ion-label class="ion-text-wrap">
 | 
				
			||||||
 | 
					                Enable Notifications Enable Notifications Enable Notifications
 | 
				
			||||||
 | 
					              </ion-label>
 | 
				
			||||||
 | 
					            </ion-checkbox>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          <div class="grid-item">
 | 
				
			||||||
 | 
					            <ion-checkbox justify="start" alignment="start">
 | 
				
			||||||
 | 
					              <ion-label class="ion-text-wrap">
 | 
				
			||||||
 | 
					                Enable Notifications Enable Notifications Enable Notifications
 | 
				
			||||||
 | 
					              </ion-label>
 | 
				
			||||||
 | 
					            </ion-checkbox>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
      </ion-content>
 | 
					      </ion-content>
 | 
				
			||||||
    </ion-app>
 | 
					    </ion-app>
 | 
				
			||||||
  </body>
 | 
					  </body>
 | 
				
			||||||
 | 
				
			|||||||