DEV Community

Illia Zub
Illia Zub

Posted on

Build badge in React without SVG and no dependencies

[4 states of build badge](https://codesandbox.io/s/build-badge-react-css-no-svg-git0q)

We at SerpApi show integration test results on documentation pages. Anyone can browse source code of our RSpec files and it’s output. There’s a build badge on all documentation pages which points to the page with the list of test files. Each test file also displays build badge.

[An example of build badges on SerpApi documentation pages](https://serpapi.com/search-api/tests)

We started with Shields.io, but then implemented badges manually in React without SVG and dependencies. Complete code on Codesandbox.io.

Badge component usage

function App() { return ( <div className="App"> <BuildBadge status="loading" summary="loading..." page_url="https://serpapi.com/search-api" /> <BuildBadge status="error" summary="125 examples, 3 failures" page_url="https://serpapi.com/organic-results" /> <BuildBadge status="success" summary="50 examples, 0 failures" page_url="https://serpapi.com/google-scholar-api" /> <BuildBadge status="pending" summary="87 examples, 2 pending" page_url="https://serpapi.com/images-results" /> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Badge component itself

function BuildBadge({ status, summary, page_url }) { let spinner; if (status === "loading") { spinner = <span className="loader" />; } return ( <div className="build-badge-container"> <a href={page_url}> <div className="badge-name">build</div> <div className={`badge-status ${status}`}> {spinner} <span>{summary}</span> </div> </a> </div> ); } 
Enter fullscreen mode Exit fullscreen mode

Badge styles

/* Thanks to https://shields.io/category/build for inspiration */ .build-badge-container { height: 20px; min-width: 200px; margin: 2px 0; } .badge-name, .badge-status { display: inline-block; height: 18px; color: #fff; font-family: Verdana, DejaVu Sans, sans-serif; font-size: 11px; line-height: 1.538; letter-spacing: 0px; text-shadow: 0px 1px rgba(1, 1, 1, 0.3); } .badge-name { background: rgb(95, 95, 95); background: linear-gradient( 180deg, rgba(95, 95, 95, 1) 0%, rgba(78, 78, 78, 1) 100% ); border-radius: 3px 0px 0px 3px; padding: 2px 4px 0px 6px; } .badge-status { border-radius: 0px 3px 3px 0px; padding: 2px 6px 0px 4px; } .badge-status.loading { background: rgb(223, 179, 23); background: linear-gradient( 180deg, rgba(223, 179, 23, 1) 0%, rgba(206, 162, 6, 1) 100% ); } .badge-status.success { background: rgb(223, 179, 23); background: linear-gradient( 180deg, rgba(85, 202, 48, 1) 0%, rgba(62, 183, 17, 1) 100% ); } .badge-status.pending { background: rgb(247, 132, 71); background: linear-gradient( 180deg, rgba(247, 132, 71, 1) 0%, rgba(228, 113, 49, 1) 100% ); } .badge-status.error, .badge-status.failed { background: rgb(221, 103, 81); background: linear-gradient( 180deg, rgba(221, 103, 81, 1) 0%, rgba(201, 84, 61, 1) 100% ); } /* Thanks to https://vineethtrv.github.io/loader/ and https://www.w3schools.com/howto/howto_css_loader.asp for inspiration */ .loader { position: relative; padding-left: 20px; /* spinner size * 2 */ } .loader::before { content: ""; display: inline-block; position: absolute; left: 0; top: 0; margin: 0px 6px 0px 2px; border: 1px solid transparent; border-radius: 50%; border-top: 2px solid #fff; width: 10px; height: 10px; animation: spin 1s ease-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } 
Enter fullscreen mode Exit fullscreen mode

Thanks to Shields.io, Vineeth TR and W3Schools for inspiration.

Top comments (0)