Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add border radius tab #220

Merged
merged 6 commits into from
Jul 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"@gravity-ui/icons": "^2.8.1",
"@gravity-ui/navigation": "^2.15.0",
"@gravity-ui/page-constructor": "^5.2.0",
"@gravity-ui/uikit": "^6.17.0",
"@gravity-ui/uikit": "^6.20.1",
"@mdx-js/mdx": "^2.3.0",
"@mdx-js/react": "^2.3.0",
"@octokit/rest": "^20.1.1",
Expand Down
13 changes: 11 additions & 2 deletions public/locales/en/themes.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,14 @@
"component_preview": "Component preview",
"is_everything_set": "Is everything set?",
"cancel": "Cancel",
"export_theme_config": "Export theme config"
}
"export_theme_config": "Export theme config",
"radius": "Radius",
"radius_regular": "Regular",
"radius_circled": "Circled",
"radius_squared": "Squared",
"radius_custom": "Custom radius",
"choose_border_radius": "Choose border radius",
"label": "Label",
"input_placeholder": "Content",
"button": "Button"
}
13 changes: 11 additions & 2 deletions public/locales/ru/themes.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,14 @@
"component_preview": "Предпросмотр компонентов",
"is_everything_set": "Все настроили?",
"cancel": "Закрыть",
"export_theme_config": "Экспорт конфигурации темы"
}
"export_theme_config": "Экспорт конфигурации темы",
"radius": "Радиус",
"radius_regular": "Стандартный",
"radius_circled": "Круглый",
"radius_squared": "Без скругления",
"radius_custom": "Настроить скругление",
"choose_border_radius": "Выберите радиус скругления",
"label": "Ярлык",
"input_placeholder": "Контент",
"button": "Кнопка"
}
28 changes: 7 additions & 21 deletions src/components/SelectableCard/SelectableCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,17 @@ export type SelecableCardProps = {
* Props for inner Text component
*/
textProps?: TextProps;
/**
* Style object to customize decorated text. Has an impact when pureText has falsie values
*/
contentStyle?: React.CSSProperties;
} & Pick<CardProps, 'selected' | 'onClick'> &
Pick<DOMProps, 'className'>;

const CardContent = ({
text,
pureText,
textProps,
contentStyle,
}: Pick<SelecableCardProps, 'text' | 'pureText' | 'textProps' | 'contentStyle'>) => {
}: Pick<SelecableCardProps, 'text' | 'pureText' | 'textProps'>) => {
const props: Record<string, unknown> = pureText
? {variant: 'body-2'}
: {color: 'inverted-primary', className: b('fake-button')};
props.style = contentStyle;
return (
<Text {...props} {...textProps}>
{text}
Expand All @@ -52,17 +46,9 @@ export const SelectableCard = ({
onClick,
className,
textProps,
contentStyle,
}: SelecableCardProps) => {
return (
<Card className={b(null, className)} type="selection" selected={selected} onClick={onClick}>
<CardContent
text={text}
pureText={pureText}
textProps={textProps}
contentStyle={contentStyle}
/>
{selected && <CircleCheckFill className={b('icon')} />}
</Card>
);
};
}: SelecableCardProps) => (
<Card className={b(null, className)} type="selection" selected={selected} onClick={onClick}>
<CardContent text={text} pureText={pureText} textProps={textProps} />
{selected && <CircleCheckFill className={b('icon')} />}
</Card>
);
3 changes: 2 additions & 1 deletion src/components/Themes/Themes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {TagItem, Tags} from '../Tags/Tags';

import './Themes.scss';
import {DEFAULT_THEME} from './lib/constants';
import {BorderRadiusTab} from './ui/BorderRadiusTab/BorderRadiusTab';
import {ColorsTab} from './ui/ColorsTab/ColorsTab';
import {PreviewTab} from './ui/PreviewTab/PreviewTab';
import {ThemeCreatorContextProvider} from './ui/ThemeCreatorContextProvider';
Expand All @@ -26,7 +27,7 @@ enum ThemeTab {
const tabToComponent: Record<ThemeTab, React.ComponentType | undefined> = {
[ThemeTab.Colors]: ColorsTab,
[ThemeTab.Typography]: () => <div>TODO Typography</div>,
[ThemeTab.BorderRadius]: () => <div>TODO borders</div>,
[ThemeTab.BorderRadius]: BorderRadiusTab,
[ThemeTab.Preview]: PreviewTab,
};

Expand Down
36 changes: 34 additions & 2 deletions src/components/Themes/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import type {ThemeOptions} from './types';
import {RadiusPresetName, RadiusValue, type ThemeOptions} from './types';

export const THEME_COLOR_VARIABLE_PREFIX = '--g-color';

export const THEME_BORDER_RADIUS_VARIABLE_PREFIX = '--g-border-radius';

export const DEFAULT_NEW_COLOR_TITLE = 'New color';

export const DEFAULT_PALETTE: ThemeOptions['palette'] = {
Expand Down Expand Up @@ -33,6 +35,33 @@ export const DEFAULT_PALETTE: ThemeOptions['palette'] = {

export const DEFAULT_PALETTE_TOKENS = new Set(Object.keys(DEFAULT_PALETTE.light));

export const DEFAULT_RADIUS: RadiusValue = {
xs: '3',
s: '5',
m: '6',
l: '8',
xl: '10',
};

export const RADIUS_PRESETS: Record<RadiusPresetName, RadiusValue> = {
[RadiusPresetName.Regular]: DEFAULT_RADIUS,
[RadiusPresetName.Circled]: {
xs: '100',
s: '100',
m: '100',
l: '100',
xl: '100',
},
[RadiusPresetName.Squared]: {
xs: '0',
s: '0',
m: '0',
l: '0',
xl: '0',
},
[RadiusPresetName.Custom]: DEFAULT_RADIUS,
};

export const DEFAULT_THEME: ThemeOptions = {
palette: DEFAULT_PALETTE,
colors: {
Expand Down Expand Up @@ -65,6 +94,9 @@ export const DEFAULT_THEME: ThemeOptions = {
'text-link-visited-hover': 'private.purple.850-solid',
},
},
borders: {},
borders: {
preset: RadiusPresetName.Regular,
values: RADIUS_PRESETS[RadiusPresetName.Regular],
},
typography: {},
};
6 changes: 6 additions & 0 deletions src/components/Themes/lib/themeCreatorContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {DEFAULT_THEME} from './constants';
import {initThemeCreator} from './themeCreatorUtils';
import type {
AddColorToThemeParams,
ChangeRadiusPresetInThemeParams,
ChangeUtilityColorInThemeParams,
RenameColorInThemeParams,
UpdateColorInThemeParams,
UpdateCustomRadiusPresetInThemeParams,
} from './themeCreatorUtils';
import type {ThemeCreatorState} from './types';

Expand All @@ -21,6 +23,8 @@ export interface ThemeCreatorMethodsContextType {
removeColor: (title: string) => void;
renameColor: (params: RenameColorInThemeParams) => void;
changeUtilityColor: (params: ChangeUtilityColorInThemeParams) => void;
changeRadiusPreset: (params: ChangeRadiusPresetInThemeParams) => void;
updateCustomRadiusPreset: (params: UpdateCustomRadiusPresetInThemeParams) => void;
}

export const ThemeCreatorMethodsContext = createContext<ThemeCreatorMethodsContextType>({
Expand All @@ -29,4 +33,6 @@ export const ThemeCreatorMethodsContext = createContext<ThemeCreatorMethodsConte
removeColor: noop,
renameColor: noop,
changeUtilityColor: noop,
changeRadiusPreset: noop,
updateCustomRadiusPreset: noop,
});
27 changes: 23 additions & 4 deletions src/components/Themes/lib/themeCreatorExport.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {DEFAULT_PALETTE, DEFAULT_THEME} from './constants';
import {
createBorderRadiusPresetForExport,
createPrivateColorCssVariable,
createPrivateColorCssVariableFromToken,
createPrivateColorToken,
Expand All @@ -8,10 +9,13 @@
} from './themeCreatorUtils';
import type {ColorOption, ThemeCreatorState, ThemeVariant} from './types';

const COMMON_VARIABLES_TEMPLATE_NAME = '%COMMON_VARIABLES%';

const SCSS_TEMPLATE = `
@use '@gravity-ui/uikit/styles/themes';

.g-root {
${COMMON_VARIABLES_TEMPLATE_NAME}
&_theme_light {
@include themes.g-theme-light;

Expand Down Expand Up @@ -61,7 +65,7 @@
}

if (paletteTokens[token]?.privateColors[themeVariant]) {
Object.entries(paletteTokens[token].privateColors[themeVariant]!).forEach(

Check warning on line 68 in src/components/Themes/lib/themeCreatorExport.ts

View workflow job for this annotation

GitHub Actions / Verify Files

Forbidden non-null assertion
([privateColorCode, color]) => {
privateColors[createPrivateColorToken(token, privateColorCode)] = color;
cssVariables += `${createPrivateColorCssVariable(
Expand Down Expand Up @@ -101,10 +105,23 @@
},
);

if (forPreview) {
cssVariables += createBorderRadiusPresetForExport({
borders: themeState.borders,
forPreview,
ignoreDefaultValues,
});
}

return cssVariables.trim();
};

return {
common: createBorderRadiusPresetForExport({
borders: themeState.borders,
forPreview,
ignoreDefaultValues,
}),
light: prepareThemeVariables('light'),
dark: prepareThemeVariables('dark'),
};
Expand All @@ -117,10 +134,12 @@
return 'not implemented';
}

const {light, dark} = exportTheme({themeState, format, forPreview: false});
const {common, light, dark} = exportTheme({themeState, format, forPreview: false});

return SCSS_TEMPLATE.replace(
'%LIGHT_THEME_VARIABLES%',
light.replaceAll('\n', '\n'.padEnd(9)),
).replace('%DARK_THEME_VARIABLES%', dark.replaceAll('\n', '\n'.padEnd(9)));
COMMON_VARIABLES_TEMPLATE_NAME,
common.replaceAll('\n', '\n'.padEnd(5)),
)
.replace('%LIGHT_THEME_VARIABLES%', light.replaceAll('\n', '\n'.padEnd(9)))
.replace('%DARK_THEME_VARIABLES%', dark.replaceAll('\n', '\n'.padEnd(9)));
}
68 changes: 68 additions & 0 deletions src/components/Themes/lib/themeCreatorUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,23 @@
import {
DEFAULT_NEW_COLOR_TITLE,
DEFAULT_PALETTE_TOKENS,
RADIUS_PRESETS,
THEME_BORDER_RADIUS_VARIABLE_PREFIX,
THEME_COLOR_VARIABLE_PREFIX,
} from './constants';
import {generatePrivateColors} from './privateColors';
import type {
BordersOption,
ColorsOptions,
Palette,
PaletteTokens,
PrivateColors,
RadiusValue,
ThemeCreatorState,
ThemeOptions,
ThemeVariant,
} from './types';
import {RadiusPresetName} from './types';

function createColorToken(title: string) {
return kebabCase(title);
Expand Down Expand Up @@ -310,7 +315,7 @@
themeState: ThemeCreatorState,
colorTitle: string,
): ThemeCreatorState {
console.log('call remove color', colorTitle);

Check warning on line 318 in src/components/Themes/lib/themeCreatorUtils.ts

View workflow job for this annotation

GitHub Actions / Verify Files

Unexpected console statement
const newThemeState = {...themeState};
const token = createColorToken(colorTitle);

Expand Down Expand Up @@ -393,7 +398,7 @@
color: palette[themeVariant][token],
title: paletteTokens[token].title,
privateColors: Object.entries(
paletteTokens[token].privateColors[themeVariant]!,

Check warning on line 401 in src/components/Themes/lib/themeCreatorUtils.ts

View workflow job for this annotation

GitHub Actions / Verify Files

Forbidden non-null assertion
).map(([privateColorCode, color]) => ({
token: createPrivateColorToken(token, privateColorCode),
title: createPrivateColorCssVariable(token, privateColorCode),
Expand Down Expand Up @@ -450,3 +455,66 @@
tokens: Object.keys(paletteTokens),
};
}

export type ChangeRadiusPresetInThemeParams = {
radiusPresetName: RadiusPresetName;
};

export function changeRadiusPresetInTheme(
themeState: ThemeCreatorState,
{radiusPresetName}: ChangeRadiusPresetInThemeParams,
): ThemeCreatorState {
const newBorderValue = {
preset: radiusPresetName,
values: {...RADIUS_PRESETS[radiusPresetName]},
};

return {...themeState, borders: newBorderValue};
}

export type UpdateCustomRadiusPresetInThemeParams = {radiusValue: Partial<RadiusValue>};

export function updateCustomRadiusPresetInTheme(
themeState: ThemeCreatorState,
{radiusValue}: UpdateCustomRadiusPresetInThemeParams,
): ThemeCreatorState {
const previousRadiusValues = themeState.borders.values;
const newCustomPresetValues = {
preset: RadiusPresetName.Custom,
values: {...previousRadiusValues, ...radiusValue},
};

return {...themeState, borders: newCustomPresetValues};
}

function createBorderRadiusCssVariable(radiusSize: string) {
return `${THEME_BORDER_RADIUS_VARIABLE_PREFIX}-${radiusSize}`;
}

/**
* Generates ready-to-use in css string with borders variables
* @returns string
*/
export function createBorderRadiusPresetForExport({
borders,
forPreview,
ignoreDefaultValues,
}: {
borders: BordersOption;
ignoreDefaultValues: boolean;
forPreview: boolean;
}) {
// Don't export radius preset that are equals to default
if (ignoreDefaultValues && borders.preset === RadiusPresetName.Regular) {
return '';
}
let cssString = '';
Object.entries(borders.values).forEach(([radiusName, radiusValue]) => {
if (radiusValue) {
cssString += `${createBorderRadiusCssVariable(radiusName)}: ${radiusValue}px${
forPreview ? ' !important' : ''
};\n`;
}
});
return cssString;
}
Loading
Loading