Skip to content

Commit

Permalink
feat: add missing icons and enforce icon sizes (#3702)
Browse files Browse the repository at this point in the history
  • Loading branch information
sashuk committed Jul 11, 2023
1 parent 9944a6e commit 10db2ff
Show file tree
Hide file tree
Showing 32 changed files with 909 additions and 11 deletions.
8 changes: 8 additions & 0 deletions .changeset/curvy-bananas-live.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@toptal/picasso': major
---

### Icon

- the `Resouces24` icon was renamed to `Resources24`, please find and replace its occurences in the code
- newly added icons have to have both `16` and `24` pixels variants (according to BASE)
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@

yarn lint-staged
yarn syncpack:list || (echo "you can use \033[0;32myarn syncpack:fix \033[0mto sync versions automatically or do it manually" && return 1)
yarn check:icon-sizes
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ To add a new icon to `@toptal/picasso` or pictogram to `@toptal/picasso-pictogra

1. Prepare your SVG:
- Make sure that it has `viewBox` attribute specified
- Make sure that `viewBox` size is `0 0 16 16` for icon and `0 0 64 64` for pictogram (be careful this isn't just a simple value set!)
- Make sure that `viewBox` sizes are `0 0 16 16` and `0 0 24 24` for icon (there should always be two icon variants) and `0 0 64 64` for pictogram (be careful this isn't just a simple value set!)
- Make sure all paths are expanded and strokes are not used
2. Add your SVG file(s) to the Picasso project:
```bash
Expand Down
72 changes: 72 additions & 0 deletions bin/check-icon-sizes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
const fs = require('fs')
const path = require('path')
const { execSync } = require('child_process')

/**
* Script checks if all icons have 16 and 24 pixels variants.
*/

const ICON_COMPONENTS_DIRECTORY = 'packages/picasso/src/Icon'
// TODO: add missing icons and remove ability to ignore icons
const IGNORED_ICONS = ['Ach', 'CreditCard']

const getIconName = iconFileName => iconFileName.replace(/(16|24).tsx/, '')

const getChangedFiles = () => {
const command = `git diff --name-only --cached`
const diffOutput = execSync(command).toString()

return diffOutput.toString().split('\n').filter(Boolean)
}

const checkIfIconIsComplete = (iconName, icons) =>
icons.indexOf(`${iconName}16.tsx`) > -1 &&
icons.indexOf(`${iconName}24.tsx`) > -1

const findIncompleteIcons = () => {
const changedFiles = getChangedFiles()
const iconsWereChanged =
changedFiles.filter(fileName =>
fileName.startsWith(ICON_COMPONENTS_DIRECTORY)
).length > 0

if (!iconsWereChanged) {
process.exit(0)
}

const iconFileNames = fs
.readdirSync(ICON_COMPONENTS_DIRECTORY)
.filter(
file => path.extname(file) === '.tsx' && file.match(/(16|24)\.tsx$/)
)

const incompleteIcons = []

iconFileNames.forEach(iconFileName => {
const iconName = getIconName(iconFileName)

if (
IGNORED_ICONS.indexOf(iconName) === -1 &&
!checkIfIconIsComplete(iconName, iconFileNames)
) {
if (incompleteIcons.indexOf(iconFileName)) {
incompleteIcons.push(iconName)
}
}
})

return incompleteIcons
}

const incompleteIcons = findIncompleteIcons()

if (incompleteIcons.length > 0) {
console.error(
`The following icons need to have both 16 and 24 pixels variants generated:\n${incompleteIcons.join(
'\n'
)}`
)
process.exit(1)
}

process.exit(0)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"build:package": "lerna run build:package",
"build:storybook": "build-storybook -c .storybook -o build/storybook --quiet",
"circularity": "madge --circular packages/*/src",
"check:icon-sizes": "node ./bin/check-icon-sizes",
"generate:component": "davinci-code new component",
"generate:example": "davinci-code new example",
"generate:svg-components": "yarn generate:icons && yarn generate:pictograms",
Expand Down
66 changes: 66 additions & 0 deletions packages/picasso/src/Icon/Attachment24.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { Ref } from 'react'
import React, { forwardRef } from 'react'
import cx from 'classnames'
import { makeStyles } from '@material-ui/core/styles'
import type { StandardProps } from '@toptal/picasso-shared'

import kebabToCamelCase from '../utils/kebab-to-camel-case'
import styles from './styles'
const BASE_SIZE = 24

type ScaleType = 1 | 2 | 3 | 4
export interface Props extends StandardProps {
scale?: ScaleType
color?: string
base?: number
}
const useStyles = makeStyles(styles, {
name: 'PicassoSvgAttachment24',
})
const SvgAttachment24 = forwardRef(function SvgAttachment24(
props: Props,
ref: Ref<SVGSVGElement>
) {
const {
className,
style = {},
color,
scale,
base,
'data-testid': testId,
} = props
const classes: Record<string, string> = useStyles(props)
const classNames = [classes.root, className]
const scaledSize = base || BASE_SIZE * Math.ceil(scale || 1)
const colorClassName = kebabToCamelCase(`${color}`)

if (classes[colorClassName]) {
classNames.push(classes[colorClassName])
}

const svgStyle = {
minWidth: `${scaledSize}px`,
minHeight: `${scaledSize}px`,
...style,
}

return (
<svg
fill='none'
viewBox='0 0 24 24'
className={cx(...classNames)}
style={svgStyle}
ref={ref}
data-testid={testId}
>
<path
fillRule='evenodd'
d='M19.63 3.366a6.5 6.5 0 0 0-9.193 0L4.073 9.73l.707.707 6.364-6.364.16-.153a5.5 5.5 0 0 1 7.618 7.931l-6.363 6.364-2.122 2.122-.14.132a3.5 3.5 0 0 1-4.81-5.082l2.122-2.121 6.364-6.364.107-.098a1.5 1.5 0 0 1 2.014 2.219L9.73 15.387l.707.707 6.364-6.364.113-.12a2.5 2.5 0 0 0-3.648-3.415l-6.364 6.364-2.122 2.12-.146.154a4.5 4.5 0 0 0 6.51 6.21l2.122-2.12 6.364-6.364.162-.168a6.5 6.5 0 0 0-.162-9.025Z'
clipRule='evenodd'
/>
</svg>
)
})

SvgAttachment24.displayName = 'SvgAttachment24'
export default SvgAttachment24
62 changes: 62 additions & 0 deletions packages/picasso/src/Icon/Bold24.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { Ref } from 'react'
import React, { forwardRef } from 'react'
import cx from 'classnames'
import { makeStyles } from '@material-ui/core/styles'
import type { StandardProps } from '@toptal/picasso-shared'

import kebabToCamelCase from '../utils/kebab-to-camel-case'
import styles from './styles'
const BASE_SIZE = 24

type ScaleType = 1 | 2 | 3 | 4
export interface Props extends StandardProps {
scale?: ScaleType
color?: string
base?: number
}
const useStyles = makeStyles(styles, {
name: 'PicassoSvgBold24',
})
const SvgBold24 = forwardRef(function SvgBold24(
props: Props,
ref: Ref<SVGSVGElement>
) {
const {
className,
style = {},
color,
scale,
base,
'data-testid': testId,
} = props
const classes: Record<string, string> = useStyles(props)
const classNames = [classes.root, className]
const scaledSize = base || BASE_SIZE * Math.ceil(scale || 1)
const colorClassName = kebabToCamelCase(`${color}`)

if (classes[colorClassName]) {
classNames.push(classes[colorClassName])
}

const svgStyle = {
minWidth: `${scaledSize}px`,
minHeight: `${scaledSize}px`,
...style,
}

return (
<svg
fill='none'
viewBox='0 0 24 24'
className={cx(...classNames)}
style={svgStyle}
ref={ref}
data-testid={testId}
>
<path d='M5 1h8a6 6 0 0 1 4.276 10.209A6.5 6.5 0 0 1 13.5 23H5V1Zm8.5 12H8v7h5.5a3.5 3.5 0 0 0 .192-6.995L13.5 13ZM13 4H8v6h5a3 3 0 0 0 .176-5.995L13 4Z' />
</svg>
)
})

SvgBold24.displayName = 'SvgBold24'
export default SvgBold24
66 changes: 66 additions & 0 deletions packages/picasso/src/Icon/DropdownArrows24.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { Ref } from 'react'
import React, { forwardRef } from 'react'
import cx from 'classnames'
import { makeStyles } from '@material-ui/core/styles'
import type { StandardProps } from '@toptal/picasso-shared'

import kebabToCamelCase from '../utils/kebab-to-camel-case'
import styles from './styles'
const BASE_SIZE = 24

type ScaleType = 1 | 2 | 3 | 4
export interface Props extends StandardProps {
scale?: ScaleType
color?: string
base?: number
}
const useStyles = makeStyles(styles, {
name: 'PicassoSvgDropdownArrows24',
})
const SvgDropdownArrows24 = forwardRef(function SvgDropdownArrows24(
props: Props,
ref: Ref<SVGSVGElement>
) {
const {
className,
style = {},
color,
scale,
base,
'data-testid': testId,
} = props
const classes: Record<string, string> = useStyles(props)
const classNames = [classes.root, className]
const scaledSize = base || BASE_SIZE * Math.ceil(scale || 1)
const colorClassName = kebabToCamelCase(`${color}`)

if (classes[colorClassName]) {
classNames.push(classes[colorClassName])
}

const svgStyle = {
minWidth: `${scaledSize}px`,
minHeight: `${scaledSize}px`,
...style,
}

return (
<svg
fill='none'
viewBox='0 0 24 24'
className={cx(...classNames)}
style={svgStyle}
ref={ref}
data-testid={testId}
>
<path
fillRule='evenodd'
d='m11.3 3.007.707-.707.707.707 5 5-.707.707-5-5-5 5-.707-.707 5-5Zm0 18-5-5 .707-.707 5 5 5-5 .707.707-5 5-.707.707-.707-.707Z'
clipRule='evenodd'
/>
</svg>
)
})

SvgDropdownArrows24.displayName = 'SvgDropdownArrows24'
export default SvgDropdownArrows24
62 changes: 62 additions & 0 deletions packages/picasso/src/Icon/Italic24.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import type { Ref } from 'react'
import React, { forwardRef } from 'react'
import cx from 'classnames'
import { makeStyles } from '@material-ui/core/styles'
import type { StandardProps } from '@toptal/picasso-shared'

import kebabToCamelCase from '../utils/kebab-to-camel-case'
import styles from './styles'
const BASE_SIZE = 24

type ScaleType = 1 | 2 | 3 | 4
export interface Props extends StandardProps {
scale?: ScaleType
color?: string
base?: number
}
const useStyles = makeStyles(styles, {
name: 'PicassoSvgItalic24',
})
const SvgItalic24 = forwardRef(function SvgItalic24(
props: Props,
ref: Ref<SVGSVGElement>
) {
const {
className,
style = {},
color,
scale,
base,
'data-testid': testId,
} = props
const classes: Record<string, string> = useStyles(props)
const classNames = [classes.root, className]
const scaledSize = base || BASE_SIZE * Math.ceil(scale || 1)
const colorClassName = kebabToCamelCase(`${color}`)

if (classes[colorClassName]) {
classNames.push(classes[colorClassName])
}

const svgStyle = {
minWidth: `${scaledSize}px`,
minHeight: `${scaledSize}px`,
...style,
}

return (
<svg
fill='none'
viewBox='0 0 24 24'
className={cx(...classNames)}
style={svgStyle}
ref={ref}
data-testid={testId}
>
<path d='M17 1v1h-3.067l-2.858 20H14v1H7v-1h3.066l2.857-20H10V1h7Z' />
</svg>
)
})

SvgItalic24.displayName = 'SvgItalic24'
export default SvgItalic24
Loading

0 comments on commit 10db2ff

Please sign in to comment.