From 0b8d7fc2d5f55f9cf8307f0f459e54cdc7e0c560 Mon Sep 17 00:00:00 2001 From: Devin Fee Date: Thu, 13 Jun 2019 02:42:22 -0700 Subject: [PATCH] moved tooltip to generic --- .size-snapshot.json | 6 +- .../components/simple-props-table/tooltip.tsx | 11 -- .../simple-props-table/type-cell.tsx | 23 ++- src/base/helpers/__tests__/tooltip.test.tsx | 135 ++++++++++++++++++ src/base/helpers/index.ts | 6 + src/base/helpers/tooltip.ts | 67 +++++++++ src/base/helpers/variables.ts | 9 ++ src/extensions/__docs__/tooltip.docs.mdx | 27 ++++ .../tooltip/__docs__/tooltip.docs.mdx | 62 -------- .../tooltip/__tests__/badge.test.tsx | 89 ------------ src/extensions/tooltip/index.ts | 1 - src/extensions/tooltip/tooltip.tsx | 80 ----------- 12 files changed, 255 insertions(+), 261 deletions(-) delete mode 100644 src/__docs__/components/simple-props-table/tooltip.tsx create mode 100644 src/base/helpers/__tests__/tooltip.test.tsx create mode 100644 src/base/helpers/tooltip.ts create mode 100644 src/extensions/__docs__/tooltip.docs.mdx delete mode 100644 src/extensions/tooltip/__docs__/tooltip.docs.mdx delete mode 100644 src/extensions/tooltip/__tests__/badge.test.tsx delete mode 100644 src/extensions/tooltip/index.ts delete mode 100644 src/extensions/tooltip/tooltip.tsx diff --git a/.size-snapshot.json b/.size-snapshot.json index a8b713c4..42ee05a6 100644 --- a/.size-snapshot.json +++ b/.size-snapshot.json @@ -81,8 +81,8 @@ "gzipped": 9217 }, "dist/rbx.umd.js": { - "bundled": 91185, - "minified": 45890, - "gzipped": 9425 + "bundled": 92904, + "minified": 46726, + "gzipped": 9618 } } diff --git a/src/__docs__/components/simple-props-table/tooltip.tsx b/src/__docs__/components/simple-props-table/tooltip.tsx deleted file mode 100644 index ce126ff4..00000000 --- a/src/__docs__/components/simple-props-table/tooltip.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from "react"; - -// todo -export type TooltipProps = { - text: React.ReactNode; - children: React.ReactNode; -}; - -export const Tooltip = ({ children, text }: TooltipProps) => ( -
{children}
-); diff --git a/src/__docs__/components/simple-props-table/type-cell.tsx b/src/__docs__/components/simple-props-table/type-cell.tsx index a76e049a..89c32a6a 100644 --- a/src/__docs__/components/simple-props-table/type-cell.tsx +++ b/src/__docs__/components/simple-props-table/type-cell.tsx @@ -1,7 +1,7 @@ import React from "react"; +import { Generic } from "src/base"; import { Table } from "src/elements"; -import { Tooltip } from "./tooltip"; import { PropDoc } from "./types"; @@ -10,17 +10,10 @@ export type TypeCellProps = { typeTip: PropDoc["typeTip"]; }; -export const TypeCell = ({ typeName, typeTip }: TypeCellProps) => { - const typeNode = - typeTip === undefined ? ( - typeName - ) : ( - {typeName} - ); - - return ( - - {typeNode} - - ); -}; +export const TypeCell = ({ typeName, typeTip }: TypeCellProps) => ( + + + {typeName} + + +); diff --git a/src/base/helpers/__tests__/tooltip.test.tsx b/src/base/helpers/__tests__/tooltip.test.tsx new file mode 100644 index 00000000..b78f6075 --- /dev/null +++ b/src/base/helpers/__tests__/tooltip.test.tsx @@ -0,0 +1,135 @@ +import { + makePropTypes, + makeValidatingTransform, +} from "src/base/helpers/tooltip"; +import { DEFAULTS } from "src/base/helpers/variables"; +import { tuple } from "../../../utils"; + +import { + validateBoolPropType, + validateOneOfPropType, + validatePropType, +} from "src/__tests__/testing"; +import { + testItShouldNotSetClassNameOnEmpty, + testItShouldPreserveCustomClassName, + testItShouldPreserveUnknown, + testItShouldUseDefaultLocationProp, +} from "./testing"; + +const CNAME = "foo"; +const LOC = "prop"; + +describe("Tooltip helpers", () => { + const propTypes = makePropTypes(); + const vtfunc = makeValidatingTransform(); + + describe("propTypes", () => { + validateBoolPropType(propTypes, "tooltipActive"); + validateOneOfPropType(propTypes, "tooltipColor", DEFAULTS.colors); + validateBoolPropType(propTypes, "tooltipMultiline"); + validateOneOfPropType( + propTypes, + "tooltipPosition", + DEFAULTS.tooltipPositions, + ); + validatePropType(propTypes, "tooltipResponsive", [ + ...DEFAULTS.breakpoints + .map(breakpoint => + DEFAULTS.tooltipPositions.map(tooltipPosition => ({ + descriptor: `${breakpoint}-${tooltipPosition}`, + valid: true, + value: { [breakpoint]: tooltipPosition }, + })), + ) + .reduce((acc, cv) => [...acc, ...cv], []), + { + error: new RegExp(`Warning.+Failed prop.+ \`tooltipResponsive\``), + valid: false, + value: false, + }, + { + error: new RegExp(`Warning.+Failed prop.+ \`tooltipResponsive.foo\``), + valid: false, + value: { foo: "asdf" }, + }, + ]); + testItShouldUseDefaultLocationProp(vtfunc, { + tooltipPosition: "__UNKNOWN", + }); + + describe("custom", () => { + const customTooltipPositions = tuple("a", "b"); + const customPropTypes = makePropTypes({ + tooltipPositions: customTooltipPositions, + }); + + validateOneOfPropType( + customPropTypes, + "tooltipPosition", + customTooltipPositions, + ); + }); + }); + + describe("transform", () => { + testItShouldPreserveUnknown(vtfunc); + testItShouldNotSetClassNameOnEmpty(vtfunc); + testItShouldPreserveCustomClassName(vtfunc); + + it("should should get tooltip className and data-tooltip", () => { + expect(vtfunc({ tooltip: "foobar" }, CNAME, LOC)).toEqual({ + className: "tooltip", + "data-tooltip": "foobar", + }); + }); + + [false, true].map(tooltipActive => { + it(`should ${tooltipActive ? "" : "not "}be tooltipActive`, () => { + expect(vtfunc({ tooltipActive }, CNAME, LOC)).toEqual({ + className: tooltipActive ? "is-tooltip-active" : "", + }); + }); + }); + + DEFAULTS.colors.map(color => { + it(`should be ${color}`, () => { + expect(vtfunc({ tooltipColor: color }, CNAME, LOC)).toEqual({ + className: `is-tooltip-${color}`, + }); + }); + }); + + [false, true].map(tooltipMultiline => { + it(`should ${tooltipMultiline ? "" : "not "}be tooltipMultiline`, () => { + expect(vtfunc({ tooltipMultiline }, CNAME, LOC)).toEqual({ + className: tooltipMultiline ? "is-tooltip-multiline" : "", + }); + }); + }); + + DEFAULTS.tooltipPositions.map(tooltipPosition => { + it(`should be position ${tooltipPosition}`, () => { + expect(vtfunc({ tooltipPosition }, CNAME, LOC)).toEqual({ + className: `is-tooltip-${tooltipPosition}`, + }); + }); + }); + + DEFAULTS.breakpoints.map(breakpoint => { + DEFAULTS.tooltipPositions.map(tooltipPosition => { + it(`should be position ${breakpoint}-${tooltipPosition}`, () => { + expect( + vtfunc( + { tooltipResponsive: { [breakpoint]: tooltipPosition } }, + CNAME, + LOC, + ), + ).toEqual({ + className: `is-tooltip-${tooltipPosition}-${breakpoint}`, + }); + }); + }); + }); + }); +}); diff --git a/src/base/helpers/index.ts b/src/base/helpers/index.ts index c3c0de3c..6df1f377 100644 --- a/src/base/helpers/index.ts +++ b/src/base/helpers/index.ts @@ -21,6 +21,10 @@ import { makeValidatingTransform as responsiveMVT, ResponsiveHelpersProps, } from "./responsive"; +import { + TooltipHelpersProps, + makeValidatingTransform as tooltipMVT, +} from "./tooltip"; import { makeValidatingTransform as typographyMVT, TypographyHelpersProps, @@ -39,6 +43,7 @@ export type HelpersProps = Prefer< FloatHelpersProps & OverflowHelpersProps & OverlayHelpersProps & + TooltipHelpersProps & TypographyHelpersProps & VisibilityHelpersProps & OtherHelpersProps & @@ -51,6 +56,7 @@ export const makeRootValidatingTransform = makeRootValidatingTransformFactory< floatMVT, overflowMVT, overlayMVT, + tooltipMVT, typographyMVT, visibilityMVT, otherMVT, diff --git a/src/base/helpers/tooltip.ts b/src/base/helpers/tooltip.ts new file mode 100644 index 00000000..de8de200 --- /dev/null +++ b/src/base/helpers/tooltip.ts @@ -0,0 +1,67 @@ +import classNames from "classnames"; +import PropTypes from "prop-types"; + +import { + makePropTypesFactory, + makeValidatingTransformFactory, + TransformFunction, +} from "./factory"; +import { DEFAULTS, Variables } from "./variables"; + +export type TooltipHelpersProps = Partial<{ + tooltip: number | string; + tooltipActive: boolean; + tooltipColor: Variables["colors"]; + tooltipMultiline: boolean; + tooltipPosition: (typeof DEFAULTS["tooltipPositions"])[number]; + tooltipResponsive: { + [K in Variables["breakpoints"]]?: (typeof DEFAULTS["tooltipPositions"])[number]; + }; +}>; + +// Factories +export const makePropTypes = makePropTypesFactory(vars => ({ + tooltip: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + tooltipActive: PropTypes.bool, + tooltipColor: PropTypes.oneOf(vars.colors), + tooltipMultiline: PropTypes.bool, + tooltipPosition: PropTypes.oneOf(vars.tooltipPositions), + tooltipResponsive: PropTypes.objectOf(PropTypes.oneOf(vars.tooltipPositions)), +})); + +export const transform: TransformFunction = props => { + const { + tooltip, + tooltipActive, + tooltipColor, + tooltipMultiline, + tooltipPosition, + tooltipResponsive = {}, + ...rest + } = props; + + rest.className = classNames( + { + "is-tooltip-active": tooltipActive, + [`is-tooltip-${tooltipColor}`]: tooltipColor, + "is-tooltip-multiline": tooltipMultiline, + [`is-tooltip-${tooltipPosition}`]: tooltipPosition, + tooltip, + }, + ...Object.keys(tooltipResponsive).map( + breakpoint => `is-tooltip-${tooltipResponsive[breakpoint]}-${breakpoint}`, + ), + rest.className, + ); + + if (tooltip !== undefined) { + rest["data-tooltip"] = tooltip; + } + + return rest; +}; + +export const makeValidatingTransform = makeValidatingTransformFactory( + makePropTypes, + transform, +); diff --git a/src/base/helpers/variables.ts b/src/base/helpers/variables.ts index e3a3b7c7..d769d6dc 100644 --- a/src/base/helpers/variables.ts +++ b/src/base/helpers/variables.ts @@ -12,6 +12,9 @@ export type VariablesDefinitions = { breakpoints: (string | number)[]; breakpointsLimited: (string | number)[]; + // Tooltip + tooltipPositions: (string | number)[]; + // Typography textAlignments: (string | number)[]; textSizes: (string | number)[]; @@ -66,6 +69,9 @@ export const DEFAULTS = { */ breakpointsLimited: tuple("mobile", "fullhd", "touch"), + // Tooltips: + tooltipPositions: tuple("top", "right", "bottom", "left"), + // Typography textAlignments: tuple("centered", "justified", "left", "right"), textSizes: tuple(1, 2, 3, 4, 5, 6, 7), @@ -90,6 +96,9 @@ export interface VariablesDefaults { breakpoints: (typeof DEFAULTS.breakpoints)[number]; breakpointsLimited: (typeof DEFAULTS.breakpointsLimited)[number]; + // Typography + tooltipPositions: (typeof DEFAULTS.tooltipPositions)[number]; + // Typography textAlignments: (typeof DEFAULTS.textAlignments)[number]; textSizes: (typeof DEFAULTS.textSizes)[number]; diff --git a/src/extensions/__docs__/tooltip.docs.mdx b/src/extensions/__docs__/tooltip.docs.mdx new file mode 100644 index 00000000..ad4c881c --- /dev/null +++ b/src/extensions/__docs__/tooltip.docs.mdx @@ -0,0 +1,27 @@ +--- +name: Tooltip +menu: Extensions +route: /extensions/tooltip +--- + +import { Playground } from "docz"; + +import { + ForwardRefAsExoticComponentDoc, + mapEnumerable, + OptionBlock, +} from "src/__docs__/components"; +import { DEFAULTS } from "src/base/helpers/variables"; +import { Block, Button, Title } from "src/elements"; + +# Tooltip + +Display a **tooltip** attached to any kind of element with different positioning. + +It can display number or strings. + + + + diff --git a/src/extensions/tooltip/__docs__/tooltip.docs.mdx b/src/extensions/tooltip/__docs__/tooltip.docs.mdx deleted file mode 100644 index 67955421..00000000 --- a/src/extensions/tooltip/__docs__/tooltip.docs.mdx +++ /dev/null @@ -1,62 +0,0 @@ ---- -name: Tooltip -menu: Extensions -route: /extensions/tooltip ---- - -import { Playground } from "docz"; - -import { - ForwardRefAsExoticComponentDoc, - mapEnumerable, - OptionBlock, -} from "src/__docs__/components"; -import { DEFAULTS } from "src/base/helpers/variables"; -import { Block, Button, Title } from "src/elements"; -import { Tooltip, TOOLTIP_DEFAULTS } from "../tooltip"; - -# Tooltip - -Display a **tooltip** attached to any kind of element with different positioning. - -It can display number or strings. - - - - - -## API - - diff --git a/src/extensions/tooltip/__tests__/badge.test.tsx b/src/extensions/tooltip/__tests__/badge.test.tsx deleted file mode 100644 index 07e568c7..00000000 --- a/src/extensions/tooltip/__tests__/badge.test.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from "react"; - -import { DEFAULTS } from "src/base/helpers/variables"; -import { Badge, BADGE_DEFAULTS } from "src/extensions/badge/badge"; - -import { - hasProperties, - makeGenericHOCShallowWrapperInContextConsumer, - testForwardRefAsExoticComponentIntegration, - testThemeIntegration, - validateBoolPropType, - validateStringOrNumberPropType, -} from "src/__tests__/testing"; - -const COMPONENT = Badge; -const DISPLAY_NAME = "Badge"; -const DEFAULT_ELEMENT = "span"; -const BULMA_CLASS_NAME = "badge"; - -describe(`${DISPLAY_NAME} component`, () => { - hasProperties(COMPONENT, { - defaultProps: { - as: DEFAULT_ELEMENT, - badgeContent: "", - }, - }); - - testForwardRefAsExoticComponentIntegration(COMPONENT, { - displayName: DISPLAY_NAME, - bulmaClassName: BULMA_CLASS_NAME, - defaultElement: DEFAULT_ELEMENT, - }); - - testThemeIntegration(COMPONENT); - - describe("props", () => { - const { propTypes } = COMPONENT; - - describe("badgeColor", () => { - validateStringOrNumberPropType(propTypes, "badgeColor"); - - DEFAULTS.colors.map(color => { - it(`should be ${color}`, () => { - const node = ; - const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node); - expect(wrapper.hasClass(`has-badge-${color}`)).toBe(true); - }); - }); - }); - - describe("badgeContent", () => { - validateStringOrNumberPropType(propTypes, "badgeContent"); - - it(`should have proper content`, () => { - const node = ; - const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node); - expect( - (wrapper.props() as React.HTMLAttributes)[ - "data-badge" - ], - ).toBe("foo"); - }); - }); - - describe("badgeOutlined", () => { - validateBoolPropType(propTypes, "badgeOutlined"); - - [false, true].map(outlined => { - it(`should ${outlined ? "" : "not "}be outlined`, () => { - const node = ; - const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node); - expect(wrapper.hasClass(`has-badge-outlined`)).toBe(outlined); - }); - }); - }); - - describe("badgeSize", () => { - validateStringOrNumberPropType(propTypes, "badgeSize"); - - BADGE_DEFAULTS.sizes.map(size => { - it(`should be ${size}`, () => { - const node = ; - const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node); - expect(wrapper.hasClass(`has-badge-${size}`)).toBe(true); - }); - }); - }); - }); -}); diff --git a/src/extensions/tooltip/index.ts b/src/extensions/tooltip/index.ts deleted file mode 100644 index 54cbb070..00000000 --- a/src/extensions/tooltip/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { Badge } from "./tooltip"; diff --git a/src/extensions/tooltip/tooltip.tsx b/src/extensions/tooltip/tooltip.tsx deleted file mode 100644 index d5896844..00000000 --- a/src/extensions/tooltip/tooltip.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import classNames from "classnames"; -import PropTypes from "prop-types"; -import React from "react"; - -import { forwardRefAs, Generic } from "../../base"; -import { HelpersProps } from "../../base/helpers"; -import { DEFAULTS, Variables } from "../../base/helpers/variables"; - -export const TOOLTIP_DEFAULTS = { - positions: ["top", "right", "bottom", "left"], -} as const; - -export type TooltipModifierProps = Partial<{ - tooltipActive: boolean; - tooltipColor: Variables["colors"]; - tooltipContent: number | string; - tooltipMultiline: boolean; - tooltipPosition: (typeof TOOLTIP_DEFAULTS["positions"])[number]; - tooltipResponsive: { - [K in Variables["breakpoints"]]?: (typeof TOOLTIP_DEFAULTS["positions"])[number]; - }; -}>; - -export type TooltipProps = HelpersProps & TooltipModifierProps; - -export const Tooltip = forwardRefAs( - ( - { - className, - tooltipActive, - tooltipColor, - tooltipContent, - tooltipMultiline, - tooltipPosition, - tooltipResponsive = {}, - ...rest - }, - ref, - ) => ( - - `is-tooltip-${tooltipResponsive[breakpoint]}-${breakpoint}`, - ), - className, - )} - data-tooltip={tooltipContent} - ref={ref} - {...rest} - /> - ), - { - as: "span", - tooltipContent: "", - }, -); - -Tooltip.displayName = "Tooltip"; -Tooltip.propTypes = { - tooltipActive: PropTypes.bool, - tooltipColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - tooltipContent: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - tooltipMultiline: PropTypes.bool, - tooltipPosition: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - tooltipResponsive: PropTypes.shape( - DEFAULTS.breakpoints - .map(breakpoint => ({ - [breakpoint]: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), - })) - .reduce((acc, cv) => ({ ...acc, ...cv }), {}), - ), -};