Skip to content

Commit

Permalink
refactor(CellButton): mv mode to appearance (#7684)
Browse files Browse the repository at this point in the history
h2. Описание

см. #7683

h2. Release notes

h2. BREAKING CHANGE
- CellButton: свойство `mode` заменено на `appearance` со значениями `'accent' | 'neutral' | 'negative'`, также для `appearance="accent"` (a.k.a `mode="primary"`) возвращён токен `--vkui--color_text_accent`, а вот при комбинации с `centered` применяется `--vkui--color_text_accent_themed`
  ```diff
  <CellButton
  -  mode="danger"
  +  appearance="negative"
  >
    Создать что-нибудь
  </CellButton>

  <CellButton
  -  mode="primary"
  +  appearance="accent"
  >
    Создать что-нибудь
  </CellButton>
  ```
  • Loading branch information
inomdzhon authored Oct 1, 2024
1 parent f488210 commit ebd2f26
Show file tree
Hide file tree
Showing 32 changed files with 233 additions and 66 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { CellButton } from '@vkontakte/vkui';
import React from 'react';

const App = () => {
return (
<React.Fragment>
{/* mode="primary" -> appearance="accent" */}
<CellButton mode="primary">
Создать что-нибудь
</CellButton>

{/* mode="primary" -> appearance="accent" */}
<CellButton mode={"primary"}>
Создать что-нибудь
</CellButton>

{/* mode="danger" -> appearance="negative" */}
<CellButton mode="danger">
Создать что-нибудь
</CellButton>

{/* mode="danger" -> appearance="negative" */}
<CellButton mode={"danger"}>
Создать что-нибудь
</CellButton>

{/* do nothing 1 */}
<CellButton>
Создать что-нибудь
</CellButton>

{/* do nothing 2 */}
<CellButton centered>
Создать что-нибудь
</CellButton>
</React.Fragment>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`cell-button transforms correctly 1`] = `
"import { CellButton } from '@vkontakte/vkui';
import React from 'react';
const App = () => {
return (
(<React.Fragment>
{/* mode="primary" -> appearance="accent" */}
<CellButton appearance="accent">
Создать что-нибудь
</CellButton>
{/* mode="primary" -> appearance="accent" */}
<CellButton appearance="accent">
Создать что-нибудь
</CellButton>
{/* mode="danger" -> appearance="negative" */}
<CellButton appearance="negative">
Создать что-нибудь
</CellButton>
{/* mode="danger" -> appearance="negative" */}
<CellButton appearance="negative">
Создать что-нибудь
</CellButton>
{/* do nothing 1 */}
<CellButton>
Создать что-нибудь
</CellButton>
{/* do nothing 2 */}
<CellButton centered>
Создать что-нибудь
</CellButton>
</React.Fragment>)
);
};"
`;
11 changes: 11 additions & 0 deletions packages/codemods/src/transforms/v7/__tests__/cell-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
jest.autoMockOff();
import { defineSnapshotTestFromFixture } from '../../../testHelpers/testHelper';

const name = 'cell-button';
const fixtures = ['basic'] as const;

describe(name, () => {
fixtures.forEach((test) =>
defineSnapshotTestFromFixture(__dirname, name, global.TRANSFORM_OPTIONS, `${name}/${test}`),
);
});
56 changes: 56 additions & 0 deletions packages/codemods/src/transforms/v7/cell-button.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { API, FileInfo, JSXAttribute } from 'jscodeshift';
import { getImportInfo } from '../../codemod-helpers';
import { report } from '../../report';
import { JSCodeShiftOptions } from '../../types';

export const parser = 'tsx';

export default function transformer(file: FileInfo, api: API, options: JSCodeShiftOptions) {
const { alias } = options;
const j = api.jscodeshift;
const source = j(file.source);
const { localName } = getImportInfo(j, file, 'CellButton', alias);
if (!localName) {
return source.toSource();
}

const attributeToReplace = 'mode';
const newAttributeName = 'appearance';

const modeToAppearance: Record<string, string> = {
primary: 'accent',
danger: 'negative',
};

const getValueFromAttribute = (attribute: JSXAttribute): string | null => {
if (attribute.value?.type === 'StringLiteral') {
return attribute.value.value;
}
if (attribute.value?.type === 'JSXExpressionContainer') {
const expression = attribute.value.expression;
if (expression.type === 'StringLiteral') {
return expression.value;
}
}
return null;
};

source
.find(j.JSXElement, { openingElement: { name: { name: localName } } })
.find(j.JSXAttribute, { name: { name: attributeToReplace } })
.forEach((path) => {
const component = path.node;
component.name.name = newAttributeName;
const value = getValueFromAttribute(component);
if (!value || !modeToAppearance[value]) {
report(
api,
`: ${localName} has been changed. Manual changes required: need to change 'mode' prop to 'appearance'`,
);
return;
}
component.value = j.stringLiteral(modeToAppearance[value]);
});

return source.toSource();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,18 @@ export const CellButtonPlayground = (props: ComponentPlaygroundProps) => {
{...props}
propSets={[
{
centered: [true],
centered: [undefined, true],
children: ['Создать что-нибудь'],
before: [undefined, <Icon24Add key="add" />],
before: [<Icon24Add key="add" />],
},
{
mode: [undefined, 'danger'],
children: ['Создать что-нибудь'],
},
{
mode: [undefined, 'danger'],
appearance: ['neutral', 'negative'],
before: [<Icon28AddOutline key="icon" />],
children: ['Создать что-нибудь'],
},
{
before: [
undefined,
<Avatar key={40} size={40}>
<Icon24Add />
</Avatar>,
Expand Down
17 changes: 15 additions & 2 deletions packages/vkui/src/components/CellButton/CellButton.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,26 @@
padding-inline-end: var(--vkui--spacing_size_m);
}

.host {
.appearanceAccent {
--vkui_internal--icon_color: var(--vkui--color_icon_accent);

color: var(--vkui--color_text_accent);
}

/* Переопределяем токен для `appearance="accent"` */
.centered {
--vkui_internal--icon_color: var(--vkui--color_icon_accent_themed);

color: var(--vkui--color_text_accent_themed);
}

.modeDanger {
.appearanceNeutral {
--vkui_internal--icon_color: var(--vkui--color_icon_primary);

color: var(--vkui--color_text_primary);
}

.appearanceNegative {
--vkui_internal--icon_color: var(--vkui--color_text_negative);

color: var(--vkui--color_text_negative);
Expand Down
28 changes: 17 additions & 11 deletions packages/vkui/src/components/CellButton/CellButton.test.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
import { render, screen } from '@testing-library/react';
import { baselineComponent } from '../../testing/utils';
import { CellButton } from './CellButton';
import { appearanceClassNames, CellButton } from './CellButton';
import styles from './CellButton.module.css';

describe('CellButton', () => {
describe(CellButton, () => {
baselineComponent((props) => <CellButton {...props}>CellButton</CellButton>);

it('should have danger className with mode danger', () => {
render(
<CellButton mode="danger" data-testid="cell">
Check
</CellButton>,
);
expect(screen.getByTestId('cell')).toHaveClass(styles.modeDanger);
});
it('should have danger className with mode danger', () => {
it.each(['accent', 'neutral', 'negative', undefined] as const)(
'should have expected className for appearance="%s"',
(appearance) => {
render(
<CellButton appearance={appearance} data-testid="cell">
Check
</CellButton>,
);
expect(screen.getByTestId('cell')).toHaveClass(
appearance ? appearanceClassNames[appearance] : appearanceClassNames.accent,
);
},
);
it('should have appearance="accent" by default if centered', () => {
render(
<CellButton centered data-testid="cell">
Check
</CellButton>,
);
expect(screen.getByTestId('cell')).toHaveClass(styles.centered);
expect(screen.getByTestId('cell')).toHaveClass(appearanceClassNames.accent);
});
});
15 changes: 12 additions & 3 deletions packages/vkui/src/components/CellButton/CellButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ import { classNames } from '@vkontakte/vkjs';
import { SimpleCell, type SimpleCellProps } from '../SimpleCell/SimpleCell';
import styles from './CellButton.module.css';

export const appearanceClassNames = {
accent: styles.appearanceAccent,
neutral: styles.appearanceNeutral,
negative: styles.appearanceNegative,
};

export interface CellButtonProps extends SimpleCellProps {
mode?: 'primary' | 'danger';
/**
* > Режим `centered` переопределяет токен для темы `"accent"`.
*/
appearance?: 'accent' | 'neutral' | 'negative';
centered?: boolean;
}

Expand All @@ -12,7 +21,7 @@ export interface CellButtonProps extends SimpleCellProps {
*/
export const CellButton = ({
centered = false,
mode = 'primary',
appearance = 'accent',
className,
...restProps
}: CellButtonProps): React.ReactNode => {
Expand All @@ -21,7 +30,7 @@ export const CellButton = ({
{...restProps}
className={classNames(
styles.host,
mode === 'danger' && styles.modeDanger,
appearanceClassNames[appearance],
centered && styles.centered,
className,
)}
Expand Down
4 changes: 2 additions & 2 deletions packages/vkui/src/components/CellButton/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
<PanelHeader>CellButton</PanelHeader>
<Group header={<Header mode="secondary">Базовый пример</Header>}>
<CellButton onClick={() => {}}>Добавить новую школу</CellButton>
<CellButton onClick={() => {}} mode="danger">
<CellButton onClick={() => {}} appearance="negative">
Удалить беседу
</CellButton>
</Group>
<Group header={<Header mode="secondary">Иконки</Header>}>
<CellButton onClick={() => {}} before={<Icon28AddOutline />}>
Добавить родственника
</CellButton>
<CellButton onClick={() => {}} before={<Icon28DeleteOutline />} mode="danger">
<CellButton onClick={() => {}} before={<Icon28DeleteOutline />} appearance="negative">
Удалить беседу
</CellButton>
</Group>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit ebd2f26

Please sign in to comment.