Skip to content
This repository has been archived by the owner on May 2, 2021. It is now read-only.

Commit

Permalink
Merge pull request #138 from no23reason/features/inline-styles
Browse files Browse the repository at this point in the history
Support CSS cell styling
  • Loading branch information
no23reason authored Feb 10, 2019
2 parents 1e21709 + 61a2ef4 commit f57ee82
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 36 deletions.
48 changes: 37 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,89 @@
[![build status](https://secure.travis-ci.org/no23reason/react-qr-svg.svg)](http://travis-ci.org/no23reason/react-qr-svg) [![npm version](https://img.shields.io/npm/v/react-qr-svg.svg)](https://www.npmjs.com/package/react-qr-svg) [![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg)](http://commitizen.github.io/cz-cli/) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Greenkeeper badge](https://badges.greenkeeper.io/no23reason/react-qr-svg.svg)](https://greenkeeper.io/)

# react-qr-svg

React component for rendering SVG QR codes

## Demo

Basic demo can be found at the [demo page](https://no23reason.github.io/react-qr-svg/#/demo).

## Why SVG?

Most of the existing React components for QR (namely [`qrcode.react`](https://github.com/zpao/qrcode.react), which was used as a starting point for this project) use `<canvas>` for rendering.

This is fine for most scenarios, however when trying to print such code, it gets blurry. This is caused by the fact that `<canvas>` contents get rastered and *then* scaled in the process resulting in the blurriness.
This is fine for most scenarios, however when trying to print such code, it gets blurry. This is caused by the fact that `<canvas>` contents get rastered and _then_ scaled in the process resulting in the blurriness.

On the other hand, SVG retains the vector information of its contents and therefore is scaled properly when printed.

## Basic Usage

Install using `npm`:

```js
npm install react-qr-svg --save
```

Then use in your application like this:

```js
import React from 'react';
import { QRCode } from 'react-qr-svg';
import React from "react";
import { QRCode } from "react-qr-svg";

class Demo extends React.Component {
render() {
return (<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
level="Q"
style={{ width: 256 }}
value="some text"
/>);
return (
<QRCode
bgColor="#FFFFFF"
fgColor="#000000"
level="Q"
style={{ width: 256 }}
value="some text"
/>
);
}
}
```

## Props

The props available are (shown with default values):

```js
{
value: '', // The value to encode in the code
level: 'L', // QR Error correction level
bgColor: '#FFFFFF', // Color of the bright squares
fgColor: '#000000', // Color of the dark squares
cellClassPrefix: '', // Prefix of the CSS classes, if not specified, bgColor and fgColor are ignored
}
```

The `level` prop corresponds to [Error correction level](https://en.wikipedia.org/wiki/QR_code#Error_correction) so the valid values are `L`, `M`, `Q` and `H`.

You can also specify all the props that are valid for the `<svg>` React element (e.g. `style`, `className` or `width` which you can use to specify the size of the QR code).

## CSS styling

You can use CSS to set the QR code colors instead of the `bgColor` and `fgColor` props. You just need to specify the `cellClassPrefix` prop and three CSS classes will become available for you to style.

Let's say you used `my-qr-code` as the `cellClassPrefix`. The generated classes are:

* `my-qr-code-cell` for all the cells
* `my-qr-code-cell-empty` for the empty cells

* `my-qr-code-cell-filled` for the filled cells

You can then set the colors using the `fill` CSS property. See [CSS Demo](https://no23reason.github.io/react-qr-svg/#/css-demo) for an example.

**Note**: If you specify `cellClassPrefix`, `bgColor` and `fgColor` values are ignored.

## Acknowledgements

This project is heavily inspired by the [`qrcode.react`](https://github.com/zpao/qrcode.react) project.

This project uses the [`react-component-boilerplate`](https://github.com/survivejs/react-component-boilerplate).

## License

*react-qr-svg* is available under MIT. See [LICENSE](https://github.com/no23reason/react-qr-svg/tree/master/LICENSE) for more details.
_react-qr-svg_ is available under MIT. See [LICENSE](https://github.com/no23reason/react-qr-svg/tree/master/LICENSE) for more details.
10 changes: 0 additions & 10 deletions demo/App.jsx

This file was deleted.

36 changes: 36 additions & 0 deletions demo/CssDemo.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from "react";
import Layout from "./Layout";
import { QRCode } from "../src";

const css = `.my-qr-code-cell {
opacity: 0.8;
}
.my-qr-code-cell-empty {
fill: lightgray;
}
.my-qr-code-cell-filled {
fill: brown;
}`;

const CssDemo = () => (
<Layout>
<style>{css}</style>
<p>CSS used:</p>
<pre>{css}</pre>
<p>
Result with <code>cellClassPrefix="my-qr-code"</code>:
</p>
<div style={{ textAlign: "center" }}>
<QRCode
cellClassPrefix="my-qr-code"
level="L"
style={{ width: 500 }}
value="You can use CSS as well!"
/>
</div>
</Layout>
);

export default CssDemo;
9 changes: 5 additions & 4 deletions demo/Demo.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from "react";
import { QRCode } from "../src/index";
import Layout from "./Layout";
import { QRCode } from "../src";

class Demo extends React.Component {
constructor(props, context) {
Expand Down Expand Up @@ -29,7 +30,7 @@ class Demo extends React.Component {
updateFgColor,
} = this;
return (
<div>
<Layout>
<form className="pure-form pure-form-stacked">
<fieldset>
<div className="pure-g">
Expand Down Expand Up @@ -73,7 +74,7 @@ class Demo extends React.Component {
</div>
</fieldset>
</form>
<div className="qrcode">
<div style={{ textAlign: "center" }}>
<QRCode
bgColor={state.bgColor}
fgColor={state.fgColor}
Expand All @@ -82,7 +83,7 @@ class Demo extends React.Component {
value={state.value}
/>
</div>
</div>
</Layout>
);
}
}
Expand Down
12 changes: 12 additions & 0 deletions demo/Layout.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from "react";
import PropTypes from "prop-types";

const Layout = ({ children }) => (
<article style={{ margin: "1rem", maxWidth: "60rem" }}>{children}</article>
);

Layout.propTypes = {
children: PropTypes.node,
};

export default Layout;
7 changes: 6 additions & 1 deletion docs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ const pages = [
{
path: "/demo",
title: "Demo",
content: pageLoader(() => import("../demo/App.jsx")),
content: pageLoader(() => import("../demo/Demo.jsx")),
},
{
path: "/css-demo",
title: "CSS Demo",
content: pageLoader(() => import("../demo/CssDemo.jsx")),
},
];

Expand Down
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ interface QRCodeProps {
* Color of the dark squares
*/
fgColor?: string;
/**
* Prefix for the cell CSS classes
*/
cellClassPrefix?: string;
}

/**
Expand Down
39 changes: 29 additions & 10 deletions src/components/qr-svg.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export function QRCode({
level = "L",
bgColor = "#FFFFFF",
fgColor = "#000000",
cellClassPrefix = "",
...otherProps
} = {}) {
// adapted from https://github.com/zpao/qrcode.react/blob/master/src/index.js
Expand All @@ -18,6 +19,12 @@ export function QRCode({

const cells = qrcode.modules;

const cellClassName = cellClassPrefix && `${cellClassPrefix}-cell`;
const emptyCellClassName =
cellClassPrefix && `${cellClassName} ${cellClassPrefix}-cell-empty`;
const filledCellClassName =
cellClassPrefix && `${cellClassName} ${cellClassPrefix}-cell-filled`;

let cellIndex = 0; // we use simple order as a key just to avoid the key warning here

return (
Expand All @@ -27,16 +34,27 @@ export function QRCode({
{...otherProps}
>
{cells.map((row, rowIndex) =>
row.map((cell, colIndex) => (
<rect
height={1}
key={cellIndex++} // string was too slow here
style={{ fill: cell ? fgColor : bgColor }}
width={1}
x={colIndex}
y={rowIndex}
/>
)),
row.map((cell, colIndex) => {
const className = cell
? filledCellClassName
: emptyCellClassName;
const classNameProp = className ? { className } : null;

// Only use the fill if no cellClassPrefix was set. See https://github.com/no23reason/react-qr-svg/issues/136 for reasoning.
const fill = !classNameProp && (cell ? fgColor : bgColor);
const styleProp = fill ? { style: { fill } } : null;
return (
<rect
height={1}
key={cellIndex++} // string was too slow here
{...styleProp}
{...classNameProp}
width={1}
x={colIndex}
y={rowIndex}
/>
);
}),
)}
</svg>
);
Expand All @@ -48,4 +66,5 @@ QRCode.propTypes = {
level: PropTypes.oneOf(["L", "M", "Q", "H"]),
bgColor: PropTypes.string,
fgColor: PropTypes.string,
cellClassPrefix: PropTypes.string,
};
1 change: 1 addition & 0 deletions tests/typescript/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Demo extends React.Component<IDemoProps> {
/>
<QRCode value="Only value here" />
<QRCode value="Style here" style={{ width: 250 }} />
<QRCode value="CSS styling" cellClassPrefix="foo" />
</div>
);
}
Expand Down

0 comments on commit f57ee82

Please sign in to comment.