Skip to content

Commit

Permalink
first hack at extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
dfee committed Jun 13, 2019
1 parent d882b62 commit 5fcbcef
Show file tree
Hide file tree
Showing 21 changed files with 1,063 additions and 3 deletions.
33 changes: 31 additions & 2 deletions package-lock.json

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

6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
},
"homepage": "https://github.com/dfee/rbx#readme",
"dependencies": {
"bulma": "0.7.5",
"bulma-badge": "^3.0.1",
"bulma-divider": "^0.2.0",
"bulma-pageloader": "^2.1.0",
"bulma-tooltip": "^2.0.2",
"classnames": "^2.2.6",
"prop-types": "^15.7.2"
},
Expand Down Expand Up @@ -57,7 +62,6 @@
"@types/react": "^16.8.19",
"@types/react-dom": "^16.8.4",
"@types/react-test-renderer": "^16.8.1",
"bulma": "0.7.5",
"coveralls": "3.0.4",
"css-loader": "^2.1.1",
"docz": "^1.2.0",
Expand Down
162 changes: 162 additions & 0 deletions src/extensions/badge/__docs__/badge.docs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
---
name: Badge
menu: Extensions
route: /extensions/badge
---

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 { Badge, BADGE_DEFAULTS } from "../badge";

# Badge

Display a **badge** element in front of another component.

By default, it renders as a `span`.
It can display number or strings.

<Playground>
<Badge badgeContent="pending" badgeColor="warning">
Notifications
</Badge>
</Playground>

But you can use the `as` prop to render any component or JSX element, like a `<Button>`.

<Playground>
<Badge as={Button} badgeContent={8} badgeColor="danger">
Button
</Badge>
</Playground>

Because the props are prefixed with `badge`, you can use `<Badge>` as a wrapping component using the `as` prop – without interferring with the props.

<Playground>
<Badge
as={Button}
badgeContent={8}
badgeColor="danger"
badgeOutlined
color="danger"
outlined
>
Button
</Badge>
</Playground>

### Colors

Use the `badgeColor` prop on `<Badge>` to specify the color.

<Playground>
{() =>
DEFAULTS.colors.map((color, i) => (
<OptionBlock props={{ color }} index={i} key={i}>
<Badge badgeColor={color}>Notifications</Badge>
</OptionBlock>
))
}
</Playground>

### Sizes

Use the `badgeSize` prop on `<Badge>` to change the size.

<Playground>
{() => {
const sizes = BADGE_DEFAULTS.sizes.map(size => ({ name: size, size }));
sizes.splice(1,0, { name: 'normal', size: undefined});

return sizes.map(({ name, size }, i) => (
<OptionBlock props={{ size }} index={i} key={i}>
<Badge badgeSize={size}>{name} badge</Badge>
</OptionBlock>
))

}}

</Playground>

### Styles

Use the `badgeOutlined` prop of `<Badge>` to use an outlined badge.

<Playground>
<Block>
<Title as="p" size={4}>
Span
</Title>
<Badge badgeOutlined badgeContent={50}>
Notifications
</Badge>
</Block>
<Block>
<Title as="p" size={4}>
Button
</Title>
<Button.Group>
<Badge as={Button} badgeOutlined badgeContent={50}>
Button
</Badge>
</Button.Group>
</Block>
</Playground>

Use the `badgeRounded` prop of `<Badge>` to round a badge.

<Playground>
<Block>
<Title as="p" size={4}>
Span
</Title>
<Badge badgeRounded badgeContent={50}>
Notifications
</Badge>
</Block>
<Block>
<Title as="p" size={4}>
Button
</Title>
<Button.Group>
<Badge as={Button} badgeRounded badgeContent={50}>
Button
</Badge>
</Button.Group>
</Block>
</Playground>

## API

<ForwardRefAsExoticComponentDoc
component={Badge}
customize
docUrl="https://wikiki.github.io/elements/badge/"
docProvider="Bulma-Extensions"
props={{
badgeContent: {
description: "the contents of the badge",
typeName: "number | string",
},
badgeColor: {
description: "the color of the badge",
typeName: "string",
typeTip: mapEnumerable(DEFAULTS.colors),
},
badgeOutlined: {
description: "outline the badge",
typeName: "boolean",
},
badgeSize: {
description: "the size of the badge",
typeName: "string",
typeTip: mapEnumerable(BADGE_DEFAULTS.sizes),
},
}}
/>
89 changes: 89 additions & 0 deletions src/extensions/badge/__tests__/badge.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
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 = <Badge badgeColor={color} />;
const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node);
expect(wrapper.hasClass(`has-badge-${color}`)).toBe(true);
});
});
});

describe("badgeContent", () => {
validateStringOrNumberPropType(propTypes, "badgeContent");

it(`should have proper content`, () => {
const node = <Badge badgeContent="foo" />;
const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node);
expect(
(wrapper.props() as React.HTMLAttributes<HTMLSpanElement>)[
"data-badge"
],
).toBe("foo");
});
});

describe("badgeOutlined", () => {
validateBoolPropType(propTypes, "badgeOutlined");

[false, true].map(outlined => {
it(`should ${outlined ? "" : "not "}be outlined`, () => {
const node = <Badge badgeOutlined={outlined} />;
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 = <Badge badgeSize={size} />;
const wrapper = makeGenericHOCShallowWrapperInContextConsumer(node);
expect(wrapper.hasClass(`has-badge-${size}`)).toBe(true);
});
});
});
});
});
65 changes: 65 additions & 0 deletions src/extensions/badge/badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import classNames from "classnames";
import PropTypes from "prop-types";
import React from "react";

import { forwardRefAs, Generic } from "../../base";
import { HelpersProps } from "../../base/helpers";
import { Variables } from "../../base/helpers/variables";
import { tuple } from "../../utils";

export const BADGE_DEFAULTS = {
sizes: tuple("small", "medium", "large"),
};

export type BadgeModifierProps = Partial<{
badgeColor: Variables["colors"];
badgeContent: number | string;
badgeOutlined: boolean;
badgeRounded: boolean;
badgeSize: (typeof BADGE_DEFAULTS["sizes"])[number];
}>;

export type BadgeProps = HelpersProps & BadgeModifierProps;

export const Badge = forwardRefAs<BadgeProps>(
(
{
className,
badgeColor,
badgeContent,
badgeOutlined,
badgeRounded,
badgeSize,
...rest
},
ref,
) => (
<Generic
className={classNames(
"badge",
{
[`has-badge-${badgeColor}`]: badgeColor,
"has-badge-outlined": badgeOutlined,
"has-badge-rounded": badgeRounded,
[`has-badge-${badgeSize}`]: badgeSize,
},
className,
)}
data-badge={badgeContent}
ref={ref}
{...rest}
/>
),
{
as: "span",
badgeContent: "",
},
);

Badge.displayName = "Badge";
Badge.propTypes = {
badgeColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
badgeContent: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
badgeOutlined: PropTypes.bool,
badgeSize: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
};
1 change: 1 addition & 0 deletions src/extensions/badge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Badge } from "./badge";
Loading

0 comments on commit 5fcbcef

Please sign in to comment.