4.1.0 • Published 1 year ago

@legendarymediatv/bootstrap v4.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

LegendaryMediaTV Bootstrap

This is a Node.js package for extending React Bootstrap (which is based on Bootstrap 5) and Gatsby 3 or 4. It also has components for class-based icons (i.e., FontAwesome, Bootstrap icons, etc.).

Recent changes

  • v4.1.0
    • updated the peer dependency for Gatsby to include 5.x
  • v4.0.0
    • upgrated to FontAwesome 6 for the default icon names
    • updated FontAwesome reference to 6.1.1
    • updated Bootstrap Icons CSS reference to 1.8.2
  • v3.5
    • updated the peer dependency for React to 17.x or 18.x
  • v3.4
    • added a new <Feature> component with title and subtitle properties
    • added <Alert> with title/subtitle to the <Demo>
    • made <ScrollToTop> component not print
    • bugfix for <ListGroup.Item> component not showing subitem when subactions property is set
  • v3.3
    • added an <Alert> component with title, subtitle, and error properties
    • made the <Demo> utilize the new <Alert> component
  • v3.2
    • added a <ListGroup.Item> component with subitem and subactions properties
    • added a sleep() function
  • v3.1
    • added a <Pagination> component that uses our Gatsby-friendly <Link> component
    • made the <Demo> component more robust
    • added a title property to the <Spinner> component
    • bugfix for <Link> opening internal links in a new tab when requested
    • bugfix for the <ListGroup> default italics class on displaySubClassName
    • updated the peer dependency for React Bootstrap to 2.x, since 2.0 stable released
    • updated the peer dependency for Gatsby to 3.x or 4.x
    • updated Bootstrap CSS reference to 5.1.3

For more information, check out the release notes and the changelog.

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

NOTE: if you are still using Bootstrap 4.6.x and React Bootstrap 1.6.x, then you can use version 2.13.1 of this package, however, it is not continuing to be maintained

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";

const Layout = (props) => {
  return (
    <>
      <Helmet htmlAttributes={{ lang: "en" }}>
        <title>{props.title}</title>

        <meta name="description" content={props.description} />

        <link
          rel="stylesheet"
          href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
          integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
          crossorigin="anonymous"
        />
        <link
          rel="stylesheet"
          href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"
          integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g=="
          crossorigin="anonymous"
          referrerpolicy="no-referrer"
        />
      </Helmet>
      <Container className="py-4">
        <h1 className="display-1">{props.title}</h1>

        {props.children}
      </Container>
    </>
  );
};

export default Layout;

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";

const SamplePage = () => {
  return (
    <Layout title="Page Title" description="Page Description">
      <Icon name="fa-solid fa-camera" />
    </Layout>
  );
};

export default SamplePage;

Components

NOTE: components can be imported at the package level or at the component level

// package-level
import { Demo } from '@legendarymediatv/bootstrap';

// component level (preferred)
import Demo from '@legendarymediatv/bootstrap/Demo';

<Alert>

An extension of React Bootstrap’s <Alert> component, but with the ability to set a title, subtitle, and/or error. It provides <Alert.Heading> as is, but converts their <Alert.Link> to our Gatsby-friendly <Link> component.

import Alert from '@legendarymediatv/bootstrap/Alert';

…

<Alert
  title="Alert Title"
  subtitle="Alert subtitle"
  variant="info"
  onClose={() => {
    alert("Insert dismiss logic here");
  }}
  dismissible
>
  Some text with a <Alert.Link to="/sample">link</Alert.Link>
</Alert>

<Alert
  error={{
    error: "Request failed with status code 401",
    url: "/",
    method: "GET",
  }}
  onRetry={() => {
    alert("Insert retry logic here");
  }}
/>

<Alert error={["Field 1 is required", "Field 2 is required"]} />

In addition to the properties provided by React Bootstrap’s <Alert> component, the following additional properties are available:

NameTypeDefaultDescription
errorJSX | objecteither a JSX component or an object containing keys for error/message and optionally url and/or method
onRetryfunctionwhen defined, a retry <Button> is rendered with this as its onClick
subtitleJSXif error is an array, then 'Please fix the following error(s):'; if error is not an array, then 'The server has encountered a situation it doesn’t know how to handle'; otherwise, blankcontent that goes inside a <p> tag styled with a lead class
titleJSXif error is an array, then 'Submission Error'; if error is not an array, then 'Process Error'; otherwise, blankcontent that goes inside an <Alert.Heading> styled as a <div> with an h3 class
variantstring'danger' if error is defined, otherwise 'primary' (inherited)Bootstrap theme color name

<BackgroundImage>

Set a background image so that it covers the whole screen without distorting and stays in place, regardless of scrolling.

import BackgroundImage from '@legendarymediatv/bootstrap/BackgroundImage';

…

<BackgroundImage src="/images/sample.jpg" />
NameTypeDefaultDescription
imageClassNamestringclassName property for the <img>
imageStyleobjectstyle property for the <img>
srcstringrequiredpath to the image file

<Blockquote>

Quote blocks of content using Bootstrap’s Blockquote.

import Blockquote from '@legendarymediatv/bootstrap/Blockquote';

…

<Blockquote>
  <p className="mb-0">
    A well-known quote, contained in a blockquote element.
  </p>
</Blockquote>

<Blockquote>
  <p>
    Success, meaningful success, begins when we take ownership and actively
    take responsibility for our part in the shortcomings of our life.
  </p>

  <Blockquote.Footer>
    Dr Eric Thomas,{" "}
    <cite>Greatness Is Upon You: Laying the Foundation</cite>
  </Blockquote.Footer>
</Blockquote>

<Breakpoint>

Quickly see what the current breakpoint is (e.g., “md”).

import Breakpoint from '@legendarymediatv/bootstrap/Breakpoint';

…

<Breakpoint />

NOTE: This component is intended to be used for development purposes and probably should be removed before deploying your app

NameTypeDefaultDescription
variantstring'info'Bootstrap theme color name

<DatePicker>

Allow someone to select a date using a calendar popover.

import DatePicker from '@legendarymediatv/bootstrap/DatePicker';
…
// use React state to track selected date
const [componentState, setComponentState] = React.useState(null);
…
// select a new date
function dateHandler(selected) => {
  setComponentState(selected);
};
…
<DatePicker
  title="Contact Date"
  value={componentState}
  onChange={dateHandler}
/>

TIP: You could make your date change handler set the value for a hidden form element in addition to setting the state so that the date is submitted with the other form values

NameTypeDefaultDescription
titleJSXDate Pickerpopover title
titleAselementType<h3>as property for the popover title
variantstringlightBootstrap theme color name applied to the display button

<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!

<Display>

Bootstrap’s display heading typography classes.

  • <Display.Heading1>
  • <Display.Heading2>
  • <Display.Heading3>
  • <Display.Heading4>
  • <Display.Heading5>
  • <Display.Heading6>
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>

<Display.Heading5>Display Heading 5</Display.Heading5>

<Display.Heading6>Display Heading 6</Display.Heading6>
NameTypeDefaultDescription
aselementType<h#> corresponding to the sizechanges the HTML tag

<Feature>

Quickly create a stylized hero link or button that uses scaling and shadows to grow on hover and appear as depressed when clicked.

TIP: use in conjunction with grid layout components to have a wall effect

TIP: since this component uses scaling, to prevent horizontal scrollbars on smaller displays, you may want to wrap your content in a <Feature.Container> component or otherwise add overflow: hidden; styling to a fluid container, your <body> tag, etc.

import Feature from '@legendarymediatv/bootstrap/Feature';

…

<Feature
  title="Featured Content"
  subtitle="content to be featured"
  to="/sample"
  variant="info"
  textShadow
  wrapperClassName="rounded-pill mb-3"
  className="text-white py-5"
/>

<Row className="text-white">
  <Col sm className="p-0">
    <Feature
      title="Sample 1"
      to="/sample-1"
      variant="dark"
      className="py-3"
    />
  </Col>

  <Col sm className="p-0">
    <Feature
      title="Sample 2"
      to="/sample-2"
      variant="success"
      className="py-3"
    />
  </Col>

  <Col sm className="p-0">
    <Feature
      title="Sample 3"
      onClick={() => {
        alert("danger!");
      }}
      variant="danger"
      className="py-3"
    />
  </Col>
</Row>

NOTE: This component is intended to be used for development purposes and probably should be removed before deploying your app

NameTypeDefaultDescription
href | tostringURL or anchor target, making the feature item our Gatsby-friendly <Link> when set, otherwise it renders as a <button> and probably should have the onClick set
idstringapplied to the wrapper <div>
subtitleJSXcontent that goes inside a <div> tag styled with lead fst-italic between the title and children
titleJSXcontent that goes inside an <h2> tag styled with display-4 mb-0 above the subtitle and/or children
textShadowbooleanfalseadd a slight shadow to the feature’s text
variantstringBootstrap theme color, if one is not provided, you should probably add background color and/or image using the provided id (images are set to center and cover)
wrapperClassNamestringclassName property for the wrapper <div>
wrapperStyleobjectstyle property for the wrapper <div>

<Flipper>

Flashcard-like component that can flip horizontally or vertically using a 3D effect either on hover or via an event.

import Flipper from '@legendarymediatv/bootstrap/Flipper';

…

<Flipper
  front={<h3>auto-flipper front content</h3>}
  frontClassName="bg-primary text-light p-2"
  back={<h3>auto-flipper back content</h3>}
  backClassName="bg-secondary text-light p-2"
/>

…

// use React state to track flipped state
const [componentState, setComponentState] = React.useState(false);
…
function flipHandler(event) => {
  // un-click the button
  event.preventDefault();

  // toggle flip state
  setComponentState(!componentState);
};
…
<Flipper
  front={
    <Button
      onClick={flipHandler}
      className="w-100"
    >
      click to flip to the back
    </Button>
  }
  frontClassName="d-flex align-items-stretch"
  back={
    <Button
      onClick={flipHandler}
      variant="secondary"
      className="w-100"
    >
      click to flip to the front
    </Button>
  }
  backClassName="d-flex align-items-stretch"
  className="text-center"
  height="10rem"
  flipped={componentState}
  horizontal
/>
NameTypeDefaultDescription
backJSXflipper back side content
backClassNamestringclassName property for the back side of the flipper
backStyleobjectstyle property for the back side of the flipper
frontJSXflipper front side content
frontClassNamestringclassName property for the front side of the flipper
frontStyleobjectstyle property for the front side of the flipper
flippedbooleannulldetermines whether the card should display as flipped over (i.e., tie events to this property), if null, then it flips on hover
heightstring15remheight property to apply to the style for the flipper and both sides
horizontalbooleanfalseflip the card horizontally instead of vertically

NOTE: if flipped is null, then doesn’t toggle aria-label for the flipper sides, because it flips on an untracked hover action rather than an event

<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>
NameTypeDefaultDescription
refReactRefinheritedref property for the <Form.Group>
aselementTypeinheritedas property for the <Form.Group>
controlIdstringinheritedcontrolId property for the <Form.Group>
infoJSXpopover content for the <InfoIcon>
infoAltstringinheritedalt property for the <InfoIcon>
infoClassNamestringclassName property for the <InfoIcon>
infoStyleobjectstyle property for the <InfoIcon>
infoNamestringinheritedname property for the <InfoIcon>
infoTitleJSXtitle propertytitle property for the <InfoIcon>
infoTitleAselementTypeinheritedtitleAs property for the <InfoIcon>
infoVariantstringinheritedvariant property for the <InfoIcon>
iconClassNamestringclassName property for the <InfoIcon>
iconStyleobjectstyle property for the <InfoIcon>
titleJSXcontent for the <Form.Label>
labelRefReactRefinheritedref property for the <Form.Label>
labelAselementTypeinheritedas property for the <Form.Label>
columnboolean | 'sm' | 'lg'inheritedcolumn property for the <Form.Label>
htmlForstringinheritedhtmlFor property for the <Form.Label>
visuallyHiddenbooleaninheritedvisuallyHidden property for the <Form.Label>
labelClassNamestringclassName property for the <Form.Label>
labelStyleobjectstyle 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 an id and styled elsewhere)
import FullPage from '@legendarymediatv/bootstrap/FullPage';

…

<FullPage>
  <FullPage.Content>Page Content</FullPage.Content>
  <FullPage.Footer>Footer Content</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 Content
      </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="fa-solid fa-camera" />

<Icon
  name="fa-solid fa-camera"
  alt="DSLR"
  variant="success"
  className="ms-3"
  style={{ fontSize: '2rem' }}
/>
NameTypeDefaultDescription
altstringvariation of name (e.g., 'camera')alternate text for the icon (i.e., ends up in aria-label)
namestringrequiredicon class name (e.g., 'fa-solid fa-camera')
variantstringBootstrap 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>
NameTypeDefaultDescription
childrenJSXpopover content
altstringvariation of name (e.g., 'camera')alternate text for the <Icon> (i.e., ends up in aria-label)
iconClassNamestringclassName property for the <Icon> (i.e., className is applied to the toggler button)
iconStyleobjectstyle property for the the <Icon> (i.e., style is applied to the toggler button)
namestring'fa-solid fa-circle-info'icon class name
titleJSXpopover title
titleAselementType<h3>as property for the popover title
variantstringinfoBootstrap theme color name 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>
NameTypeDefaultDescription
href | toURLrequiredURL or anchor target
externalbooleantrue if the URL starts with http: or https: or externalIcon is setexplicitly (un-)flag an external link icon (also forces an <a> tag when enabled), which goes inside its own <small> tag
externalNewTabbooleanfalseset newTab to true when external is true
externalIconicon class name'fa-solid fa-arrow-up-right-from-square'external icon class name
externalVariantstringinfoBootstrap theme color name (e.g., 'primary') applied to the icon
externalClassNamestring'small ps-1 align-text-top'className property for the <Icon> (i.e., className is applied to the toggler button)
externalStyleobjectstyle property for the the <Icon> (i.e., style is applied to the toggler button)
newTabbooleanfalseforce the link to open in a new tab (sets target="_blank" rel="noopener")

<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 our Gatsby-friendly <Link> component, otherwise it is rendered as our <ListGroup.Item> instead.

import ListGroup 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',
    subtitle: "additional information in a subtitle",
    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"
/>
NameTypeDefaultDescription
activeKeyunknowninheritedactiveKey property
aselementTypeinheritedas property for the list group
defaultActiveKeyunknowninheriteddefaultActiveKey property
horizontaltrue | 'sm' | 'md' | 'lg' | 'xl'inheritedhorizontal property
onSelectfunctioninheritedwhen items is an array of objects, this is the onClick callback function that passes the clicked item as an argument
variant'flush'inheritedvariant property
displayFieldstring'title'when items is an array of objects, this is the object field to display
displaySubFieldstring'subtitle'when items is an array of objects, this is the object field to subtly display below the displayField
displaySubClassNamestringfst-italic small text-mutedwhen items is an array of objects, this is the className property for the displaySubField
itemsstring[] or object[]requiredarray of URL strings or an array of objects
itemsAselementTypeinheritedas property for the list group items
keyFieldstring'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
titlestringlist group title
titleAselementType<h3>as property for the list group title
titleVariantstring'primary'Bootstrap theme color name for the list group title
titleClassNamestringclassName property for the list group title
titleStyleobjectstyle property for the list group title
urlFieldstring'url'when items is an array of objects, this is the object field to use as the link URL

<ListGroup.Item>

An extension of React Bootstrap’s <ListGroup.Item> that adds support for sub-items, sub-actions, auto-conversion to a Gatsby-friendly <Link> when a URL is provided, and auto-conversion to an action when a URL or click handler are defined.

The subactions property should be an array of objects corresponding containing <ListGroup.Item> properties.

import ListGroup from '@legendarymediatv/bootstrap/ListGroup';

…

<ListGroup
  title="ListGroup with items"
  titleVariant="info"
>
  <ListGroup.Item subitem="sample sub-item">
    ListGroup.Item with a sub-item below
  </ListGroup.Item>

  <ListGroup.Item to="/sample">
    ListGroup.Item auto-converted to a link/action
  </ListGroup.Item>

  <ListGroup.Item
    onClick={() => {
      alert("clicked");
    }}
  >
    ListGroup.Item auto-converted to a button
  </ListGroup.Item>

  <ListGroup.Item
    to="#list-group"
    subactions={[
      {
        to: "/sample",
        variant: "info",
        children: <Icon name="fa-solid fa-camera" />,
      },
      {
        onClick: () => {
          alert("deleted!");
        },
        variant: "danger",
        children: <Icon name="fa-solid fa-trash-can" />,
      },
    ]}
  >
    ListGroup.Item with a URL and sub-actions
  </ListGroup.Item>
</ListGroup.Item>
NameTypeDefaultDescription
actionbooleaninherited / truemarks the item as actionable; will be set to true when href / to / onClick are defined
activebooleaninheritedmarks the item as active
aselementTypeinherited / Linkas property for the item; becomes our Gatsby-friendly Link when the href or to property is defined
childrenJSXcontent for the main list item (will be nested if subactions property is set)
disabledbooleaninheritedmarks the item as disabled
eventKeystring | numberinheritedunique identifier for when using events
href | toURLURL or anchor target for the <Link>
onClickfunctionfired when the item is clicked
subitemJSXto subtly display below the children
subitemClassNamestring'fst-italic small text-muted'className property for the subitem
variantstringBootstrap theme color name (e.g., 'primary')

<Pagination>

Basically a rebuild of React Bootstrap’s <Pagination> and <PageItem> components, but based off of our <Link> component (in order to be Gatsby-friendly).

Sub-components include:

  • <Pagination.Item> – creates a pagination item containing a <Link> or <button> (native), depending on if a URL is provided in the href/to property
  • <Pagination.First><Pagination.Item> with the content as an ARIA-friendly « by default
  • <Pagination.Last><Pagination.Item> with the content as an ARIA-friendly » by default
  • <Pagination.Prev><Pagination.Item> with the content as an ARIA-friendly by default
  • <Pagination.Next><Pagination.Item> with the content as an ARIA-friendly by default
  • <Pagination.Ellipsis><Pagination.Item> with the content as an ARIA-friendly by default

TIP: if you prefer to use icons, you can override the default content of any of the above by making the child an <Icon>

import Pagination from '@legendarymediatv/bootstrap/Pagination';
…
<Pagination>
  <Pagination.First />
  <Pagination.Prev />

  <Pagination.Ellipsis />

  <Pagination.Item>1</Pagination.Item>
  <Pagination.Item to="/sample">2</Pagination.Item>
  <Pagination.Item onClick={sampleHandler.bind(this, 3)}>3</Pagination.Item>
  <Pagination.Item active>4</Pagination.Item>
  <Pagination.Item disabled>5</Pagination.Item>

  <Pagination.Ellipsis />

  <Pagination.Next />
  <Pagination.Last />
</Pagination>

…

<Pagination size="sm">
  <Pagination.First>
    <Icon name="fa-solid fa-angles-left" alt="first" />
  </Pagination.First>

  <Pagination.Prev>
    <Icon name="fa-solid fa-angle-left" alt="previous" />
  </Pagination.Prev>

  <Pagination.Ellipsis>
    <Icon name="fa-solid fa-ellipsis" alt="more" />
  </Pagination.Ellipsis>

  <Pagination.Next>
    <Icon name="fa-solid fa-angle-right" alt="next" />
  </Pagination.Next>

 <Pagination.Last>
    <Icon name="fa-solid fa-angles-right" alt="last" />
  </Pagination.Last>
</Pagination>

<Pagination> properties

NameTypeDefaultDescription
size'sm' | 'lg'sets the sizing for the whole pagination

<Pagination.*> properties

NameTypeDefaultDescription
activebooleanfalsesets the pagination item as active and appends the children with a <VisuallyHidden> tag containing the activeLabel
activeLabelstring(current)content of the <VisuallyHidden> tag when flagged as active
disabledbooleanfalsesets the pagination item as disabled
href | toURLURL or anchor target for the <Link>; if blank, then a <button> is rendered and probably should have an onClick defined
onClickfunctioncallback function for when the component is clicked; TIP: as in the example above, use bind() when assigning the property in order to tell which pagination item is clicked

<ScrollToTop>

Customizable icon that automatically appears in the bottom-right corner when you’re scrolled down the page a bit and smoothly scrolls to the top of the page when clicked.

import ScrollToTop from '@legendarymediatv/bootstrap/ScrollToTop';

…

<ScrollToTop />

<ScrollToTop name="fa-solid fa-square-caret-up" variant="success" />

NOTE: the scrollToTop() handler function can be exported as well; see below for details

NameTypeDefaultDescription
altstring'up arrow'alternate text for the icon (i.e., ends up in aria-label)
namestring'fa-solid fa-circle-chevron-up'icon class name
variantstring'dark'Bootstrap theme color name
iconClassNamestringclassName property for the <Icon>
iconStyleobjectstyle property for the <Icon>

<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 Spinner from '@legendarymediatv/bootstrap/Spinner';

…

<Spinner />

<Spinner
  animation="grow"
  variant="success"
/>

<Spinner alert />

<Spinner
  title="Reticulating splines …"
  variant="primary"
/>
NameTypeDefaultDescription
childrenJSX'loading…'content for <VisuallyHidden> child component
animation'border' | 'grow''border'changes the animation style of the spinner
alertbooleanfalsewrap the spinner in an <Alert> (centered with py-5 padding), defaulting variant to 'info', and apply non-spinner properties to the alert
asstring'div'custom HTML tag
rolestring'status'ARIA accessibility role
sizestringcomponent size variations (e.g., sm)
titleJSXcontent for <Alert.Heading>, also wraps the spinner in an <Alert> (centered with py-4 padding), see alert above
variantstring'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>
NameTypeDefaultDescription
focusablebooleanfalseitem is focusable

Functions

combine(array) and separate(string)

Use separate() to split a string (e.g., className) by whitespace into an array, always returning at least an empty array.

Use combine() to join an array with at least one element via a space separator, otherwise return null.

NOTE: these are helpful when used together or in conjunction with prepare() in order to join className 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 join className 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 the form’s element data as key–value pairs. Key names are pulled from either the form element name (preferred) or id attribute, otherwise unnamed/unidentified elements are omitted. Unselected radio elements are ignored as well.

NOTE: JSON data returned from this function could be utilized in API calls via extensions like Axios

import { formData } from "@legendarymediatv/bootstrap/functions";

...

const submitHander = (event) => {
  // don't traditionally submit the form
  event.preventDefault();

  // extract 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>

sleep(milliseconds)

Promise-based wrapper for JavaScript’s setTimeout() function, allowing your script to pause using await or .then() syntax.

import { sleep } from '@legendarymediatv/bootstrap/functions';

…

// wait one second and then do something
sleep(1000)
  .then(() => {
    // do something
  });

function async sample() {
  // do something

  // wait 1/4 second
  await sleep(250);

  // do something else
}
NameTypeDefaultDescription
millisecondsintegerrequirednumber of milliseconds to wait

title(site, title, parent)

Generate an SEO-friendly HTML title in the format Title | Site. Optionally, include the parent argument to render Title – Parent | Site. Also, if title and parent are omitted, then it just uses the site.

NOTE: this is designed to be used in conjunction with a plugin like React Helmet

import { title } from '@legendarymediatv/bootstrap/functions';

…

<Helmet>
  <title>{title("LegendaryMediaTV", "Bootstrap Demo")}</title>
</Helmet>

<Helmet>
  <title>
    {title("LegendaryMediaTV", "Full Page Demo", "Bootstrap Demo")}
  </title>
</Helmet>
NameTypeDefaultDescription
sitestringrequiredsite/company name
titlestringthis page’s title
parentstringparent page’s title
siteSeparatorstringpipe: |separator between the site and the title/parent
parentSeparatorstringen dash: '–'separator between the title and parent
separatorReplacerstringforward slash: '/'replacement character when title or parent contain the parentSeparator

scrollToTopHandler(event)

Add the ability for any component to smoothly scroll to the top of the window.

import { scrollToTopHandler } from '@legendarymediatv/bootstrap/ScrollToTop';

…

<Button onClick={scrollToTopHandler}>Scroll to Top</Button>

<Link to="#" onClick={scrollToTopHandler}>
  scroll to top
</Link>

NOTE: see the <ScrollToTop> component above for a turnkey 🦃 scroll-to-top solution

Additional examples

For more examples of usage, see /src/pages

4.1.0

1 year ago

4.0.0

2 years ago

3.5.0

2 years ago

3.4.6

2 years ago

3.4.4

2 years ago

3.4.5

2 years ago

3.4.0

3 years ago

3.4.3

3 years ago

3.4.2

3 years ago

3.4.1

3 years ago

3.3.1

3 years ago

3.3.0

3 years ago

3.2.0

3 years ago

3.1.5

3 years ago

3.1.3

3 years ago

3.1.4

3 years ago

3.1.2

3 years ago

3.1.1

3 years ago

3.0.4

3 years ago

3.0.3

3 years ago

3.0.2

3 years ago

3.1.0

3 years ago

3.0.1

3 years ago

3.0.0

3 years ago

2.13.1

3 years ago

2.13.0

3 years ago

2.12.0

3 years ago

2.11.1

3 years ago

2.11.0

3 years ago

2.10.1

3 years ago

2.10.0

3 years ago

2.9.5

3 years ago

2.9.4

3 years ago

2.9.2

3 years ago

2.9.1

3 years ago

2.9.3

3 years ago

2.9.0

3 years ago

2.8.0

3 years ago

2.7.0

3 years ago

2.6.2

3 years ago

2.6.1

3 years ago

2.6.0

3 years ago

2.5.0

3 years ago

2.4.0

3 years ago

2.3.0

3 years ago

2.2.0

3 years ago

2.1.0

3 years ago

2.0.1

3 years ago

2.0.0

3 years ago

1.14.0

3 years ago

1.13.4

3 years ago

1.13.3

3 years ago

1.13.2

3 years ago

1.13.1

3 years ago

1.13.0

3 years ago

1.12.1

3 years ago

1.12.0

3 years ago

1.11.0

3 years ago

1.10.0

3 years ago

1.9.1

3 years ago

1.9.0

3 years ago

1.8.0

3 years ago

1.7.0

3 years ago

1.6.0

3 years ago

1.5.1

3 years ago

1.5.0

3 years ago

1.4.0

3 years ago

1.3.0

3 years ago

1.2.0

3 years ago

1.2.1

3 years ago

1.1.0

3 years ago

1.0.0

3 years ago

0.9.0

3 years ago

0.9.2

3 years ago

0.9.1

3 years ago

0.8.7

3 years ago

0.8.6

3 years ago

0.8.5

3 years ago

0.8.4

3 years ago

0.8.3

3 years ago

0.8.2

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago