Package Exports
- @legendarymediatv/bootstrap
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@legendarymediatv/bootstrap) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
LegendaryMediaTV Bootstrap
This is a Node.js package for extending React Bootstrap (which is based on Bootstrap 4) and Gatsby. It also has components for class-based icons (i.e., FontAwesome, Bootstrap icons, etc.).
Getting started
Installation
Install peer dependencies (if they aren't already).
npm install react react-dom react-bootstrap gatsby
Optionally, install React Helmet (useful for linking Bootstrap resources).
npm install react-helmet
Install this package.
npm install @legendarymediatv/bootstrap
Preparation
Modify the Babel loader to transpile JSX for this package.
NOTE: not configuring this will result in the following error when running
gatsby build
: ERROR #98123 WEBPACK – Generating development JavaScript bundle failed: Unexpected token
Sample /gatsby-node.js
exports.onCreateWebpackConfig = ({ actions, loaders, getConfig }) => {
const config = getConfig();
config.module.rules = [
// omit the default rule where test === '\.jsx?$'
...config.module.rules.filter(
(rule) => String(rule.test) !== String(/\.jsx?$/)
),
// re-create it with custom exclude filter
{
// apply required Babel presets/plugins and merge in your configuration from `babel.config.js`.
...loaders.js(),
test: /\.jsx?$/,
// exclude all node_modules from transpilation, except for this plugin
// NOTE: their pattern has "\/" but this has "[\\\/]" to support all OS path separators
exclude: (modulePath) =>
/node_modules/.test(modulePath) &&
!/node_modules[\\\/]@legendarymediatv[\\\/]bootstrap/.test(modulePath),
},
];
// replace the webpack config with the modified object.
actions.replaceWebpackConfig(config);
};
Either import Bootstrap CSS or link Bootstrap into your layout or app file.
Sample /src/components/Layout.js
(link, with FontAwesome)
import React from "react";
import { Helmet } from "react-helmet";
import Container from "react-bootstrap/Container";
export default (props) => {
return (
<>
<Helmet>
<title>{props.title}</title>
<meta name="description" content={props.description} />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"
integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.15.1/css/all.css"
/>
</Helmet>
<Container className="py-4">
<h1 className="display-1">{props.title}</h1>
{props.children}
</Container>
</>
);
};
Finally, import the components as needed into your app/components.
Sample /src/pages/index.js
// dependencies
import React from "react";
// page layout template
import Layout from "../components/Layout";
// sample LegendaryMediaTV component
import Icon from "@legendarymediatv/bootstrap/Icon";
export default () => {
return (
<Layout title="Page Title" description="Page Description">
<Icon name="fas fa-camera" />
</Layout>
);
};
Components
NOTE: components can be imported at the package level or at the component level
// package-level
import { Demo } from '@legendarymediatv/bootstrap';
// component level
import Demo from '@legendarymediatv/bootstrap/Demo';
<Breakpoint>
Quickly see what the current breakpoint is (e.g., 'md').
NOTE: This component is intended to be used for development purposes and probably should be removed before deploying your app
Name | Type | Default | Description |
---|---|---|---|
variant |
string | info | Bootstrap theme color name |
<Demo>
This component is intended to be used for development purposes (e.g., testing your custom Bootstrap theme) by having everything all one one page!
WARNING: This component is still under development and often uses Bootstrap’s raw classes instead of React Bootstrap components or even this package’s components. Stay tuned for more updates!
<Display>
Bootstrap’s display heading typography classes.
<Display.Heading1>
<Display.Heading2>
<Display.Heading3>
<Display.Heading4>
import Display from '@legendarymediatv/bootstrap/Display';
…
<Display.Heading1>Display Heading 1</Display.Heading1>
<Display.Heading2>Display Heading 2</Display.Heading2>
<Display.Heading3>Display Heading 3</Display.Heading3>
<Display.Heading4>Display Heading 4</Display.Heading4>
Name | Type | Default | Description |
---|---|---|---|
as |
elementType | <h#> corresponding to the size |
changes the HTML tag |
<FormGroup>
An extension of React Bootstrap’s <Form.Group>
, which automatically contains a React Bootstrap <Form.Label>
. The label then optionally includes a <InfoIcon>
when the info
property is set.
import FormGroup from '@legendarymediatv/bootstrap/FormGroup';
…
<FormGroup
title="Sample textbox"
info={<p>Things, <i>stuff</i>, <b>content</b>!</p>}
>
<Form.Control
name="sample"
maxLength="80"
defaultValue="eleventeen"
/>
</FormGroup>
Name | Type | Default | Description |
---|---|---|---|
ref |
ReactRef | inherited | ref property for the <Form.Group> |
as |
elementType | inherited | as property for the <Form.Group> |
controlId |
string | inherited | controlId property for the <Form.Group> |
info |
JSX | popover content for the <InfoIcon> |
|
infoAlt |
string | inherited | alt property for the <InfoIcon> |
infoClassName |
string | className property for the <InfoIcon> |
|
infoStyle |
object | style property for the <InfoIcon> |
|
infoName |
string | inherited | name property for the <InfoIcon> |
infoTitle |
JSX | title property |
title property for the <InfoIcon> |
infoTitleAs |
elementType | inherited | titleAs property for the <InfoIcon> |
infoVariant |
string | inherited | variant property for the <InfoIcon> |
iconClassName |
string | className property for the <InfoIcon> |
|
iconStyle |
object | style property for the <InfoIcon> |
|
title |
JSX | content for the <Form.Label> |
|
labelRef |
ReactRef | inherited | ref property for the <Form.Label> |
labelAs |
elementType | inherited | as property for the <Form.Label> |
column |
boolean | 'sm' | 'lg' |
inherited | column property for the <Form.Label> |
htmlFor |
string | inherited | htmlFor property for the <Form.Label> |
srOnly |
boolean | inherited | srOnly property for the <Form.Label> |
labelClassName |
string | className property for the <Form.Label> |
|
labelStyle |
object | style property for the <Form.Label> |
<FullPage>
Make your page always use at least the full height of the browser window using flexbox instead of fixed/sticky styling. Plus, it has a footer component that will display at the bottom of the page without forcing a scrollbar!
This component set doesn't have any special properties, but it is made up of three parts:
<FullPage>
– the wrapper (should only contain the other FullPage components below)<FullPage.Content>
(required) – page content (should contain your<Navbar>
and page copy components such as<article>
)<FullPage.Footer>
(optional) – page footer (can be styled directly or given anid
and styled elsewhere)
import FormGroup from '@legendarymediatv/bootstrap/FormGroup';
…
<FullPage>
<FullPage.Content>Page Content</FullPage.Content>
<FullPage.Footer>Footer</FullPage.Footer>
</FullPage>
Containerized example:
<div className="bg-dark">
<Container className="bg-light p-0">
<FullPage>
<FullPage.Content>
<Navbar bg="primary" variant="dark">
<Navbar.Brand>LegendaryMediaTV</Navbar.Brand>
</Navbar>
<article className="py-4 px-2">
<h1>Title or whatever</h1>
<p>Things, stuff, content!</p>
</article>
</FullPage.Content>
<FullPage.Footer className="bg-secondary py-2 text-center text-white">
Footer
</FullPage.Footer>
</FullPage>
</Container>
</div>
NOTE: if using React Helmet, you can use its
bodyAttributes
property instead of a<div>
wrapper to set the main background color:<Helmet bodyAttributes={{ class: "bg-dark" }}>
<Icon>
Class-based icon (<i>
tag) that can automatically add an ARIA label based on the icon name.
import Icon from '@legendarymediatv/bootstrap/Icon';
…
<Icon name="fas fa-camera" />
<Icon
name="fas fa-camera"
alt="DSLR"
variant="success"
className="ml-3"
style={{ fontSize: '2rem' }}
/>
Name | Type | Default | Description |
---|---|---|---|
alt |
string | variation of name (e.g., 'camera' ) |
alternate text for the icon (i.e., ends up in aria-label ) |
name |
string | required | icon class name (e.g., 'fas fa-camera' ) |
variant |
string | Bootstrap theme color name (e.g., 'primary' ) |
<InfoIcon>
An extension of React Bootstrap’s <Popover>
(with rootClose
set to auto-close when it loses focus) that contains an <Icon>
.
import InfoIcon from '@legendarymediatv/bootstrap/InfoIcon';
…
<InfoIcon title="Info Title">Info Content</InfoIcon>
<InfoIcon
title="Info Title"
name="bi bi-info-circle-fill"
alt="help me!"
variant="danger"
iconStyle={{ fontSize: "2rem" }}
>
Things, <i>stuff</i>, <b>content</b>!
</InfoIcon>
Name | Type | Default | Description |
---|---|---|---|
children | JSX | popover content | |
alt |
string | variation of name (e.g., 'camera' ) |
alternate text for the <Icon> (i.e., ends up in aria-label ) |
iconClassName |
string | className property for the <Icon> (i.e., className is applied to the toggler button) |
|
iconStyle |
object | style property for the the <Icon> (i.e., style is applied to the toggler button) |
|
name |
string | 'fas fa-question-circle' |
icon class name |
title |
JSX | popover title | |
titleAs |
elementType | <h3> |
as property for the popover title |
variant |
string | info |
Bootstrap theme color name (e.g., 'primary' ) applied to the icon |
<Link>
A combination of an HTML <a>
tag and Gatsby’s <Link>
. It mostly uses the normal <a>
tag properties, but accepting either href
or to
in order to set the URL, so that you can simply swith the import of Gatsby’s <Link>
to this one instead, plus you can set the as
property for any React Bootstrap to be this component so that links work properly in Gatsby.
If href
property begins with #
(i.e., anchor), a protocol (e.g., https://
or mailto:
), or ends with a file extension (e.g., sample.jpg
), or external
is set, then it uses an <a>
tag. Otherwise, it uses Gatsby’s <Link>
tag, so that it doesn’t force a page reload.
import Link from '@legendarymediatv/bootstrap/Link';
…
<Link href="/">Gatsby link</Link>
<Link href="#link">HTML link</Link>
<Link href="https://www.legendarymediatv.com">auto-external HTML link</Link>
<Link
href="/external-somehow"
externalIcon="bi bi-box-arrow-up-right"
externalVariant="danger"
>
HTML link with custom external icon and color
</Link>
<Navbar.Brand as={Link} to='/'>LegendaryMediaTV</Navbar.Brand>
<Nav.Link as={Link} to='/'>Home</Nav.Link>
Name | Type | Default | Description |
---|---|---|---|
href | to |
URL | required | alternate text for the icon (i.e., ends up in aria-label ) |
external |
boolean | true if the URL starts with http: or https: or externalIcon is set |
explicitly (un-)flag an external link icon (also forces an <a> tag when enabled), which goes inside its own <small> tag |
externalIcon |
icon class name | 'fas fa-external-link-alt' |
external icon class name |
externalVariant |
string | info |
Bootstrap theme color name (e.g., 'primary' ) applied to the icon |
externalClassName |
string | 'small pl-1 align-text-top' |
className property for the <Icon> (i.e., className is applied to the toggler button) |
externalStyle |
object | style property for the the <Icon> (i.e., style is applied to the toggler button) |
<ListGroup>
An extension of React Bootstrap’s <ListGroup>
that has a title, accepting arrays of URL strings and arrays of obects as items. If the item has a URL, then it is rendered as a <Link>
component, otherwise it is rendered as a Bootstrap React <ListGroup.Item>
instead.
import from '@legendarymediatv/bootstrap/ListGroup';
…
const linkArray = [
'/test',
'/sample'
];
…
<ListGroup title="Array of Links" items={linkArray} />
…
const linkObjects = [
{ title: 'Test Link', url: '/test' },
{ title: 'Sample Link', url: '/sample' }
];
…
<ListGroup title="Array of Objects with Links" items={linkObjects} />
…
function sampleHandler(itemSelected) {
alert(JSON.stringify(itemSelected, null, 4));
}
…
const objectArray = [
{ id: 1, title: 'Test Non-Link' },
{ id: 2, title: 'Sample Non-Link' }
];
…
<ListGroup
title="Array of Objects with Click Handler"
titleVariant="success"
items={objectArray}
click={sampleHandler}
className="mt-3"
/>
Name | Type | Default | Description |
---|---|---|---|
activeKey |
unknown | inherited | activeKey property |
as |
elementType | inherited | as property |
defaultActiveKey |
unknown | inherited | defaultActiveKey property |
horizontal |
true | 'sm' | 'md' | 'lg' | 'xl' |
inherited | horizontal property |
onSelect |
SelectCallback | inherited | onSelect property |
variant |
'flush' | inherited | variant property |
click |
function | when items is an array of objects, this is the onClick callback function that passes the clicked item as an argument |
|
displayField |
string | 'title' |
when items is an array of objects, this is the object field to display |
items |
string[] or object[] | required | array of URL strings or an array of objects |
keyField |
string | 'id' |
when items is an array of objects, this is the object field to use as the React list key; otherwise it just uses the array index as the key |
title |
string | list group title | |
titleAs |
elementType | <h3> |
as property for the list group title |
titleVariant |
string | 'primary' |
Bootstrap theme color name for the list group title |
titleClassName |
string | className property for the list group title |
|
titleStyle |
object | style property for the list group title |
|
urlField |
string | 'url' |
when items is an array of objects, this is the object field to use as the link URL |
<Spinner>
An extension of React Bootstrap’s <Spinner>
that automatically selects the border
animation and adds the screen reader and ARIA role, so it can be self-closing and easily ensure the maximum accessibility.
import Icon from '@legendarymediatv/bootstrap/Icon';
…
<Spinner />
<Spinner
animation="grow"
variant="success"
/>
Name | Type | Default | Description |
---|---|---|---|
children | JSX | 'loading…' |
content for <VisuallyHidden> child component |
animation |
'border' | 'grow' |
'border' |
changes the animation style of the spinner |
as |
string | 'div' |
custom HTML tag |
role |
string | 'status' |
ARIA accessibility role |
size |
string | component size variations (e.g., sm ) |
|
variant |
string | 'primary' |
Bootstrap theme color name (e.g., 'primary' ) |
<VisuallyHidden>
Bootstrap’s visually hidden content (a.k.a., screen reader only).
import VisuallyHidden from '@legendarymediatv/bootstrap/VisuallyHidden';
…
<p className="text-danger">
<VisuallyHidden>Danger: </VisuallyHidden>
This action is not reversible
</p>
Name | Type | Default | Description |
---|---|---|---|
focusable | boolean | false | item is focusable |
Functions
combine(array)
If an array has elements, join()
them via space separator, otherwise return null
.
NOTE: this is helpful when used in conjunction with
prepare(props)
in order to joinclassName
before rendering the component; see the example there
prepare(props)
A React component's properties cannot be altered, so use this function to create a new properties
array and children
variable. Then, manipulate the array as you see fit, and spread out the new properties in your component.
import { combine, prepare } from "@legendarymediatv/bootstrap/functions";
…
// prepare properties
const [properties, children] = prepare(props);
// add variant to class
properties.className.push(`text-${properties.variant}`);
delete properties.variant;
// merge classes
properties.className = combine(properties.className);
// render component
return (
<div {...properties}>{children}</div>
);
NOTE: this is helpful when used in conjunction with
prepare(props)
in order to joinclassName
before rendering the component
formData(formObject)
Pass this function a form object (e.g., via an onSubmit
event handler’s event.target
) and it will return a JSON object containing key–value pairs. Key names are pulled from either the form element name
or id
attribute, otherwise the unnamed/unidentified element is omitted. Unchecked/unselected checkbox
and radio
elements are ignored as well.
NOTE: JSON data returned from this function could be utilized in API calls via Axios
import { formData } from "@legendarymediatv/bootstrap/functions";
...
const submitHander = (event) => {
// don't traditionally submit the form
event.preventDefault();
// get the data from the form
const data = formData(event.target);
// display the form data object
alert(JSON.stringify(data, null, 4));
}
...
<Form onSubmit={submitHandler}>
<FormGroup title="Simple textbox">
<Form.Control name="sample" />
</FormGroup>
<Button type="submit">Submit</Button>
</Form>
Additional examples
For more examples of usage, see '/src/pages/index.js