diff --git a/.changeset/early-drinks-love.md b/.changeset/early-drinks-love.md deleted file mode 100644 index 95ec581ed48..00000000000 --- a/.changeset/early-drinks-love.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -'@primer/components': major ---- - -Removes deprecated presentational theme variables in favor of _functional variables_ for styling components that are consistent across multiple themes. - -## Migration guide - -If you don't use any color-related system props (e.g. `color`, `bg`, `borderColor`), all components should work without changes. If you're using color-related system props, you'll need to update them to use the new functional variables. Reference the tables below to see how old variables map to new functional variables. - -If you have any questions, feel free to reach out in the #design-systems channel. - -#### Text - -| `v25` | `v26` | -| ------------------------ | ------------------------ | -| `color="text.gray"` | `color="text.secondary"` | -| `color="text.grayLight"` | `color="text.tertiary"` | -| `color="text.grayDark"` | `color="text.primary"` | -| `color="text.red"` | `color="text.danger"` | -| `color="text.white"` | `color="text.inverse"` | -| `color="gray.6"` | `color="text.secondary"` | -| `color="gray.5"` | `color="text.tertiary"` | -| `color="gray.9"` | `color="text.primary"` | -| `color="red.6"` | `color="text.danger"` | -| `color="white"` | `color="text.inverse"` | -| `color="blue.5"` | `color="text.link"` | -| `color="gray.4"` | `color="text.disabled"` | -| `color="green.5"` | `color="text.success"` | -| `color="yellow.8"` | `color="text.warning"` | - -#### Icon - -| `v25` | `v25` | -| ------------------ | ------------------------ | -| `color="gray.9"` | `color="icon.primary"` | -| `color="gray.6"` | `color="icon.secondary"` | -| `color="gray.4"` | `color="icon.tertiary"` | -| `color="blue.5"` | `color="icon.info"` | -| `color="red.5"` | `color="icon.danger"` | -| `color="green.6"` | `color="icon.success"` | -| `color="yellow.8"` | `color="icon.warning"` | - -#### Border - -| `v25` | `v26` | -| --------------------------------- | ------------------------------- | -| `borderColor="border.blue"` | `borderColor="border.info"` | -| `borderColor="border.blueLight"` | n/a | -| `borderColor="border.grayLight"` | `borderColor="border.primary"` | -| `borderColor="border.grayDark"` | `borderColor="border.tertiary"` | -| `borderColor="border.grayDarker"` | n/a | -| `borderColor="border.green"` | `borderColor="border.success"` | -| `borderColor="border.greenLight"` | n/a | -| `borderColor="border.purple"` | n/a | -| `borderColor="border.red"` | `borderColor="border.danger"` | -| `borderColor="border.redLight"` | n/a | -| `borderColor="border.white"` | `borderColor="border.inverse"` | -| `borderColor="border.whiteFace"` | n/a | -| `borderColor="border.yellow"` | `borderColor="border.warning"` | -| `borderColor="border.blackFade"` | `borderColor="fade.fg15"` | -| `borderColor="border.whiteFade"` | `borderCOlor="fade.white15"` | -| `borderColor="blue.5"` | `borderColor="border.info"` | -| `borderColor="gray.2"` | `borderColor="border.primary"` | -| `borderColor="gray.3"` | `borderColor="border.tertiary"` | -| `borderColor="green.4"` | `borderColor="border.success"` | -| `borderColor="red.5"` | `borderColor="border.danger"` | -| `borderColor="white"` | `borderColor="border.inverse"` | - -#### Background - -| `v25` | `v26` | -| ------------------- | ------------------------ | -| `bg="white"` | `bg="bg.primary"` | -| `bg="bg.grayLight"` | `bg="bg.secondary"` | -| `bg="bg.gray"` | `bg="bg.tertiary"` | -| `bg="bg.grayDark"` | `bg="bg.canvasInverse"` | -| `bg="blue.0"` | `bg="bg.info"` | -| `bg="blue.5"` | `bg="bg.infoInverse"` | -| `bg="red.0"` | `bg="bg.danger"` | -| `bg="red.5"` | `bg="bg.dangerInverse"` | -| `bg="green.1"` | `bg="bg.success"` | -| `bg="green.5"` | `bg="bg.successInverse"` | - -#### Labels - -_Note the change in pluralization from 'labels' to 'label'._ - -| `v25` | `v26` | -| ----------------------------- | ------------------------------------- | -| `color="labels.grayDarkText"` | `color="label.primary.text` | -| `borderColor="labels.gray"` | `borderColor="label.primary.border` | -| `color="labels.grayText"` | `color="label.secondary.text` | -| `borderColor="labels.gray"` | `borderColor="label.secondary.border` | -| `color="labels.blueText"` | `color="label.info.text` | -| `borderColor="labels.blue"` | `borderColor="label.info.border` | -| `color="labels.greenText"` | `color="label.success.text` | -| `borderColor="labels.green"` | `borderColor="label.success.border` | -| `color="labels.yellowText"` | `color="label.warning.text` | -| `borderColor="labels.yellow"` | `borderColor="label.warning.border` | -| `color="labels.redText"` | `color="label.danger.text` | -| `borderColor="labels.red"` | `borderColor="label.danger.border` | -| `color="labels.orangeText"` | `color="label.primary.text` | -| `borderColor="labels.orange"` | `borderColor="label.primary.text` | -| `color="labels.pinkText"` | n/a | -| `borderColor="labels.pink"` | n/a | -| `color="labels.purpleText"` | n/a | -| `borderColor="labels.purple"` | n/a | - -#### Counters - -| `v25` | `v26` | -| --------------------- | -------------------- | -| `scheme="gray"` | `scheme="primary"` | -| `scheme="gray-light"` | `scheme="secondary"` | - -#### Timeline - -| `v25` | `v26` | -| ----------------------------------------- | ----------------------------- | -| `bg="red.5"` | `bg="prState.closed.bg"` | -| `bg="green.5"` | `bg="prState.open.bg"` | -| `bg="purple.5"` | `bg="prState.merged.bg"` | -| `bg="gray.5"` | `bg="prState.draft.bg"` | -| `color="white"` (context: closed PR icon) | `color="prState.closed.text"` | -| `color="white"` (context: open PR icon) | `color="prState.open.text"` | -| `color="white"` (context: merged PR icon) | `color="prState.merged.text"` | -| `color="white"` (context: merged PR icon) | `color="prState.draft.text"` | diff --git a/.eslintrc.json b/.eslintrc.json index f7511ce506b..e9cadd12f9e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -60,7 +60,7 @@ "files": ["**/*.ts", "**/*.tsx"], "extends": ["plugin:@typescript-eslint/recommended"], "rules": { - "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/no-explicit-any": 2, "@typescript-eslint/explicit-module-boundary-types": 0, "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 687235e1bfe..7943e15bbfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,134 @@ # @primer/components +## 26.0.0 + +### Major Changes + +- [`016a273f`](https://github.com/primer/components/commit/016a273fde30f0185e23309e1a39c1bc034174f8) [#1115](https://github.com/primer/components/pull/1115) Thanks [@VanAnderson](https://github.com/VanAnderson)! - Removes deprecated presentational theme variables in favor of _functional variables_ for styling components that are consistent across multiple themes. + + ## Migration guide + + If you don't use any color-related system props (e.g. `color`, `bg`, `borderColor`), all components should work without changes. If you're using color-related system props, you'll need to update them to use the new functional variables. Reference the tables below to see how old variables map to new functional variables. + + If you have any questions, feel free to reach out in the #design-systems channel. + + #### Text + + | `v25` | `v26` | + | ------------------------ | ------------------------ | + | `color="text.gray"` | `color="text.secondary"` | + | `color="text.grayLight"` | `color="text.tertiary"` | + | `color="text.grayDark"` | `color="text.primary"` | + | `color="text.red"` | `color="text.danger"` | + | `color="text.white"` | `color="text.inverse"` | + | `color="gray.6"` | `color="text.secondary"` | + | `color="gray.5"` | `color="text.tertiary"` | + | `color="gray.9"` | `color="text.primary"` | + | `color="red.6"` | `color="text.danger"` | + | `color="white"` | `color="text.inverse"` | + | `color="blue.5"` | `color="text.link"` | + | `color="gray.4"` | `color="text.disabled"` | + | `color="green.5"` | `color="text.success"` | + | `color="yellow.8"` | `color="text.warning"` | + + #### Icon + + | `v25` | `v25` | + | ------------------ | ------------------------ | + | `color="gray.9"` | `color="icon.primary"` | + | `color="gray.6"` | `color="icon.secondary"` | + | `color="gray.4"` | `color="icon.tertiary"` | + | `color="blue.5"` | `color="icon.info"` | + | `color="red.5"` | `color="icon.danger"` | + | `color="green.6"` | `color="icon.success"` | + | `color="yellow.8"` | `color="icon.warning"` | + + #### Border + + | `v25` | `v26` | + | --------------------------------- | ------------------------------- | + | `borderColor="border.blue"` | `borderColor="border.info"` | + | `borderColor="border.blueLight"` | n/a | + | `borderColor="border.grayLight"` | `borderColor="border.primary"` | + | `borderColor="border.grayDark"` | `borderColor="border.tertiary"` | + | `borderColor="border.grayDarker"` | n/a | + | `borderColor="border.green"` | `borderColor="border.success"` | + | `borderColor="border.greenLight"` | n/a | + | `borderColor="border.purple"` | n/a | + | `borderColor="border.red"` | `borderColor="border.danger"` | + | `borderColor="border.redLight"` | n/a | + | `borderColor="border.white"` | `borderColor="border.inverse"` | + | `borderColor="border.whiteFace"` | n/a | + | `borderColor="border.yellow"` | `borderColor="border.warning"` | + | `borderColor="border.blackFade"` | `borderColor="fade.fg15"` | + | `borderColor="border.whiteFade"` | `borderCOlor="fade.white15"` | + | `borderColor="blue.5"` | `borderColor="border.info"` | + | `borderColor="gray.2"` | `borderColor="border.primary"` | + | `borderColor="gray.3"` | `borderColor="border.tertiary"` | + | `borderColor="green.4"` | `borderColor="border.success"` | + | `borderColor="red.5"` | `borderColor="border.danger"` | + | `borderColor="white"` | `borderColor="border.inverse"` | + + #### Background + + | `v25` | `v26` | + | ------------------- | ------------------------ | + | `bg="white"` | `bg="bg.primary"` | + | `bg="bg.grayLight"` | `bg="bg.secondary"` | + | `bg="bg.gray"` | `bg="bg.tertiary"` | + | `bg="bg.grayDark"` | `bg="bg.canvasInverse"` | + | `bg="blue.0"` | `bg="bg.info"` | + | `bg="blue.5"` | `bg="bg.infoInverse"` | + | `bg="red.0"` | `bg="bg.danger"` | + | `bg="red.5"` | `bg="bg.dangerInverse"` | + | `bg="green.1"` | `bg="bg.success"` | + | `bg="green.5"` | `bg="bg.successInverse"` | + + #### Labels + + _Note the change in pluralization from 'labels' to 'label'._ + + | `v25` | `v26` | + | ----------------------------- | ------------------------------------- | + | `color="labels.grayDarkText"` | `color="label.primary.text` | + | `borderColor="labels.gray"` | `borderColor="label.primary.border` | + | `color="labels.grayText"` | `color="label.secondary.text` | + | `borderColor="labels.gray"` | `borderColor="label.secondary.border` | + | `color="labels.blueText"` | `color="label.info.text` | + | `borderColor="labels.blue"` | `borderColor="label.info.border` | + | `color="labels.greenText"` | `color="label.success.text` | + | `borderColor="labels.green"` | `borderColor="label.success.border` | + | `color="labels.yellowText"` | `color="label.warning.text` | + | `borderColor="labels.yellow"` | `borderColor="label.warning.border` | + | `color="labels.redText"` | `color="label.danger.text` | + | `borderColor="labels.red"` | `borderColor="label.danger.border` | + | `color="labels.orangeText"` | `color="label.primary.text` | + | `borderColor="labels.orange"` | `borderColor="label.primary.text` | + | `color="labels.pinkText"` | n/a | + | `borderColor="labels.pink"` | n/a | + | `color="labels.purpleText"` | n/a | + | `borderColor="labels.purple"` | n/a | + + #### Counters + + | `v25` | `v26` | + | --------------------- | -------------------- | + | `scheme="gray"` | `scheme="primary"` | + | `scheme="gray-light"` | `scheme="secondary"` | + + #### Timeline + + | `v25` | `v26` | + | ----------------------------------------- | ----------------------------- | + | `bg="red.5"` | `bg="prState.closed.bg"` | + | `bg="green.5"` | `bg="prState.open.bg"` | + | `bg="purple.5"` | `bg="prState.merged.bg"` | + | `bg="gray.5"` | `bg="prState.draft.bg"` | + | `color="white"` (context: closed PR icon) | `color="prState.closed.text"` | + | `color="white"` (context: open PR icon) | `color="prState.open.text"` | + | `color="white"` (context: merged PR icon) | `color="prState.merged.text"` | + | `color="white"` (context: merged PR icon) | `color="prState.draft.text"` | + ## 25.0.0 ### Major Changes diff --git a/docs/.eslintrc b/docs/.eslintrc new file mode 100644 index 00000000000..e69de29bb2d diff --git a/package.json b/package.json index 5b73aa84aa6..e9105f12a28 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@primer/components", - "version": "25.0.0", + "version": "26.0.0", "description": "Primer react components", "main": "lib/index.js", "module": "lib-esm/index.js", diff --git a/src/Caret.tsx b/src/Caret.tsx index 59e209722b4..d81b14983c3 100644 --- a/src/Caret.tsx +++ b/src/Caret.tsx @@ -1,6 +1,7 @@ import React from 'react' import {ThemeContext} from 'styled-components' import {style} from 'styled-system' +import {Theme} from './ThemeProvider' type Location = | 'top' @@ -56,7 +57,7 @@ export type CaretProps = { borderWidth?: string | number size?: number location?: Location - theme?: any + theme?: Theme } function Caret(props: CaretProps) { diff --git a/src/DropdownStyles.ts b/src/DropdownStyles.ts index 0dc528a951c..47c9a6cd4ed 100644 --- a/src/DropdownStyles.ts +++ b/src/DropdownStyles.ts @@ -1,6 +1,7 @@ import {get} from './constants' +import {Theme} from './ThemeProvider' -const getDirectionStyles = (theme: any, direction: 'ne' | 'e' | 'se' | 's' | 'sw' | 'w') => { +const getDirectionStyles = (theme: Theme, direction: 'ne' | 'e' | 'se' | 's' | 'sw' | 'w') => { const map = { w: ` top: 0; diff --git a/src/SelectMenu/hooks/useKeyboardNav.js b/src/SelectMenu/hooks/useKeyboardNav.js index 4675d13d157..3ccdf3bd210 100644 --- a/src/SelectMenu/hooks/useKeyboardNav.js +++ b/src/SelectMenu/hooks/useKeyboardNav.js @@ -70,6 +70,7 @@ function useKeyboardNav(details, open, setOpen) { } } break + default: } }, [details, open, setOpen] diff --git a/src/ThemeProvider.tsx b/src/ThemeProvider.tsx index 6f36a806210..6979ffb148a 100644 --- a/src/ThemeProvider.tsx +++ b/src/ThemeProvider.tsx @@ -7,7 +7,8 @@ const defaultColorMode = 'day' const defaultDayScheme = 'light' const defaultNightScheme = 'dark' -type Theme = any +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type Theme = {[key: string]: any} type ColorMode = 'day' | 'night' type ColorModeWithAuto = ColorMode | 'auto' diff --git a/src/__tests__/BreadcrumbItem.tsx b/src/__tests__/BreadcrumbItem.tsx index 6d18c19d4fc..176213ff2e1 100644 --- a/src/__tests__/BreadcrumbItem.tsx +++ b/src/__tests__/BreadcrumbItem.tsx @@ -26,7 +26,7 @@ describe('Breadcrumb.Item', () => { }) it('adds activeClassName={SELECTED_CLASS} when it gets a "to" prop', () => { - const Link = ({theme: _ignoredTheme, ...props}: any) =>
+ const Link = ({theme: _ignoredTheme, ...props}: Record) =>
expect(render()).toMatchSnapshot() }) }) diff --git a/src/__tests__/Pagination/PaginationModel.tsx b/src/__tests__/Pagination/PaginationModel.tsx index 30bb2183ee8..fb5b7341f07 100644 --- a/src/__tests__/Pagination/PaginationModel.tsx +++ b/src/__tests__/Pagination/PaginationModel.tsx @@ -1,11 +1,13 @@ import 'babel-polyfill' import {buildPaginationModel} from '../../Pagination/model' +// eslint-disable-next-line @typescript-eslint/no-explicit-any function first(array: Array, count = 1) { const slice = array.slice(0, count) return count === 1 ? slice[0] : slice } +// eslint-disable-next-line @typescript-eslint/no-explicit-any function last(array: Array, count = 1) { const len = array.length const slice = array.slice(len - count, len) diff --git a/src/__tests__/SelectMenu.tsx b/src/__tests__/SelectMenu.tsx index 4bf822be5e4..24abc9ba01b 100644 --- a/src/__tests__/SelectMenu.tsx +++ b/src/__tests__/SelectMenu.tsx @@ -13,6 +13,7 @@ const BasicSelectMenu = ({ align = 'left' }: { onClick?: SelectMenuItemProps['onClick'] + // eslint-disable-next-line @typescript-eslint/no-explicit-any as?: any align?: SelectMenuModalProps['align'] }) => { diff --git a/src/__tests__/SubNavLink.tsx b/src/__tests__/SubNavLink.tsx index 42a7aa414d0..5702dfb2354 100644 --- a/src/__tests__/SubNavLink.tsx +++ b/src/__tests__/SubNavLink.tsx @@ -26,7 +26,7 @@ describe('SubNav.Link', () => { }) it('adds activeClassName={SELECTED_CLASS} when it gets a "to" prop', () => { - const Link = ({theme: _ignoredTheme, ...props}: any) =>
+ const Link = ({theme: _ignoredTheme, ...props}: Record) =>
expect(render()).toMatchSnapshot() }) }) diff --git a/src/__tests__/UnderlineNavLink.tsx b/src/__tests__/UnderlineNavLink.tsx index 204a2421eec..7051451fb3b 100644 --- a/src/__tests__/UnderlineNavLink.tsx +++ b/src/__tests__/UnderlineNavLink.tsx @@ -26,7 +26,7 @@ describe('UnderlineNav.Link', () => { }) it('adds activeClassName={SELECTED_CLASS} when it gets a "to" prop', () => { - const Link = ({theme: _ignoredTheme, ...props}: any) =>
+ const Link = ({theme: _ignoredTheme, ...props}: Record) =>
expect(render()).toMatchSnapshot() }) }) diff --git a/src/__tests__/filterObject.ts b/src/__tests__/filterObject.ts index 601aa11e4e2..0c956a2d47f 100644 --- a/src/__tests__/filterObject.ts +++ b/src/__tests__/filterObject.ts @@ -39,7 +39,7 @@ describe('filterObject', () => { } } - expect(filterObject(colors, (value: any) => isColorValue(value))).toEqual(expected) + expect(filterObject(colors, (value: unknown) => isColorValue(value))).toEqual(expected) }) it('filters out color values', () => { @@ -49,6 +49,6 @@ describe('filterObject', () => { } } - expect(filterObject(colors, (value: any) => isShadowValue(value))).toEqual(expected) + expect(filterObject(colors, (value: unknown) => isShadowValue(value))).toEqual(expected) }) }) diff --git a/src/hooks/useSafeTimeout.ts b/src/hooks/useSafeTimeout.ts index 114c0ebd085..a1c2511bbf4 100644 --- a/src/hooks/useSafeTimeout.ts +++ b/src/hooks/useSafeTimeout.ts @@ -1,6 +1,6 @@ import {useCallback, useEffect, useRef} from 'react' -type SetTimeout = (handler: TimerHandler, timeout?: number, ...args: any[]) => number +type SetTimeout = (handler: TimerHandler, timeout?: number, ...args: unknown[]) => number type ClearTimeout = (id: number) => void /** @@ -11,11 +11,14 @@ type ClearTimeout = (id: number) => void export default function useSafeTimeout(): {safeSetTimeout: SetTimeout; safeClearTimeout: ClearTimeout} { const timers = useRef>(new Set()) - const safeSetTimeout = useCallback((handler: TimerHandler, timeout?: number | undefined, ...args: any[]): number => { - const id = window.setTimeout(handler, timeout, ...args) - timers.current.add(id) - return id - }, []) + const safeSetTimeout = useCallback( + (handler: TimerHandler, timeout?: number | undefined, ...args: unknown[]): number => { + const id = window.setTimeout(handler, timeout, ...args) + timers.current.add(id) + return id + }, + [] + ) const safeClearTimeout = useCallback((id: number) => { clearTimeout(id) diff --git a/src/stories/useFocusZone.stories.tsx b/src/stories/useFocusZone.stories.tsx index ef1200217e2..378a0929988 100644 --- a/src/stories/useFocusZone.stories.tsx +++ b/src/stories/useFocusZone.stories.tsx @@ -447,7 +447,7 @@ export const ActiveDescendant = () => { bindKeys: FocusKeys.ArrowVertical, onActiveDescendantChanged: (current, previous) => { if (current) { - current.style.outline = `2px solid ${theme.colors.border.info}` + current.style.outline = `2px solid ${theme?.colors.border.info}` } if (previous) { previous.style.outline = '' diff --git a/src/theme-preval.js b/src/theme-preval.js index d8a9329309f..392a0c6202d 100644 --- a/src/theme-preval.js +++ b/src/theme-preval.js @@ -108,7 +108,8 @@ const theme = { colors: darkColors, shadows: darkShadows }, - ['dark_dimmed']: { + // eslint-disable-next-line camelcase + dark_dimmed: { colors: darkDimmedColors, shadows: darkDimmedShadows } diff --git a/src/utils/isNumeric.tsx b/src/utils/isNumeric.tsx index 6555165d725..613d627e784 100644 --- a/src/utils/isNumeric.tsx +++ b/src/utils/isNumeric.tsx @@ -1,3 +1,4 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any export default function isNumeric(n: any) { return !isNaN(parseFloat(n)) && isFinite(n) } diff --git a/src/utils/testing.tsx b/src/utils/testing.tsx index 9bb938cc061..266dc04f988 100644 --- a/src/utils/testing.tsx +++ b/src/utils/testing.tsx @@ -6,6 +6,8 @@ import Adapter from '@wojtekmaj/enzyme-adapter-react-17' import {ThemeProvider} from '..' import {default as defaultTheme} from '../theme' +type ComputedStyles = Record> + // eslint-disable-next-line @typescript-eslint/no-var-requires const readFile = promisify(require('fs').readFile) @@ -85,18 +87,18 @@ export function percent(value: number | string): string { return typeof value === 'number' ? `${value}%` : value } -export function renderStyles(node: React.ReactElement): any { +export function renderStyles(node: React.ReactElement) { const { props: {className} } = render(node) return getComputedStyles(className) } -export function getComputedStyles(className: string): Record> { +export function getComputedStyles(className: string) { const div = document.createElement('div') div.className = className - const computed = {} as any + const computed: ComputedStyles = {} for (const sheet of document.styleSheets) { // CSSRulesLists assumes every rule is a CSSRule, not a CSSStyleRule for (const rule of sheet.cssRules) { @@ -123,7 +125,7 @@ export function getComputedStyles(className: string): Record - systemPropArray: any[] + systemPropArray: unknown[] toRender?: () => React.ReactElement options?: Options } @@ -230,6 +233,7 @@ export function behavesAsComponent({Component, toRender, options}: BehavesAsComp }) } +// eslint-disable-next-line @typescript-eslint/no-explicit-any export function checkExports(path: string, exports: Record): void { it('has declared exports', () => { // eslint-disable-next-line @typescript-eslint/no-var-requires