Skip to content

Commit 5726788

Browse files
authored
fix(flex): ensure utility styles override component styles (DS-5175) (#438)
1 parent 2cd7c3f commit 5726788

8 files changed

Lines changed: 400 additions & 98 deletions

File tree

Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
.base {
2+
--flex-type: flex;
3+
--flex-wrap: nowrap;
4+
--flex-direction: row;
5+
--flex-align-items: flex-start;
6+
--flex-justify-content: flex-start;
7+
8+
gap: var(--flex-row-gap) var(--flex-column-gap);
9+
display: var(--flex-type);
10+
align-items: var(--flex-align-items);
11+
justify-content: var(--flex-justify-content);
12+
flex-flow: var(--flex-direction) var(--flex-wrap);
13+
}
14+
15+
.alignItems_flex-start {
16+
--flex-align-items: flex-start;
17+
}
18+
19+
.alignItems_flex-end {
20+
--flex-align-items: flex-end;
21+
}
22+
23+
.alignItems_center {
24+
--flex-align-items: center;
25+
}
26+
27+
.alignItems_baseline {
28+
--flex-align-items: baseline;
29+
}
30+
31+
.alignItems_stretch {
32+
--flex-align-items: stretch;
33+
}
34+
35+
.justifyContent_flex-start {
36+
--flex-justify-content: flex-start;
37+
}
38+
39+
.justifyContent_flex-end {
40+
--flex-justify-content: flex-end;
41+
}
42+
43+
.justifyContent_center {
44+
--flex-justify-content: center;
45+
}
46+
47+
.justifyContent_space-between {
48+
--flex-justify-content: space-between;
49+
}
50+
51+
.justifyContent_space-around {
52+
--flex-justify-content: space-around;
53+
}
54+
55+
.justifyContent_space-evenly {
56+
--flex-justify-content: space-evenly;
57+
}
58+
59+
.flex_flex {
60+
--flex-type: flex;
61+
}
62+
63+
.flex_inline-flex {
64+
--flex-type: inline-flex;
65+
}
66+
67+
.wrap_wrap {
68+
--flex-wrap: wrap;
69+
}
70+
71+
.wrap_nowrap {
72+
--flex-wrap: nowrap;
73+
}
74+
75+
.wrap_wrap-reverse {
76+
--flex-wrap: wrap-reverse;
77+
}
78+
79+
.direction_row {
80+
--flex-direction: row;
81+
}
82+
83+
.direction_row-reverse {
84+
--flex-direction: row-reverse;
85+
}
86+
87+
.direction_column {
88+
--flex-direction: column;
89+
}
90+
91+
.direction_column-reverse {
92+
--flex-direction: column-reverse;
93+
}
94+
95+
/* column-gap */
96+
.gap_column_3xs {
97+
--flex-column-gap: var(--kbq-size-3xs);
98+
}
99+
100+
.gap_column_xxs {
101+
--flex-column-gap: var(--kbq-size-xxs);
102+
}
103+
104+
.gap_column_xs {
105+
--flex-column-gap: var(--kbq-size-xs);
106+
}
107+
108+
.gap_column_s {
109+
--flex-column-gap: var(--kbq-size-s);
110+
}
111+
112+
.gap_column_m {
113+
--flex-column-gap: var(--kbq-size-m);
114+
}
115+
116+
.gap_column_l {
117+
--flex-column-gap: var(--kbq-size-l);
118+
}
119+
120+
.gap_column_xl {
121+
--flex-column-gap: var(--kbq-size-xl);
122+
}
123+
124+
.gap_column_xxl {
125+
--flex-column-gap: var(--kbq-size-xxl);
126+
}
127+
128+
.gap_column_3xl {
129+
--flex-column-gap: var(--kbq-size-3xl);
130+
}
131+
132+
.gap_column_4xl {
133+
--flex-column-gap: var(--kbq-size-4xl);
134+
}
135+
136+
.gap_column_5xl {
137+
--flex-column-gap: var(--kbq-size-5xl);
138+
}
139+
140+
.gap_column_6xl {
141+
--flex-column-gap: var(--kbq-size-6xl);
142+
}
143+
144+
.gap_column_7xl {
145+
--flex-column-gap: var(--kbq-size-7xl);
146+
}
147+
148+
/* row-gap */
149+
.gap_row_3xs {
150+
--flex-row-gap: var(--kbq-size-3xs);
151+
}
152+
153+
.gap_row_xxs {
154+
--flex-row-gap: var(--kbq-size-xxs);
155+
}
156+
157+
.gap_row_xs {
158+
--flex-row-gap: var(--kbq-size-xs);
159+
}
160+
161+
.gap_row_s {
162+
--flex-row-gap: var(--kbq-size-s);
163+
}
164+
165+
.gap_row_m {
166+
--flex-row-gap: var(--kbq-size-m);
167+
}
168+
169+
.gap_row_l {
170+
--flex-row-gap: var(--kbq-size-l);
171+
}
172+
173+
.gap_row_xl {
174+
--flex-row-gap: var(--kbq-size-xl);
175+
}
176+
177+
.gap_row_xxl {
178+
--flex-row-gap: var(--kbq-size-xxl);
179+
}
180+
181+
.gap_row_3xl {
182+
--flex-row-gap: var(--kbq-size-3xl);
183+
}
184+
185+
.gap_row_4xl {
186+
--flex-row-gap: var(--kbq-size-4xl);
187+
}
188+
189+
.gap_row_5xl {
190+
--flex-row-gap: var(--kbq-size-5xl);
191+
}
192+
193+
.gap_row_6xl {
194+
--flex-row-gap: var(--kbq-size-6xl);
195+
}
196+
197+
.gap_row_7xl {
198+
--flex-row-gap: var(--kbq-size-7xl);
199+
}

packages/components/src/components/FlexBox/FlexBox.test.tsx

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import { createRef } from 'react';
22

3-
import { render } from '@testing-library/react';
3+
import { render, screen } from '@testing-library/react';
44
import { describe, it, expect } from 'vitest';
55

6+
import { BreakpointsContext, type BreakpointsContextType } from '../Provider';
7+
8+
import s from './FlexBox.module.css';
69
import { FlexBox } from './index';
710
import type { FlexBoxProps } from './index';
811

@@ -27,4 +30,54 @@ describe('FlexBox', () => {
2730
const flexBox = container.querySelector('div');
2831
expect(ref.current).toBe(flexBox);
2932
});
33+
34+
it('should apply flex classes from props', () => {
35+
render(
36+
<FlexBox
37+
data-testid="flex-box"
38+
flex="inline-flex"
39+
wrap="wrap-reverse"
40+
gap="m"
41+
rowGap="l"
42+
colGap="xl"
43+
direction="column-reverse"
44+
alignItems="center"
45+
justifyContent="space-between"
46+
/>
47+
);
48+
49+
expect(screen.getByTestId('flex-box')).toHaveClass(
50+
s.base,
51+
s['flex_inline-flex'],
52+
s['wrap_wrap-reverse'],
53+
s.gap_row_l,
54+
s.gap_column_xl,
55+
s['direction_column-reverse'],
56+
s.alignItems_center,
57+
s['justifyContent_space-between']
58+
);
59+
});
60+
61+
it('should apply flex classes from responsive props', () => {
62+
const breakpoints = {
63+
xs: true,
64+
l: true,
65+
} as BreakpointsContextType;
66+
67+
render(
68+
<BreakpointsContext.Provider value={breakpoints}>
69+
<FlexBox
70+
data-testid="flex-box"
71+
gap={{ xs: 's', l: 'm' }}
72+
direction={{ xs: 'column', l: 'row' }}
73+
/>
74+
</BreakpointsContext.Provider>
75+
);
76+
77+
expect(screen.getByTestId('flex-box')).toHaveClass(
78+
s.gap_row_m,
79+
s.gap_column_m,
80+
s.direction_row
81+
);
82+
});
3083
});

packages/components/src/components/FlexBox/FlexBox.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ import type { ComponentPropsWithRef, ElementType } from 'react';
55
import { clsx, polymorphicForwardRef } from '@koobiq/react-core';
66

77
import { getResponsiveValue } from '../../utils';
8-
import { flex as flexBox } from '../layout';
98
import { useMatchedBreakpoints } from '../Provider';
109

10+
import s from './FlexBox.module.css';
1111
import type { FlexBoxBaseProps } from './index';
1212

1313
/**
@@ -38,26 +38,29 @@ export const FlexBox = polymorphicForwardRef<'div', FlexBoxBaseProps>(
3838

3939
const flex = getResponsiveValue(flexProp, breakpoints);
4040
const gap = getResponsiveValue(gapProp, breakpoints);
41-
const colGap = getResponsiveValue(colGapProp, breakpoints);
42-
const rowGap = getResponsiveValue(rowGapProp, breakpoints);
41+
const colGap = getResponsiveValue(colGapProp, breakpoints) ?? gap;
42+
const rowGap = getResponsiveValue(rowGapProp, breakpoints) ?? gap;
4343
const wrap = getResponsiveValue(wrapProp, breakpoints);
4444
const alignItems = getResponsiveValue(alignItemsProp, breakpoints);
4545
const direction = getResponsiveValue(directionProp, breakpoints);
4646
const justifyContent = getResponsiveValue(justifyContentProp, breakpoints);
4747

48-
const flexCn = flexBox({
49-
gap,
50-
flex,
51-
wrap,
52-
colGap,
53-
rowGap,
54-
direction,
55-
alignItems,
56-
justifyContent,
57-
});
58-
5948
return (
60-
<Tag className={clsx(flexCn, className)} {...other} ref={ref}>
49+
<Tag
50+
className={clsx(
51+
s.base,
52+
flex && s[`flex_${flex}`],
53+
wrap && s[`wrap_${wrap}`],
54+
rowGap && s[`gap_row_${rowGap}`],
55+
colGap && s[`gap_column_${colGap}`],
56+
direction && s[`direction_${direction}`],
57+
alignItems && s[`alignItems_${alignItems}`],
58+
justifyContent && s[`justifyContent_${justifyContent}`],
59+
className
60+
)}
61+
{...other}
62+
ref={ref}
63+
>
6164
{children}
6265
</Tag>
6366
);

packages/components/src/components/layout/flex/flex.stories.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ import {
1010
flexPropGap,
1111
flexPropJustifyContent,
1212
flexPropOrder,
13-
type FlexProps,
1413
flexPropWrap,
15-
} from './flex';
14+
} from './index';
15+
import type { FlexProps } from './index';
1616

1717
const meta = {
1818
title: 'Mixins/flex',
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { flex } from './flex';
4+
import s from './flex.module.css';
5+
6+
describe('flex', () => {
7+
it('should generate classes for every flex property', () => {
8+
expect(
9+
flex(
10+
{
11+
flex: 'inline-flex',
12+
wrap: 'wrap-reverse',
13+
order: -1,
14+
gap: 'm',
15+
rowGap: 'l',
16+
colGap: 'xl',
17+
direction: 'column-reverse',
18+
alignItems: 'center',
19+
justifyContent: 'space-between',
20+
},
21+
'custom-class'
22+
)
23+
).toBe(
24+
[
25+
s.base,
26+
s['flex_inline-flex'],
27+
s['wrap_wrap-reverse'],
28+
s['order_-1'],
29+
s.gap_row_l,
30+
s.gap_column_xl,
31+
s['direction_column-reverse'],
32+
s.alignItems_center,
33+
s['justifyContent_space-between'],
34+
'custom-class',
35+
].join(' ')
36+
);
37+
});
38+
39+
it('should use gap as the row and column gap fallback', () => {
40+
expect(flex({ gap: 'm' })).toBe(
41+
[s.base, s.gap_row_m, s.gap_column_m].join(' ')
42+
);
43+
});
44+
45+
it('should generate class for zero order', () => {
46+
expect(flex({ order: 0 })).toBe([s.base, s.order_0].join(' '));
47+
});
48+
});

0 commit comments

Comments
 (0)