diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c7fde62c68..ad851ae9bfb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ - Don't propagate a null `onClick` on EuiPanels ([#473](https://github.com/elastic/eui/pull/473)) - Use 1.1px for the `EuiHorizontalRule` height, in order to work around strange Chrome height calculations ([#473](https://github.com/elastic/eui/pull/473)) +- New icons for `logoGithub` and `logoSketch` ([#494](https://github.com/elastic/eui/pull/494)) +- `EuiCard` now has an `href` and `isClickable` prop for better handling hover animations. ([#494](https://github.com/elastic/eui/pull/494)) +- Added `calculateContrast` and `rgbToHex` to services ([#494](https://github.com/elastic/eui/pull/494)) + +**Bug fixes** + +- Fix `reponsive={false}` prop not working when flex groups were nested. ([#494](https://github.com/elastic/eui/pull/494)) +- `EuiBadge` wrapping element changed from a `div` to `span` so it can be nested in text blocks ([#494](https://github.com/elastic/eui/pull/494)) # [`0.0.26`](https://github.com/elastic/eui/tree/v0.0.26) diff --git a/package.json b/package.json index 36bd42173b4..69b082c4434 100644 --- a/package.json +++ b/package.json @@ -96,6 +96,7 @@ "redux-thunk": "^2.2.0", "rimraf": "^2.6.2", "sass-loader": "^6.0.6", + "sass-vars-to-js-loader": "^2.0.2", "shelljs": "^0.8.1", "sinon": "^4.0.1", "style-loader": "^0.19.0", diff --git a/src-docs/src/components/guide_components.scss b/src-docs/src/components/guide_components.scss index b22c9facc9a..e35b7bd7de0 100644 --- a/src-docs/src/components/guide_components.scss +++ b/src-docs/src/components/guide_components.scss @@ -150,6 +150,8 @@ $guideZLevelHighest: $euiZLevel9 + 1000; } } + +@import "../views/guidelines/index"; @import "guide_section/index"; @import "guide_rule/index"; diff --git a/src-docs/src/routes.js b/src-docs/src/routes.js index 5dfca92640b..f9c4e076123 100644 --- a/src-docs/src/routes.js +++ b/src-docs/src/routes.js @@ -19,6 +19,9 @@ import { import ButtonGuidelines from './views/guidelines/button'; +import ColorGuidelines + from './views/guidelines/colors'; + import ModalGuidelines from './views/guidelines/modals'; @@ -222,6 +225,9 @@ const navigation = [{ items: [{ name: 'Buttons', component: ButtonGuidelines, + }, { + name: 'Colors', + component: ColorGuidelines, }, { name: 'Modals', component: ModalGuidelines, diff --git a/src-docs/src/views/guidelines/button.js b/src-docs/src/views/guidelines/button.js index 80912312ed5..bb4caf9f5d8 100644 --- a/src-docs/src/views/guidelines/button.js +++ b/src-docs/src/views/guidelines/button.js @@ -33,9 +33,8 @@ import { import ContextMenu from '../context_menu/context_menu'; export default() => ( - + -

Button guidelines

This page documents patterns for button design, including types, placement, color, and size.

diff --git a/src-docs/src/views/guidelines/colors.js b/src-docs/src/views/guidelines/colors.js new file mode 100644 index 00000000000..619d5c86179 --- /dev/null +++ b/src-docs/src/views/guidelines/colors.js @@ -0,0 +1,245 @@ +import React, { + Fragment, +} from 'react'; +import lightColors from '!!sass-vars-to-js-loader!../../../../src/global_styling/variables/_colors.scss' +import darkColors from '!!sass-vars-to-js-loader!../../../../src/themes/eui/eui_colors_dark.scss' +import { calculateContrast, rgbToHex } from '../../../../src/services' + + +import { + Link, +} from 'react-router'; + +import { + GuidePage, +} from '../../components'; + +import { + EuiText, + EuiSpacer, + EuiFlexGroup, + EuiFlexGrid, + EuiFlexItem, + EuiIcon, + EuiHorizontalRule, + EuiBadge, + EuiToolTip, + EuiDescriptionList, + EuiDescriptionListTitle, + EuiDescriptionListDescription, + EuiLink, +} from '../../../../src/components'; + +const allowedColors = [ + 'euiColorEmptyShade', + 'euiColorLightestShade', + 'euiColorLightShade', + 'euiColorMediumShade', + 'euiColorDarkShade', + 'euiColorDarkestShade', + 'euiColorFullShade', + 'euiColorPrimary', + 'euiColorSecondary', + 'euiColorWarning', + 'euiColorDanger', + 'euiColorAccent', +] + +const visColors = [ + 'euiColorVis0', + 'euiColorVis1', + 'euiColorVis2', + 'euiColorVis3', + 'euiColorVis4', + 'euiColorVis5', + 'euiColorVis6', + 'euiColorVis7', + 'euiColorVis8', + 'euiColorVis9', +] + +const ratingAAA = AAA; + +const ratingAA = AA; + +const ratingAA18 = AA18; + +function renderPaletteColor(color, index) { + return ( + +
+
+ + {color} + + RGB {lightColors[color].r}, {lightColors[color].g}, {lightColors[color].b}
+ HEX {rgbToHex(lightColors[color].rgba).toUpperCase()} +
+
+ + ); +} + +export default() => ( + + + + + +

Core palette

+

+ Elastic UI builds with a very limited palette. We use a core set of three colors, + combined with a green / orange / red qualitative set of three, and finally combine + those against a six-color grayscale. Variation behond these colors is minimal and + always dont with math manipulation against the original set. +

+
+ + + + + {allowedColors.map(function(color, index) { + return renderPaletteColor(color, index); + })} + + + + + +

Qualitative visualization palette

+

+ The following colors are color-blind safe and should be used in + qualitative visualizations. +

+
+ + + + + + {visColors.map(function(color, index) { + return renderPaletteColor(color, index); + })} + + + + + + +

Accessible text contrast

+

+ + WCAG specifications + defines specific contrast ratios between forground text and a background color. + The grid below displays which color combinations pass that rating. In general you sould try to use + a color combination that is AA or above except when using + large text. +

+

Rating definitions

+
    +
  • + {ratingAAA} Passes with a contrast of 7+ +
  • +
  • + AA{' '} + {ratingAA} Passes with a contrast of 4.5+ +
  • +
  • + AA18{' '} + {ratingAA18} Passes with a contrast of 3+, but only if the text displayed is 18px or larger +
  • +
+
+ + + +
+ {allowedColors.map(function(color, index) { + return ( + + + {allowedColors.map(function(color2, index) { + const contrast = ( + calculateContrast( + [lightColors[color].r, lightColors[color].g, lightColors[color].b], + [lightColors[color2].r, lightColors[color2].g, lightColors[color2].b], + ) + ); + + let contrastRating; + if (contrast > 7) { + contrastRating = ( +
+ + {ratingAAA} +
+ ); + } else if (contrast > 4.4) { + contrastRating = ( +
+ + {ratingAA} +
+ ); + } else if (contrast >= 2.9) { + contrastRating = ( +
+ + {ratingAA18} +
+ ); + } + + return ( + + + + Text + + + + +
+ + + {color2} + + + + + Background + + + + +
+ + + {color} + + + + + } + > +
+
+
Text
+
+ {contrastRating} +
+ + + ); + })} + + + + ); + })} +
+ +); diff --git a/src-docs/src/views/guidelines/index.scss b/src-docs/src/views/guidelines/index.scss new file mode 100644 index 00000000000..d2ca66b14fd --- /dev/null +++ b/src-docs/src/views/guidelines/index.scss @@ -0,0 +1,20 @@ +.guidelineColor__palette { + padding: $euiSize; + padding-bottom: $euiSizeXL; +} + +.guidelineColor__swatch { + height: $euiSizeM; + width: $euiSizeM; + border-radius: 50%; +} + +.guidelineColor__stripe { + height: $euiSizeL; + line-height: $euiSizeL; +} + +.guidelineColor__test { + text-align: center; + font-size: $euiFontSizeS; +} diff --git a/src-docs/src/views/guidelines/modals.js b/src-docs/src/views/guidelines/modals.js index 01ee64c6139..fd3452189d3 100644 --- a/src-docs/src/views/guidelines/modals.js +++ b/src-docs/src/views/guidelines/modals.js @@ -24,10 +24,9 @@ import { } from '../../../../src/components'; export default () => ( - + -

Modal guidelines

A modal says “pay attention to me and nothing else.” They work best for focusing users' attention on a short amount of content and getting them to make a decision. @@ -74,16 +73,16 @@ export default () => ( - + - + Input - - + + ( - + - + - - + + @@ -155,8 +154,8 @@ export default () => ( @@ -191,7 +190,7 @@ export default () => ( url="https://imgur.com/cZXGOtz.jpg" />

- + @@ -234,7 +233,7 @@ export default () => (
- + @@ -394,6 +393,6 @@ export default () => ( - +
); diff --git a/src-docs/src/views/guidelines/toasts.js b/src-docs/src/views/guidelines/toasts.js index db639cee6e0..47779ef4fbc 100644 --- a/src-docs/src/views/guidelines/toasts.js +++ b/src-docs/src/views/guidelines/toasts.js @@ -22,9 +22,8 @@ import { } from '../../../../src/components'; export default () => ( - + -

Toast guidelines

This page documents patterns for using toasts, short messages that appears on the lower right corner and time out after a few seconds. diff --git a/src-docs/src/views/guidelines/writing.js b/src-docs/src/views/guidelines/writing.js index c2acf6b1129..21c5aaf399b 100644 --- a/src-docs/src/views/guidelines/writing.js +++ b/src-docs/src/views/guidelines/writing.js @@ -47,7 +47,7 @@ const GuideRuleWriting = ({ }; export default () => ( - +

You can have the most beautiful UI, diff --git a/src-docs/src/views/home/home_view.js b/src-docs/src/views/home/home_view.js index fb86f421d7b..e23bb3b3c02 100644 --- a/src-docs/src/views/home/home_view.js +++ b/src-docs/src/views/home/home_view.js @@ -1,4 +1,10 @@ import React from 'react'; +import {hashHistory} from 'react-router'; +import sassColors from '!!sass-vars-to-js-loader!../../../../src/global_styling/variables/_colors.scss' + +import { + Link, +} from 'react-router'; import { EuiText, @@ -8,138 +14,162 @@ import { EuiFlexItem, EuiSpacer, EuiHorizontalRule, + EuiCard, + EuiIcon, + EuiButton, + EuiTitle, + EuiLink, + EuiToolTip, } from '../../../../src/components'; const pkg = require('../../../../package.json'); -const colors = [ - { - color: 'euiColorPrimary', - hex: '#0079a5', - }, - { - color: 'euiColorSecondary', - hex: '#00A69B', - }, - { - color: 'euiColorAccent', - hex: '#DD0A73', - }, - { - color: 'euiColorDanger', - hex: '#A30000', - }, - { - color: 'euiColorWarning', - hex: '#E5830E', - }, -]; - -const grays = [ - { - color: 'euiColorEmptyShade', - hex: '#FFF', - textColor: '#222' - }, - { - color: 'euiColorLightestShade', - hex: '#F5F5F5', - textColor: '#222' - }, - { - color: 'euiColorLightShade', - hex: '#D9D9D9', - textColor: '#222' - }, - { - color: 'euiColorMediumShade', - hex: '#999999', - textColor: '#FFF' - }, - { - color: 'euiColorDarkShade', - hex: '#666666', - textColor: '#FFF' - }, - { - color: 'euiColorDarkestShade', - hex: '#3F3F3F', - textColor: '#FFF' - }, - { - color: 'euiColorFullShade', - hex: '#000000', - textColor: '#FFF' - }, -]; - -const sizes = [ - { - name: 'Extra small', - size: 4, - }, - { - name: 'Small', - size: 8, - }, - { - name: 'Medium', - size: 12, - }, - { - name: 'default', - size: 16, - }, - { - name: 'Large', - size: 24, - }, - { - name: 'Extra large', - size: 32, - }, - { - name: 'Extra extra large', - size: 40, - }, -]; - -const fontSizes = [ - { - name: 'Extra small', - size: 12, - }, - { - name: 'Small', - size: 14, - }, - { - name: 'Default', - size: 16, - }, - { - name: 'Large', - size: 24, - }, - { - name: 'Extra extra large', - size: 32, - }, -]; - export const HomeView = () => (

+ + + +

Elastic UI framework

+
+
+ + + + +

+ Version:{' '} + + { pkg.version } + +

+
+ + + +
+
+ + + + + + + Sketch libraries + + + + + + + + + +
+ -

Elastic UI Framework

-

Version: { pkg.version }

- Elastic UI teams use the UI Framework to build Kibana’s user interface. Please see - the general Kibana docs for information on how to use Kibana, and - the plugin-specific section for - help developing Kibana plugins. You can find the source for the Elastic UI Framework on GitHub. + The Elastic UI framework (EUI) is a design library in use at Elastic to + build internal products that need to share our aesthetics. + It distributes UI React components and static assets for use + in building web layouts. Alongside the React components is a SASS/CSS + layer that can be used independently on its own. + If this is your first time using EUI you might want to read up on{' '} + how to consume EUI{' '} + and Kibana plugin development{' '} + in general.

- -

Goals

+
+ + + + + + + + + + + + + + + + } + title="Icons" + description="Our SVG icon library gives you full control over size and color" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Design goals

EUI has the following primary goals..

  • EUI is accessible to everyone. Use high contrast, @@ -159,105 +189,5 @@ export const HomeView = () => (
- - - - - - -

Colors

-

- The UI Framework uses a very limited palette. Every color is - calculated using Sass color from one of the below. -

-

Theming

-

- Theming is achieved by overwriting these twelve colors with - a different set. This is why it is very important never to use hex colors in - EUI outside of the global variable files. -

-

Accessibility

-

- We aim to be at least AA compliant in our design. That means that only some of the colors - to the right should be used for text. -

-
-
- - - {colors.map((item, index) => { - return ( - -

${item.color}

-

{item.hex}

-
- ); - })} - - {grays.map((item, index) => { - return ( - -

${item.color}

-

{item.hex}

-
- ); - })} -
-
-
- - - - -

Spacing and sizing

-

- EUI is a minimalist design and as such needs to be very precise - with the spacing and padding between and around items. 16px is our - magic number. It is our default font-size and our default spacing size. - Larger numbers can be used, but must always be - a multiple of 16px beyond these sizes below. -

- -

Sizing when passed as values to props should always be xs / s / m / l / xl ...etc

- -
- - - - - -

Element sizes / paddings / margins

- {sizes.map((item, index) => { - return ( -
- - - -
- - -

- {item.size}px - {item.name} -

-
- -
- ); - })} -
- -

Font sizes

- {fontSizes.map((item, index) => { - return ( -
- {item.name} is {item.size}: Something about a lazy fox? -
- ); - })} -
-
- - -
); diff --git a/src-docs/src/views/icon/logos.js b/src-docs/src/views/icon/logos.js index 60c65af899b..1e0d1db01f4 100644 --- a/src-docs/src/views/icon/logos.js +++ b/src-docs/src/views/icon/logos.js @@ -16,6 +16,7 @@ const iconTypes = [ 'logoElastic', 'logoElasticSearch', 'logoElasticStack', + 'logoGithub', 'logoGmail', 'logoKibana', 'logoKubernetes', @@ -23,6 +24,7 @@ const iconTypes = [ 'logoMySQL', 'logoNginx', 'logoRedis', + 'logoSketch', 'logoSlack', 'logoWebhook', 'logoXpack', diff --git a/src-docs/src/views/image/image.js b/src-docs/src/views/image/image.js index 5b3ec595e17..12439358179 100644 --- a/src-docs/src/views/image/image.js +++ b/src-docs/src/views/image/image.js @@ -8,8 +8,8 @@ export default () => ( ); diff --git a/src-docs/src/views/image/image_size.js b/src-docs/src/views/image/image_size.js index 7f02f61f802..d22c40bc363 100644 --- a/src-docs/src/views/image/image_size.js +++ b/src-docs/src/views/image/image_size.js @@ -13,7 +13,7 @@ export default () => ( allowFullScreen caption="Small" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" /> ( allowFullScreen caption="Medium" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" /> ( allowFullScreen caption="Large" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" /> ( allowFullScreen caption="Extra large" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" /> ( allowFullScreen caption="Original" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" /> ( size="fullWidth" caption="Full width" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/1000x1000/?Nature" />
); diff --git a/src-docs/src/views/image/image_zoom.js b/src-docs/src/views/image/image_zoom.js index 67e9f3534f8..38f791edfb2 100644 --- a/src-docs/src/views/image/image_zoom.js +++ b/src-docs/src/views/image/image_zoom.js @@ -15,7 +15,7 @@ export default () => ( allowFullScreen caption="Click me" alt="Accessible image alt goes here" - url="https://i.imgur.com/4qx7HhE.jpg" + url="https://source.unsplash.com/2000x1000/?darkbackground" /> @@ -26,7 +26,7 @@ export default () => ( caption="Click me" alt="Accessible image alt goes here" fullScreenIconColor="dark" - url="https://78.media.tumblr.com/a68012e7630f4633e83f58f49cb4fb0a/tumblr_ni61qyN2X91rv33k2o1_500.jpg" + url="https://source.unsplash.com/1000x2000/?lightbackground" /> diff --git a/src/components/badge/__snapshots__/badge.test.js.snap b/src/components/badge/__snapshots__/badge.test.js.snap index 4c58bc5fb44..040662074b3 100644 --- a/src/components/badge/__snapshots__/badge.test.js.snap +++ b/src/components/badge/__snapshots__/badge.test.js.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`EuiBadge is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color accent is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color danger is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color default is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color primary is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color secondary is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props color warning is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props iconSide left is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props iconSide right is rendered 1`] = ` -
-
+ `; exports[`EuiBadge props iconType is rendered 1`] = ` -
-
+ `; diff --git a/src/components/badge/badge.js b/src/components/badge/badge.js index d5328b52c62..c7c910d08ac 100644 --- a/src/components/badge/badge.js +++ b/src/components/badge/badge.js @@ -98,7 +98,7 @@ export const EuiBadge = ({ ); } else { return ( -
-
+ ); } }; diff --git a/src/components/card/card.js b/src/components/card/card.js index 08f0547b089..34c6c7de737 100644 --- a/src/components/card/card.js +++ b/src/components/card/card.js @@ -5,6 +5,10 @@ import classNames from 'classnames'; import { EuiText } from '../text'; import { EuiTitle } from '../title'; +import { + checkHrefAndOnClick, +} from '../../services'; + const textAlignToClassNameMap = { left: 'euiCard--leftAligned', center: 'euiCard--centerAligned', @@ -21,14 +25,16 @@ export const EuiCard = ({ image, footer, onClick, + href, textAlign, + isClickable, ...rest, }) => { const classes = classNames( 'euiCard', textAlignToClassNameMap[textAlign], { - 'euiCard--isClickable': onClick, + 'euiCard--isClickable': onClick || href || isClickable, }, className, ); @@ -48,12 +54,18 @@ export const EuiCard = ({ ); } - const OuterElement = onClick ? 'button' : 'div'; + let OuterElement = 'div'; + if (onClick) { + OuterElement = 'button'; + } else if (href) { + OuterElement = 'a'; + } return ( @@ -102,6 +114,7 @@ EuiCard.propTypes = { * Use only if you want to forego a button in the footer and make the whole card clickable */ onClick: PropTypes.func, + href: checkHrefAndOnClick, textAlign: PropTypes.oneOf(ALIGNMENTS), }; diff --git a/src/components/flex/_flex_item.scss b/src/components/flex/_flex_item.scss index 25d2af6aac5..58423628af1 100644 --- a/src/components/flex/_flex_item.scss +++ b/src/components/flex/_flex_item.scss @@ -23,7 +23,7 @@ // On mobile we force them to stack and act the same. @include screenXSmall { - .euiFlexGroup--responsive .euiFlexItem { + .euiFlexGroup--responsive > .euiFlexItem { width: 100% !important; flex-basis: 100% !important; margin-left: 0 !important; diff --git a/src/components/icon/__snapshots__/icon.test.js.snap b/src/components/icon/__snapshots__/icon.test.js.snap index b26cc370362..5d0ad7a3534 100644 --- a/src/components/icon/__snapshots__/icon.test.js.snap +++ b/src/components/icon/__snapshots__/icon.test.js.snap @@ -2229,6 +2229,20 @@ exports[`EuiIcon renders type logoElasticStack 1`] = ` `; +exports[`EuiIcon renders type logoGithub 1`] = ` + + + +`; + exports[`EuiIcon renders type logoGmail 1`] = ` `; +exports[`EuiIcon renders type logoSketch 1`] = ` + + + + + + + + + + +`; + exports[`EuiIcon renders type logoSlack 1`] = ` + + diff --git a/src/components/icon/assets/logo_sketch.svg b/src/components/icon/assets/logo_sketch.svg new file mode 100644 index 00000000000..455dec85485 --- /dev/null +++ b/src/components/icon/assets/logo_sketch.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/components/icon/icon.js b/src/components/icon/icon.js index 4989c540517..8da6080330e 100644 --- a/src/components/icon/icon.js +++ b/src/components/icon/icon.js @@ -83,6 +83,7 @@ import logoDocker from './assets/logo_docker.svg'; import logoElastic from './assets/logo_elastic.svg'; import logoElasticSearch from './assets/logo_elastic_search.svg'; import logoElasticStack from './assets/logo_elastic_stack.svg'; +import logoGithub from './assets/logo_github.svg'; import logoGmail from './assets/logo_gmail.svg'; import logoKibana from './assets/logo_kibana.svg'; import logoKubernetes from './assets/logo_kubernetes.svg'; @@ -90,6 +91,7 @@ import logoLogstash from './assets/logo_logstash.svg'; import logoMySQL from './assets/logo_mysql.svg'; import logoNginx from './assets/logo_nginx.svg'; import logoRedis from './assets/logo_redis.svg'; +import logoSketch from './assets/logo_sketch.svg'; import logoSlack from './assets/logo_slack.svg'; import logoWebhook from './assets/logo_webhook.svg'; import logoXpack from './assets/logo_xpack.svg'; @@ -226,12 +228,14 @@ const typeToIconMap = { logoElasticSearch, logoElasticStack, logoGmail, + logoGithub, logoKibana, logoKubernetes, logoLogstash, logoMySQL, logoNginx, logoRedis, + logoSketch, logoSlack, logoWebhook, logoXpack, diff --git a/src/global_styling/variables/_colors.scss b/src/global_styling/variables/_colors.scss index d386ddca5e3..53566f70f51 100644 --- a/src/global_styling/variables/_colors.scss +++ b/src/global_styling/variables/_colors.scss @@ -29,7 +29,7 @@ // Core $euiColorPrimary: #0079a5 !default; -$euiColorSecondary: #00A69B !default; +$euiColorSecondary: #017F75 !default; $euiColorAccent: #DD0A73 !default; $euiColorHighlight: #FFFBF1 !default; $euiColorGhost: #FFF !default; @@ -37,7 +37,7 @@ $euiColorGhost: #FFF !default; // Status $euiColorSuccess: $euiColorSecondary !default; $euiColorDanger: #A30000 !default; -$euiColorWarning: #E5830E !default; +$euiColorWarning: #CF3800 !default; // Grays $euiColorEmptyShade: #FFF !default; diff --git a/src/services/color/index.js b/src/services/color/index.js index 589bc7b25bb..750249aabcb 100644 --- a/src/services/color/index.js +++ b/src/services/color/index.js @@ -1,3 +1,5 @@ export { isColorDark } from './is_color_dark'; -export { hexToRgb } from './hex_to_rgb.js'; +export { hexToRgb } from './hex_to_rgb'; +export { rgbToHex } from './rgb_to_hex'; +export { calculateContrast, calculateLuminance } from './luminance_and_contrast'; export { VISUALIZATION_COLORS } from './visualization_colors'; diff --git a/src/services/color/luminance_and_contrast.js b/src/services/color/luminance_and_contrast.js new file mode 100644 index 00000000000..23ce35692df --- /dev/null +++ b/src/services/color/luminance_and_contrast.js @@ -0,0 +1,23 @@ +function calculateLuminance(r, g, b) { + var a = [r, g, b].map(function (v) { + v /= 255; + return v <= 0.03928 + ? v / 12.92 + : Math.pow( (v + 0.055) / 1.055, 2.4 ); + }); + return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722; +} + +function calculateContrast(rgb1, rgb2) { + let contrast = ( + (calculateLuminance(rgb1[0], rgb1[1], rgb1[2]) + 0.05) + / (calculateLuminance(rgb2[0], rgb2[1], rgb2[2]) + 0.05) + ); + + if (contrast < 1) { + contrast = 1 / contrast; + } + return contrast; +} + +export { calculateLuminance, calculateContrast }; diff --git a/src/services/color/rgb_to_hex.js b/src/services/color/rgb_to_hex.js new file mode 100644 index 00000000000..e4d0d06ab62 --- /dev/null +++ b/src/services/color/rgb_to_hex.js @@ -0,0 +1,9 @@ +function rgbToHex(rgb){ + rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i); + return (rgb && rgb.length === 4) ? "#" + + ("0" + parseInt(rgb[1],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[2],10).toString(16)).slice(-2) + + ("0" + parseInt(rgb[3],10).toString(16)).slice(-2) : ''; +} + +export { rgbToHex }; diff --git a/src/services/index.js b/src/services/index.js index c3c1fea6743..b4598f5f9e1 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -17,6 +17,10 @@ export { export { isColorDark, + calculateContrast, + calculateLuminance, + hexToRgb, + rgbToHex, VISUALIZATION_COLORS, } from './color'; diff --git a/yarn.lock b/yarn.lock index 537f89bb405..9cd4a6399b5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -408,7 +408,7 @@ async@^1.4.0, async@^1.4.2, async@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" -async@^2.1.2, async@^2.1.4, async@^2.1.5, async@^2.5.0: +async@^2.1.2, async@^2.1.4, async@^2.1.5, async@^2.5.0, async@^2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/async/-/async-2.6.0.tgz#61a29abb6fcc026fea77e56d1c6ec53a795951f4" dependencies: @@ -3413,7 +3413,7 @@ fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" -fs-extra@5.0.0: +fs-extra@5.0.0, fs-extra@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-5.0.0.tgz#414d0110cdd06705734d055652c5411260c31abd" dependencies: @@ -4224,7 +4224,13 @@ interpret@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" -invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: +invariant@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.1.tgz#b097010547668c7e337028ebe816ebe36c8a8d54" + dependencies: + loose-envify "^1.0.0" + +invariant@2.2.2, invariant@^2.0.0, invariant@^2.2.0, invariant@^2.2.1, invariant@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.2.tgz#9e1f56ac0acdb6bf303306f338be3b204ae60360" dependencies: @@ -5259,6 +5265,14 @@ lodash.flattendeep@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" +lodash.foreach@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + +lodash.frompairs@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/lodash.frompairs/-/lodash.frompairs-4.0.1.tgz#bc4e5207fa2757c136e573614e9664506b2b1bd2" + lodash.get@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-3.7.0.tgz#3ce68ae2c91683b281cc5394128303cbf75e691f" @@ -5274,6 +5288,10 @@ lodash.isarray@^3.0.0: version "3.0.4" resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" +lodash.isarray@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403" + lodash.isequal@^4.1.1: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" @@ -5282,6 +5300,10 @@ lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" +lodash.mapkeys@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.mapkeys/-/lodash.mapkeys-4.6.0.tgz#df2cfa231d7c57c7a8ad003abdad5d73d3ea5195" + lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -5314,14 +5336,18 @@ lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" -lodash@^3.10.1, lodash@^3.3.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" +lodash@4.11.1: + version "4.11.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.11.1.tgz#a32106eb8e2ec8e82c241611414773c9df15f8bc" -lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.4: +lodash@4.17.4, lodash@^4.0.0, lodash@^4.0.1, lodash@^4.11.1, lodash@^4.13.1, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.2, lodash@^4.17.3, lodash@^4.2.0, lodash@^4.2.1, lodash@^4.3.0, lodash@~4.17.4: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +lodash@^3.10.1, lodash@^3.3.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" + lodash@^4.17.4: version "4.17.5" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" @@ -6959,6 +6985,13 @@ qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" +query-ast@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/query-ast/-/query-ast-1.0.1.tgz#6bb4ea8b7731cc5e90208e79c41bc9c3f09c52aa" + dependencies: + invariant "2.2.2" + lodash "4.17.4" + query-string@^4.1.0, query-string@^4.2.2: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -7697,6 +7730,21 @@ sass-loader@^6.0.6: lodash.tail "^4.1.1" pify "^3.0.0" +sass-vars-to-js-loader@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/sass-vars-to-js-loader/-/sass-vars-to-js-loader-2.0.2.tgz#210e97be7b02c3f305dddff2a4bc76e80d4ac0e1" + dependencies: + async "^2.6.0" + fs-extra "^5.0.0" + loader-utils "^1.1.0" + lodash.camelcase "^4.3.0" + lodash.foreach "^4.5.0" + lodash.frompairs "^4.0.1" + lodash.isarray "^4.0.0" + lodash.mapkeys "^4.6.0" + query-ast "^1.0.1" + scss-parser "^1.0.0" + sax@^1.2.4, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -7711,6 +7759,13 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" +scss-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/scss-parser/-/scss-parser-1.0.0.tgz#1d50a98c9afc77dcf9308e851f5c0c5693487868" + dependencies: + invariant "2.2.1" + lodash "4.11.1" + scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"