diff --git a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlock.tsx b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlock.tsx
index 18a07f44235..a73ea082b60 100644
--- a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlock.tsx
+++ b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlock.tsx
@@ -33,6 +33,7 @@ const I18n = useI18nScope('block-editor')
export const GroupBlock = (props: GroupBlockProps) => {
const {
alignment = GroupBlock.craft.defaultProps.alignment,
+ verticalAlignment = GroupBlock.craft.defaultProps.verticalAlignment,
layout = GroupBlock.craft.defaultProps.layout,
resizable = GroupBlock.craft.defaultProps.resizable,
} = props
@@ -44,6 +45,7 @@ export const GroupBlock = (props: GroupBlockProps) => {
'group-block',
`${layout}-layout`,
`${alignment}-align`,
+ `${verticalAlignment}-valign`,
])
const {node} = useNode((n: Node) => {
return {
@@ -76,6 +78,7 @@ GroupBlock.craft = {
displayName: I18n.t('Group'),
defaultProps: {
alignment: 'start',
+ verticalAlignment: 'start',
layout: 'column',
resizable: true,
},
diff --git a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlockToolbar.tsx b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlockToolbar.tsx
index a282270ed1b..531d68e33f8 100644
--- a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlockToolbar.tsx
+++ b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/GroupBlockToolbar.tsx
@@ -60,15 +60,33 @@ export const GroupBlockToolbar = () => {
[setProp]
)
- const renderAlignmentIcon = () => {
- switch (props.alignment) {
+ const handleChangeVerticalAlignment = useCallback(
+ (e, value) => {
+ setProp((prps: GroupBlockProps) => {
+ prps.verticalAlignment = value as GroupAlignment
+ })
+ },
+ [setProp]
+ )
+
+ const rotate = {
+ rotate: '90deg',
+ }
+
+ const renderAlignmentIcon = (vertical: boolean) => {
+ let icon
+ const align = vertical ? props.verticalAlignment : props.alignment
+ switch (align) {
case 'start':
- return
+ icon =
+ break
case 'center':
- return
+ icon =
+ break
case 'end':
- return
+ icon =
}
+ return vertical ? {icon} : icon
}
return (
@@ -93,15 +111,16 @@ export const GroupBlockToolbar = () => {
{I18n.t('Row')}
+
+
+
)
}
diff --git a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlock.test.tsx b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlock.test.tsx
index 9bc75d24028..a5e26b1e280 100644
--- a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlock.test.tsx
+++ b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlock.test.tsx
@@ -63,4 +63,16 @@ describe('ColumnsSection', () => {
expect(container.querySelector('.group-block')).toBeInTheDocument()
expect(container.querySelector('.group-block')).toHaveClass('row-layout')
})
+
+ it('should render with center horizontal alignment', () => {
+ const {container} = renderBlock({alignment: 'center'})
+ expect(container.querySelector('.group-block')).toBeInTheDocument()
+ expect(container.querySelector('.group-block')).toHaveClass('center-align')
+ })
+
+ it('should render with center vertical alignment', () => {
+ const {container} = renderBlock({verticalAlignment: 'center'})
+ expect(container.querySelector('.group-block')).toBeInTheDocument()
+ expect(container.querySelector('.group-block')).toHaveClass('center-valign')
+ })
})
diff --git a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlockToolbar.test.tsx b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlockToolbar.test.tsx
index 75998ca8861..b78e592f131 100644
--- a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlockToolbar.test.tsx
+++ b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/__tests__/GroupBlockToolbar.test.tsx
@@ -49,34 +49,104 @@ describe('GroupBlockToolbar', () => {
const {getByText} = render()
expect(getByText('Layout direction')).toBeInTheDocument()
+ expect(getByText('Align Horizontally')).toBeInTheDocument()
+ expect(getByText('Align Vertically')).toBeInTheDocument()
})
- it('checks the right layout direction', async () => {
- const {getByText} = render()
+ describe('layout direction', () => {
+ it('checks the right layout direction', async () => {
+ const {getByText} = render()
- const btn = getByText('Layout direction').closest('button') as HTMLButtonElement
- await userEvent.click(btn)
+ const btn = getByText('Layout direction').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
- const colMenuItem = screen.getByText('Column')
- const rowMenuItem = screen.getByText('Row')
+ const colMenuItem = screen.getByText('Column')
+ const rowMenuItem = screen.getByText('Row')
- expect(colMenuItem).toBeInTheDocument()
- expect(rowMenuItem).toBeInTheDocument()
+ expect(colMenuItem).toBeInTheDocument()
+ expect(rowMenuItem).toBeInTheDocument()
- const li = colMenuItem.closest('li') as HTMLLIElement
- expect(li.querySelector('svg[name="IconCheck"]')).toBeInTheDocument()
+ const li = colMenuItem.closest('li') as HTMLLIElement
+ expect(li.querySelector('svg[name="IconCheck"]')).toBeInTheDocument()
+ })
+
+ it('changes the direction prop', async () => {
+ const {getByText} = render()
+
+ const btn = getByText('Layout direction').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
+
+ const rowMenuItem = screen.getByText('Row')
+ await userEvent.click(rowMenuItem)
+
+ expect(mockSetProp).toHaveBeenCalled()
+ expect(props.layout).toBe('row')
+ })
})
- it('changes the direction prop', async () => {
- const {getByText} = render()
+ describe('horizontal alignment', () => {
+ it('checks the right alignment', async () => {
+ const {getByText} = render()
- const btn = getByText('Layout direction').closest('button') as HTMLButtonElement
- await userEvent.click(btn)
+ const btn = getByText('Align Horizontally').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
- const rowMenuItem = screen.getByText('Row')
- await userEvent.click(rowMenuItem)
+ const startMenuItem = screen.getByText('Align to start')
+ const centerMenuItem = screen.getByText('Align to center')
+ const endMenuItem = screen.getByText('Align to end')
- expect(mockSetProp).toHaveBeenCalled()
- expect(props.layout).toBe('row')
+ expect(startMenuItem).toBeInTheDocument()
+ expect(centerMenuItem).toBeInTheDocument()
+ expect(endMenuItem).toBeInTheDocument()
+
+ const startLi = startMenuItem.closest('li') as HTMLLIElement
+ expect(startLi.querySelector('svg[name="IconCheck"]')).toBeInTheDocument()
+ })
+
+ it('changes the alignment prop', async () => {
+ const {getByText} = render()
+
+ const btn = getByText('Align Horizontally').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
+
+ const centerMenuItem = screen.getByText('Align to center')
+ await userEvent.click(centerMenuItem)
+
+ expect(mockSetProp).toHaveBeenCalled()
+ expect(props.alignment).toBe('center')
+ })
+ })
+
+ describe('vertical alignment', () => {
+ it('checks the right alignment', async () => {
+ const {getByText} = render()
+
+ const btn = getByText('Align Vertically').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
+
+ const startMenuItem = screen.getByText('Align to start')
+ const centerMenuItem = screen.getByText('Align to center')
+ const endMenuItem = screen.getByText('Align to end')
+
+ expect(startMenuItem).toBeInTheDocument()
+ expect(centerMenuItem).toBeInTheDocument()
+ expect(endMenuItem).toBeInTheDocument()
+
+ const startLi = startMenuItem.closest('li') as HTMLLIElement
+ expect(startLi.querySelector('svg[name="IconCheck"]')).toBeInTheDocument()
+ })
+
+ it('changes the vertical alignment prop', async () => {
+ const {getByText} = render()
+
+ const btn = getByText('Align Vertically').closest('button') as HTMLButtonElement
+ await userEvent.click(btn)
+
+ const centerMenuItem = screen.getByText('Align to center')
+ await userEvent.click(centerMenuItem)
+
+ expect(mockSetProp).toHaveBeenCalled()
+ expect(props.verticalAlignment).toBe('center')
+ })
})
})
diff --git a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/types.ts b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/types.ts
index 3382c6c3ff7..210f0fb105b 100644
--- a/ui/shared/block-editor/react/components/user/blocks/GroupBlock/types.ts
+++ b/ui/shared/block-editor/react/components/user/blocks/GroupBlock/types.ts
@@ -22,5 +22,6 @@ export type GroupAlignment = 'start' | 'center' | 'end'
export type GroupBlockProps = {
layout?: GroupLayout
alignment?: GroupAlignment
+ verticalAlignment?: GroupAlignment
resizable?: boolean
}
diff --git a/ui/shared/block-editor/react/style.css b/ui/shared/block-editor/react/style.css
index 1abdb99de78..d45df1f027d 100644
--- a/ui/shared/block-editor/react/style.css
+++ b/ui/shared/block-editor/react/style.css
@@ -312,22 +312,31 @@
flex-direction: column;
}
&.row-layout {
- &> .no-sections {
+ &> .group-block__inner {
flex-direction: row;
flex-wrap: wrap;
}
- &.center-align > .no-sections {
+ &.center-align > .group-block__inner {
justify-content: center;
}
- &.end-align > .no-sections {
+ &.end-align > .group-block__inner {
justify-content: flex-end;
}
+ &.start-valign > .group-block__inner {
+ align-items: flex-start;
+ }
+ &.center-valign > .group-block__inner {
+ align-items: center;
+ }
+ &.end-valign > .group-block__inner {
+ align-items: flex-end;
+ }
}
&.column-layout {
- &.center-align > .no-sections {
+ &.center-align > .group-block__inner {
align-items: center;
}
- &.end-align > .no-sections {
+ &.end-align > .group-block__inner {
align-items: flex-end;
}
}