Categories
React Bootstrap

React Bootstrap — Images, Jumbotrons, and Figures

React Bootstrap is one version of Bootstrap made for React.

It’s a set of React components that have Bootstrap styles.

In this article, we’ll look at how to add images, figures, and jumbotrons to a React app with React Bootstrap.

Images

React Bootstrap has the Image component to let us add an image of various shapes.

We can have images that are rounded, a circle, or a thumbnail.

For example, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Image from "react-bootstrap/Image";

export default function App() {
  return (
    <div>
      <Image src="http://placekitten.com/200/200" rounded />
    </div>
  );
}

to add an image with a rounded corner with the rounded prop.

Likewise, we can add the roundedCircle prop to make the image display in a circle:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Image from "react-bootstrap/Image";

export default function App() {
  return (
    <div>
      <Image src="http://placekitten.com/200/200" roundedCircle />
    </div>
  );
}

We can also add the thumbnail prop to display them as thumbnails:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Image from "react-bootstrap/Image";

export default function App() {
  return (
    <div>
      <Image src="http://placekitten.com/200/200" thumbnail />
    </div>
  );
}

Fluid Images

We can use the fluid prop to scale images to the parent element’s width.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Image from "react-bootstrap/Image";

export default function App() {
  return (
    <div>
      <Image src="http://placekitten.com/200/200" fluid />
    </div>
  );
}

to make the image scale to the parent’s width.

Figures

We can display a piece of content with the Figure component.

One good thing to display with it are images with a caption.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Figure from "react-bootstrap/Figure";

export default function App() {
  return (
    <div>
      <Figure>
        <Figure.Image
          width={171}
          height={180}
          alt="171x180"
          src="http://placekitten.com/200/200"
        />
        <Figure.Caption>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
          efficitur massa tellus, non ultrices augue sagittis ornare. Sed
          ultrices ligula in est tempus tincidunt. Nam id consequat lacus, et
          mattis turpis. Sed velit nibh, tincidunt in ante a, accumsan fringilla
          odio. Etiam fermentum euismod enim id faucibus. Etiam facilisis nulla
          id leo imperdiet aliquet. In dignissim nulla non magna commodo
          ullamcorper. Fusce non ligula id tellus dapibus tempor sit amet in
          libero. Proin malesuada vulputate augue in bibendum. In mollis felis
          eu ante pharetra, ut vehicula sapien malesuada. Nulla imperdiet, urna
          a laoreet ullamcorper, massa nunc posuere neque, iaculis egestas urna
          arcu a metus.
        </Figure.Caption>
      </Figure>
    </div>
  );
}

We have the Figure component, which is a wrapper for the Figure.Image to display an image.

And we have the Figure.Caption component to display the caption below the image.

Jumbotron

A jumbotron is a lightweight and flexible component that can extend the whole viewport to show key content on our app.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Jumbotron from "react-bootstrap/Jumbotron";
import Button from "react-bootstrap/Button";

export default function App() {
  return (
    <div>
      <Jumbotron>
        <h1>Title!</h1>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
          efficitur massa tellus, non ultrices augue sagittis ornare. Sed
          ultrices ligula in est tempus tincidunt. Nam id consequat lacus, et
          mattis turpis. Sed velit nibh, tincidunt in ante a, accumsan fringilla
          odio. Etiam fermentum euismod enim id faucibus. Etiam facilisis nulla
          id leo imperdiet aliquet. In dignissim nulla non magna commodo
          ullamcorper. Fusce non ligula id tellus dapibus tempor sit amet in
          libero. Proin malesuada vulputate augue in bibendum. In mollis felis
          eu ante pharetra, ut vehicula sapien malesuada. Nulla imperdiet, urna
          a laoreet ullamcorper, massa nunc posuere neque, iaculis egestas urna
          arcu a metus.
        </p>
        <p>
          <Button variant="primary">Read more</Button>
        </p>
      </Jumbotron>
    </div>
  );
}

to show a jumbotron with a title and some body text.

At the bottom, we have a button.

We can make it scale with the parent with the fluid prop.

We write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Jumbotron from "react-bootstrap/Jumbotron";
import Button from "react-bootstrap/Button";

export default function App() {
  return (
    <div>
      <Jumbotron fluid>
        <h1>Title!</h1>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi
          efficitur massa tellus, non ultrices augue sagittis ornare. Sed
          ultrices ligula in est tempus tincidunt. Nam id consequat lacus, et
          mattis turpis. Sed velit nibh, tincidunt in ante a, accumsan fringilla
          odio. Etiam fermentum euismod enim id faucibus. Etiam facilisis nulla
          id leo imperdiet aliquet. In dignissim nulla non magna commodo
          ullamcorper. Fusce non ligula id tellus dapibus tempor sit amet in
          libero. Proin malesuada vulputate augue in bibendum. In mollis felis
          eu ante pharetra, ut vehicula sapien malesuada. Nulla imperdiet, urna
          a laoreet ullamcorper, massa nunc posuere neque, iaculis egestas urna
          arcu a metus.
        </p>
        <p>
          <Button variant="primary">Read more</Button>
        </p>
      </Jumbotron>
    </div>
  );
}

to make it fluid.

Conclusion

React Bootstrap comes with the Image component to display images.

It also has the Figure and Jumbotron to let us display content in different ways.

Categories
React Bootstrap

React Bootstrap — Customizing Overlays

React Bootstrap is one version of Bootstrap made for React.

It’s a set of React components that have Bootstrap styles.

In this article, we’ll look at how to add overlays with React Bootstrap.

Disabled Elements

If we want to trigger overlays on a disabled element, we’ve to trigger the overlay from a wrapper element that isn’t disabled.

This is because disabled elements aren’t interactive.

For example, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Tooltip from "react-bootstrap/Tooltip";

export default function App() {
  return (
    <>
      <OverlayTrigger
        trigger="click"
        placement="right"
        overlay={<Tooltip id="tooltip-disabled">Tooltip!</Tooltip>}
      >
        <span className="d-inline-block">
          <Button disabled style={{ pointerEvents: "none" }}>
            Disabled button
          </Button>
        </span>
      </OverlayTrigger>
    </>
  );
}

We add the trigger and placement props so that we see the tooltip when we click on the disabled button.

This is possible because we have a span around the button, which lets us trigger the tooltip when the span is clicked.

Changing Containers

We can change the container to control the DOM element that the overlay is appended to.

For example, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import Overlay from "react-bootstrap/Overlay";
import Popover from "react-bootstrap/Popover";

export default function App() {
  const [show, setShow] = React.useState(false);
  const [target, setTarget] = React.useState(null);
  const ref = React.useRef(null);

  const handleClick = event => {
    setShow(!show);
    setTarget(event.target);
  };

  return (
    <div ref={ref}>
      <Button onClick={handleClick}>click me</Button>

      <Overlay
        show={show}
        target={target}
        placement="bottom"
        container={ref.current}
        containerPadding={20}
      >
        <Popover>
          <Popover.Title as="h1">Title</Popover.Title>
          <Popover.Content>
            Lorem ipsum dolor sit amet, consectetur adipiscing <b>elit</b>.
          </Popover.Content>
        </Popover>
      </Overlay>
    </div>
  );
}

to attach the popover to the div instead of the button.

we set the container to the ref of the div’s ref.

The rest of the code is the same as other popovers.

Updating Position Dynamically

The position of the popover can be updated dynamically.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Button from "react-bootstrap/Button";
import OverlayTrigger from "react-bootstrap/OverlayTrigger";
import Popover from "react-bootstrap/Popover";

const UpdatingPopover = React.forwardRef(
  ({ popper, children, show: _, ...props }, ref) => {
    React.useEffect(() => {
      popper.scheduleUpdate();
    }, [children, popper]);

    return (
      <Popover ref={ref} content {...props}>
        {children}
      </Popover>
    );
  }
);

const longContent = `
  Lorem ipsum dolor sit amet,
  consectetur adipiscing elit.
  Cras ac urna bibendum, pretium magna id,
  imperdiet erat.
`;
const shortContent = "Lorem ipsum";

export default function App() {
  const [content, setContent] = React.useState(shortContent);

  React.useEffect(() => {
    const timerId = setInterval(() => {
      setContent(content === shortContent ? longContent : shortContent);
    }, 3000);

    return () => clearInterval(timerId);
  });

  return (
    <>
      <style type="text/css">
        {`
        .btn-primary {
          position: absolute;
          top: 50vh;
          left: 0vw;
        }
      `}
      </style>
      <OverlayTrigger
        trigger="click"
        overlay={<UpdatingPopover>{content}</UpdatingPopover>}
      >
        <Button>click me!</Button>
      </OverlayTrigger>
    </>
  );
}

to create a tooltip that changes text periodically.

We have th UpdatingPopover component that has the useEffect hook to watch for changes.

We call scheduleUpdate to update the popover.

We watch for changes for the children and popper props to make sure that we call scheduleUpdate when those changes.

We pass the ref and other props to the popover over so the position and other things can be applied.

children is the content of our tooltip.

In App , we have the OverlayTrigger with the text that changes periodically.

It’s triggered when we click on the button.

The content of the tooltip is set by setContent function in the useEffect callback.

Then function we return in there is for clearing the timer when we unmount the component.

Conclusion

We can make popovers dynamic.

Also, we can trigger overlays in disabled elements by adding a wrapper around them.

We can specify the container to attach the overlay to.

Categories
React Bootstrap

React Bootstrap — Customize Navbars

React Bootstrap is one version of Bootstrap made for React.

It’s a set of React components that have Bootstrap styles.

In this article, we’ll look at how to customize navbars to a React app with React Bootstrap.

Containers

We may wrap a navbar in the Container component to center it on a page.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import Container from "react-bootstrap/Container";

export default function App() {
  return (
    <>
      <Container>
        <Navbar bg="primary" variant="dark">
          <Navbar.Brand href="#home">Navbar</Navbar.Brand>
          <Nav className="mr-auto">
            <Nav.Link href="#home">Home</Nav.Link>
            <Nav.Link href="#foo">foo</Nav.Link>
            <Nav.Link href="#bar">bar</Nav.Link>
          </Nav>
        </Navbar>
      </Container>
    </>
  );
}

We center the navbar with the Container .

Placement

We can change the placement of the nav bar with the position utilities that comes with Bootstrap.

We pass in the fixed or sticky props to make the nav stick to the top or the bottom.

For example, we can write:

<Navbar fixed="top" />

to make the navbar stay fixed to the top.

And we can write:

<Navbar fixed="bottom" />

to make it fixed to the bottom.

We can replace fixed with sticky .

Fixed is displayed with respect to the viewport.

And sticky is positioned based on the user’s scroll position.

So we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import Container from "react-bootstrap/Container";

export default function App() {
  return (
    <>
      <Container>
        <Navbar fixed="top">
          <Navbar.Brand href="#home">Navbar</Navbar.Brand>
          <Nav className="mr-auto">
            <Nav.Link href="#home">Home</Nav.Link>
            <Nav.Link href="#foo">foo</Nav.Link>
            <Nav.Link href="#bar">bar</Nav.Link>
          </Nav>
        </Navbar>
      </Container>
    </>
  );
}

to make the navbar always stay on the top of the viewport.

Responsive Behaviors

To make the navbar responsive, we add the Navbar.Toggle and Navbar.Collkapse components to display the collapsed navbar as a menu when the screen is narrower than the given breakpoint.

For instance, we can write:

import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Navbar from "react-bootstrap/Navbar";
import Nav from "react-bootstrap/Nav";
import NavDropdown from "react-bootstrap/NavDropdown";

export default function App() {
  return (
    <>
      <Navbar collapseOnSelect expand="lg" bg="dark" variant="dark">
        <Navbar.Brand href="#home">App</Navbar.Brand>
        <Navbar.Toggle />
        <Navbar.Collapse>
          <Nav className="mr-auto">
            <Nav.Link href="#foo">foo</Nav.Link>
            <Nav.Link href="#bar">bar</Nav.Link>
            <NavDropdown title="Dropdown" id="collasible-nav-dropdown">
              <NavDropdown.Item href="#action/1">action 1</NavDropdown.Item>
              <NavDropdown.Item href="#action/2">action 2</NavDropdown.Item>
              <NavDropdown.Item href="#action/3">action 3</NavDropdown.Item>
              <NavDropdown.Divider />
              <NavDropdown.Item href="#action/4">action 4</NavDropdown.Item>
            </NavDropdown>
          </Nav>
          <Nav>
            <Nav.Link href="#baz">baz</Nav.Link>
            <Nav.Link eventKey={2} href="#qux">
              qux
            </Nav.Link>
          </Nav>
        </Navbar.Collapse>
      </Navbar>
    </>
  );
}

to create a navbar that’s collapsed into a hamburger menu when the screen is narrower than the lg breakpoint.

We have the Navbar.Toggle to display a toggle when the navbar is collapsed.

And Navbar.Collapse lets us display a collapsed navbar for narrow screens.

It’ll be expanded to the full navbar if the screen is within the lg breakpoint or higher.

Inside the Navbar.Collapse component, we have all the content for the navbar like the dropdown, links, and forms.

Navbar.Brand is displayed on the left side.

Conclusion

We can customize navbars with our own styling.

Also, we can make it responsive by adding a few components and props.

Categories
Vue

Create a Todo List with the Oruga Library for Vue

The Oruga library is made by the same developer as the popular Buefy library.

It works with Vue 2.x.

In this article, we’ll look at how to create a todo list app with the Oruga library.

Get Started

We can create a project with Vue CLI by running:

npx vue create todo-list

To get started, we run:

npm install @oruga-ui/oruga --save

or:

yarn add @oruga-ui/oruga

to install the library.

It’s also available from a CDN that we can add to our HTML with a link and script tag:

<link rel="stylesheet" href="//unpkg.com/oruga/dist/oruga.css" />
<script src="//unpkg.com/oruga/dist/oruga.js"></script>

Once we installed the library, we can use it by writing:

import Vue from "vue";
import App from "./App.vue";
import Oruga from "@oruga-ui/oruga";
import "@oruga-ui/oruga/dist/oruga.css";

Vue.use(Oruga);
Vue.config.productionTip = false;

new Vue({
  render: h => h(App)
}).$mount("#app");

in main.js .

We add the CSS and the Oruga plugin.

The components can be added individually with Vue.use also.

Building the App

To build the app, we create the form with:

<form @submit.prevent="addTodo">
  <o-field>
    <o-input placeholder="todo" type="text" v-model="todo"></o-input>
    <o-button type="submit">add</o-button>
  </o-field>
</form>

in App.vue .

We use the o-field compoennt to create the field and the o-input component to add the input.

v-model binds the input value to the todo state.

We add a type button with the o-button component.

Then we add our todo list with:

<div v-for="(t, i) of todos" :key="t.id" class="row">
  <div>
    <o-checkbox v-model="t.done"></o-checkbox>
  </div>
  <div :style="{'text-decoration' : t.done ? 'line-through' : ''}">{{ t.todo }}</div>
  <div>
    <o-button @click="deleteTodo(i)">delete</o-button>
  </div>
</div>

We render a list by using the v-for directive to loop through the todos array.

We have the o-checkbox to create the checkbox.

v-model binds to the done property to let us check and uncheck the box.

t.done is used to show the strikethrough effect if the todo is checked off.

The strikethrough effect is added with the :style binding.

And we have an o-button compoennt to let us delete the todo item when it’s clicked.

In our script tag, we have:

<script>
import { v4 as uuidv4 } from "uuid";

export default {
  name: "App",
  data() {
    return {
      todo: "",
      todos: [],
      columns: [
        {
          field: "todo",
          label: "todo"
        }
      ]
    };
  },
  methods: {
    addTodo() {
      this.todos.push({
        id: uuidv4(),
        todo: this.todo
      });
    },
    deleteTodo(index) {
      this.todos.splice(index, 1);
    }
  }
};
</script>

We have the states used in the templaye.

And we have some methods.

We have the addTodo to add a todo item with a unique ID.

And we have the deleteTodo method to remove the item by its index.

We layout the list rows by writing:

<style>
.row {
  display: flex;
  justify-content: space-between;
}
</style>

This lets us space out the items in the row.

Now we have:

todo list

on the screen.

We can add, check off, and delete an item.

Conclusion

Oruga is an easy to use the component library from the developer that developed Buefy.

We can use it to build interactive Vue apps.

Categories
BootstrapVue

BootstrapVue — Tooltips

In this article, we look at how to use the v-b-tooltip directive to add tooltips.

Tooltips

We can add tooltips with the v-b-tooltip directive.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip.hover title="Tooltip">Hover Me</b-button>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We have the v-b-tooltip directive on our button.

title has the content of the tooltip.

The hover modifier makes the tooltip open on hover.

A tooltip on a disabled element must be triggered by its wrapper element.

Positioning

We can change the position that the tooltip is displayed with modifiers.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip.hover.bottomright title="Tooltip">Hover Me</b-button>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We have the bottomright modifier to display the tooltip on the bottom right.

Other possible choices include top, topleft, topright, right, righttop, rightbottom, bottom, bottomleft, bottomright, left, lefttop, and leftbottom .

Triggers

We can change how the tooltip is triggered by some modifiers.

We can have no modifier, which means it’s opened when an element is hovered or focused.

hover means the tooltip opens on hover.

click means the tooltip opens on click.

focus means the tooltip opens on focus.

We can write:

<template>
  <div id="app">
    <b-button v-b-tooltip.click title="Tooltip">Hover Me</b-button>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Now the tooltip opens on click because of the click modifier.

Disabled Elements

We have to trigger the tooltip on a wrapper if we want to open a tooltip on a disabled element.

For example, we can write:

<template>
  <div id="app">
    <span v-b-tooltip title="Disabled tooltip">
      <b-button variant="primary" disabled>Disabled</b-button>
    </span>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

We put the v-b-tooltip on the span instead of the disabled button.

The result is still having the tooltip disabled on hover or focus.

Focus and Button

Since b-button is rendered as a tag if we add the focus trigger.

We need to add the tabindex='0' attribute.

For instance, we can write:

<template>
  <div id="app">
    <b-button href="#" tabindex="0" v-b-tooltip.focus title="Tooltip">Link</b-button>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Dismiss on Next Click

We need to add the click and blur modifiers to add a tooltip that only opens when the element is clicked and closed when anything in the document is clicked or receives focus.

For example, we write:

<template>
  <div id="app">
    <b-button v-b-tooltip.click.blur title="Tooltip">Link</b-button>
  </div>
</template>

<script>
export default {
  name: "App"
};
</script>

Title

We can set the value of the v-b-tooltip directive to an object to set the options for the tooltip.

The object can have the title property to set the title.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip="options">Link</b-button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      options: {
        title: "hello <strong>world</strong>",
        html: true
      }
    };
  }
};
</script>

We have the title property with some HTML inside.

html is set to true so that the HTML is rendered.

Variants

To change the style, we can add the variant property to the object.

For example, we can write:

<template>
  <div id="app">
    <b-button v-b-tooltip="options">Link</b-button>
  </div>
</template>

<script>
export default {
  name: "App",
  data() {
    return {
      options: {
        title: "hello <strong>world</strong>",
        html: true,
        variant: "info"
      }
    };
  }
};
</script>

Then variant is 'info' , so the background will be green.

Other possible values include, 'primary' , 'secondary' , 'warning' , 'success' , etc.

Make the Tooltip Non-Interactive

We can make a tooltip non-interactive with the noninteractive prop.

Hiding and Showing Tooltips via $root Events

To show a tooltip, we can write:

this.$root.$emit('bv::show::tooltip', 'trigger-button-id')

to show a tooltip that’s added to the element with ID trigger-button-id .

To hide all tooltips, we can write:

this.$root.$emit('bv::hide::tooltip')

this is the component.

Disabling and Enabling Tooltips via $root Events

We can disable all tooltips by writing:

this.$root.$emit('bv::disable::tooltip')

to disable a tooltip by element ID, we can write:

this.$root.$emit('bv::disable::tooltip', 'trigger-button-id')

and to enable a tooltip by ID, we can write:

this.$root.$emit('bv::enable::tooltip', 'trigger-button-id')

Conclusion

We can add a tooltip to an element with the v-b-tooltip directive.

The content can be plain text or HTML.