@ewc-lib/ewc-icon-button-group 2.0.2-alpha → 3.0.0-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/events.png ADDED
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ewc-lib/ewc-icon-button-group",
3
3
  "//": "please always keep version in sync with constructor in main.js",
4
- "version": "2.0.2-alpha",
4
+ "version": "3.0.0-alpha",
5
5
  "basedOnStandard": "3.0.1",
6
6
  "description": "",
7
7
  "main": "src/main.js",
@@ -16,6 +16,6 @@
16
16
  "@ewc-lib/ewc-css-common": "0.1.0"
17
17
  },
18
18
  "dependencies": {
19
- "@ewc-lib/ewc-icon-button": "2.0.1-alpha"
19
+ "@ewc-lib/ewc-icon-button": "2.1.0-alpha"
20
20
  }
21
21
  }
package/readme.md CHANGED
@@ -7,8 +7,8 @@ The EWC Icon-button group component provides standardized radiobuttons for Euros
7
7
  ## Features
8
8
 
9
9
  - Responsive design that adapts to different screen sizes
10
- - Customizable
11
- - Tab-Focus trap, keeping focus within the dialog
10
+ - Customizable (there are 4 buttons available, arbitrary order)
11
+ - Button group respects tri-state of button (pressed/not pressed/disabled)
12
12
  - Accessibility compliant
13
13
 
14
14
  ## Screenshot
@@ -23,37 +23,83 @@ The ewc-icon-button-group HTML tag encloses ewc-icon-buttons. It modifies their
23
23
 
24
24
  Note that adding/removing children at runtime is not supported.
25
25
 
26
- Regarding focus, arrow keys work analoguous to tab key.
26
+ Regarding focus, arrow keys work alongside the tab key.
27
27
 
28
- Within a button-group, only buttons that are not currently pressed can be focussed.
28
+ Within a button-group, only buttons that are not currently pressed and not disabled can be focussed.
29
29
 
30
30
  # API
31
31
 
32
32
  ## Properties and Attributes
33
33
 
34
- | Attribute | Type | Default | Description
35
- |-----------------------|---------------------|---------|------------
36
- | selectedIndex | Number | 0 | The ordinal number of the button pressed. 0 based.
37
- | breakpoint | String | 650px | if viewport width is smaller than this, the buttons are displayed without label
34
+ | Property | Attribute | Type | Default | Description
35
+ |----------------|-----------------------|---------------------|---------|------------
36
+ | selectedIndex | selectedIndex | Number | 0 | The 0-based ordinal number of the button pressed.
37
+ | selectedId | selectedId | Number | - | The id of the button pressed. Can be null if the id attribute is not set.
38
+ | breakpoint | breakpoint | CSS String | 650px | if viewport width is smaller than this, the buttons are displayed without label.
39
+ | selectedElement| | HTML element | - | The HTML element currently selected. Read only.
40
+
38
41
 
39
42
  Notes:
40
43
 
41
- - The attributes do not support modification at runtime.
44
+ - The attribute **breakpoint** does not support modification at runtime, all others do.
42
45
  - The width of an ewc-icon-button (when used in conjunction with the ewc-icon-button-group) is determined as follows:
43
46
  - width of button-group < breakpoint: size or weight attribute of ewc-icon-button
44
- - width of button-group > breakpoint: 125px as per standard definition
47
+ - width of button-group > breakpoint: 125px as per definition in the EWC standards
48
+
49
+ ## Enabling / Disabling
50
+
51
+ While selection is handled via attributes and properties, enabling/disabling is done with the following public member functions.
52
+
53
+ setEnabledById(id, isEnabled)
54
+ setEnabledByIndex(index, isEnabled)
55
+
56
+ - isEnabled is a boolean
57
+ - id is of type string
58
+ - index of type number
59
+
60
+ ## Caution
61
+
62
+ - ❗Refrain from setting state on a button directly when used in a group.
63
+ - This is because ewc-button-icon group is not aware of state changes it doesn't initiate itself.
64
+ - For the state "true" and "false", let ewc-button-icon handle this via **selectedIndex** or **selectedId**
65
+ - To disable a button, use **setEnabledByIndex** or **setEnabledById**
66
+ - Note that reading the state of a button is unproblematic - this note is just about setting the state.
67
+
68
+ ### Responsabilities
69
+
70
+ - Precaution has to be taken in case the button being disabled is the currently selected one.
71
+ - The user of the component retains full control over what's happening in this case.
72
+ - For instance, programmatically switching to another button **before** disabling a certain button.
73
+ - And of course the effect such a button switch has in the host project / application.
74
+ - Disabling all buttons is technically supported.
75
+ - But what that means in the context of the application is the user's responsability - the component can't know that.
76
+ - In this case, the same applies - the user is responsible for setting a button when not all buttons are disabled anymore.
77
+
78
+ Example code for toggling between state "disabled" and "false"
79
+
80
+ ```javascript
81
+ const button = document.getElementById("myButton")
82
+ const group = document.getElementById("myButtonGroup")
83
+ group.setEnabledByIndex(0, button.state==="disabled")
84
+ ```
85
+
86
+ ❗ Don't miss to see also usage-examples/ directory for more examples, especially how to handle enable/disabling of a single button and also all buttons at once.
45
87
 
46
88
  ## Events
47
89
 
48
90
  - When a user attempts to press a button, a custom event named "action" is dispatched.
49
91
  - The event detail contains the 0-based index of the button which was pressed.
50
- - It's the component user's responsability to actually set it pressed.
92
+ - It's the component user's responsability to actually set the button state to "pressed".
51
93
  - This is for two reasons:
52
- - the developer has a possibility to prevent the button from being pressed
53
- - to be consistent with the usage of the ewc-icon-button
94
+ - provides possibility to prevent the button from being pressed
95
+ - is consistent with the usage of the ewc-icon-button
54
96
 
55
97
  Please see usage-examples/ directory which contains working source-code demonstrating how this works.
56
98
 
99
+ ### UML
100
+
101
+ ![events](./events.png)
102
+
57
103
  # Usage
58
104
 
59
105
  ## Installation
@@ -72,7 +118,7 @@ import '@ewc-lib/ewc-icon-button-group';
72
118
 
73
119
  ### Note about ewc-css-common
74
120
 
75
- - "ewc-css-common/custom-props.css" is necessary and downloaded along with ewc-dialog.
121
+ - "ewc-css-common/custom-props.css" is necessary and downloaded along with this component.
76
122
  - It needs to be imported by the host project because it's imported neither by ewc-icon-button nor ewc-icon-button-group.
77
123
 
78
124
 
@@ -92,12 +138,33 @@ For an explanation about the attribute **use-config**, please refer to the [read
92
138
 
93
139
  Note: The usage-example/ directory contains a working example.
94
140
 
141
+ # Migration guide
142
+
143
+ ## Updating to 3.0.0-alpha (from any older version)
144
+
145
+ ### Option to use ID instead of index
146
+
147
+ Referring to a button in a group can now be done via ID, additionally to the previously existing index.
148
+
149
+ ### ID in the event details
150
+
151
+ e.detail was only a number before (containing an ordinal index). Now it's an object w/ 2 fields: index and id.
152
+
153
+ ```javascript
154
+ document.getElementById("lightEnabled").addEventListener("action",(e)=>{
155
+ console.log("button clicked or selected w/ kdb: ", e.detail.id, e.detail.index)
156
+ })
157
+ ```
158
+
159
+ The ID is taken from the HTML tag's "id" attribute. If it's missing, e.detail.id is null.
160
+
161
+
95
162
  # Notes
96
163
 
97
164
  ## Accessibility
98
165
 
99
166
  The component is designed with accessibility in mind:
100
- - Proper semantic HTML structure (dialog and header elements)
167
+ - Proper semantic HTML structure
101
168
  - Keyboard navigable elements
102
169
  - Sufficient color contrast
103
170
  - Screen reader friendly with appropriate ARIA attributes
@@ -115,6 +182,16 @@ European Union Public License (EUPL)
115
182
 
116
183
  # Changelog
117
184
 
185
+ - 3.0.0-alpha
186
+ - properly support disabled state,
187
+ - add selection by id
188
+ - add id-info to event
189
+ - update usage examples
190
+ - update documentation
191
+
192
+ - 2.0.3-alpha
193
+ - fix label casing bug
194
+
118
195
  - 2.0.2-alpha
119
196
  - support integration, update dependency, add aria-label
120
197
 
@@ -0,0 +1,52 @@
1
+ /*
2
+ handles pressed state.
3
+ oblivious about disabled state.
4
+ deals only with index, not with element IDs
5
+ */
6
+ export class ButtonGroup {
7
+ #currentIndex
8
+ #pressedBtnElement = null
9
+ #pressedBtnElementIcon = null // accomodate the possibility that the button might have a different icon in pressed state
10
+
11
+ applyCurrentSelection(nodes) {
12
+ this.setPressed(nodes, this.#currentIndex)
13
+ }
14
+
15
+ #storePressed(el) {
16
+ if(el) {
17
+ this.#pressedBtnElement=el
18
+ this.#pressedBtnElementIcon=el.getAttribute("icon")
19
+ }
20
+ }
21
+
22
+ #restorePressed() {
23
+ if(this.#pressedBtnElement) {
24
+ this.#pressedBtnElement.setAttribute("icon", this.#pressedBtnElementIcon)
25
+ }
26
+ }
27
+
28
+ // ensures that max 1 button is pressed
29
+ setPressed(allElements, selectedElIdx) {
30
+ //console.debug("ewc-icon-button-group setPressed: ", selectedElIdx)
31
+ this.#restorePressed()
32
+ for(let i=0;i<allElements.length;i++) {
33
+ const el = allElements[i]
34
+ if(el.getAttribute("state")==="disabled") {continue}
35
+ if(i===selectedElIdx){
36
+ el.setAttribute("state","true")
37
+ this.#storePressed(el)
38
+ } else {
39
+ el.setAttribute("state","false")
40
+ }
41
+ }
42
+ this.#currentIndex = Number(selectedElIdx)
43
+ }
44
+
45
+ getPressedIndex() {
46
+ return this.#currentIndex
47
+ }
48
+
49
+ getPressedElement() {
50
+ return this.#pressedBtnElement
51
+ }
52
+ }
package/src/main.js CHANGED
@@ -5,56 +5,13 @@ keyboard navigation:
5
5
  - a group can't get a focus
6
6
  - buttons in the group can get a focus
7
7
  - only not-pressed buttons can get a focus
8
+ - disabled buttons can't be pressed
8
9
  - left/up and right/down keys move the focus
9
10
  - enter and space key presses a button, releases the currently pressed button
10
11
  */
11
12
 
12
13
  import CSS from "./css.js"
13
-
14
-
15
- class ButtonGroup {
16
- #pressedBtnElement = null
17
- #pressedBtnElementIcon = null
18
- #currentIndex
19
-
20
- #storeCurrentBtn(el) {
21
- if(el) {
22
- this.#pressedBtnElement=el
23
- this.#pressedBtnElementIcon=el.getAttribute("icon")
24
- }
25
- }
26
-
27
- #restoreCurrent() {
28
- if(this.#pressedBtnElement) {
29
- this.#pressedBtnElement.setAttribute("icon", this.#pressedBtnElementIcon)
30
- }
31
- }
32
-
33
- setPressed(allElements, selectedElIdx) {
34
- this.#restoreCurrent()
35
- for(let i=0;i<allElements.length;i++) {
36
- const el = allElements[i]
37
- if(i===selectedElIdx){
38
- el.setAttribute("tabindex","-1")
39
- el.setAttribute("state","true")
40
- this.#storeCurrentBtn(el)
41
- } else {
42
- el.setAttribute("tabindex","0")
43
- el.setAttribute("state","false")
44
- }
45
- }
46
- this.#currentIndex = Number(selectedElIdx)
47
- }
48
-
49
- getCurrentIndex() {
50
- return this.#currentIndex
51
- }
52
-
53
- getCurrentElement() {
54
- return this.#pressedBtnElement
55
- }
56
- }
57
-
14
+ import {ButtonGroup} from "./buttonGroup.js"
58
15
 
59
16
  class Element extends HTMLElement {
60
17
  // only affect ewc-icon-buttons which are children of this element
@@ -67,80 +24,166 @@ class Element extends HTMLElement {
67
24
  return r
68
25
  }
69
26
 
27
+ constructor() {
28
+ super()
29
+ }
30
+
70
31
  connectedCallback() {
71
- this.setAttribute("ewc-version", "2.0.1-alpha") // please always keep in sync with version in package.json
32
+ this.setAttribute("ewc-version", "3.0.0-alpha") // please always keep in sync with version in package.json
72
33
  if(this.#isInitialised == true) {return}
73
34
 
74
35
  this.classList.add(this.#cssClassPrefix)
75
36
  this.appendChild(CSS(this.#cssClassPrefix, this.getAttr("breakpoint","480px")).cloneNode(true)) // .ecl-col-s- in ECL 4.8.1.
76
- this.#installEventHandlers()
37
+
38
+ const nodes = this.querySelectorAll("ewc-icon-button")
39
+ this.#setIndexOnNodes(nodes)
40
+ this.#installEventHandlers(nodes)
41
+ // attributeChangedCallback() might have been called before this, so it just stored the number but couldn't yet press the button. let it catch up now.
42
+ this.#buttonGroup.applyCurrentSelection(nodes)
43
+
77
44
  this.#isInitialised = true
78
45
  }
79
46
 
80
- constructor() {
81
- super()
47
+ get selectedIndex() {
48
+ return this.#buttonGroup.getPressedIndex()
49
+ }
50
+
51
+ set selectedIndex(index) {
52
+ this.setAttribute("selectedindex", index)
53
+ }
54
+
55
+ // convenience
56
+ get selectedId() {
57
+ return this.selectedElement.getAttribute("id")
58
+ }
59
+
60
+ set selectedId(id) {
61
+ this.setAttribute("selectedid", id)
62
+ }
63
+
64
+ get selectedElement() {
65
+ return this.#buttonGroup.getPressedElement()
66
+ }
67
+
68
+ setEnabledByIndex(index, isEnabled) {
69
+ const el = this.#getElByIndex(index)
70
+ if(el) {
71
+ el.state = isEnabled ? "false":"disabled"
72
+ } else {
73
+ console.error("ewc-icon-button-group: no button with given index found. index=", id)
74
+ }
75
+ }
76
+
77
+ setEnabledById(id, isEnabled) {
78
+ const [index,el] = this.#getElById(id)
79
+ if(el) {
80
+ this.setEnabledByIndex(index, isEnabled)
81
+ } else {
82
+ console.error("ewc-icon-button-group: no button with given id found. id=", id)
83
+ }
84
+ }
85
+
86
+ #getElByIndex(index) {
87
+ const el = this.querySelector(`ewc-icon-button[__index='${index}']`)
88
+ return el ? el : null
89
+ }
90
+
91
+ #getElById(id) {
92
+ const allElements = this.querySelectorAll("ewc-icon-button")
93
+ for(let i=0;i<allElements.length;i++) {
94
+ const el = allElements[i]
95
+ if(el.getAttribute("id")==id) {return [i,el]}
96
+ }
97
+ return [-1,null]
82
98
  }
83
99
 
84
- static observedAttributes = ["selectedindex"]
100
+
101
+ static observedAttributes = ["selectedindex", "selectedid"]
85
102
 
86
103
  attributeChangedCallback(name, oldValue, newValue) {
87
104
  if (name==="selectedindex") {
88
- //console.log(Number(newValue),this.#buttonGroup.getCurrentIndex())
89
- if(Number(newValue)!==this.#buttonGroup.getCurrentIndex()) {
105
+ if(Number(newValue)!==this.#buttonGroup.getPressedIndex()) {
90
106
  this.#buttonGroup.setPressed(this.querySelectorAll("ewc-icon-button"), Number(newValue))
91
107
  }
92
108
  }
109
+ if (name==="selectedid") {
110
+ const [index,el] = this.#getElById(newValue)
111
+ if(el) {
112
+ this.#buttonGroup.setPressed(this.querySelectorAll("ewc-icon-button"), index)
113
+ }
114
+ }
93
115
  }
94
116
 
95
- #installEventHandlers() {
96
-
97
- const nodes = this.querySelectorAll("ewc-icon-button")
98
117
 
118
+ #installActionEventHandler(nodes) {
99
119
  // relay click/enter presses
100
120
  for(let i=0;i<nodes.length;i++) {
101
121
  nodes[i].addEventListener("action", (ev) => {
122
+ //console.debug("ewc-icon-button-group: got action event", this.#buttonGroup.getPressedIndex(),i)
123
+
102
124
  ev.stopPropagation()
103
- if(this.#buttonGroup.getCurrentIndex() !== i) {
104
- const event = new CustomEvent("action", { detail: i});
105
- this.dispatchEvent(event)
125
+ if(this.#buttonGroup.getPressedIndex() == i) {
126
+ // no operation. the already pressed button has been clicked again.
127
+ } else {
128
+ if(this.selectedElement) {
129
+ const event = new CustomEvent("action", { detail: {"index":i, "id":this.selectedElement.getAttribute("id")} });
130
+ this.dispatchEvent(event)
131
+ }
132
+ //console.debug("ewc-icon-button-group: sent new action event")
106
133
  }
107
134
  })
108
- nodes[i].setAttribute("__index", i)
109
135
  }
136
+ }
137
+
110
138
 
111
- // move focus w/ tab. TODO: make the code elegant
112
- this.addEventListener("keydown", function(ev) {
113
- let idx = Number(document.activeElement.getAttribute("__index"))
114
- const nodes = this.querySelectorAll("ewc-icon-button")
115
-
116
- if(ev.key=="ArrowLeft" || ev.key=="ArrowUp") {
117
- idx-=1
118
- if(idx<0) {idx=nodes.length-1}
119
- if(nodes[idx].getAttribute("tabindex")=="-1") {
120
- idx-=1
121
- if(idx<0) {idx=nodes.length-1}
139
+ #installArrowKeyEventHandler(nodes) {
140
+ // move focus, considering state (jump over disabled and pressed buttons).
141
+ // it should behave like tab/shift-tab but additionally, wrap.
142
+ this.addEventListener("keydown", function(ev) {
143
+ if(!["ArrowLeft","ArrowUp","ArrowRight","ArrowDown"].includes(ev.key)) {return}
144
+
145
+ const startIdx = Number(document.activeElement.getAttribute("__index")) // note: currently focused, not currently selected/pressed
146
+ const direction = ev.key=="ArrowLeft" || ev.key=="ArrowUp" ? -1 : 1
147
+
148
+ function findNextFocusableButtonIndex(nodes, startIdx, direction) {
149
+ var currentIdx = startIdx + direction
150
+ var globalCounter = 0
151
+ const l = nodes.length
152
+ while(currentIdx!=startIdx && startIdx>-1) {
153
+ currentIdx = currentIdx % l
154
+ if(currentIdx<0) {currentIdx=l-1}
155
+ if(nodes[currentIdx].getAttribute("tabindex")!="-1") {return currentIdx}
156
+ currentIdx += direction
157
+ if(++globalCounter>l-1) {
158
+ // we're not supposed to get in here, but it happens under as of yet unknown circumstances.
159
+ // once the issue is clear and fixed, this can be removed.
160
+ console.error("ewc-icon-button-group: endless-loop guard intervention")
161
+ break
162
+ }
122
163
  }
123
- nodes[idx].focus()
164
+ return -1
124
165
  }
125
- if(ev.key=="ArrowRight" || ev.key=="ArrowDown") {
126
- idx+=1
127
- if(idx>nodes.length-1) {idx=0}
128
- if(nodes[idx].getAttribute("tabindex")=="-1") {
129
- idx+=1
130
- if(idx>nodes.length-1) {idx=0}
131
- }
166
+
167
+ const idx = findNextFocusableButtonIndex(nodes,startIdx,direction)
168
+ if(idx>-1) {
132
169
  nodes[idx].focus()
133
170
  }
134
171
  }.bind(this))
135
- }
172
+ }
136
173
 
137
- getCurrentlySelectedIndex() {
138
- return this.#buttonGroup.getCurrentIndex()
174
+ // assign 0-based ordinal number to each button
175
+ // TODO: remove and replace w/ loops
176
+ #setIndexOnNodes(nodes) {
177
+ for(let i=0;i<nodes.length;i++) {
178
+ nodes[i].setAttribute("__index", i)
179
+ }
139
180
  }
140
181
 
141
- getCurrentlySelectedElement() {
142
- return this.#buttonGroup.getCurrentElement()
182
+ #installEventHandlers(nodes) {
183
+ this.#installActionEventHandler(nodes)
184
+ this.#installArrowKeyEventHandler(nodes)
143
185
  }
186
+
144
187
  }
145
188
 
146
189
 
@@ -28,43 +28,151 @@
28
28
  <p style="margin-bottom: 50px;">Buttons available, on light and dark background</p>
29
29
 
30
30
  <div style="margin:20px; padding:20px;">
31
- <ewc-icon-button-group style="width:600px;" selectedIndex="0" breakpoint="800px" id="one">
32
- <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
33
- <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart"></ewc-icon-button>
34
- <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot"></ewc-icon-button>
35
- <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table"></ewc-icon-button>
31
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedIndex="0" breakpoint="800px" id="lightEnabled">
32
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" ></ewc-icon-button>
33
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" ></ewc-icon-button>
34
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" ></ewc-icon-button>
35
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" ></ewc-icon-button>
36
36
  </ewc-icon-button-group>
37
37
  </div>
38
38
 
39
+ <div style="margin:20px; padding:20px;">
40
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedIndex="0" breakpoint="800px" id="lightDisabled">
41
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" state="disabled"></ewc-icon-button>
42
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" state="disabled"></ewc-icon-button>
43
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" state="disabled"></ewc-icon-button>
44
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" state="disabled"></ewc-icon-button>
45
+ </ewc-icon-button-group>
46
+ </div>
47
+
48
+
39
49
  <div style="margin:20px; padding:20px; background: darkblue;">
40
- <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="two">
41
- <ewc-icon-button state="disabled" icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
50
+ <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="darkEnabled">
51
+ <ewc-icon-button icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
42
52
  <ewc-icon-button icon="barchart" background="dark" use-config="grp-barchart" btn-aria-label="Bar chart" label="Bar chart"></ewc-icon-button>
43
53
  <ewc-icon-button icon="dotplot" background="dark" use-config="grp-dotplot" btn-aria-label="Dot plot" label="Dot plot"></ewc-icon-button>
44
54
  <ewc-icon-button icon="table" background="dark" use-config="grp-table" btn-aria-label="Table" label="Table"></ewc-icon-button>
45
55
  </ewc-icon-button-group>
46
56
  </div>
47
- </div>
48
57
 
49
- <script>
50
- window.addEventListener('DOMContentLoaded',function () {
51
- // catch events of all buttons at once
52
- document.getElementById("one").addEventListener("action",(e)=>{
53
- document.getElementById("one").setAttribute("selectedIndex",e.detail)
54
- const el = document.getElementById("one").getCurrentlySelectedElement()
55
- console.log("button clicked or selected w/ kdb: ", e.detail, el)
56
- })
57
- })
58
-
59
- window.addEventListener('DOMContentLoaded',function () {
60
- // catch events of all buttons at once
61
- document.getElementById("two").addEventListener("action",(e)=>{
62
- document.getElementById("two").setAttribute("selectedIndex",e.detail)
63
- const el = document.getElementById("two").getCurrentlySelectedElement()
64
- console.log("button clicked or selected w/ kdb: ", e.detail, el)
58
+ <div style="margin:20px; padding:20px; background: darkblue;">
59
+ <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="darkDisabled">
60
+ <ewc-icon-button state="disabled" icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
61
+ <ewc-icon-button state="disabled" icon="barchart" background="dark" use-config="grp-barchart" btn-aria-label="Bar chart" label="Bar chart"></ewc-icon-button>
62
+ <ewc-icon-button state="disabled" icon="dotplot" background="dark" use-config="grp-dotplot" btn-aria-label="Dot plot" label="Dot plot"></ewc-icon-button>
63
+ <ewc-icon-button state="disabled" icon="table" background="dark" use-config="grp-table" btn-aria-label="Table" label="Table"></ewc-icon-button>
64
+ </ewc-icon-button-group>
65
+ </div>
66
+
67
+
68
+ <script>
69
+ window.addEventListener('DOMContentLoaded',function () {
70
+
71
+ // catch events of all buttons at once
72
+ document.getElementById("lightEnabled").addEventListener("action",(e)=>{
73
+ document.getElementById("lightEnabled").setAttribute("selectedIndex",e.detail.index)
74
+ const el = document.getElementById("lightEnabled").selectedElement
75
+ console.log("button clicked or selected w/ kdb: ", e.detail, el)
76
+ })
77
+
78
+ document.getElementById("darkEnabled").addEventListener("action",(e)=>{
79
+ document.getElementById("darkEnabled").setAttribute("selectedIndex",e.detail.index)
80
+ const el = document.getElementById("darkEnabled").selectedElement
81
+ console.log("button clicked or selected w/ kdb: ", e.detail, el)
82
+ })
83
+
65
84
  })
66
- })
67
- </script>
85
+ </script>
86
+
87
+
88
+
89
+
90
+ <details>
91
+ <summary>Click to see more detailled information intended for developers</summary>
92
+
93
+ <p>
94
+ This section demonstrates the "feel" part of look & feel.
95
+ <br>
96
+ It takes into consideration the many cases that emerge by having a group of tri-state buttons.
97
+ <br>
98
+ For instance, what happens when a currently pressed button gets disabled. Or when all buttons get disabled and enabled again.
99
+ <br>
100
+ The component is flexible enough to be able to leave the answer to those questions to the developer who uses the component.
101
+ </p>
102
+
103
+ <div style="margin:20px; padding:20px;">
104
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedId="grp1-table" breakpoint="800px" id="ForDevelopers">
105
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" id="grp1-line"></ewc-icon-button>
106
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" id="grp1-bar"></ewc-icon-button>
107
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" id="grp1-dot"></ewc-icon-button>
108
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" id="grp1-table"></ewc-icon-button>
109
+ </ewc-icon-button-group>
110
+ <div style="padding-top:10px;">
111
+ <button id="toggleOne">Toggle linechart disabled</button>
112
+ <button id="toggleAll">Toggle all disabled</button>
113
+ </div>
114
+ </div>
115
+
116
+
117
+ <script>
118
+ window.addEventListener('DOMContentLoaded',function () {
119
+
120
+ document.getElementById("ForDevelopers").addEventListener("action",(e)=>{
121
+ document.getElementById("ForDevelopers").setAttribute("selectedIndex",e.detail.index)
122
+ const el = document.getElementById("ForDevelopers").selectedElement
123
+ console.log("button clicked or selected w/ kdb: ", e.detail, el)
124
+ })
125
+
126
+ // handle a single button being toggled (disabled/re-enabled)
127
+ document.getElementById("toggleOne").addEventListener("click", ()=>{
128
+ const button = document.querySelector("#ForDevelopers > ewc-icon-button[icon='linechart']")
129
+ const buttonNext = document.querySelector("#ForDevelopers > ewc-icon-button[icon='barchart']")
130
+ const group = document.getElementById("ForDevelopers")
131
+
132
+ if(button.state=="disabled") {
133
+ group.setEnabledByIndex(0, "true")
134
+ group.selectedIndex = 0
135
+ } else {
136
+ // note that it's the component user's responsability to define what happens when currently pressed button gets disabled
137
+
138
+ if(group.selectedIndex===0) {
139
+ if(buttonNext.state == "disabled") {
140
+ console.log("Do nothing")
141
+ group.selectedIndex = -1
142
+ } else {
143
+ group.selectedIndex = 1
144
+ }
145
+ }
146
+ group.setEnabledByIndex(0, false)
147
+
148
+ }
149
+ })
150
+
151
+
152
+ // handle all buttons being disabled at once
153
+ document.getElementById("toggleAll").addEventListener("click", ()=>{
154
+ const group = document.getElementById("ForDevelopers")
155
+ // doesnt have to be the last, any button will do, really
156
+ const lastButton = document.querySelector("#ForDevelopers > ewc-icon-button[icon='table']")
157
+ const toSet = lastButton.state=="disabled" ? true : false
158
+
159
+ group.setEnabledByIndex(0, toSet)
160
+ group.setEnabledByIndex(1, toSet)
161
+ group.setEnabledById("grp1-dot", toSet)
162
+ group.setEnabledById("grp1-table", toSet)
163
+
164
+ // note that it's the component user's responsability
165
+ // to define what happens when ALL button get disabled and re-enabled again.
166
+ // it's important to set the current index to -1 when all buttons are disabled/deselected.
167
+ group.selectedIndex = toSet ? 0 : -1
168
+ })
169
+
170
+ })
171
+ </script>
172
+
173
+ </details>
174
+
175
+ </div>
68
176
 
69
177
  </body>
70
178
 
@@ -16,7 +16,7 @@
16
16
  outline:2px solid darkblue;
17
17
  outline-offset: 5px;
18
18
  }
19
- </style>
19
+ </style>
20
20
  </head>
21
21
 
22
22
  <body>
@@ -25,22 +25,71 @@
25
25
  <p style="margin-bottom: 50px;">Buttons available, on light and dark background</p>
26
26
 
27
27
  <div style="margin:20px; padding:20px;">
28
- <ewc-icon-button-group style="width:600px;" selectedIndex="0" breakpoint="800px" id="one">
29
- <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
30
- <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart"></ewc-icon-button>
31
- <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot"></ewc-icon-button>
32
- <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table"></ewc-icon-button>
28
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedIndex="0" breakpoint="800px" id="lightEnabled">
29
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" ></ewc-icon-button>
30
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" ></ewc-icon-button>
31
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" ></ewc-icon-button>
32
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" ></ewc-icon-button>
33
33
  </ewc-icon-button-group>
34
34
  </div>
35
35
 
36
+ <div style="margin:20px; padding:20px;">
37
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedIndex="0" breakpoint="800px" id="lightDisabled">
38
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" state="disabled"></ewc-icon-button>
39
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" state="disabled"></ewc-icon-button>
40
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" state="disabled"></ewc-icon-button>
41
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" state="disabled"></ewc-icon-button>
42
+ </ewc-icon-button-group>
43
+ </div>
44
+
45
+
36
46
  <div style="margin:20px; padding:20px; background: darkblue;">
37
- <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="two">
38
- <ewc-icon-button state="disabled" icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
47
+ <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="darkEnabled">
48
+ <ewc-icon-button icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
39
49
  <ewc-icon-button icon="barchart" background="dark" use-config="grp-barchart" btn-aria-label="Bar chart" label="Bar chart"></ewc-icon-button>
40
50
  <ewc-icon-button icon="dotplot" background="dark" use-config="grp-dotplot" btn-aria-label="Dot plot" label="Dot plot"></ewc-icon-button>
41
51
  <ewc-icon-button icon="table" background="dark" use-config="grp-table" btn-aria-label="Table" label="Table"></ewc-icon-button>
42
52
  </ewc-icon-button-group>
43
53
  </div>
54
+
55
+ <div style="margin:20px; padding:20px; background: darkblue;">
56
+ <ewc-icon-button-group style="width:600px;" selectedIndex="3" breakpoint="800px" id="darkDisabled">
57
+ <ewc-icon-button state="disabled" icon="linechart" background="dark" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart"></ewc-icon-button>
58
+ <ewc-icon-button state="disabled" icon="barchart" background="dark" use-config="grp-barchart" btn-aria-label="Bar chart" label="Bar chart"></ewc-icon-button>
59
+ <ewc-icon-button state="disabled" icon="dotplot" background="dark" use-config="grp-dotplot" btn-aria-label="Dot plot" label="Dot plot"></ewc-icon-button>
60
+ <ewc-icon-button state="disabled" icon="table" background="dark" use-config="grp-table" btn-aria-label="Table" label="Table"></ewc-icon-button>
61
+ </ewc-icon-button-group>
62
+ </div>
63
+
64
+
65
+ <details>
66
+ <summary>Click to see more detailled information intended for developers</summary>
67
+
68
+ <p>
69
+ This section demonstrates the "feel" part of look & feel.
70
+ <br>
71
+ It takes into consideration the many cases that emerge by having a group of tri-state buttons.
72
+ <br>
73
+ For instance, what happens when a currently pressed button gets disabled. Or when all buttons get disabled and enabled again.
74
+ <br>
75
+ The component is flexible enough to be able to leave the answer to those questions to the developer who uses the component.
76
+ </p>
77
+
78
+ <div style="margin:20px; padding:20px;">
79
+ <ewc-icon-button-group style="width:600px; padding-right:10px;" selectedId="grp1-table" breakpoint="800px" id="ForDevelopers">
80
+ <ewc-icon-button icon="linechart" use-config="grp-linechart" label="Line chart" btn-aria-label="Line chart" id="grp1-line"></ewc-icon-button>
81
+ <ewc-icon-button icon="barchart" use-config="grp-barchart" label="Bar chart" btn-aria-label="Bar chart" id="grp1-bar"></ewc-icon-button>
82
+ <ewc-icon-button icon="dotplot" use-config="grp-dotplot" label="Dot plot" btn-aria-label="Dot plot" id="grp1-dot"></ewc-icon-button>
83
+ <ewc-icon-button icon="table" use-config="grp-table" label="Table" btn-aria-label="Table" id="grp1-table"></ewc-icon-button>
84
+ </ewc-icon-button-group>
85
+ <div style="padding-top:10px;">
86
+ <button id="toggleOne">Toggle linechart disabled</button>
87
+ <button id="toggleAll">Toggle all disabled</button>
88
+ </div>
89
+ </div>
90
+
91
+ </details>
92
+
44
93
  </div>
45
94
 
46
95
  </body>
@@ -2,20 +2,75 @@ import "@ewc-lib/ewc-css-common/custom-props.css"
2
2
  import "@ewc-lib/ewc-icon-button"
3
3
  import "@ewc-lib/ewc-icon-button-group"
4
4
 
5
+
5
6
  window.addEventListener('DOMContentLoaded',function () {
7
+
6
8
  // catch events of all buttons at once
7
- document.getElementById("one").addEventListener("action",(e)=>{
8
- document.getElementById("one").setAttribute("selectedIndex",e.detail)
9
- const el = document.getElementById("one").getCurrentlySelectedElement()
9
+ document.getElementById("lightEnabled").addEventListener("action",(e)=>{
10
+ document.getElementById("lightEnabled").setAttribute("selectedIndex",e.detail.index)
11
+ const el = document.getElementById("lightEnabled").selectedElement
12
+ console.log("button clicked or selected w/ kdb: ", e.detail, el)
13
+ })
14
+
15
+ document.getElementById("darkEnabled").addEventListener("action",(e)=>{
16
+ document.getElementById("darkEnabled").setAttribute("selectedIndex",e.detail.index)
17
+ const el = document.getElementById("darkEnabled").selectedElement
10
18
  console.log("button clicked or selected w/ kdb: ", e.detail, el)
11
19
  })
20
+
12
21
  })
13
22
 
23
+
14
24
  window.addEventListener('DOMContentLoaded',function () {
15
- // catch events of all buttons at once
16
- document.getElementById("two").addEventListener("action",(e)=>{
17
- document.getElementById("two").setAttribute("selectedIndex",e.detail)
18
- const el = document.getElementById("two").getCurrentlySelectedElement()
25
+
26
+ document.getElementById("ForDevelopers").addEventListener("action",(e)=>{
27
+ document.getElementById("ForDevelopers").setAttribute("selectedIndex",e.detail.index)
28
+ const el = document.getElementById("ForDevelopers").selectedElement
19
29
  console.log("button clicked or selected w/ kdb: ", e.detail, el)
20
30
  })
31
+
32
+ // handle a single button being toggled (disabled/re-enabled)
33
+ document.getElementById("toggleOne").addEventListener("click", ()=>{
34
+ const button = document.querySelector("#ForDevelopers > ewc-icon-button[icon='linechart']")
35
+ const buttonNext = document.querySelector("#ForDevelopers > ewc-icon-button[icon='barchart']")
36
+ const group = document.getElementById("ForDevelopers")
37
+
38
+ if(button.state=="disabled") {
39
+ group.setEnabledByIndex(0, "true")
40
+ group.selectedIndex = 0
41
+ } else {
42
+ // note that it's the component user's responsability to define what happens when currently pressed button gets disabled
43
+
44
+ if(group.selectedIndex===0) {
45
+ if(buttonNext.state == "disabled") {
46
+ console.log("Do nothing")
47
+ group.selectedIndex = -1
48
+ } else {
49
+ group.selectedIndex = 1
50
+ }
51
+ }
52
+ group.setEnabledByIndex(0, false)
53
+
54
+ }
55
+ })
56
+
57
+
58
+ // handle all buttons being disabled at once
59
+ document.getElementById("toggleAll").addEventListener("click", ()=>{
60
+ const group = document.getElementById("ForDevelopers")
61
+ // doesnt have to be the last, any button will do, really
62
+ const lastButton = document.querySelector("#ForDevelopers > ewc-icon-button[icon='table']")
63
+ const toSet = lastButton.state=="disabled" ? true : false
64
+
65
+ group.setEnabledByIndex(0, toSet)
66
+ group.setEnabledByIndex(1, toSet)
67
+ group.setEnabledById("grp1-dot", toSet)
68
+ group.setEnabledById("grp1-table", toSet)
69
+
70
+ // note that it's the component user's responsability
71
+ // to define what happens when ALL button get disabled and re-enabled again.
72
+ // it's important to set the current index to -1 when all buttons are disabled/deselected.
73
+ group.selectedIndex = toSet ? 0 : -1
74
+ })
75
+
21
76
  })
@@ -17,7 +17,7 @@
17
17
  "@ewc-lib/ewc-css-common": "0.1.0"
18
18
  },
19
19
  "dependencies": {
20
- "@ewc-lib/ewc-icon-button": "2.0.0-alpha",
20
+ "@ewc-lib/ewc-icon-button": "latest",
21
21
  "@ewc-lib/ewc-icon-button-group": "file:../../"
22
22
  },
23
23
  "devDependencies": {
package/bla.md DELETED
File without changes
package/notes.txt DELETED
@@ -1,90 +0,0 @@
1
- width: 125px;
2
- height: 45px;
3
- /* UI Properties */
4
- background: #FFFFFF 0% 0% no-repeat padding-box;
5
- border: 1px solid #0D40B7;
6
- border-radius: 0px 200px 200px 0px;
7
- opacity: 1;
8
-
9
-
10
- <ewc-icon-button-group id="g">
11
- <ewc-icon-button icon="linechart" label="Line chart"></ewc-icon-button>
12
- <ewc-icon-button icon="barchart" label="Bar chart"></ewc-icon-button>
13
- <ewc-icon-button icon="table" label="Table"></ewc-icon-button>
14
- </ewc-icon-button-group>
15
-
16
- <ewc-icon-button-group id="g" buttons="linechart,barchart,table"></ewc-icon-button-group>
17
-
18
-
19
-
20
-
21
- allow to pass an array with objects holding id, text and icon name per item (order to be preserved)
22
- should be possible to preselect one item
23
- callback event for clicked item
24
- it should be possible to change the selection programmatically
25
- needs to be "responsive"
26
- with smaller screens (or even based on available container width) it should remove the text and only keep the icon
27
- @JAURENA Marc (ESTAT-EXT): please check with Federico, if the pill should reduce the width of the pill based on the text (and reduce it if text is removed)
28
- needs to follow basic a11y requirements => The group should be one "tabbable" element and selection could be done via left-right, space => as with radio button groups
29
-
30
-
31
-
32
- semantic HTML or not?
33
-
34
- WCAG / APG says:
35
-
36
- "Robust accessibility can be further optimized by choosing implementation patterns that maximize use of semantic HTML and heeding the warning that No ARIA is better than Bad ARIA."
37
- https://www.w3.org/WAI/ARIA/apg/patterns/radio/examples/radio-activedescendant/
38
-
39
- semantic would be:
40
-
41
- <form method="get">
42
- <fieldset>
43
-
44
- but in our situation, it's not applicable - there is nothing to submit - hence form is inappropriate and fieldset makes only sense within form.
45
-
46
-
47
- <div role="radiogroup"
48
- aria-labelledby="group_label_1"
49
- id="rg1">
50
- <h3 id="group_label_1">
51
- Pizza Crust
52
- </h3>
53
- <div role="radio"
54
- aria-checked="false"
55
- tabindex="0">
56
- Regular crust
57
- </div>
58
- <div role="radio"
59
- aria-checked="false"
60
- tabindex="-1">
61
- Deep dish
62
- </div>
63
- <div role="radio"
64
- aria-checked="false"
65
- tabindex="-1">
66
- Thin crust
67
- </div>
68
- </div>
69
- <div role="radiogroup"
70
- aria-labelledby="group_label_2"
71
- id="rg2">
72
- <h3 id="group_label_2">
73
- Pizza Delivery
74
- </h3>
75
- <div role="radio"
76
- aria-checked="false"
77
- tabindex="0">
78
- Pickup
79
- </div>
80
- <div role="radio"
81
- aria-checked="false"
82
- tabindex="-1">
83
- Home Delivery
84
- </div>
85
- <div role="radio"
86
- aria-checked="false"
87
- tabindex="-1">
88
- Dine in
89
- </div>
90
- </div>