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

Deprecate the AddItems icon #2099

Merged
merged 2 commits into from
May 12, 2023
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
5 changes: 5 additions & 0 deletions .changeset/sweet-mice-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sumup/icons': minor
---

Deprecated the AddItems icon. Use the Add or Items icons instead.
21 changes: 20 additions & 1 deletion .storybook/components/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
Select,
typography,
BaseStyles,
Badge,
} from '@sumup/circuit-ui';

function groupBy(icons: IconsManifest['icons'], key: string) {
Expand Down Expand Up @@ -72,9 +73,11 @@ const Wrapper = styled.div`
text-align: center;
margin-top: ${(p) => p.theme.spacings.giga};
margin-bottom: ${(p) => p.theme.spacings.giga};
position: relative;
`;

const Size = styled.p`
const Size = styled.span`
display: block;
color: var(--cui-fg-subtle);
font-style: italic;
`;
Expand All @@ -96,6 +99,13 @@ const iconStyles = (color: string) =>
: 'var(--cui-bg-normal)'};
`;

const badgeStyles = css`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-30deg);
`;

const Icons = () => {
const [search, setSearch] = useState('');
const [size, setSize] = useState('all');
Expand Down Expand Up @@ -189,6 +199,15 @@ const Icons = () => {
{icon.name}
{size === 'all' && <Size>{icon.size}</Size>}
</span>
{icon.deprecation && (
<Badge
title={icon.deprecation}
variant="notify"
css={badgeStyles}
>
Deprecated
</Badge>
)}
</Wrapper>
);
})}
Expand Down
56 changes: 19 additions & 37 deletions package-lock.json

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

15 changes: 10 additions & 5 deletions packages/icons/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This page outlines the process of contributing an icon to the `@sumup/icons` pac

> Note that icons should be added by internal contributors with access to the SumUp [Figma icons library](https://www.figma.com/file/vnFVuPNlqF45rkw1u9toBC/SumUp-Iconography) (internal link). If you don't have access but would like to see an icon added to `@sumup/icons`, please [open an issue](https://github.com/sumup-oss/circuit-ui/issues/new).

## Adding a new icon to `@sumup/icons`
## Adding a new icon

1. Create a new SVG file for each icon size in [`packages/web/icons/v2/`](https://github.com/sumup-oss/circuit-ui/tree/main/packages/icons/web/v2) with the name `name_size.svg` (e.g. `add_items_24`—this will generate an `<AddItems />` component).
2. Export the icon as SVG from the [Figma icons library](https://www.figma.com/file/vnFVuPNlqF45rkw1u9toBC/SumUp-Iconography) (internal link). If the icon isn't in the library, make a request with the design team first.
Expand All @@ -14,9 +14,9 @@ This page outlines the process of contributing an icon to the `@sumup/icons` pac
5. Add an icon object to the icons manifest file at [`packages/icons/manifest.json`](https://github.com/sumup-oss/circuit-ui/blob/9146e47a21dcd6880f437d1a47a0c54d5a164bfd/packages/icons/manifest.json). The icons are manually ordered alphabetically by icon category, then name (should match the file name), and finally by size (descending).
6. Build the icons package (`npx lerna run build --scope=@sumup/icons`) and run the Storybook (`npm run docs`). Verify that your icon renders correctly on the [Icons page](http://localhost:6006/?path=/docs/features-icons--docs) (local link).

## Caveats
### Caveats
connor-baer marked this conversation as resolved.
Show resolved Hide resolved

### Do not hardcode the icon's color
#### Do not hardcode the icon's color

Unless icons are a brand logo (e.g. the Mastercard logo), all SVG fills should always be `currentColor`. This lets developers style icons using CSS instead of overriding fill colors.

Expand All @@ -29,7 +29,7 @@ Unless icons are a brand logo (e.g. the Mastercard logo), all SVG fills should a

You can test this by running Storybook and changing the icons color on the [Icons page](http://localhost:6006/?path=/docs/features-icons--docs) (local link).

### Correct icon size
#### Correct icon size

Icons come in three sizes: `16` (16x16), `24` (24x24) and `32` (32x24).

Expand All @@ -39,7 +39,7 @@ If they don't (e.g. the SVG has `viewBox="0 0 24 25"`), check that you've copied

_(Note: this can also be a symptom of another issue with the icon's placement on the Figma canvas. See "Beware clip-path" below.)_

### Beware clip-path
#### Beware clip-path

If the SVG includes a `<g clip-path="">` element, there's a chance that the icon wasn't exported properly.

Expand Down Expand Up @@ -88,3 +88,8 @@ To fix this, copy the icon and paste it on a draft Figma file. Make sure that it
```

</details>

## Deprecating an icon

1. Use the `deprecation` field in the icons manifest file at [`packages/icons/manifest.json`](https://github.com/sumup-oss/circuit-ui/blob/9146e47a21dcd6880f437d1a47a0c54d5a164bfd/packages/icons/manifest.json) to add a deprecation notice for the icon. Ideally, the notice should include a reason and recommend an alternative. The field supports markdown syntax. Add a [changeset](https://circuit.sumup.com/?path=/docs/contributing-release-process--docs#changesets) to release the change in a minor version.
2. In the next major version of `@sumup/icons`, remove the icon from the manifest and delete the SVG.
3 changes: 2 additions & 1 deletion packages/icons/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
{
"name": "add_items",
"category": "Action",
"size": "24"
"size": "24",
"deprecation": "Use the `Add` or `Items` icons instead."
},
{
"name": "chevron_down",
Expand Down
6 changes: 2 additions & 4 deletions packages/icons/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,9 @@
"@babel/preset-env": "^7.21.5",
"@babel/preset-react": "^7.18.6",
"@types/babel__core": "^7.20.0",
"@types/dedent": "^0.7.0",
"@types/lodash": "^4.14.194",
"@types/prettier": "^2.7.2",
"babel-plugin-inline-react-svg": "^2.0.2",
"dedent": "^0.7.0",
"lodash": "^4.17.21",
"prettier": "^2.8.8",
"ts-node": "^10.9.1",
"ts-node-dev": "^2.0.0",
"typescript": "^5.0.4"
Expand Down
63 changes: 38 additions & 25 deletions packages/icons/scripts/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@
import fs from 'fs';
import path from 'path';

import dedent from 'dedent';
import { entries, flow, groupBy, map } from 'lodash/fp';
connor-baer marked this conversation as resolved.
Show resolved Hide resolved
import prettier from 'prettier';
import { transformSync } from '@babel/core';

import manifest from '../manifest.json';
Expand All @@ -26,23 +25,29 @@ const BASE_DIR = path.join(__dirname, '..');
const ICON_DIR = path.join(BASE_DIR, './web/v2');
const DIST_DIR = path.join(BASE_DIR, 'dist');

enum IconSize {
SIZE_16 = '16',
SIZE_24 = '24',
SIZE_32 = '32',
}

type Icon = {
name: string;
category: string;
size: IconSize;
size: '16' | '24' | '32';
deprecation?: string;
};

type Component = {
name: string;
icons: Icon[];
deprecation?: string;
};

function createDeprecationComment(deprecation?: string) {
if (!deprecation) {
return '';
}
return `
/**
* @deprecated ${deprecation}
*/`;
}

function getComponentName(name: string): string {
// Split on non-word characters
const words = name.split(/[^a-z0-9]/i);
Expand Down Expand Up @@ -78,17 +83,16 @@ function buildComponentFile(component: Component): string {
/**
* TODO look into whether we still need the React import here
*/
return dedent`
return `
import React from 'react';
${iconImports.join('\n')}

const sizeMap = {
${sizeMap.join('\n')}
}

export const ${
component.name
} = ({ size = '${defaultSize}', ...props }) => {
${createDeprecationComment(component.deprecation)}
export function ${component.name}({ size = '${defaultSize}', ...props }) {
const Icon = sizeMap[size] || sizeMap['${defaultSize}'];

if (
Expand All @@ -114,11 +118,13 @@ function buildDeclarationFile(components: Component[]): string {
const declarationStatements = components.map((component) => {
const sizes = component.icons.map(({ size }) => `'${size}'`).sort();
const SizesType = sizes.join(' | ');
return `declare const ${component.name}: FC<IconProps<${SizesType}>>;`;
return `
${createDeprecationComment(component.deprecation)}
declare const ${component.name}: FC<IconProps<${SizesType}>>;`;
});
const exportNames = components.map((file) => file.name);
return dedent`
import { FC, SVGProps } from 'react';
return `
import type { FC, SVGProps } from 'react';

export interface IconProps<Sizes = '16' | '24' | '32'> extends SVGProps<SVGSVGElement> {
/**
Expand All @@ -136,6 +142,7 @@ function buildDeclarationFile(components: Component[]): string {
name: string;
category: string;
size: '16' | '24' | '32';
deprecation?: boolean;
}[];
};
`;
Expand Down Expand Up @@ -166,25 +173,31 @@ function transpileModule(fileName: string, code: string): void {
function writeFile(dir: string, fileName: string, fileContent: string): void {
const filePath = path.join(dir, fileName);
const directory = path.dirname(filePath);
const formattedContent = prettier.format(fileContent, { filepath: filePath });
if (directory && directory !== '.') {
fs.mkdirSync(directory, { recursive: true });
}
return fs.writeFile(filePath, fileContent, { flag: 'w' }, (err) => {
return fs.writeFile(filePath, formattedContent, { flag: 'w' }, (err) => {
if (err) {
throw err;
}
});
}

function main(): void {
const components = flow(
groupBy('name'),
entries,
map((group: [string, Icon[]]) => ({
name: getComponentName(group[0]),
icons: group[1],
})),
)(manifest.icons) as Component[];
const icons = manifest.icons as Icon[];
const iconsByName = icons.reduce((acc, icon) => {
acc[icon.name] = acc[icon.name] || [];
acc[icon.name].push(icon);
return acc;
}, {} as Record<string, Icon[]>);
const components = Object.entries(iconsByName).map(
([name, icons]): Component => ({
name: getComponentName(name),
icons,
deprecation: icons.find((icon) => icon.deprecation)?.deprecation,
}),
);

const indexRaw = buildIndexFile(components);
const declarationFile = buildDeclarationFile(components);
Expand Down