aboutsummaryrefslogtreecommitdiffstats
path: root/webui/src/Label.js
blob: 826d21f55daf509f4db5ab84b58367d7129a68dc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import React from 'react';
import { makeStyles } from '@material-ui/styles';
import {
  getContrastRatio,
  darken,
} from '@material-ui/core/styles/colorManipulator';
import * as allColors from '@material-ui/core/colors';
import { common } from '@material-ui/core/colors';

// JS's modulo returns negative numbers sometimes.
// This ensures the result is positive.
const mod = (n, m) => ((n % m) + m) % m;

// Minimum contrast between the background and the text color
const contrastThreshold = 2.5;

// Filter out the "common" color
const labelColors = Object.entries(allColors)
  .filter(([key, value]) => value !== common)
  .map(([key, value]) => value);

// Generate a hash (number) from a string
const hash = string =>
  string.split('').reduce((a, b) => ((a << 5) - a + b.charCodeAt(0)) | 0, 0);

// Get the background color from the label
const getColor = label =>
  labelColors[mod(hash(label), labelColors.length)][500];

// Guess the text color based on the background color
const getTextColor = background =>
  getContrastRatio(background, common.white) >= contrastThreshold
    ? common.white // White on dark backgrounds
    : common.black; // And black on light ones

const _genStyle = background => ({
  backgroundColor: background,
  color: getTextColor(background),
  borderBottomColor: darken(background, 0.2),
});

// Generate a style object (text, background and border colors) from the label
const genStyle = label => _genStyle(getColor(label));

const useStyles = makeStyles(theme => ({
  label: {
    ...theme.typography.body2,
    padding: '0 6px',
    fontSize: '0.9em',
    margin: '0 1px',
    borderRadius: '3px',
    display: 'inline-block',
    borderBottom: 'solid 1.5px',
    verticalAlign: 'bottom',
  },
}));

function Label({ label }) {
  const classes = useStyles();
  return (
    <span className={classes.label} style={genStyle(label)}>
      {label}
    </span>
  );
}

export default Label;