-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(color-picker): add color picker (#444)
* feat(color-picker): add color picker * fix(color-dialog): import test path * chore(color-picker): update code style * fix(color-picker): update snapshot ignore style * fix(color-picker): add missing end tag * chore(color-picker): rename test file
- Loading branch information
1 parent
edcc6df
commit 3718003
Showing
23 changed files
with
664 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<!-- | ||
type: page | ||
title: Color Picker | ||
location: ./elements/color-picker | ||
layout: default | ||
--> | ||
|
||
# Color Picker | ||
:: | ||
```javascript | ||
::color-picker:: | ||
``` | ||
```css | ||
<style> | ||
section { | ||
display:flex; | ||
justify-content: left; | ||
align-items: baseline; | ||
height: 380px; | ||
padding: 4px; | ||
} | ||
ef-color-picker { | ||
margin-right: 2px; | ||
} | ||
</style> | ||
``` | ||
```html | ||
<section> | ||
<ef-color-picker></ef-color-picker> | ||
<ef-color-picker value="#ff3300"></ef-color-picker> | ||
<ef-color-picker value="#00ff99"></ef-color-picker> | ||
<ef-color-picker value="#0066ff" opened></ef-color-picker> | ||
</section> | ||
``` | ||
:: | ||
|
||
`ef-color-picker` allows users to pick any colours from colour dialog. | ||
|
||
### Basic usage | ||
You can set an initial value via `value` attribute. The `value` must be a string of hex colour code. | ||
|
||
```html | ||
<ef-color-picker value="#001EFF"></ef-color-picker> | ||
``` | ||
|
||
### Getting value | ||
A value of Color picker can be accessed through `value` property. It will fire `value-changed` event when users picked a new colour. `value` will be an empty string if users choose No Color. | ||
|
||
### 'No Color' option | ||
In some circumstances, it might be necessary that the component should allow user to select "no color". This can be done by using a property/attribute `allow-nocolor` to activate this feature. | ||
|
||
Color picker will set attribute/property `value` to `""` when users select no-color from the colour dialog. | ||
|
||
```html | ||
<ef-color-picker allow-nocolor></ef-color-picker> | ||
``` |
33 changes: 33 additions & 0 deletions
33
packages/elemental-theme/src/custom-elements/ef-color-picker.less
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
|
||
@import 'element:ef-color-dialog'; | ||
@import '../responsive'; | ||
|
||
:host { | ||
@color-picker-size: @button-height; | ||
@color-picker-border: @control-border-color; | ||
@color-picker-focused-border-color: @scheme-color-primary; | ||
|
||
outline: none; | ||
box-sizing: border-box; | ||
height: @color-picker-size; | ||
min-width: @color-picker-size; | ||
border: 1px solid @color-picker-border; | ||
|
||
&[disabled], &[readonly] { | ||
border-color: @input-disabled-border-color; | ||
} | ||
|
||
[part="color-item"] { | ||
cursor: pointer; | ||
height: 100%; | ||
} | ||
|
||
&[disabled] [part="color-item"], | ||
&[readonly] [part="color-item"] { | ||
pointer-events: none; | ||
} | ||
|
||
&[focused=visible] { | ||
border-color: @color-picker-focused-border-color; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
packages/elements/src/color-dialog/__test__/color-helpers.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
<title>Color Picker</title> | ||
<link rel="stylesheet" href="/node_modules/@refinitiv-ui/demo-block/demo.css"> | ||
</head> | ||
<body> | ||
<script type="module"> | ||
import '@refinitiv-ui/phrasebook/locale/de/color-picker.js'; | ||
import '@refinitiv-ui/phrasebook/locale/ja/color-picker.js'; | ||
import '@refinitiv-ui/phrasebook/locale/zh/color-picker.js'; | ||
import '@refinitiv-ui/phrasebook/locale/zh-hant/color-picker.js'; | ||
</script> | ||
<script type="module"> | ||
import '@refinitiv-ui/elements/color-picker'; | ||
import '@refinitiv-ui/demo-block'; | ||
</script> | ||
<style> | ||
.output { | ||
width: 100%; | ||
height: 100px; | ||
} | ||
|
||
#hexInputDefault { | ||
width: 100px; | ||
} | ||
|
||
textarea { | ||
height: 100px; | ||
width: 100%; | ||
resize: none; | ||
} | ||
</style> | ||
<demo-block header="Default" layout="normal" tags="default"> | ||
<ef-color-picker id="defaultColorPicker"></ef-color-picker> | ||
<div> | ||
Default Hex Value (Optional): <input id="hexInputDefault" class="hex-input" value=""> | ||
</div> | ||
<div> | ||
<p> Output: </p> | ||
<textarea readonly id="defaultColorOutput"></textarea> | ||
</div> | ||
<script> | ||
// Default Color Picker | ||
const defaultColorPicker = document.getElementById('defaultColorPicker'); | ||
const hexInputDefault = document.getElementById('hexInputDefault'); | ||
const defaultColorOutput = document.getElementById('defaultColorOutput'); | ||
hexInputDefault.addEventListener('change', event => { | ||
defaultColorPicker.setAttribute('value', hexInputDefault.value); | ||
}); | ||
defaultColorPicker.addEventListener('value-changed', event => { | ||
const value = event.detail.value; | ||
hexInputDefault.value = value; | ||
defaultColorOutput.value += 'Value Change : ' + value + '\n'; | ||
}); | ||
</script> | ||
</demo-block> | ||
<demo-block header="Readonly/Disabled" layout="normal" tags="readonly,disabled"> | ||
<ef-color-picker readonly value="#ffffcc"></ef-color-picker> | ||
<ef-color-picker disabled value="#ffffcc"></ef-color-picker> | ||
</demo-block> | ||
</body> | ||
</html> |
42 changes: 42 additions & 0 deletions
42
packages/elements/src/color-picker/__snapshots__/ColorPicker.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
# `color-picker/ColorPicker` | ||
|
||
## `DOM structure` | ||
|
||
#### `DOM structure is correct` | ||
|
||
```html | ||
<div | ||
part="color-item" | ||
style="background-color:#001EFF;" | ||
> | ||
</div> | ||
|
||
``` | ||
|
||
#### `DOM structure is correct when opened` | ||
|
||
```html | ||
<div | ||
part="color-item" | ||
style="background-color:#001EFF;" | ||
> | ||
</div> | ||
<ef-overlay-viewport> | ||
</ef-overlay-viewport> | ||
<ef-overlay-backdrop style="z-index: 103;"> | ||
</ef-overlay-backdrop> | ||
<ef-color-dialog | ||
aria-modal="true" | ||
draggable="" | ||
offset="4" | ||
opened="" | ||
part="dialog" | ||
role="dialog" | ||
style="z-index: 103; pointer-events: auto;" | ||
tabindex="-1" | ||
with-shadow="" | ||
> | ||
</ef-color-dialog> | ||
|
||
``` | ||
|
114 changes: 114 additions & 0 deletions
114
packages/elements/src/color-picker/__test__/color-picker.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import { fixture, expect, elementUpdated, keyboardEvent, oneEvent } from '@refinitiv-ui/test-helpers'; | ||
// import element and theme | ||
import '@refinitiv-ui/elements/color-picker'; | ||
import '@refinitiv-ui/elemental-theme/light/ef-color-picker'; | ||
|
||
describe('color-picker/ColorPicker', () => { | ||
|
||
describe('DOM structure', () => { | ||
it('DOM structure is correct', async () => { | ||
const el = await fixture('<ef-color-picker value="#001EFF"></ef-color-picker>'); | ||
expect(el).shadowDom.to.equalSnapshot(); | ||
}); | ||
it('DOM structure is correct when opened', async () => { | ||
const el = await fixture('<ef-color-picker value="#001EFF" opened></ef-color-picker>'); | ||
expect(el).shadowDom.to.equalSnapshot({ ignoreAttributes: ['class', 'style'] }); | ||
}); | ||
}); | ||
|
||
describe('Value property', () => { | ||
it('Should have default value', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
expect(el.value).to.equal(''); | ||
}); | ||
it('Should update value when set hex color', async () => { | ||
const el = await fixture('<ef-color-picker value="#001EFF"></ef-color-picker>'); | ||
expect(el.value).to.equal('#001EFF'); | ||
}); | ||
it('Should reset to default value when value is invalid', async () => { | ||
const el = await fixture('<ef-color-picker value="hello"></ef-color-picker>'); | ||
expect(el.value).to.equal(''); | ||
}); | ||
it("Should not fires value-changed event when programmatically changes value", async () => { | ||
const value = '#001EFF'; | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
|
||
let eventFired = false; | ||
el.addEventListener('value-changed', () => { | ||
eventFired = true; | ||
}); | ||
el.value = value; | ||
expect(el.value).to.equal(value); | ||
expect(eventFired).to.equal(false); | ||
}); | ||
it('Should fires value-changed event when value change by user interactions', async () => { | ||
const el = await fixture('<ef-color-picker value="#001EFF" opened></ef-color-picker>'); | ||
const dialogEl = el.dialogEl; | ||
const redInput = dialogEl.shadowRoot.getElementById('redInput'); | ||
const confirmBtn = dialogEl.shadowRoot.getElementById('confirmButton'); | ||
redInput.value = 200; | ||
redInput.dispatchEvent(new Event('value-changed')); | ||
await elementUpdated(); | ||
setTimeout(() => confirmBtn.click()); | ||
await oneEvent(el, 'value-changed'); | ||
await elementUpdated(); | ||
expect(el.value).to.equal('#c81eff'); | ||
}); | ||
}); | ||
|
||
describe('No color property', () => { | ||
it('Should not have allow-nocolor property on color dialog', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
el.opened = true; | ||
await elementUpdated(el); | ||
expect(el.dialogEl.hasAttribute('allow-nocolor')).to.be.equal(false); | ||
}); | ||
it('Should pass allow-nocolor property to color dialog', async () => { | ||
const el = await fixture('<ef-color-picker allow-nocolor></ef-color-picker>'); | ||
el.opened = true; | ||
await elementUpdated(el); | ||
expect(el.dialogEl.hasAttribute('allow-nocolor')).to.be.equal(true); | ||
}); | ||
}); | ||
|
||
describe('Color dialog', () => { | ||
it('Should open dialog when click on color picker', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
el.click(); | ||
await elementUpdated(el); | ||
expect(el.dialogEl.opened).to.be.equal(true, 'clicking on color picker should open color dialog'); | ||
}); | ||
it('Should open dialog when opened programmatically', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
el.opened = true; | ||
await elementUpdated(el); | ||
expect(el.dialogEl.hasAttribute('opened')).to.be.equal(true); | ||
}); | ||
it('Should not open color dialog when disabled', async () => { | ||
const el = await fixture('<ef-color-picker disabled></ef-color-picker>'); | ||
el.click(); | ||
expect(el.opened).to.be.equal(false, 'clicking on disabled should do nothing'); | ||
}); | ||
it('Should not open color dialog when readonly', async () => { | ||
const el = await fixture('<ef-color-picker readonly></ef-color-picker>'); | ||
el.click(); | ||
expect(el.opened).to.be.equal(false, 'clicking on readonly should do nothing'); | ||
}); | ||
}); | ||
|
||
describe('Navigation', () => { | ||
it('Should open dialog when press enter key', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
el.dispatchEvent(keyboardEvent('keydown', { key: 'Enter' })); | ||
await elementUpdated(el); | ||
expect(el.dialogEl.opened).to.be.equal(true, 'Enter should open dialog'); | ||
}); | ||
it('Should open dialog when press spacebar key', async () => { | ||
const el = await fixture('<ef-color-picker></ef-color-picker>'); | ||
el.dispatchEvent(keyboardEvent('keydown', { key: 'Spacebar' })); | ||
await elementUpdated(el); | ||
expect(el.dialogEl.opened).to.be.equal(true, 'Spacebar should open dialog'); | ||
}); | ||
}); | ||
}); | ||
|
Oops, something went wrong.