# Ant Design and Styles

We won't talk much about AntD components a lot but should mention some things about them and how apply styles to them.&#x20;

You can read their [official documentation](https://ant.design/) and follow that information to do everything.

## AntD Components

Need to notice what AntD version do we used in moment when we develop this app.

```json
        "antd": "^5.20.0",
        "antd-img-crop": "^4.21.0",
```

Almost in all cases we used their components. And sometimes they acts really interesting and hard. Especially when we talk about table filters. Why them? In process of development we realized that the filters for the table and the same filters that should be elsewhere could not be produced by a single component. Perhaps this is a mistake in the development itself, and perhaps a misunderstanding between the developers of this project and the developers of AntD.

Also AntD do not give us an flexible input for the phone. Because of that you need to use third-party libraries for this. Accordingly, this component sometimes does not fit well with AntD components.&#x20;

Back to the table filters. Here is an example of filters from the `Leads page`.

{% code title="Leads.js" %}

```javascript
filterDropdown: ({ filters, close }) =>
                !mobileDevicesBreakpoint && (
                    <TableFilterDropdown
                        filters={filters}
                        close={close}
                        filterKey="status"
                        selectedFilters={selectedFilters}
                        setSelectedFilters={setSelectedFilters}
                        setFilteredInfo={setFilteredInfo}
                    />
                ),
```

{% endcode %}

AntD provides us with information how to work with these filters, but if you want to put them in another place, or even develop an option for mobile applications, then everything needs to be done through states.

It would be more logical to make one state or two and control the filters with them, but it does not work. As a result, we see a bunch of states on the same page that need to control this.

{% code title="Leads.js" %}

```javascript
const [filteredInfo, setFilteredInfo] = useState({});
const [selectedFilterValue, setSelectedFilterValue] = useState({});
const [selectedFilters, setSelectedFilters] = useState({
        states: [],
        statuses: [],
        businesses: [],
    });
const filterOptions = {
        state: leadState.map(state => ({
            text: state.label,
            value: state.value,
        })),
        status: statuses.map(status => ({
            text: status.name,
            value: status.id,
        })),
        business: [
            {
                text: 'No business',
                value: 'No business',
            },
            ...businesses.map(business => ({
                text: business.name,
                value: business.name,
            })),
        ],
    };
```

{% endcode %}

Or, for example, resetting the form.

{% code title="Leads.js" %}

```javascript
setTimeout(() => {
                form.resetFields();
}, 1000);
```

{% endcode %}

**Something needs to be done using the setTimeout function.** Again, for some it may be obvious things, but for some it is not. All the same, this should be mentioned since these are that certain features in our application.

More examples. Adding or reducing the number of inputs for social medias. Just look at how difficult everything is here (sorry that you need to flip through so much, a very large nesting):

{% code title="leadForm.js" fullWidth="true" %}

```javascript
<Form.Item label={t('socials')}>
	<Form.List name="socialMedia" initialvalue={[{ type: 'facebook', url: '' }]}>
		{(fields, { add, remove }) => {
			return (
			<>
			{fields.map(({ key, name, fieldKey, ...restField }, index) => {
				const initialvalue = lead?.socialMedia && lead?.socialMedia.length > index
							? lead.socialMedia[index].url
							: form.getFieldValue(['socialMedia', index, 'type']);

				return (
					<Flex key={key} align="center" style={{ width: isSmallDevice && '100%' }}>
						<Form.Item {...restField} style={{ marginBottom: spacing[4], width: isSmallDevice && '100%' }}>
							<Flex vertical={isSmallDevice} align="center" gap={spacing[1]}>
								<Form.Item {...restField} name={[socialsList[index], 'type']} noStyle>
									<Flex align="center" justify="space-between" style={{ width: isSmallDevice && '100%' }}>
										<Select
											filterOption={filterOption}
											style={{
												height: spacing[7],
												width: 82,
											}}
											options={socialMediaOptions}
											defaultValue={
												socialsList[index] || form.getFieldValue(['socialMedia', index, 'type'])
											}
											onChange={e => {
											handleSocialsListChange(index, e);
											}}
												optionRender={option => {
													if (option.data.disabled) {
														return <div style={{ opacity: 0.5 }}>{option.data.label}</div>;
													}
													
													return option.data.label;
											}}
										/>
											{index === 0 ? null : isSmallDevice && (
												<DeleteButton
													onDelete={() => {
														handleRemoveSocialMediaField(remove, name);
													}}
												/>
											)}
									</Flex>
								</Form.Item>
								<Form.Item
									{...restField}
									name={[name, 'url']}
									fieldKey={[fieldKey, 'url']}
									noStyle
									rules={[
										getSocialMediaValidationRules(
										form.getFieldValue(['socialMedia', index, 'type']) || 'facebook', t),
									]}
								>
									<Input
										placeholder={t('placeholder.socials')}
										style={{ width: isSmallDevice ? '100%' : 278 }}
										initialvalue={mode === 'edit' ? initialvalue : ''}
									/>
								</Form.Item>
									{index === 0 ? null : !isSmallDevice && (
										<DeleteButton
											onDelete={() => {
												handleRemoveSocialMediaField(remove, name);
											}}
										/>
									)}
							</Flex>
						</Form.Item>
					</Flex>
				);
			})}

			{Object.keys(socialsList).length < 4 && (
				<Button
					onClick={() => handleAddSocialMediaField(add)}
					className={classes['add-phone-button']}
					icon={<i className={`fi-rr-add ${classes['add-phone-button-icon']}`} />}
				>
					{t('buttons.add-social')}
				</Button>
			)}
			</>
		);
		}}
	</Form.List>
</Form.Item>
```

{% endcode %}

And the functions that regulate the number of inputs for social networks:

{% code title="" fullWidth="true" %}

```javascript
const handleAddSocialMediaField = () => {
	const keys = Object.keys(socialsList).map(Number);
	const maxKey = keys.length > 0 ? Math.max(...keys) : 0;

	const defaultSocialValue = getDefaultSocialSelectValue(socialsList);

	handleSocialsListChange(maxKey + 1, defaultSocialValue);
	form.setFieldValue(['socialMedia', maxKey + 1, 'type'], defaultSocialValue);
	setSocialsList({ ...socialsList, [maxKey + 1]: defaultSocialValue });
};

const handleRemoveSocialMediaField = (removeFunc, name) => {
	const { [name]: removed, ...remainingSocialsList } = socialsList;

	const newSocialsList = Object.fromEntries(
		Object.entries(remainingSocialsList).map(([key, value], index) => [index, value])
	);

	setSocialsList(newSocialsList);
	setSocialMediaOptions(prev =>
		prev.map(option => {
			if (option.value === removed) {
				return {
					...option,
					disabled: false,
				};
			}

			return option;
		})
	);
	removeFunc(name);
};
```

{% endcode %}

It is difficult to understand all this the first time. In the code of our project you may find a lot of examples. This may be the hardest one. But this is only half the problem.

## Styling

Here comes another problem. Components rarely give the opportunity to change their stylization. Some small part can be stylized using JavaScript, the rest using ordinary styles using SCSS. Other words, use the usual className's or id.

### SCSS

This is where this problem manifests itself. Using this approach, we again cannot change the entire stylization.

It is necessary to change their classes to suit their own needs.

For example

{% code title="App.scss" %}

```scss
.ant-layout-header {
    padding: $spacing-1 $spacing-6;

    @media screen and (width <= 768px) {
        padding: $spacing-1 $spacing-3;
    }
}
```

{% endcode %}

It is necessary, using a browser, to find the class of the element that we want to change.

Or:

```scss
.odd-table-cell {
    .ant-table-cell-fix-left,
    .ant-table-cell-fix-right {
        background-color: $gray-25;
    }
    background-color: $gray-25;
}
```

Here we are adding "native" classes to our own.

And most importantly, there is such an option, the best from the point of code support:

```scss
actions-menu {
    :global {
        .ant-dropdown-menu {
            gap: $spacing-1;

            .ant-dropdown-menu-item:hover {
                background-color: $gray-50;
            }

            .ant-dropdown-menu-item:active {
                background-color: $blue-50;
            }
        }
    }
}
```

Use "`: global`" and continue to prescribe classes.

### JS

Some of the styling is done by using JavaScript.

Either write as "style in JS" using all the features of the optional render, or stylize through the props provided by AntD:

```javascript
<Flex
                    vertical={mobileDevicesBreakpoint}
                    gap={mobileDevicesBreakpoint ? spacing[1] : spacing[3]}
                    align="center"
                    justify="space-between"
                    style={{
                        marginBottom: mobileDevicesBreakpoint ? spacing[3] : spacing[4],
                    }}
>
```

It is worth noting that certain style constants are used here. They are on the path: ...ui/src/theming/

There you will find everything you need, as well as the following:

```javascript
export const themeConfig = {
    token,
    components,
};
```

Config file for AntD theme. It is used in App.js.

Look in components.js. You will find there how to customize certain styles for components. Here is part of the code from there:

```javascript
export const components = {
    // Here can be defined the components' styles
    Button: {
        colorPrimary: backgroundColor.Action,
        colorPrimaryActive: backgroundColor.ActionActive,
        colorPrimaryBorder: borderColor.actionPrimary,
        colorPrimaryHover: backgroundColor.ActionHover,
        colorTextLightSolid: textColor.white,
        borderRadius: radius.md,
        defaultBg: backgroundColor.white,
        defaultHoverBg: primitiveColors.blue100,
        defaultActiveBg: primitiveColors.blue200,
        defaultBorderColor: backgroundColor.Action,
        defaultColor: textColor.brandPrimary,
        textHoverBg: primitiveColors.blue100,
        colorBgTextActive: primitiveColors.blue200,
        colorText: textColor.brandPrimary,
        colorTextDisabled: primitiveColors.gray200,
        borderColorDisabled: 'transparent',
        colorBgContainerDisabled: primitiveColors.gray50,
        colorError: backgroundColor.error,
        colorErrorBg: backgroundColor.error,
        colorErrorBgActive: primitiveColors.red700,
        colorErrorHover: primitiveColors.red700,
        colorErrorBorderHover: primitiveColors.red600,
        colorErrorActive: backgroundColor.errorActive,
        colorLink: primitiveColors.gray200,
    },
}
```

{% hint style="warning" %}
N.B. By using the AntD guideline, you can adjust the stylization for yourself and your needs. It's also worth remembering that styling an app requires flexibility with which styles you should use. Use all approaches to achieve maximum results, or just  one for greater code purity.
{% endhint %}

## Icons

It is also worth considering which icons we use. This is [Flaticon](https://www.flaticon.com/). Regular, rounded. Use search inside Flaticon documentation to find for what icon you need.

Locally all icons are in ***.../ui/src/assets/icons/***

Usage:

```javascript
<i className={`fi fi-rr-edit ${icon.md}`} style={{ color: textColor.subtle }} />
```

This example mean "edit" icon. We can understand it by the class name.

{% hint style="danger" %}
N.B. This is important to have all the icons inside assets. Official documents says to use regular class instead always write className.
{% endhint %}

## Architecture and results

* SCSS is located in the folder of each page and component, and there is also one common to all - App.scss and index.scss. Overall SCSS styles modules are in ***.../ui/src/common/styles/***
* SCSS is overwhelmingly used as modules.
* JS constants are in... ui/src/theming/- if possible, use them.
* Styling through props of AntD components - this will help keep the code clean.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://intercode.gitbook.io/intercode-saas-kit/animation-and-styles/ant-design-and-styles.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
