@eeacms/volto-tabs-block 3.0.1 → 4.0.1

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/CHANGELOG.md CHANGED
@@ -4,6 +4,36 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [4.0.1](https://github.com/eea/volto-tabs-block/compare/4.0.0...4.0.1) - 4 April 2023
8
+
9
+ #### :rocket: New Features
10
+
11
+ - feat(EditBlockWrapper.jsx): add buildStyleClassNamesFromData helper function to import [Miu Razvan - [`b3cd3c8`](https://github.com/eea/volto-tabs-block/commit/b3cd3c84aecea5d858a77cdd208dd669ee4bf328)]
12
+
13
+ #### :bug: Bug Fixes
14
+
15
+ - fix(Edit.jsx): add key prop to MenuItem component to avoid warning in console [Miu Razvan - [`55cc784`](https://github.com/eea/volto-tabs-block/commit/55cc784f452637cf686f80a40aef3809784032f6)]
16
+
17
+ #### :hammer_and_wrench: Others
18
+
19
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`52bc1b0`](https://github.com/eea/volto-tabs-block/commit/52bc1b0fbd4611173b8ca9dc2cf4033b31474420)]
20
+ ## [4.0.0](https://github.com/eea/volto-tabs-block/compare/3.0.1...4.0.0) - 10 March 2023
21
+
22
+ #### :house: Internal changes
23
+
24
+ - chore(accordion): Cleanup menuColor [Alin Voinea - [`de63905`](https://github.com/eea/volto-tabs-block/commit/de639056210d426d64e2e4762aeec2e215563854)]
25
+ - chore(typo): Fix typo accesibilty [Alin Voinea - [`cc7754e`](https://github.com/eea/volto-tabs-block/commit/cc7754eeb2e224966f942b9053638c3db94d834c)]
26
+
27
+ #### :hammer_and_wrench: Others
28
+
29
+ - Release 4.0.0 [Alin Voinea - [`8fc4cc9`](https://github.com/eea/volto-tabs-block/commit/8fc4cc9d8dc71e623e6586b95871cb3b98dc385f)]
30
+ - Add Sonarqube tag using eea-website-frontend addons list [EEA Jenkins - [`22d5bdc`](https://github.com/eea/volto-tabs-block/commit/22d5bdc1b3579cc46c73ce855041ca09154eb502)]
31
+ - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`fde4324`](https://github.com/eea/volto-tabs-block/commit/fde4324f962cde8e8de0d76a44bee4b67d216bf8)]
32
+ - Add Sonarqube tag using advisory-board-frontend addons list [EEA Jenkins - [`9175e47`](https://github.com/eea/volto-tabs-block/commit/9175e470d793edc63b62a99940aed25dd45f3713)]
33
+ - test(Jenkins): Run tests and cypress with latest canary @plone/volto [Alin Voinea - [`3348950`](https://github.com/eea/volto-tabs-block/commit/334895036f8e367281abb35a20879c32dfbfc292)]
34
+ - Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`39bfb39`](https://github.com/eea/volto-tabs-block/commit/39bfb39fa6e8483e639491ff998293e758ac6384)]
35
+ - yarn 3 [Alin Voinea - [`7e98df5`](https://github.com/eea/volto-tabs-block/commit/7e98df59669d71945be461e86e282b913538b805)]
36
+ - Add Sonarqube tag using demo-kitkat-frontend addons list [EEA Jenkins - [`079d7a4`](https://github.com/eea/volto-tabs-block/commit/079d7a43480e92fe280a9372399ff2d4d28537ae)]
7
37
  ### [3.0.1](https://github.com/eea/volto-tabs-block/compare/3.0.0...3.0.1) - 16 November 2022
8
38
 
9
39
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-tabs-block",
3
- "version": "3.0.1",
3
+ "version": "4.0.1",
4
4
  "description": "volto-tabs-block: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -26,8 +26,8 @@
26
26
  "slick-carousel": "^1.8.1"
27
27
  },
28
28
  "devDependencies": {
29
- "@plone/scripts": "*",
30
29
  "@cypress/code-coverage": "^3.10.0",
30
+ "@plone/scripts": "*",
31
31
  "babel-plugin-transform-class-properties": "^6.24.1",
32
32
  "md5": "^2.3.0"
33
33
  },
@@ -1,6 +1,9 @@
1
1
  import React from 'react';
2
2
  import { Icon, BlockChooser } from '@plone/volto/components';
3
- import { blockHasValue } from '@plone/volto/helpers';
3
+ import {
4
+ blockHasValue,
5
+ buildStyleClassNamesFromData,
6
+ } from '@plone/volto/helpers';
4
7
  import config from '@plone/volto/registry';
5
8
  import { Button } from 'semantic-ui-react';
6
9
  import includes from 'lodash/includes';
@@ -81,12 +84,16 @@ class EditBlockWrapper extends React.Component {
81
84
  ? data.required
82
85
  : includes(config.blocks.requiredBlocks, type);
83
86
 
87
+ const styles = buildStyleClassNamesFromData(data.styles);
88
+
84
89
  return (
85
90
  <div ref={this.blockNode} className="block-wrapper">
86
91
  <div
87
92
  ref={draginfo?.innerRef}
88
93
  {...(selected ? draginfo?.draggableProps : null)}
89
- className={`block-editor-${data['@type']}`}
94
+ className={cx(`block-editor-${data['@type']}`, styles, {
95
+ [data.align]: data.align,
96
+ })}
90
97
  >
91
98
  {!selected && (
92
99
  <div
@@ -47,6 +47,7 @@ const View = (props) => {
47
47
  >
48
48
  <TabsView
49
49
  {...props}
50
+ tabIndex={0}
50
51
  activeTab={activeTab}
51
52
  activeTabIndex={activeTabIndex}
52
53
  node={view}
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { useLayoutEffect } from 'react';
2
2
  import cx from 'classnames';
3
3
  import { compose } from 'redux';
4
4
  import { withRouter } from 'react-router';
@@ -31,7 +31,12 @@ class Tab extends React.Component {
31
31
 
32
32
  render() {
33
33
  return (
34
- <AnimateHeight animateOpacity duration={500} height={this.state.height}>
34
+ <AnimateHeight
35
+ animateOpacity
36
+ duration={500}
37
+ height={this.state.height}
38
+ aria-hidden={false}
39
+ >
35
40
  <RenderBlocks {...this.props} />
36
41
  </AnimateHeight>
37
42
  );
@@ -45,7 +50,9 @@ const View = (props) => {
45
50
  tabs = {},
46
51
  activeTabIndex = 0,
47
52
  setActiveTab = () => {},
53
+ id,
48
54
  } = props;
55
+
49
56
  const accordionConfig =
50
57
  config.blocks.blocksConfig[TABS_BLOCK].templates?.['accordion'] || {};
51
58
  const { icons, semanticIcon, transformWidth = 800 } = accordionConfig;
@@ -94,7 +101,9 @@ const View = (props) => {
94
101
  {title || defaultTitle}{' '}
95
102
  </>
96
103
  ),
97
- getContent: () => <Tab {...props} tab={tab} content={tabs[tab]} />,
104
+ getContent: () => (
105
+ <Tab {...props} tab={tab} content={tabs[tab]} aria-hidden={false} />
106
+ ),
98
107
  key: tab,
99
108
  tabClassName: cx('ui button item title', { active }),
100
109
  panelClassName: cx('ui bottom attached segment tab', {
@@ -115,12 +124,36 @@ const View = (props) => {
115
124
  );
116
125
  }, [mounted]);
117
126
 
127
+ useLayoutEffect(() => {
128
+ if (document.activeElement.role !== 'tab') return;
129
+ if (
130
+ document.getElementById(id)?.getElementsByClassName('tab active').length >
131
+ 0
132
+ ) {
133
+ let activeTabDiv = document
134
+ .getElementById(id)
135
+ .getElementsByClassName('tab active')[0];
136
+ activeTabDiv.setAttribute('tabindex', '0');
137
+ activeTabDiv.setAttribute('className', 'accessibility-accordion-tab');
138
+ activeTabDiv.focus();
139
+ }
140
+ }, [activeTabIndex, id]);
141
+
118
142
  return (
119
- <>
143
+ <div
144
+ tabIndex="0"
145
+ onKeyDown={(e) => {
146
+ if (e.key === 'Enter') {
147
+ e.preventDefault();
148
+ const focusedElement = document.activeElement;
149
+ if (focusedElement) focusedElement.click();
150
+ }
151
+ }}
152
+ role="tab"
153
+ >
120
154
  <Tabs
121
155
  ref={tabsContainer}
122
156
  transformWidth={initialWidth}
123
- className="tabs aa"
124
157
  selectedTabKey={tabsList[activeTabIndex]}
125
158
  items={items}
126
159
  onChange={(tab) => {
@@ -131,15 +164,17 @@ const View = (props) => {
131
164
  }
132
165
  }}
133
166
  tabsWrapperClass={cx(
167
+ props?.data?.accordionIconRight ? 'tabs-accordion-icon-right' : '',
134
168
  'ui pointing secondary menu',
135
- getDataValue('menuColor'),
169
+ 'tabs-accessibility',
170
+ data?.theme ? `theme-${data?.theme}` : '',
136
171
  {
137
172
  inverted: getDataValue('menuInverted'),
138
173
  },
139
174
  )}
140
175
  showMore={false}
141
176
  />
142
- </>
177
+ </div>
143
178
  );
144
179
  };
145
180
 
@@ -1,3 +1,5 @@
1
+ import config from '@plone/volto/registry';
2
+
1
3
  export default () => ({
2
4
  title: 'Accordion tabs block',
3
5
  fieldsets: [
@@ -9,36 +11,40 @@ export default () => ({
9
11
  {
10
12
  id: 'menu',
11
13
  title: 'Menu',
12
- fields: ['menuColor', 'menuInverted'],
14
+ fields: ['menuInverted', 'accordionIconRight'],
15
+ },
16
+ {
17
+ id: 'style',
18
+ title: 'Style',
19
+ fields: ['theme'],
13
20
  },
14
21
  ],
15
22
  properties: {
16
23
  description: {
17
24
  title: 'Description',
18
25
  },
19
- menuColor: {
20
- title: 'Color',
21
- defaultValue: 'green',
22
- choices: [
23
- ['red', 'Red'],
24
- ['orange', 'Orange'],
25
- ['yellow', 'Yellow'],
26
- ['olive', 'Olive'],
27
- ['green', 'Green'],
28
- ['teal', 'Teal'],
29
- ['blue', 'Blue'],
30
- ['violet', 'Violet'],
31
- ['purple', 'Purple'],
32
- ['pink', 'Pink'],
33
- ['brown', 'Brown'],
34
- ['grey', 'Grey'],
35
- ['black', 'Black'],
36
- ],
26
+ accordionIconRight: {
27
+ title: 'Icon position on the right',
28
+ description: 'Position left/right of the icon in the accordion tab',
29
+ type: 'boolean',
37
30
  },
38
31
  menuInverted: {
39
32
  title: 'Inverted',
40
33
  type: 'boolean',
41
34
  },
35
+ theme: {
36
+ title: 'Theme',
37
+ description: 'Set the theme for the accordion tabs block',
38
+ widget: 'theme_picker',
39
+ colors: [
40
+ ...(config.settings && config.settings.themeColors
41
+ ? config.settings.themeColors.map(({ value, title }) => ({
42
+ name: value,
43
+ label: title,
44
+ }))
45
+ : []),
46
+ ],
47
+ },
42
48
  },
43
49
  required: [],
44
50
  });
@@ -29,6 +29,7 @@ const Dots = (props) => {
29
29
  >
30
30
  <button
31
31
  aria-label={`Select slide ${index + 1}`}
32
+ tabIndex={0}
32
33
  onClick={() => {
33
34
  if (slider.current) {
34
35
  slider.current.slickGoTo(index);
@@ -65,6 +66,7 @@ const ArrowsGroup = (props) => {
65
66
  slider.current.slickPrev();
66
67
  }
67
68
  }}
69
+ tabIndex={0}
68
70
  >
69
71
  <Icon name={leftArrowSVG} size="50px" />
70
72
  </button>
@@ -80,6 +82,7 @@ const ArrowsGroup = (props) => {
80
82
  slider.current.slickNext();
81
83
  }
82
84
  }}
85
+ tabIndex={0}
83
86
  >
84
87
  <Icon name={rightArrowSVG} size="50px" />
85
88
  </button>
@@ -93,6 +96,7 @@ const ArrowsGroup = (props) => {
93
96
  const View = (props) => {
94
97
  const slider = React.useRef(null);
95
98
  const [hashlinkOnMount, setHashlinkOnMount] = React.useState(false);
99
+ const blockId = props.id;
96
100
  const {
97
101
  activeTab = null,
98
102
  data = {},
@@ -128,10 +132,24 @@ const View = (props) => {
128
132
  for (let element of slider.current.innerSlider.list.querySelectorAll(
129
133
  ".slick-slide[aria-hidden='true'] a",
130
134
  )) {
131
- element.setAttribute('aria-hiden', 'true');
135
+ element.setAttribute('aria-hidden', 'false');
132
136
  }
133
137
  });
134
138
  }, [activeTab]);
139
+ React.useEffect(() => {
140
+ if (!slider.current?.innerSlider?.list) return;
141
+ let unaccesibileElements = slider.current.innerSlider.list.querySelectorAll(
142
+ '.slick-slide',
143
+ );
144
+ for (let element of unaccesibileElements) {
145
+ element.setAttribute('tabindex', '0');
146
+ element.setAttribute('aria-hidden', 'false');
147
+ element.style.removeProperty('outline');
148
+ }
149
+ if (document.getElementsByClassName('slick-slider')?.length > 0)
150
+ for (let carouselDiv of document.getElementsByClassName('slick-slider'))
151
+ carouselDiv.setAttribute('tabindex', '0');
152
+ }, []);
135
153
 
136
154
  React.useEffect(() => {
137
155
  const urlHash = props.location.hash.substring(1) || '';
@@ -183,7 +201,24 @@ const View = (props) => {
183
201
 
184
202
  return (
185
203
  <>
186
- <Slider {...settings} ref={slider} className={cx(uiContainer)}>
204
+ <Slider
205
+ {...settings}
206
+ ref={slider}
207
+ className={cx(uiContainer, 'tabs-accessibility')}
208
+ accessibility={true}
209
+ afterChange={() => {
210
+ if (
211
+ document
212
+ .getElementById(blockId)
213
+ ?.getElementsByClassName('slick-slider')?.length > 0
214
+ ) {
215
+ document
216
+ .getElementById(blockId)
217
+ .getElementsByClassName('slick-current')[0]
218
+ .focus();
219
+ }
220
+ }}
221
+ >
187
222
  {panes.length ? panes.map((pane) => pane.renderItem) : ''}
188
223
  </Slider>
189
224
  <ArrowsGroup activeTab={activeTab} tabsList={tabsList} slider={slider} />
@@ -193,6 +193,7 @@ const Edit = (props) => {
193
193
  menuItem: (
194
194
  <MenuItem
195
195
  {...props}
196
+ key={tab}
196
197
  editingTab={editingTab}
197
198
  index={index}
198
199
  setEditingTab={setEditingTab}
@@ -274,7 +275,10 @@ const Edit = (props) => {
274
275
  menu={{
275
276
  attached: menuPosition.attached,
276
277
  borderless: getDataValue('menuBorderless'),
277
- color: getDataValue('menuColor'),
278
+ color:
279
+ props?.template === 'accordion' && props?.data?.theme
280
+ ? `theme-${props?.data?.theme}`
281
+ : getDataValue('menuColor'),
278
282
  compact: getDataValue('menuCompact'),
279
283
  fluid: getDataValue('menuFluid'),
280
284
  inverted: getDataValue('menuInverted'),
@@ -22,11 +22,12 @@ const MenuItem = (props) => {
22
22
  setActiveTab = () => {},
23
23
  tabsTitle,
24
24
  tabsDescription,
25
+ blockId,
25
26
  } = props;
27
+
26
28
  const { tab, index } = props;
27
29
  const title = tabs[tab].title;
28
30
  const tabIndex = index + 1;
29
-
30
31
  const defaultTitle = `Tab ${tabIndex}`;
31
32
 
32
33
  return (
@@ -40,11 +41,30 @@ const MenuItem = (props) => {
40
41
  <Menu.Item
41
42
  name={defaultTitle}
42
43
  active={tab === activeTab}
44
+ tabIndex={0}
43
45
  onClick={() => {
44
46
  if (activeTab !== tab) {
45
47
  setActiveTab(tab);
46
48
  }
47
49
  }}
50
+ onKeyDown={(e) => {
51
+ if (e.key === 'Enter') {
52
+ e.preventDefault();
53
+ if (
54
+ document
55
+ .getElementById(blockId)
56
+ ?.getElementsByClassName('active tab').length > 0
57
+ ) {
58
+ const tabDiv = document
59
+ .getElementById(blockId)
60
+ .getElementsByClassName('active tab')[0];
61
+ tabDiv.focus();
62
+ }
63
+ if (activeTab !== tab) {
64
+ setActiveTab(tab);
65
+ }
66
+ }
67
+ }}
48
68
  >
49
69
  <span className={'menu-item-count'}>{tabIndex}</span>
50
70
  <p className={'menu-item-text'}>{title || defaultTitle}</p>
@@ -64,7 +84,6 @@ const View = (props) => {
64
84
  hashlink = {},
65
85
  setActiveTab = () => {},
66
86
  } = props;
67
-
68
87
  const [menuPosition, setMenuPosition] = React.useState({});
69
88
 
70
89
  React.useEffect(() => {
@@ -134,11 +153,12 @@ const View = (props) => {
134
153
  index={index}
135
154
  tabsTitle={tabsTitle}
136
155
  tabsDescription={tabsDescription}
156
+ blockId={props?.id || ''}
137
157
  />
138
158
  ),
139
159
  render: () => {
140
160
  return (
141
- <Tab.Pane as={isContainer ? Container : undefined}>
161
+ <Tab.Pane as={isContainer ? Container : undefined} tabIndex={0}>
142
162
  <RenderBlocks {...props} metadata={metadata} content={tabs[tab]} />
143
163
  </Tab.Pane>
144
164
  );
@@ -150,7 +170,7 @@ const View = (props) => {
150
170
  <>
151
171
  <Tab
152
172
  activeIndex={activeTabIndex}
153
- className="default tabs"
173
+ className="default tabs tabs-accessibility"
154
174
  menu={{
155
175
  attached: menuPosition.attached,
156
176
  borderless: getDataValue('menuBorderless'),
@@ -18,30 +18,76 @@ import {
18
18
  import '@eeacms/volto-tabs-block/less/menu.less';
19
19
 
20
20
  const MenuItem = (props) => {
21
- const { activeTab = null, tabs = {}, setActiveTab = () => {} } = props;
21
+ const {
22
+ activeTab = null,
23
+ tabs = {},
24
+ setActiveTab = () => {},
25
+ blockId,
26
+ } = props;
22
27
  const { tabsTitle, tabsDescription, tab, index } = props;
23
28
  const title = tabs[tab].title;
24
29
  const tabIndex = index + 1;
25
-
26
30
  const defaultTitle = `Tab ${tabIndex}`;
27
31
 
28
32
  return (
29
33
  <React.Fragment>
30
34
  {index === 0 && (tabsTitle || tabsDescription) && (
31
- <Menu.Item className="menu-title">
35
+ <Menu.Item
36
+ className="menu-title"
37
+ tabIndex={0}
38
+ onKeyDown={(e) => {
39
+ if (e.key === 'Enter') {
40
+ e.preventDefault();
41
+ if (
42
+ document
43
+ .getElementById(blockId)
44
+ ?.getElementsByClassName('active tab')?.length > 0
45
+ ) {
46
+ const tabDiv = document
47
+ .getElementById(blockId)
48
+ .getElementsByClassName('active tab')[0];
49
+ tabDiv.focus();
50
+ }
51
+ if (activeTab !== tab) {
52
+ setActiveTab(tab);
53
+ }
54
+ }
55
+ }}
56
+ >
32
57
  <SimpleMarkdown md={tabsTitle} defaultTag="##" className="title" />
33
58
  <SimpleMarkdown md={tabsDescription} className="description" />
34
59
  </Menu.Item>
35
60
  )}
36
61
  <Button
37
62
  as="a"
38
- className={cx('item', { active: tab === activeTab })}
63
+ tabIndex={0}
64
+ className={cx('item', 'accesibility-button', {
65
+ active: tab === activeTab,
66
+ })}
39
67
  item-data={tab}
40
68
  onClick={() => {
41
69
  if (activeTab !== tab) {
42
70
  setActiveTab(tab);
43
71
  }
44
72
  }}
73
+ onKeyDown={(e) => {
74
+ if (e.key === 'Enter') {
75
+ e.preventDefault();
76
+ if (
77
+ document
78
+ .getElementById(blockId)
79
+ ?.getElementsByClassName('active tab').length > 0
80
+ ) {
81
+ const tabDiv = document
82
+ .getElementById(blockId)
83
+ .getElementsByClassName('active tab')[0];
84
+ tabDiv.focus();
85
+ }
86
+ if (activeTab !== tab) {
87
+ setActiveTab(tab);
88
+ }
89
+ }
90
+ }}
45
91
  >
46
92
  <span className={'menu-item-count'}>{tabIndex}</span>
47
93
  <p className={'menu-item-text'}>{title || defaultTitle}</p>
@@ -92,7 +138,7 @@ const MenuWrapper = (props) => {
92
138
 
93
139
  return (
94
140
  <React.Fragment>
95
- <div className="menu-wrapper">
141
+ <div className="menu-wrapper tabs-accessibility">
96
142
  {panes.map((pane, index) => (
97
143
  <React.Fragment key={`menu-item-${index}-${pane.id}`}>
98
144
  {pane.menuItem}
@@ -207,6 +253,7 @@ const View = (props) => {
207
253
  key={tab}
208
254
  tab={tab}
209
255
  tabsList={tabsList}
256
+ blockId={props.id}
210
257
  index={index}
211
258
  lastIndex={tabsList.length - 1}
212
259
  tabsTitle={tabsTitle}
@@ -216,7 +263,7 @@ const View = (props) => {
216
263
  render: () => {
217
264
  return (
218
265
  <>
219
- <Tab.Pane as={isContainer ? Container : undefined}>
266
+ <Tab.Pane as={isContainer ? Container : undefined} tabIndex={0}>
220
267
  <RenderBlocks
221
268
  {...props}
222
269
  metadata={metadata}
@@ -55,12 +55,10 @@
55
55
  flex-direction: column;
56
56
  align-items: flex-start;
57
57
  justify-content: center;
58
- background: @menuTitleBackgrounnd;
59
58
  font-size: @menuTitleFontSize;
60
59
  font-weight: @menuTitleFontWeight;
61
60
 
62
61
  &:hover {
63
- background: @menuTitleHoverBackground;
64
62
  color: @menuTitleHoverColor;
65
63
  }
66
64
 
@@ -143,6 +141,13 @@
143
141
  }
144
142
  }
145
143
 
144
+ .ui.menu.RRT__accordion.tabs-accordion-icon-right {
145
+ .ui.item {
146
+ flex-direction: row-reverse;
147
+ justify-content: space-between;
148
+ }
149
+ }
150
+
146
151
  .ui.menu.RRT__accordion {
147
152
  &::before {
148
153
  display: none;
@@ -153,11 +158,9 @@
153
158
  .ui.item {
154
159
  display: flex;
155
160
  width: 100%;
156
- padding: 0.75rem 1rem !important;
157
- border-width: 0 !important;
158
- border-bottom: none !important;
161
+ padding: 0 1rem !important;
162
+ border-bottom: 0.0625rem solid #e6e7e8;
159
163
  margin: 0 !important;
160
- background-color: @accordionMenuItemBackground;
161
164
 
162
165
  .icon {
163
166
  margin: 0 !important;
@@ -174,7 +177,58 @@
174
177
  }
175
178
  }
176
179
 
180
+ .RRT__tab:not(.active) .icon {
181
+ color: #808285;
182
+ }
183
+
184
+ &.theme-primary {
185
+ .ui.item:not(.active):hover {
186
+ color: @primaryColor !important;
187
+
188
+ .icon {
189
+ color: @primaryColor !important;
190
+ }
191
+ }
192
+
193
+ .ui.item.active {
194
+ background-color: @primaryColor !important;
195
+ color: #fff !important;
196
+ }
197
+ }
198
+
199
+ &.theme-secondary {
200
+ .ui.item:not(.active):hover {
201
+ color: @secondaryColor !important;
202
+
203
+ .icon {
204
+ color: @secondaryColor !important;
205
+ }
206
+ }
207
+
208
+ .ui.item.active {
209
+ background-color: @secondaryColor !important;
210
+ color: #fff !important;
211
+ }
212
+ }
213
+
214
+ &.theme-tertiary {
215
+ .ui.item:not(.active):hover {
216
+ color: @tertiaryColor !important;
217
+
218
+ .icon {
219
+ color: @tertiaryColor !important;
220
+ }
221
+ }
222
+
223
+ .ui.item.active {
224
+ background-color: @tertiaryColor !important;
225
+ color: #fff !important;
226
+ }
227
+ }
228
+
177
229
  &.red {
230
+ color: @red !important;
231
+
178
232
  .ui.item.active {
179
233
  background-color: @red !important;
180
234
  color: #fff !important;
@@ -182,6 +236,10 @@
182
236
  }
183
237
 
184
238
  &.orange {
239
+ .ui.item:hover {
240
+ color: @orange !important;
241
+ }
242
+
185
243
  .ui.item.active {
186
244
  background-color: @orange !important;
187
245
  color: #fff !important;
@@ -189,6 +247,10 @@
189
247
  }
190
248
 
191
249
  &.yellow {
250
+ .ui.item:hover {
251
+ color: @yellow !important;
252
+ }
253
+
192
254
  .ui.item.active {
193
255
  background-color: @yellow !important;
194
256
  color: #fff !important;
@@ -196,6 +258,10 @@
196
258
  }
197
259
 
198
260
  &.olive {
261
+ .ui.item:hover {
262
+ color: @olive !important;
263
+ }
264
+
199
265
  .ui.item.active {
200
266
  background-color: @olive !important;
201
267
  color: #fff !important;
@@ -203,6 +269,10 @@
203
269
  }
204
270
 
205
271
  &.green {
272
+ .ui.item:hover {
273
+ color: @green !important;
274
+ }
275
+
206
276
  .ui.item.active {
207
277
  background-color: @green !important;
208
278
  color: #fff !important;
@@ -210,6 +280,10 @@
210
280
  }
211
281
 
212
282
  &.teal {
283
+ .ui.item:hover {
284
+ color: @teal !important;
285
+ }
286
+
213
287
  .ui.item.active {
214
288
  background-color: @teal !important;
215
289
  color: #fff !important;
@@ -217,6 +291,10 @@
217
291
  }
218
292
 
219
293
  &.blue {
294
+ .ui.item:hover {
295
+ color: @blue !important;
296
+ }
297
+
220
298
  .ui.item.active {
221
299
  background-color: @blue !important;
222
300
  color: #fff !important;
@@ -224,6 +302,10 @@
224
302
  }
225
303
 
226
304
  &.violet {
305
+ .ui.item:hover {
306
+ color: @violet !important;
307
+ }
308
+
227
309
  .ui.item.active {
228
310
  background-color: @violet !important;
229
311
  color: #fff !important;
@@ -231,6 +313,10 @@
231
313
  }
232
314
 
233
315
  &.purple {
316
+ .ui.item:hover {
317
+ color: @purple !important;
318
+ }
319
+
234
320
  .ui.item.active {
235
321
  background-color: @purple !important;
236
322
  color: #fff !important;
@@ -238,6 +324,10 @@
238
324
  }
239
325
 
240
326
  &.brown {
327
+ .ui.item:hover {
328
+ color: @brown !important;
329
+ }
330
+
241
331
  .ui.item.active {
242
332
  background-color: @brown !important;
243
333
  color: #fff !important;
@@ -245,6 +335,10 @@
245
335
  }
246
336
 
247
337
  &.grey {
338
+ .ui.item:hover {
339
+ color: @grey !important;
340
+ }
341
+
248
342
  .ui.item.active {
249
343
  background-color: @grey !important;
250
344
  color: #fff !important;
@@ -252,6 +346,10 @@
252
346
  }
253
347
 
254
348
  &.black {
349
+ .ui.item:hover {
350
+ color: @black !important;
351
+ }
352
+
255
353
  .ui.item.active {
256
354
  background-color: @black !important;
257
355
  color: #fff !important;
@@ -266,4 +364,70 @@
266
364
  }
267
365
  }
268
366
 
367
+ .ui.menu.RRT__tabs {
368
+ .item.ui {
369
+ color: #323232;
370
+ }
371
+
372
+ &.theme-primary {
373
+ .item.ui:hover {
374
+ color: @primaryColor !important;
375
+ }
376
+
377
+ .item.ui.active {
378
+ border-bottom: 0.1875rem solid @primaryColor !important;
379
+ color: @primaryColor !important;
380
+ }
381
+ }
382
+
383
+ &.theme-secondary {
384
+ .item.ui:hover {
385
+ color: @secondaryColor !important;
386
+ }
387
+
388
+ .item.ui.active {
389
+ border-bottom: 0.1875rem solid @secondaryColor !important;
390
+ color: @secondaryColor !important;
391
+ }
392
+ }
393
+
394
+ &.theme-tertiary {
395
+ .item.ui:hover {
396
+ color: @tertiaryColor !important;
397
+ }
398
+
399
+ .ui.item.active {
400
+ border-bottom: 0.1875rem solid @tertiaryColor !important;
401
+ color: @tertiaryColor !important;
402
+ }
403
+ }
404
+ }
405
+
406
+ .tabs-block {
407
+ .theme-primary {
408
+ .active.item {
409
+ border-bottom: 0.1875rem solid @primaryColor !important;
410
+ color: @primaryColor !important;
411
+ }
412
+ }
413
+
414
+ .theme-secondary {
415
+ .active.item {
416
+ border-bottom: 0.1875rem solid @secondaryColor !important;
417
+ color: @secondaryColor !important;
418
+ }
419
+ }
420
+
421
+ .theme-tertiary {
422
+ .active.item {
423
+ border-bottom: 0.1875rem solid @tertiaryColor !important;
424
+ color: @tertiaryColor !important;
425
+ }
426
+ }
427
+ }
428
+
429
+ // .tabs-block .ui.menu.RRT__accordion .ui.item .icon {
430
+ // color: #808285;
431
+ // }
432
+
269
433
  .loadAddonOverrides();
@@ -20,3 +20,8 @@
20
20
 
21
21
  @accordionMenuItemBackground: #F3F4F5;
22
22
  @accordionTabBackground: transparent;
23
+
24
+ /* Theme variables */
25
+ @primaryColor : #004B7F;
26
+ @secondaryColor : #007B6C;
27
+ @tertiaryColor : #3D5265;
@@ -7,6 +7,31 @@
7
7
  .loadAddonVariables();
8
8
 
9
9
  .tabs-block {
10
+ .tabs-accessibility {
11
+ .ui.button.item:focus-visible {
12
+ outline: 1px dotted #212121 !important;
13
+ outline: 5px auto -webkit-focus-ring-color !important;
14
+ }
15
+
16
+ a:focus-visible {
17
+ outline: 1px dotted #212121 !important;
18
+ outline: 5px auto -webkit-focus-ring-color !important;
19
+ }
20
+
21
+ .slick-current:focus-visible {
22
+ outline: 1px dotted #212121 !important;
23
+ outline: 5px auto -webkit-focus-ring-color !important;
24
+ }
25
+
26
+ .accessibility-accordion-tab {
27
+ outline: none;
28
+ }
29
+
30
+ .accessibility-accordion-tab:focus-visible {
31
+ outline: 1px dotted #212121 !important;
32
+ outline: 5px auto -webkit-focus-ring-color !important;
33
+ }
34
+ }
10
35
  color: @tabsBlockColor;
11
36
 
12
37
  > .styled {