Skip to content

Commit

Permalink
Merge branch 'feat/theme-creator' into feat/create-theme-page
Browse files Browse the repository at this point in the history
  • Loading branch information
dgaponov committed Jun 16, 2024
2 parents 71733a1 + 08e3b8c commit fc895ec
Show file tree
Hide file tree
Showing 47 changed files with 2,386 additions and 67 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"bem-cn-lite": "^4.1.0",
"chroma-js": "^2.4.2",
"husky": "^8.0.3",
"i18next": "^23.8.3",
"javascript-time-ago": "^2.5.9",
Expand Down Expand Up @@ -45,6 +46,7 @@
"@gravity-ui/stylelint-config": "^2.0.0",
"@gravity-ui/tsconfig": "^1.0.0",
"@svgr/webpack": "^6.5.1",
"@types/chroma-js": "^2.4.4",
"@types/jest": "^29.2.4",
"@types/lodash": "^4.14.197",
"@types/micromatch": "^4.0.7",
Expand Down
6 changes: 5 additions & 1 deletion public/locales/en/component.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
"title": "Components",
"searchPlaceholder": "Search by component name",
"color-input_validation-format-error": "Incorrect format",
"maintainers": "Maintainers:"
"maintainers": "Maintainers:",
"theme": "Switch theme",
"rtlOn": "Switch RTL on",
"rtlOff": "Switch RTL off",
"rtlNotSupported": "RTL not supported"
}
7 changes: 6 additions & 1 deletion public/locales/ru/component.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,10 @@
"actions_openInFigma": "Открыть в Figma",
"title": "Компоненты",
"searchPlaceholder": "Поиск по названию",
"color-input_validation-format-error": "Неверный формат"
"color-input_validation-format-error": "Неверный формат",
"maintainers": "Maintainers:",
"theme": "Переключить тему",
"rtlOn": "Включить RTL",
"rtlOff": "Выключить RTL",
"rtlNotSupported": "RTL не поддерживается"
}
22 changes: 16 additions & 6 deletions src/components/ColorPickerInput/ColorPickerInput.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,28 @@
$block: '.#{variables.$ns}color-picker';

#{$block} {
--g-border-radius-xl: 8px;
flex-grow: 1;
position: relative;

&__text-input {
z-index: 1;
}

&__preview {
width: 16px;
height: 16px;
margin-inline-start: var(--g-spacing-2);
margin-inline-end: var(--g-spacing-1);
border-radius: var(--g-border-radius-xs);
}

&__input {
width: 100%;
height: 0;
width: 35px;
opacity: 0;
border: 1px solid transparent;
padding: 0;
margin: 0;
border: 0;
position: absolute;
bottom: 0;
right: 0;
z-index: 0;
}
}
31 changes: 21 additions & 10 deletions src/components/ColorPickerInput/ColorPickerInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {useTranslation} from 'next-i18next';
import React, {ChangeEventHandler, useCallback, useRef, useState} from 'react';

import {block} from '../../utils';
import {ColorPreview} from '../ColorPreview/ColorPreview';

import './ColorPickerInput.scss';
import {ColorPreview} from './ColorPreview';
import {NativeColorPicker} from './NativeColorPicker';
import {hexRegexp, parseRgbStringToHex, rgbRegexp, rgbaRegexp} from './utils';

Expand All @@ -16,8 +16,9 @@ export interface ColorPickerInputProps {
defaultValue: string;
name?: string;
value?: string;
onChange?: (color: string) => void;
onChange: (color: string) => void;
errorMessage?: string;
size?: TextInputProps['size'];
}

export const ColorPickerInput = ({
Expand All @@ -26,6 +27,7 @@ export const ColorPickerInput = ({
onChange: onChangeExternal,
defaultValue,
errorMessage,
size = 'l',
}: ColorPickerInputProps) => {
const {t} = useTranslation('component');

Expand All @@ -37,10 +39,14 @@ export const ColorPickerInput = ({

const managedValue = value || inputValue;

React.useEffect(() => {
setColor(defaultValue);
}, [defaultValue]);

const onChange: ChangeEventHandler<HTMLInputElement> = useCallback(
(event) => {
const newValue = event.target.value.replaceAll(' ', '');
onChangeExternal?.(newValue);
onChangeExternal(newValue);
setInputValue(newValue);
setValidationError(undefined);

Expand All @@ -64,12 +70,16 @@ export const ColorPickerInput = ({
[onChangeExternal],
);

const onNativeInputChange: ChangeEventHandler<HTMLInputElement> = useCallback((e) => {
const newValue = e.target.value.toUpperCase();
const onNativeInputChange: ChangeEventHandler<HTMLInputElement> = useCallback(
(e) => {
const newValue = e.target.value.toUpperCase();

setColor(newValue);
setInputValue(newValue);
}, []);
setColor(newValue);
setInputValue(newValue);
onChangeExternal(newValue);
},
[onChangeExternal],
);

const onBlur = useCallback(() => {
if (
Expand All @@ -85,15 +95,16 @@ export const ColorPickerInput = ({
return (
<Flex className={b()} direction="column">
<TextInput
className={b('text-input')}
name={name}
value={managedValue}
errorPlacement="inside"
errorMessage={errorMessage || t('color-input_validation-format-error')}
validationState={validationError}
view="normal"
size="l"
size={size}
onChange={onChange}
startContent={<ColorPreview color={color} />}
startContent={<ColorPreview className={b('preview')} color={color} />}
endContent={
<Button
view="flat-action"
Expand Down
15 changes: 0 additions & 15 deletions src/components/ColorPickerInput/ColorPreview.tsx

This file was deleted.

35 changes: 35 additions & 0 deletions src/components/ColorPreview/ColorPreview.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@use '../../variables.scss';

$block: '.#{variables.$ns}color-preview';

#{$block} {
--chess: rgb(235, 235, 235);
--surface: rgb(255, 255, 255);
--opacity-pattern: repeating-conic-gradient(var(--chess) 0% 25%, var(--surface) 0% 50%) 50% /
8px 8px;

width: 16px;
height: 16px;
border-radius: var(--g-border-radius-xs);
overflow: hidden;
position: relative;

&__color {
position: relative;
width: 100%;
height: 100%;
}

&_with-opacity {
&::before {
content: '';
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: var(--opacity-pattern);
}
}
}
22 changes: 22 additions & 0 deletions src/components/ColorPreview/ColorPreview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import {block} from '../../utils';

import './ColorPreview.scss';

export interface ColorPreviewProps {
color?: string;
className?: string;
}

const b = block('color-preview');

const isColorWithOpacity = (color?: string) => !color || color?.startsWith('rgba');

export const ColorPreview = ({color, className}: ColorPreviewProps) => {
return (
<div className={b({'with-opacity': isColorWithOpacity(color)}, className)}>
<div className={b('color')} style={{backgroundColor: color}} />
</div>
);
};
85 changes: 51 additions & 34 deletions src/components/SandboxBlock/SandboxBlock.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import {ChevronsCollapseUpRight, ChevronsExpandUpRight, TextAlignRight} from '@gravity-ui/icons';
import {
ChevronsCollapseUpRight,
ChevronsExpandUpRight,
TextAlignLeft,
TextAlignRight,
} from '@gravity-ui/icons';
import {
Col,
Direction,
Expand All @@ -13,6 +18,7 @@ import {
Theme,
Tooltip,
} from '@gravity-ui/uikit';
import {useTranslation} from 'next-i18next';
import React from 'react';

import themeIcon from '../../assets/icons/theme.svg';
Expand All @@ -29,6 +35,8 @@ const SandboxBlock: React.FC<SandboxBlockTypes> = ({
sandboxConfig,
isSupportRTL,
}) => {
const {t} = useTranslation('component');

const [props, setProps] = React.useState({});

const [isIframeLoaded, setIsIframeLoaded] = React.useState(false);
Expand Down Expand Up @@ -178,6 +186,10 @@ const SandboxBlock: React.FC<SandboxBlockTypes> = ({
}
}, [isIframeLoaded, props, iframeTheme, iframeDirection]);

const isRtl = iframeDirection === 'rtl';

const rtlIcon = isRtl ? TextAlignRight : TextAlignLeft;

return (
<div className={b({'full-screen': isFullScreen})}>
<Row space="0">
Expand All @@ -193,39 +205,44 @@ const SandboxBlock: React.FC<SandboxBlockTypes> = ({
<Col s="12" l="4" m="4">
<div className={b('top-actions')}>
<div className={b('top-actions-wrapper')}>
<div
tabIndex={0}
role="button"
className={b('control-icon')}
onClick={() => {
setIframeTheme(iframeTheme === 'dark' ? 'light' : 'dark');
}}
>
<Icon data={themeIcon} size={18} />
</div>
<div
tabIndex={0}
role="button"
className={
isSupportRTL ? b('control-icon') : b('control-icon-disabled')
}
onClick={() => {
if (isSupportRTL) {
setIframeDirection(
iframeDirection === 'ltr' ? 'rtl' : 'ltr',
);
}
}}
>
{isSupportRTL && (
<Icon className={b('icon')} data={TextAlignRight} size={18} />
)}
{!isSupportRTL && (
<Tooltip content={'RTL not supported'}>
<Icon data={TextAlignRight} size={18} />
</Tooltip>
)}
</div>
<Tooltip content={t('theme')}>
<div
tabIndex={0}
role="button"
className={b('control-icon')}
onClick={() => {
setIframeTheme(iframeTheme === 'dark' ? 'light' : 'dark');
}}
>
<Icon data={themeIcon} size={18} />
</div>
</Tooltip>

{isSupportRTL && (
<Tooltip content={isRtl ? t('rtlOff') : t('rtlOn')}>
<div
tabIndex={0}
role="button"
className={b('control-icon')}
onClick={() => {
setIframeDirection(isRtl ? 'ltr' : 'rtl');
}}
>
<Icon className={b('icon')} data={rtlIcon} size={18} />
</div>
</Tooltip>
)}
{!isSupportRTL && (
<Tooltip content={t('rtlNotSupported')}>
<div
tabIndex={0}
role="button"
className={b('control-icon-disabled')}
>
<Icon data={rtlIcon} size={18} />
</div>
</Tooltip>
)}
</div>
<div
tabIndex={0}
Expand Down
Loading

0 comments on commit fc895ec

Please sign in to comment.