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 }), {}),
- ),
-};