diff --git a/packages/components/src/components/FlexBox/FlexBox.module.css b/packages/components/src/components/FlexBox/FlexBox.module.css
new file mode 100644
index 000000000..b99f00063
--- /dev/null
+++ b/packages/components/src/components/FlexBox/FlexBox.module.css
@@ -0,0 +1,199 @@
+.base {
+ --flex-type: flex;
+ --flex-wrap: nowrap;
+ --flex-direction: row;
+ --flex-align-items: flex-start;
+ --flex-justify-content: flex-start;
+
+ gap: var(--flex-row-gap) var(--flex-column-gap);
+ display: var(--flex-type);
+ align-items: var(--flex-align-items);
+ justify-content: var(--flex-justify-content);
+ flex-flow: var(--flex-direction) var(--flex-wrap);
+}
+
+.alignItems_flex-start {
+ --flex-align-items: flex-start;
+}
+
+.alignItems_flex-end {
+ --flex-align-items: flex-end;
+}
+
+.alignItems_center {
+ --flex-align-items: center;
+}
+
+.alignItems_baseline {
+ --flex-align-items: baseline;
+}
+
+.alignItems_stretch {
+ --flex-align-items: stretch;
+}
+
+.justifyContent_flex-start {
+ --flex-justify-content: flex-start;
+}
+
+.justifyContent_flex-end {
+ --flex-justify-content: flex-end;
+}
+
+.justifyContent_center {
+ --flex-justify-content: center;
+}
+
+.justifyContent_space-between {
+ --flex-justify-content: space-between;
+}
+
+.justifyContent_space-around {
+ --flex-justify-content: space-around;
+}
+
+.justifyContent_space-evenly {
+ --flex-justify-content: space-evenly;
+}
+
+.flex_flex {
+ --flex-type: flex;
+}
+
+.flex_inline-flex {
+ --flex-type: inline-flex;
+}
+
+.wrap_wrap {
+ --flex-wrap: wrap;
+}
+
+.wrap_nowrap {
+ --flex-wrap: nowrap;
+}
+
+.wrap_wrap-reverse {
+ --flex-wrap: wrap-reverse;
+}
+
+.direction_row {
+ --flex-direction: row;
+}
+
+.direction_row-reverse {
+ --flex-direction: row-reverse;
+}
+
+.direction_column {
+ --flex-direction: column;
+}
+
+.direction_column-reverse {
+ --flex-direction: column-reverse;
+}
+
+/* column-gap */
+.gap_column_3xs {
+ --flex-column-gap: var(--kbq-size-3xs);
+}
+
+.gap_column_xxs {
+ --flex-column-gap: var(--kbq-size-xxs);
+}
+
+.gap_column_xs {
+ --flex-column-gap: var(--kbq-size-xs);
+}
+
+.gap_column_s {
+ --flex-column-gap: var(--kbq-size-s);
+}
+
+.gap_column_m {
+ --flex-column-gap: var(--kbq-size-m);
+}
+
+.gap_column_l {
+ --flex-column-gap: var(--kbq-size-l);
+}
+
+.gap_column_xl {
+ --flex-column-gap: var(--kbq-size-xl);
+}
+
+.gap_column_xxl {
+ --flex-column-gap: var(--kbq-size-xxl);
+}
+
+.gap_column_3xl {
+ --flex-column-gap: var(--kbq-size-3xl);
+}
+
+.gap_column_4xl {
+ --flex-column-gap: var(--kbq-size-4xl);
+}
+
+.gap_column_5xl {
+ --flex-column-gap: var(--kbq-size-5xl);
+}
+
+.gap_column_6xl {
+ --flex-column-gap: var(--kbq-size-6xl);
+}
+
+.gap_column_7xl {
+ --flex-column-gap: var(--kbq-size-7xl);
+}
+
+/* row-gap */
+.gap_row_3xs {
+ --flex-row-gap: var(--kbq-size-3xs);
+}
+
+.gap_row_xxs {
+ --flex-row-gap: var(--kbq-size-xxs);
+}
+
+.gap_row_xs {
+ --flex-row-gap: var(--kbq-size-xs);
+}
+
+.gap_row_s {
+ --flex-row-gap: var(--kbq-size-s);
+}
+
+.gap_row_m {
+ --flex-row-gap: var(--kbq-size-m);
+}
+
+.gap_row_l {
+ --flex-row-gap: var(--kbq-size-l);
+}
+
+.gap_row_xl {
+ --flex-row-gap: var(--kbq-size-xl);
+}
+
+.gap_row_xxl {
+ --flex-row-gap: var(--kbq-size-xxl);
+}
+
+.gap_row_3xl {
+ --flex-row-gap: var(--kbq-size-3xl);
+}
+
+.gap_row_4xl {
+ --flex-row-gap: var(--kbq-size-4xl);
+}
+
+.gap_row_5xl {
+ --flex-row-gap: var(--kbq-size-5xl);
+}
+
+.gap_row_6xl {
+ --flex-row-gap: var(--kbq-size-6xl);
+}
+
+.gap_row_7xl {
+ --flex-row-gap: var(--kbq-size-7xl);
+}
diff --git a/packages/components/src/components/FlexBox/FlexBox.test.tsx b/packages/components/src/components/FlexBox/FlexBox.test.tsx
index f4332914f..cb801a9d8 100644
--- a/packages/components/src/components/FlexBox/FlexBox.test.tsx
+++ b/packages/components/src/components/FlexBox/FlexBox.test.tsx
@@ -1,8 +1,11 @@
import { createRef } from 'react';
-import { render } from '@testing-library/react';
+import { render, screen } from '@testing-library/react';
import { describe, it, expect } from 'vitest';
+import { BreakpointsContext, type BreakpointsContextType } from '../Provider';
+
+import s from './FlexBox.module.css';
import { FlexBox } from './index';
import type { FlexBoxProps } from './index';
@@ -27,4 +30,54 @@ describe('FlexBox', () => {
const flexBox = container.querySelector('div');
expect(ref.current).toBe(flexBox);
});
+
+ it('should apply flex classes from props', () => {
+ render(
+
+ );
+
+ expect(screen.getByTestId('flex-box')).toHaveClass(
+ s.base,
+ s['flex_inline-flex'],
+ s['wrap_wrap-reverse'],
+ s.gap_row_l,
+ s.gap_column_xl,
+ s['direction_column-reverse'],
+ s.alignItems_center,
+ s['justifyContent_space-between']
+ );
+ });
+
+ it('should apply flex classes from responsive props', () => {
+ const breakpoints = {
+ xs: true,
+ l: true,
+ } as BreakpointsContextType;
+
+ render(
+
+
+
+ );
+
+ expect(screen.getByTestId('flex-box')).toHaveClass(
+ s.gap_row_m,
+ s.gap_column_m,
+ s.direction_row
+ );
+ });
});
diff --git a/packages/components/src/components/FlexBox/FlexBox.tsx b/packages/components/src/components/FlexBox/FlexBox.tsx
index 6e21a3e01..2aa7e8961 100644
--- a/packages/components/src/components/FlexBox/FlexBox.tsx
+++ b/packages/components/src/components/FlexBox/FlexBox.tsx
@@ -5,9 +5,9 @@ import type { ComponentPropsWithRef, ElementType } from 'react';
import { clsx, polymorphicForwardRef } from '@koobiq/react-core';
import { getResponsiveValue } from '../../utils';
-import { flex as flexBox } from '../layout';
import { useMatchedBreakpoints } from '../Provider';
+import s from './FlexBox.module.css';
import type { FlexBoxBaseProps } from './index';
/**
@@ -38,26 +38,29 @@ export const FlexBox = polymorphicForwardRef<'div', FlexBoxBaseProps>(
const flex = getResponsiveValue(flexProp, breakpoints);
const gap = getResponsiveValue(gapProp, breakpoints);
- const colGap = getResponsiveValue(colGapProp, breakpoints);
- const rowGap = getResponsiveValue(rowGapProp, breakpoints);
+ const colGap = getResponsiveValue(colGapProp, breakpoints) ?? gap;
+ const rowGap = getResponsiveValue(rowGapProp, breakpoints) ?? gap;
const wrap = getResponsiveValue(wrapProp, breakpoints);
const alignItems = getResponsiveValue(alignItemsProp, breakpoints);
const direction = getResponsiveValue(directionProp, breakpoints);
const justifyContent = getResponsiveValue(justifyContentProp, breakpoints);
- const flexCn = flexBox({
- gap,
- flex,
- wrap,
- colGap,
- rowGap,
- direction,
- alignItems,
- justifyContent,
- });
-
return (
-
+
{children}
);
diff --git a/packages/components/src/components/layout/flex/flex.stories.tsx b/packages/components/src/components/layout/flex/flex.stories.tsx
index 3b50be176..07d1a9df0 100644
--- a/packages/components/src/components/layout/flex/flex.stories.tsx
+++ b/packages/components/src/components/layout/flex/flex.stories.tsx
@@ -10,9 +10,9 @@ import {
flexPropGap,
flexPropJustifyContent,
flexPropOrder,
- type FlexProps,
flexPropWrap,
-} from './flex';
+} from './index';
+import type { FlexProps } from './index';
const meta = {
title: 'Mixins/flex',
diff --git a/packages/components/src/components/layout/flex/flex.test.ts b/packages/components/src/components/layout/flex/flex.test.ts
new file mode 100644
index 000000000..469b309e6
--- /dev/null
+++ b/packages/components/src/components/layout/flex/flex.test.ts
@@ -0,0 +1,48 @@
+import { describe, expect, it } from 'vitest';
+
+import { flex } from './flex';
+import s from './flex.module.css';
+
+describe('flex', () => {
+ it('should generate classes for every flex property', () => {
+ expect(
+ flex(
+ {
+ flex: 'inline-flex',
+ wrap: 'wrap-reverse',
+ order: -1,
+ gap: 'm',
+ rowGap: 'l',
+ colGap: 'xl',
+ direction: 'column-reverse',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ },
+ 'custom-class'
+ )
+ ).toBe(
+ [
+ s.base,
+ s['flex_inline-flex'],
+ s['wrap_wrap-reverse'],
+ s['order_-1'],
+ s.gap_row_l,
+ s.gap_column_xl,
+ s['direction_column-reverse'],
+ s.alignItems_center,
+ s['justifyContent_space-between'],
+ 'custom-class',
+ ].join(' ')
+ );
+ });
+
+ it('should use gap as the row and column gap fallback', () => {
+ expect(flex({ gap: 'm' })).toBe(
+ [s.base, s.gap_row_m, s.gap_column_m].join(' ')
+ );
+ });
+
+ it('should generate class for zero order', () => {
+ expect(flex({ order: 0 })).toBe([s.base, s.order_0].join(' '));
+ });
+});
diff --git a/packages/components/src/components/layout/flex/flex.ts b/packages/components/src/components/layout/flex/flex.ts
index d94551c04..1f9146d17 100644
--- a/packages/components/src/components/layout/flex/flex.ts
+++ b/packages/components/src/components/layout/flex/flex.ts
@@ -1,82 +1,7 @@
import { clsx } from '@koobiq/react-core';
import s from './flex.module.css';
-
-export const flexPropAlignItems = [
- 'flex-start',
- 'flex-end',
- 'center',
- 'baseline',
- 'stretch',
-] as const;
-export type FlexPropAlignItems = (typeof flexPropAlignItems)[number];
-
-export const flexPropGap = [
- '3xs',
- 'xxs',
- 'xs',
- 's',
- 'm',
- 'l',
- 'xl',
- 'xxl',
- '3xl',
- '4xl',
- '5xl',
- '6xl',
- '7xl',
-] as const;
-export type FlexPropGap = (typeof flexPropGap)[number];
-
-export const flexPropJustifyContent = [
- 'flex-start',
- 'flex-end',
- 'center',
- 'space-between',
- 'space-around',
- 'space-evenly',
-] as const;
-export type FlexPropJustifyContent = (typeof flexPropJustifyContent)[number];
-
-export const flexPropFlex = ['flex', 'inline-flex'] as const;
-export type FlexPropFlex = (typeof flexPropFlex)[number];
-
-export const flexPropWrap = ['nowrap', 'wrap', 'wrap-reverse'] as const;
-export type FlexPropWrap = (typeof flexPropWrap)[number];
-
-export const flexPropDirection = [
- 'row',
- 'row-reverse',
- 'column',
- 'column-reverse',
-] as const;
-export type FlexPropDirection = (typeof flexPropDirection)[number];
-
-export const flexPropOrder = [-1, 0, 1] as const;
-export type FlexPropOrder = (typeof flexPropOrder)[number];
-
-export type FlexProps = {
- /** Defines the `gap` property. */
- gap?: FlexPropGap;
- /** Defines the `column-gap` property. */
- colGap?: FlexPropGap;
- /** Defines the `row-gap` property. */
- rowGap?: FlexPropGap;
- /** Defines the `display` property with `flex` or `inline-flex` value. */
- flex?: FlexPropFlex;
- /** Defines the `flex-wrap` property. */
- wrap?: FlexPropWrap;
- /** Defines the `order` property. */
- order?: FlexPropOrder;
- /** Defines the `flex-direction` property. */
- direction?: FlexPropDirection;
- /** Defines the `align-items` property. */
- alignItems?: FlexPropAlignItems;
- /** Defines the `justify-content` property. */
- justifyContent?: FlexPropJustifyContent;
-};
-
-export type FlexParams = (props: FlexProps, className?: string) => string;
+import type { FlexParams } from './types';
/** The flex mixin turns the element it’s applied to into a flex container. */
export const flex: FlexParams = (props, className) => {
@@ -89,11 +14,9 @@ export const flex: FlexParams = (props, className) => {
gap,
rowGap: rowGapProp,
colGap: colGapProp,
- order: orderProp,
+ order,
} = props;
- const order = String(orderProp);
-
const colGap = colGapProp ?? gap;
const rowGap = rowGapProp ?? gap;
@@ -101,7 +24,7 @@ export const flex: FlexParams = (props, className) => {
s.base,
flex && s[`flex_${flex}`],
wrap && s[`wrap_${wrap}`],
- order && s[`order_${order}`],
+ order !== undefined && s[`order_${order}`],
rowGap && s[`gap_row_${rowGap}`],
colGap && s[`gap_column_${colGap}`],
direction && s[`direction_${direction}`],
diff --git a/packages/components/src/components/layout/flex/index.ts b/packages/components/src/components/layout/flex/index.ts
index ece6890a3..6ef28bf01 100644
--- a/packages/components/src/components/layout/flex/index.ts
+++ b/packages/components/src/components/layout/flex/index.ts
@@ -1 +1,2 @@
export * from './flex';
+export * from './types';
diff --git a/packages/components/src/components/layout/flex/types.ts b/packages/components/src/components/layout/flex/types.ts
new file mode 100644
index 000000000..80bbe14a9
--- /dev/null
+++ b/packages/components/src/components/layout/flex/types.ts
@@ -0,0 +1,75 @@
+export const flexPropAlignItems = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'baseline',
+ 'stretch',
+] as const;
+export type FlexPropAlignItems = (typeof flexPropAlignItems)[number];
+
+export const flexPropGap = [
+ '3xs',
+ 'xxs',
+ 'xs',
+ 's',
+ 'm',
+ 'l',
+ 'xl',
+ 'xxl',
+ '3xl',
+ '4xl',
+ '5xl',
+ '6xl',
+ '7xl',
+] as const;
+export type FlexPropGap = (typeof flexPropGap)[number];
+
+export const flexPropJustifyContent = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'space-between',
+ 'space-around',
+ 'space-evenly',
+] as const;
+export type FlexPropJustifyContent = (typeof flexPropJustifyContent)[number];
+
+export const flexPropFlex = ['flex', 'inline-flex'] as const;
+export type FlexPropFlex = (typeof flexPropFlex)[number];
+
+export const flexPropWrap = ['nowrap', 'wrap', 'wrap-reverse'] as const;
+export type FlexPropWrap = (typeof flexPropWrap)[number];
+
+export const flexPropDirection = [
+ 'row',
+ 'row-reverse',
+ 'column',
+ 'column-reverse',
+] as const;
+export type FlexPropDirection = (typeof flexPropDirection)[number];
+
+export const flexPropOrder = [-1, 0, 1] as const;
+export type FlexPropOrder = (typeof flexPropOrder)[number];
+
+export type FlexProps = {
+ /** Defines the `gap` property. */
+ gap?: FlexPropGap;
+ /** Defines the `column-gap` property. */
+ colGap?: FlexPropGap;
+ /** Defines the `row-gap` property. */
+ rowGap?: FlexPropGap;
+ /** Defines the `display` property with `flex` or `inline-flex` value. */
+ flex?: FlexPropFlex;
+ /** Defines the `flex-wrap` property. */
+ wrap?: FlexPropWrap;
+ /** Defines the `order` property. */
+ order?: FlexPropOrder;
+ /** Defines the `flex-direction` property. */
+ direction?: FlexPropDirection;
+ /** Defines the `align-items` property. */
+ alignItems?: FlexPropAlignItems;
+ /** Defines the `justify-content` property. */
+ justifyContent?: FlexPropJustifyContent;
+};
+
+export type FlexParams = (props: FlexProps, className?: string) => string;