-
Notifications
You must be signed in to change notification settings - Fork 184
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
tech: add SimpleGrid component (#6233)
* tech: add SimpleGrid component * feat: add align prop * chore: add default align * fix: remove React import + minor changes * feat(SimpleGrid): use common gaps + add e2e tests * CHORE: Update screenshots * fix: fix grid item in tests * fix: fix column count in tests * CHORE: Update screenshots * fix: revert gap logic * chore: add v7 Flex gap order note * chore: add v7 SimpleGrid gap order note * chore: run prettier --------- Co-authored-by: GitHub Action <[email protected]>
- Loading branch information
1 parent
7f0a169
commit 12fff65
Showing
15 changed files
with
443 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
Базовый компонент для позиционирования элементов, каждый из которых занимает равное количество пространства. | ||
Построен на базе `grid layout`. Можно указать либо `columns` (тогда пространство будет поделено на заданное количество колонок), либо `minColWidth` (тогда пространство будет распределено с учетом минимальной ширины колонки) | ||
|
||
```jsx { "props": { "layout": false, "iframe": false } } | ||
const halsey = { | ||
subtitle: 'ALBUM', | ||
header: 'Halsey – Badlands', | ||
caption: 'Blue Vinyl · EU · 2015', | ||
text: 'Badlands is the story about dreams and cruel reality...', | ||
}; | ||
|
||
const lorde = { | ||
subtitle: 'ALBUM', | ||
header: 'Lorde – Melodrama', | ||
caption: 'Blue Vinyl · EU · 2018', | ||
text: 'Lorde captures emotions like none other. Her second album is a masterful study of being a young woman, a sleek and humid pop record full of grief and hedonism, crafted with the utmost care and wisdom.', | ||
}; | ||
|
||
const GapSelectValues = [ | ||
{ | ||
label: '2xs', | ||
value: '2xs', | ||
}, | ||
{ | ||
label: 'xs', | ||
value: 'xs', | ||
}, | ||
{ | ||
label: 's', | ||
value: 's', | ||
}, | ||
{ | ||
label: 'm', | ||
value: 'm', | ||
}, | ||
{ | ||
label: 'l', | ||
value: 'l', | ||
}, | ||
{ | ||
label: 'xl', | ||
value: 'xl', | ||
}, | ||
{ | ||
label: '2xl', | ||
value: '2xl', | ||
}, | ||
{ | ||
label: '3xl', | ||
value: '3xl', | ||
}, | ||
{ | ||
label: '4xl', | ||
value: '4xl', | ||
}, | ||
]; | ||
|
||
const Example = () => { | ||
const [gap, setGap] = useState('m'); | ||
const [rowGap, setRowGap] = useState('m'); | ||
const [columnGap, setColumnGap] = useState('m'); | ||
const [columns, setColumns] = useState(3); | ||
const [itemsCount, setItemsCount] = useState(5); | ||
const [margin, setMargin] = useState('none'); | ||
const [complexGap, setComplexGap] = useState(false); | ||
const [align, setAlign] = useState('stretch'); | ||
const platform = usePlatform(); | ||
|
||
return ( | ||
<div style={{ display: 'flex', flexDirection: 'row-reverse', justifyContent: 'flex-end' }}> | ||
<div> | ||
<SimpleGrid | ||
align={align} | ||
columns={columns} | ||
gap={complexGap ? [columnGap, rowGap] : gap} | ||
margin={margin} | ||
> | ||
{Array.from({ length: itemsCount }, (item, index) => { | ||
return <ContentCard {...(index % 2 === 0 ? lorde : halsey)} />; | ||
})} | ||
</SimpleGrid> | ||
</div> | ||
<div style={{ minWidth: 200 }}> | ||
<FormItem top={`item count: ${itemsCount}`}> | ||
<Slider | ||
min={1} | ||
max={20} | ||
step={1} | ||
value={itemsCount} | ||
onChange={(value) => setItemsCount(value)} | ||
/> | ||
</FormItem> | ||
<FormItem top={`columns ${columns}`}> | ||
<Slider | ||
min={1} | ||
max={10} | ||
step={1} | ||
value={columns} | ||
onChange={(value) => setColumns(value)} | ||
/> | ||
</FormItem> | ||
<FormItem top="margin"> | ||
<RadioGroup> | ||
<Radio | ||
name="margin" | ||
value="none" | ||
checked={margin === 'none'} | ||
onChange={(e) => setMargin(e.target.value)} | ||
> | ||
none | ||
</Radio> | ||
<Radio | ||
name="margin" | ||
value="auto" | ||
checked={margin === 'auto'} | ||
onChange={(e) => setMargin(e.target.value)} | ||
> | ||
auto | ||
</Radio> | ||
<Radio | ||
name="margin" | ||
value="auto-inline" | ||
checked={margin === 'auto-inline'} | ||
onChange={(e) => setMargin(e.target.value)} | ||
> | ||
auto-inline | ||
</Radio> | ||
<Radio | ||
name="margin" | ||
value="auto-block" | ||
checked={margin === 'auto-block'} | ||
onChange={(e) => setMargin(e.target.value)} | ||
> | ||
auto-block | ||
</Radio> | ||
</RadioGroup> | ||
</FormItem> | ||
<FormItem top="align"> | ||
<Select | ||
value={align} | ||
onChange={(e) => setAlign(e.target.value || 'stretch')} | ||
placeholder="Не выбрано" | ||
options={[ | ||
{ label: 'start', value: 'start' }, | ||
{ label: 'end', value: 'end' }, | ||
{ label: 'center', value: 'center' }, | ||
{ label: 'stretch', value: 'stretch' }, | ||
{ label: 'baseline', value: 'baseline' }, | ||
]} | ||
allowClearButton | ||
/> | ||
</FormItem> | ||
<Checkbox value={complexGap} onChange={(e) => setComplexGap(e.target.checked)}> | ||
Complex Gap | ||
</Checkbox> | ||
{!complexGap && ( | ||
<FormItem top="gap"> | ||
<Select | ||
value={gap} | ||
onChange={(e) => setGap(e.target.value)} | ||
options={GapSelectValues} | ||
/> | ||
</FormItem> | ||
)} | ||
{complexGap && ( | ||
<FormItem top="row gap"> | ||
<Select | ||
value={rowGap} | ||
onChange={(e) => setRowGap(e.target.value)} | ||
options={GapSelectValues} | ||
/> | ||
</FormItem> | ||
)} | ||
{complexGap && ( | ||
<FormItem top="column gap"> | ||
<Select | ||
value={columnGap} | ||
onChange={(e) => setColumnGap(e.target.value)} | ||
options={GapSelectValues} | ||
/> | ||
</FormItem> | ||
)} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
<Example />; | ||
``` |
32 changes: 32 additions & 0 deletions
32
packages/vkui/src/components/SimpleGrid/SimpleGrid.e2e-playground.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { ComponentPlayground, type ComponentPlaygroundProps } from '@vkui-e2e/playground-helpers'; | ||
import { SimpleGrid, type SimpleGridProps } from './SimpleGrid'; | ||
|
||
const ChildNode = () => <div style={{ height: 50, backgroundColor: 'red' }}>Grid Item</div>; | ||
|
||
export const SimpleGridPlayground = (props: ComponentPlaygroundProps) => { | ||
return ( | ||
<ComponentPlayground | ||
{...props} | ||
propSets={[ | ||
{ | ||
children: [[<ChildNode key="1" />, <ChildNode key="2" />]], | ||
columns: [1, 2], | ||
gap: ['m'], | ||
margin: ['auto'], | ||
}, | ||
{ | ||
margin: ['auto-inline', 'auto-block'], | ||
children: [[<ChildNode key="1" />, <ChildNode key="2" />]], | ||
gap: ['xl'], | ||
}, | ||
{ | ||
children: [[<ChildNode key="1" />, <ChildNode key="2" />, <ChildNode key="3" />]], | ||
gap: [[8, 16]], | ||
columns: [2], | ||
}, | ||
]} | ||
> | ||
{(props: SimpleGridProps) => <SimpleGrid {...props} />} | ||
</ComponentPlayground> | ||
); | ||
}; |
16 changes: 16 additions & 0 deletions
16
packages/vkui/src/components/SimpleGrid/SimpleGrid.e2e.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { test } from '@vkui-e2e/test'; | ||
import { SimpleGridPlayground } from './SimpleGrid.e2e-playground'; | ||
|
||
test.describe('SimpleGrid', () => { | ||
test.use({ | ||
onlyForAppearances: ['light'], | ||
}); | ||
test('Rendering', async ({ | ||
mount, | ||
expectScreenshotClippedToContent, | ||
componentPlaygroundProps, | ||
}) => { | ||
await mount(<SimpleGridPlayground {...componentPlaygroundProps} />); | ||
await expectScreenshotClippedToContent(); | ||
}); | ||
}); |
45 changes: 45 additions & 0 deletions
45
packages/vkui/src/components/SimpleGrid/SimpleGrid.module.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
.SimpleGrid { | ||
--vkui_internal--grid_columns: 1; | ||
--vkui_internal--min_col_width: 0; | ||
|
||
display: grid; | ||
gap: var(--vkui_internal--row_gap) var(--vkui_internal--column_gap); | ||
grid-template-columns: repeat(var(--vkui_internal--grid_columns), minmax(0, 1fr)); | ||
} | ||
|
||
.SimpleGrid--margin-auto { | ||
margin-inline: var(--vkui--size_base_padding_horizontal--regular); | ||
margin-block: var(--vkui--size_base_padding_vertical--regular); | ||
} | ||
|
||
.SimpleGrid--margin-auto-inline { | ||
margin-inline: var(--vkui--size_base_padding_horizontal--regular); | ||
} | ||
|
||
.SimpleGrid--margin-auto-block { | ||
margin-block: var(--vkui--size_base_padding_vertical--regular); | ||
} | ||
|
||
.SimpleGrid--with-min-width { | ||
grid-template-columns: repeat(auto-fit, minmax(var(--vkui_internal--min_col_width), 1fr)); | ||
} | ||
|
||
.SimpleGrid--align-start { | ||
align-items: flex-start; | ||
} | ||
|
||
.SimpleGrid--align-end { | ||
align-items: flex-end; | ||
} | ||
|
||
.SimpleGrid--align-center { | ||
align-items: center; | ||
} | ||
|
||
.SimpleGrid--align-stretch { | ||
align-items: stretch; | ||
} | ||
|
||
.SimpleGrid--align-baseline { | ||
align-items: baseline; | ||
} |
42 changes: 42 additions & 0 deletions
42
packages/vkui/src/components/SimpleGrid/SimpleGrid.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import { Meta, StoryObj } from '@storybook/react'; | ||
import { CanvasFullLayout, DisableCartesianParam } from '../../storybook/constants'; | ||
import { ContentCard } from '../ContentCard/ContentCard'; | ||
import { SimpleGrid, SimpleGridProps } from './SimpleGrid'; | ||
|
||
const story: Meta<SimpleGridProps> = { | ||
title: 'Layout/SimpleGrid', | ||
component: SimpleGrid, | ||
parameters: { ...CanvasFullLayout, ...DisableCartesianParam }, | ||
}; | ||
|
||
export default story; | ||
|
||
type Story = StoryObj<SimpleGridProps>; | ||
|
||
export const Playground: Story = { | ||
args: { | ||
gap: 'm', | ||
}, | ||
render: (args) => ( | ||
<SimpleGrid {...args}> | ||
{Array.from({ length: 5 }, (_, index) => { | ||
return ( | ||
<ContentCard | ||
key={index} | ||
subtitle="ALBUM" | ||
header="Halsey – Badlands" | ||
caption="Blue Vinyl · EU · 2015" | ||
text="Badlands is the story about dreams and cruel reality..." | ||
/> | ||
); | ||
})} | ||
</SimpleGrid> | ||
), | ||
decorators: [ | ||
(Component) => ( | ||
<div style={{ width: '80%', border: '1px dotted red' }}> | ||
<Component /> | ||
</div> | ||
), | ||
], | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
import { baselineComponent } from '../../testing/utils'; | ||
import { SimpleGrid } from './SimpleGrid'; | ||
|
||
describe('SimpleGrid', () => { | ||
baselineComponent(SimpleGrid); | ||
}); |
Oops, something went wrong.