@ember-eui/core 5.0.0-alpha.3 → 5.0.0-alpha.4

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.
@@ -1,45 +1,32 @@
1
- {{#let
2
- (unique-id)
3
- (optional @onTabClick)
4
- (arg-or-default @autoFocus 'initial')
5
- (use-state
6
- (get-tab-id
7
- (arg-or-default (or @selectedTab @initialSelectedTab) (object-at 0 @tabs))
8
- )
9
- )
10
- as |id onTabClick autoFocus selectedTab|
11
- }}
1
+ {{#let (unique-id) as |rootId|}}
12
2
  <div class={{@className}} ...attributes>
13
3
  <EuiTabs
14
- @selectedTab={{selectedTab.value}}
15
4
  @expand={{@expand}}
16
5
  @display={{@display}}
17
6
  @size={{@size}}
18
- as |EuiTab|
7
+ {{on "focus" this.initializeFocus}}
8
+ {{did-insert this.setTabsRef}}
19
9
  >
20
10
  {{#each @tabs as |tab|}}
21
11
  <EuiTab
22
12
  @id={{tab.id}}
23
- aria-controls={{id}}
24
- @selectedTabId={{selectedTab.value}}
25
- @onClick={{pipe selectedTab.setState (fn onTabClick tab)}}
26
- @focusFn={{selectedTab.setState}}
13
+ aria-controls={{rootId}}
14
+ @isSelected={{eq tab.id this.selectedTab.id}}
27
15
  @disabled={{tab.disabled}}
16
+ {{on "click" (fn this.onTabClick tab)}}
28
17
  >
29
18
  {{tab.name}}
30
19
  </EuiTab>
31
20
  {{/each}}
32
21
  </EuiTabs>
33
- {{#let (find-by "id" selectedTab.value @tabs) as |currentTab|}}
34
- {{#if currentTab}}
35
- <div role="tabpanel" id={{id}} aria-labelledby={{currentTab.id}}>
36
- {{#if (has-block "selectedTabContent")}}
37
- {{yield currentTab to="selectedTabContent"}}
38
- {{else}}
39
- {{currentTab.content}}
40
- {{/if}}
41
- </div>
42
- {{/if}}
22
+ {{#let (find-by "id" this.selectedTab.id @tabs) as |currentTab|}}
23
+ <div role="tabpanel" id={{rootId}} aria-labelledby={{currentTab.id}}>
24
+ {{#if (has-block "selectedTabContent")}}
25
+ {{yield currentTab to="selectedTabContent"}}
26
+ {{else}}
27
+ {{currentTab.content}}
28
+ {{/if}}
29
+ </div>
43
30
  {{/let}}
44
31
  </div>
45
32
  {{/let}}
@@ -0,0 +1,134 @@
1
+ import { scheduleOnce } from '@ember/runloop';
2
+ import Component from '@glimmer/component';
3
+ import { tracked } from '@glimmer/tracking';
4
+ import { CommonArgs } from '../common';
5
+
6
+ export interface EuiTabbedContentTab {
7
+ id: string;
8
+ name: string;
9
+ content: Component;
10
+ }
11
+
12
+ export type EuiTabbedContentArgs = CommonArgs & {
13
+ /**
14
+ * When tabbing into the tabs, set the focus on `initial` for the first tab,
15
+ * or `selected` for the currently selected tab. Best use case is for inside of
16
+ * overlay content like popovers or flyouts.
17
+ */
18
+ autoFocus?: 'initial' | 'selected';
19
+ /**
20
+ * Choose `default` or alternative `condensed` display styles
21
+ */
22
+ display?: string;
23
+ /**
24
+ * Evenly stretches each tab to fill the horizontal space
25
+ */
26
+ expand?: boolean;
27
+ /**
28
+ * Use this prop to set the initially selected tab while letting the tabbed content component
29
+ * control selection state internally
30
+ */
31
+ initialSelectedTab?: EuiTabbedContentTab;
32
+ onTabClick?: (selectedTab: EuiTabbedContentTab) => void;
33
+ /**
34
+ * Use this prop if you want to control selection state within the owner component
35
+ */
36
+ selectedTab?: EuiTabbedContentTab;
37
+ size?: string;
38
+ /**
39
+ * Each tab needs id and content properties, so we can associate it with its panel for accessibility.
40
+ * The name property (a node) is also required to display to the user.
41
+ */
42
+ tabs: EuiTabbedContentTab[];
43
+ };
44
+
45
+ export default class EuiTabbedContentComponent extends Component<EuiTabbedContentArgs> {
46
+ @tracked selectedTabId;
47
+ @tracked inFocus: boolean = false;
48
+ tabsRef?: Element;
49
+
50
+ get autoFocus() {
51
+ return this.args.autoFocus || 'initial';
52
+ }
53
+
54
+ constructor(owner: unknown, args: EuiTabbedContentArgs) {
55
+ super(owner, args);
56
+
57
+ const { initialSelectedTab, selectedTab, tabs } = this.args;
58
+
59
+ // Only track selection state if it's not controlled externally.
60
+ if (!selectedTab) {
61
+ this.selectedTabId =
62
+ (initialSelectedTab && initialSelectedTab.id) || tabs[0].id;
63
+ }
64
+ }
65
+
66
+ get selectedTab() {
67
+ const { selectedTab: externalSelectedTab, tabs } = this.args;
68
+ return (
69
+ externalSelectedTab ||
70
+ tabs.find((tab: EuiTabbedContentTab) => tab.id === this.selectedTabId)
71
+ );
72
+ }
73
+
74
+ setTabsRef = (element: Element) => {
75
+ this.tabsRef = element;
76
+ // Current short-term solution for event listener (see https://github.com/elastic/eui/pull/2717)
77
+ this.tabsRef.addEventListener('focusout' as 'blur', this.removeFocus);
78
+ };
79
+
80
+ willDestroy(): void {
81
+ super.willDestroy();
82
+ if (this.tabsRef) {
83
+ this.tabsRef.removeEventListener('focusout' as 'blur', this.removeFocus);
84
+ }
85
+ }
86
+
87
+ removeFocus = (blurEvent: FocusEvent) => {
88
+ // only set inFocus to false if the wrapping div doesn't contain the now-focusing element
89
+ const currentTarget = blurEvent.currentTarget! as HTMLElement;
90
+ const relatedTarget = blurEvent.relatedTarget! as HTMLElement;
91
+ if (currentTarget.contains(relatedTarget) === false) {
92
+ this.inFocus = true;
93
+ }
94
+ };
95
+
96
+ onTabClick = (selectedTab: EuiTabbedContentTab) => {
97
+ const { onTabClick, selectedTab: externalSelectedTab } = this.args;
98
+
99
+ if (onTabClick) {
100
+ onTabClick(selectedTab);
101
+ }
102
+
103
+ // Only track selection state if it's not controlled externally.
104
+ if (!externalSelectedTab) {
105
+ this.selectedTabId = selectedTab.id;
106
+ const focusTab = () => {
107
+ this.focusTab();
108
+ };
109
+ scheduleOnce('afterRender', this, focusTab);
110
+ }
111
+ };
112
+
113
+ focusTab = () => {
114
+ if (this.tabsRef) {
115
+ const targetTab: HTMLDivElement | null = this.tabsRef.querySelector(
116
+ `#${this.selectedTabId}`
117
+ );
118
+ targetTab!.focus();
119
+ }
120
+ };
121
+
122
+ initializeFocus = () => {
123
+ if (!this.inFocus && this.autoFocus === 'selected') {
124
+ // Must wait for setState to finish before calling `.focus()`
125
+ // as the focus call triggers a blur on the first tab
126
+ this.inFocus = true;
127
+
128
+ const focusTab = () => {
129
+ this.focusTab();
130
+ };
131
+ scheduleOnce('afterRender', this, focusTab);
132
+ }
133
+ };
134
+ }
@@ -1,36 +1,27 @@
1
1
  ---
2
- order: 4
2
+ order: 1
3
3
  ---
4
4
 
5
- # Tab sizes
6
5
 
7
6
  <EuiText>
8
- <p><strong>EuiTabs</strong> allow a <EuiCode>size</EuiCode> prop. In general you should always use the default (medium) size. The small size is best for when placing inside popovers or other small containers. Reserve using the large size for when using as primary page navigation, like inside of <a href="#/layout/page-header"><strong>EuiPageHeader</strong></a>.</p>
9
- <p>You can also use the <EuiCode>expand</EuiCode> prop to evenly stretch each tab horizontally.</p>
7
+ <p><strong>EuiTabs</strong> is a wrapping component that requires <strong>EuiTab</strong> components as direct children. You control the displayed contents and current state through props on EuiTab like <EuiCode>isSelected</EuiCode> and <EuiCode>onClick</EuiCode>.</p><p>Use the <EuiCode>prepend</EuiCode> and <EuiCode>append</EuiCode> tab props to add content before and after the tab label respectively.</p>
10
8
  </EuiText>
11
9
 
12
10
  ```hbs template
13
- <div>
14
- <EuiPopover
15
- @ownFocus={{true}}
16
- @isOpen={{this.popover}}
17
- @anchorPosition='downLeft'
18
- @closePopover={{set this 'popover' false}}
19
- >
20
- <:button>
21
- <EuiButton
22
- @iconType='arrowDown'
23
- @iconSide='right'
24
- {{on 'click' (set this 'popover' true)}}
25
- >
26
- Show Popover
27
- </EuiButton>
28
- </:button>
29
- <:content>
30
- <EuiTabbedContent @tabs={{this.tabsItems1}} />
31
- </:content>
32
- </EuiPopover>
33
- </div>
11
+ <EuiTabs>
12
+ {{#each this.tabs as |tab|}}
13
+ <EuiTab
14
+ @isSelected={{eq tab.id this.selectedTab.id}}
15
+ {{on 'click' (set this 'selectedTab' tab)}}
16
+ >
17
+ {{tab.name}}
18
+ </EuiTab>
19
+ {{/each}}
20
+ </EuiTabs>
21
+ <EuiSpacer />
22
+ <EuiText>
23
+ {{this.selectedTab.content}}
24
+ </EuiText>
34
25
  ```
35
26
 
36
27
  ```js component
@@ -39,54 +30,38 @@ import { action } from '@ember/object';
39
30
  import { tracked } from '@glimmer/tracking';
40
31
 
41
32
  export default class DemoTabsComponent extends Component {
42
- @tracked tabsIndex2 = 0;
43
-
33
+ @tracked selectedTab = 0;
34
+ @tracked tabs = [
35
+ {
36
+ id: 'cobalt--id',
37
+ name: 'Cobalt',
38
+ content:
39
+ ' Cobalt is a chemical element with symbol Co and atomic number 27. Like nickel, cobalt is found in the Earth&rsquo;s crust only in chemically combined form, save for small deposits found in alloys of natural meteoric iron. The free element, produced by reductive smelting, is a hard, lustrous, silver-gray metal.'
40
+ },
41
+ {
42
+ id: 'dextrose--id',
43
+ name: 'Dextrose',
44
+ content:
45
+ 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
46
+ },
47
+ {
48
+ id: 'hydrogen--id',
49
+ name: 'Hydrogen',
50
+ prepend: 'heatmap',
51
+ disabled: true,
52
+ content:
53
+ 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
54
+ },
55
+ {
56
+ id: 'monosodium_glutammate--id',
57
+ name: 'Monosodium Glutamate',
58
+ content:
59
+ ' Monosodium glutamate (MSG, also known as sodium glutamate) is the sodium salt of glutamic acid, one of the most abundant naturally occurring non-essential amino acids. Monosodium glutamate is found naturally in tomatoes, cheese and other foods.'
60
+ }
61
+ ];
44
62
  constructor() {
45
63
  super(...arguments);
46
-
47
- this.tabsItems1 = [
48
- {
49
- id: 'example1',
50
- name: 'Example 1',
51
- content: 'Example 1 content.'
52
- },
53
- {
54
- id: 'example2',
55
- name: 'Example 2',
56
- content: 'Example 2 content.'
57
- }
58
- ];
59
-
60
- this.tabsItems2 = [
61
- {
62
- id: 'one',
63
- name: 'Click me 1!',
64
- content: "Same ol' 1 content."
65
- },
66
- {
67
- id: 'two',
68
- name: 'Click me 2!',
69
- content: "Same ol' 2 content."
70
- },
71
- {
72
- id: 'three',
73
- name: 'Click me 3!',
74
- content: "Same ol' 3 content."
75
- }
76
- ];
77
- }
78
-
79
- sayMyName(tab) {
80
- alert(`I am ${tab.name || tab.id}`);
81
- }
82
-
83
- @action
84
- cycleTabs() {
85
- this.tabsIndex2++;
86
-
87
- if (this.tabsIndex2 >= this.tabsItems2.length) {
88
- this.tabsIndex2 = 0;
89
- }
64
+ this.selectedTab = this.tabs[0];
90
65
  }
91
66
  }
92
67
  ```
@@ -1,15 +1,46 @@
1
1
  ---
2
- order: 1
2
+ order: 2
3
3
  ---
4
4
 
5
- # Tabbed Content
5
+ # Tab sizes
6
6
 
7
7
  <EuiText>
8
- <p><strong>EuiTabbedContent</strong> makes it easier to associate tabs with content based on the selected tab. Use the <EuiCode>initialSelectedTab</EuiCode> prop to specify which tab to initially select.</p>
8
+ <p><strong>EuiTabs</strong> allow a <EuiCode>size</EuiCode> prop. In general you should always use the default (medium) size. The small size is best for when placing inside popovers or other small containers. Reserve using the large size for when using as primary page navigation, like inside of <a href="#/layout/page-header"><strong>EuiPageHeader</strong></a>.</p><p>You can also use the <EuiCode>expand</EuiCode> prop to evenly stretch each tab horizontally.</p>
9
9
  </EuiText>
10
10
 
11
11
  ```hbs template
12
- <EuiTabbedContent @tabs={{this.tabsItems1}} />
12
+ <div>
13
+ <EuiPopover
14
+ @ownFocus={{true}}
15
+ @isOpen={{this.popover}}
16
+ @anchorPosition='downLeft'
17
+ @closePopover={{set this 'popover' false}}
18
+ >
19
+ <:button>
20
+ <EuiButton
21
+ @iconType='arrowDown'
22
+ @iconSide='right'
23
+ {{on 'click' (set this 'popover' true)}}
24
+ >
25
+ Show Popover
26
+ </EuiButton>
27
+ </:button>
28
+ <:content>
29
+ <EuiTabs>
30
+ {{#each this.tabs as |tab|}}
31
+ <EuiTab
32
+ @isSelected={{eq this.selectedTab.id tab.id}}
33
+ {{on 'click' (set this 'selectedTab' tab)}}
34
+ >
35
+ {{tab.name}}
36
+ </EuiTab>
37
+ {{/each}}
38
+ </EuiTabs>
39
+ <EuiSpacer />
40
+ {{this.selectedTab.content}}
41
+ </:content>
42
+ </EuiPopover>
43
+ </div>
13
44
  ```
14
45
 
15
46
  ```js component
@@ -18,39 +49,25 @@ import { action } from '@ember/object';
18
49
  import { tracked } from '@glimmer/tracking';
19
50
 
20
51
  export default class DemoTabsComponent extends Component {
21
- @tracked tabsIndex2 = 0;
52
+ @tracked selectedTab;
22
53
 
23
54
  constructor() {
24
55
  super(...arguments);
25
56
 
26
- this.tabsItems1 = [
57
+ this.tabs = [
27
58
  {
28
- id: 'cobalt--id',
29
- name: 'Cobalt',
30
- content:
31
- ' Cobalt is a chemical element with symbol Co and atomic number 27. Like nickel, cobalt is found in the Earth&rsquo;s crust only in chemically combined form, save for small deposits found in alloys of natural meteoric iron. The free element, produced by reductive smelting, is a hard, lustrous, silver-gray metal.'
59
+ id: 'example1',
60
+ name: 'Example 1',
61
+ content: 'Example 1 content.'
32
62
  },
33
63
  {
34
- id: 'dextrose--id',
35
- name: 'Dextrose',
36
- content:
37
- 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
38
- },
39
- {
40
- id: 'hydrogen--id',
41
- name: 'Hydrogen',
42
- prepend: 'heatmap',
43
- disabled: true,
44
- content:
45
- 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
46
- },
47
- {
48
- id: 'monosodium_glutammate--id',
49
- name: 'Monosodium Glutamate',
50
- content:
51
- ' Monosodium glutamate (MSG, also known as sodium glutamate) is the sodium salt of glutamic acid, one of the most abundant naturally occurring non-essential amino acids. Monosodium glutamate is found naturally in tomatoes, cheese and other foods.'
64
+ id: 'example2',
65
+ name: 'Example 2',
66
+ content: 'Example 2 content.'
52
67
  }
53
68
  ];
69
+
70
+ this.selectedTab = this.tabs[0];
54
71
  }
55
72
  }
56
73
  ```
@@ -1,25 +1,54 @@
1
1
  ---
2
- order: 2
2
+ order: 3
3
3
  ---
4
4
 
5
- # Controlled tabbed content
5
+ # Bottom border
6
6
 
7
7
  <EuiText>
8
- <p>You can also use the <code class="euiCode" data-code-language="text">selectedTab</code> and <code class="euiCode" data-code-language="text">onTabClick</code> props to take complete control over tab selection. This can be useful if you want to change tabs based on user interaction with another part of the UI.</p>
8
+ <p>The <EuiCode>bottomBorder</EuiCode> helps to separate the tab group from the content below and is on by default. However, some components like <a href="/docs/core/docs/layout/flyout">flyouts</a> already provide borders which can act as the divider. In this case you can turn the border off with <EuiCode>bottomBorder<span class="token operator">=</span><span class="token punctuation">{</span><span class="token boolean">false</span><span class="token punctuation">}</span></EuiCode>.</p>
9
9
  </EuiText>
10
10
 
11
11
  ```hbs template
12
- <EuiButton @color='primary' {{on 'click' this.cycleTabs}}>
13
- Next tab
12
+ <EuiButton {{on 'click' this.openFlyout}}>
13
+ Show tabs flyout header
14
14
  </EuiButton>
15
- Outer selected tab:
16
- {{get (object-at this.tabsIndex2 this.tabsItems1) 'name'}}
17
- <EuiTabbedContent
18
- @tabs={{this.tabsItems1}}
19
- @selectedTab={{object-at this.tabsIndex2 this.tabsItems1}}
20
- />
21
-
22
- <EuiSpacer />
15
+ {{#if this.flyoutOpen}}
16
+ <EuiFlyout @onClose={{this.closeFlyout}}>
17
+ <EuiFlyoutHeader @hasBorder={{true}}>
18
+ <EuiTitle @size='m'>
19
+ <h2>Flyout header</h2>
20
+ </EuiTitle>
21
+ <EuiSpacer @size='s' />
22
+ <EuiText @color='subdued'>
23
+ Put navigation items in the header, and cross tab actions in a footer.
24
+ </EuiText>
25
+ <EuiSpacer @size='s' />
26
+ <EuiTabs @bottomBorder={{false}} style='margin-bottom: -24px;'>
27
+ {{#each this.tabs as |tab|}}
28
+ <EuiTab
29
+ {{on 'click' (set this 'selectedTab' tab)}}
30
+ @isSelected={{eq this.selectedTab.id tab.id}}
31
+ >
32
+ {{tab.name}}
33
+ </EuiTab>
34
+ {{/each}}
35
+ </EuiTabs>
36
+ </EuiFlyoutHeader>
37
+ <EuiFlyoutBody>
38
+ {{this.selectedTab.content}}
39
+ </EuiFlyoutBody>
40
+ <EuiFlyoutFooter>
41
+ <EuiFlexGroup @justifyContent='spaceBetween' @gutterSize='s'>
42
+ <EuiButton {{on 'click' this.closeFlyout}}>
43
+ Cancel
44
+ </EuiButton>
45
+ <EuiButton @fill={{true}} {{on 'click' this.closeFlyout}}>
46
+ Send
47
+ </EuiButton>
48
+ </EuiFlexGroup>
49
+ </EuiFlyoutFooter>
50
+ </EuiFlyout>
51
+ {{/if}}
23
52
  ```
24
53
 
25
54
  ```js component
@@ -28,12 +57,24 @@ import { action } from '@ember/object';
28
57
  import { tracked } from '@glimmer/tracking';
29
58
 
30
59
  export default class DemoTabsComponent extends Component {
31
- @tracked tabsIndex2 = 0;
60
+ @tracked selectedTab;
61
+
62
+ @tracked flyoutOpen = false;
63
+
64
+ @action
65
+ openFlyout() {
66
+ this.flyoutOpen = true;
67
+ }
68
+
69
+ @action
70
+ closeFlyout(flyout) {
71
+ this.flyoutOpen = false;
72
+ }
32
73
 
33
74
  constructor() {
34
75
  super(...arguments);
35
76
 
36
- this.tabsItems1 = [
77
+ this.tabs = [
37
78
  {
38
79
  id: 'cobalt--id',
39
80
  name: 'Cobalt',
@@ -61,19 +102,8 @@ export default class DemoTabsComponent extends Component {
61
102
  ' Monosodium glutamate (MSG, also known as sodium glutamate) is the sodium salt of glutamic acid, one of the most abundant naturally occurring non-essential amino acids. Monosodium glutamate is found naturally in tomatoes, cheese and other foods.'
62
103
  }
63
104
  ];
64
- }
65
-
66
- sayMyName(tab) {
67
- alert(`I am ${tab.name || tab.id}`);
68
- }
69
-
70
- @action
71
- cycleTabs() {
72
- this.tabsIndex2++;
73
105
 
74
- if (this.tabsIndex2 >= this.tabsItems2.length) {
75
- this.tabsIndex2 = 0;
76
- }
106
+ this.selectedTab = this.tabs[0];
77
107
  }
78
108
  }
79
109
  ```
@@ -1,36 +1,27 @@
1
1
  ---
2
- order: 3
2
+ order: 4
3
3
  ---
4
4
 
5
- # Bottom border
5
+ # Tabbed content
6
6
 
7
7
  <EuiText>
8
- <p>The <EuiCode>bottomBorder</EuiCode> helps to separate the tab group from the content below and is on by default. However, some components like <a href="#/layout/flyout">flyouts</a> already provide borders which can act as the divider. In this case you can turn the border off with <EuiCode>bottomBorder<span class="token operator">=</span><span class="token punctuation">{</span><span class="token boolean">false</span><span class="token punctuation">}</span></EuiCode>.</p>
8
+ <p><strong>EuiTabbedContent</strong> makes it easier to associate tabs with content based on the selected tab. Use the <EuiCode>initialSelectedTab</EuiCode> prop to specify which tab to initially select.</p>
9
9
  </EuiText>
10
10
 
11
11
  ```hbs template
12
- <EuiButton {{on 'click' this.openFlyout}}>
13
- Show tabs flyout header
14
- </EuiButton>
15
- {{#if this.flyoutOpen}}
16
- <EuiFlyout @onClose={{this.closeFlyout}}>
17
- <EuiFlyoutHeader @hasBorder={{true}}>
18
- <EuiTitle @size='l'>Flyout header</EuiTitle>
19
- <EuiTabbedContent @tabs={{this.tabsItems1}} />
20
- </EuiFlyoutHeader>
21
- <EuiFlyoutBody />
22
- <EuiFlyoutFooter>
23
- <EuiFlexGroup @justifyContent='spaceBetween' @gutterSize='s'>
24
- <EuiButton {{on 'click' this.closeFlyout}}>
25
- Cancel
26
- </EuiButton>
27
- <EuiButton @fill={{true}} {{on 'click' this.closeFlyout}}>
28
- Send
29
- </EuiButton>
30
- </EuiFlexGroup>
31
- </EuiFlyoutFooter>
32
- </EuiFlyout>
33
- {{/if}}
12
+ <EuiTabbedContent
13
+ @tabs={{this.tabs}}
14
+ @initialSelectedTab={{object-at this.tabs 1}}
15
+ @autoFocus='selected'
16
+ @onTabClick={{fn this.sayMyName}}
17
+ >
18
+ <:selectedTabContent as |selected|>
19
+ <EuiSpacer />
20
+ <EuiText>
21
+ {{selected.content}}
22
+ </EuiText>
23
+ </:selectedTabContent>
24
+ </EuiTabbedContent>
34
25
  ```
35
26
 
36
27
  ```js component
@@ -41,22 +32,10 @@ import { tracked } from '@glimmer/tracking';
41
32
  export default class DemoTabsComponent extends Component {
42
33
  @tracked tabsIndex2 = 0;
43
34
 
44
- @tracked flyoutOpen = false;
45
-
46
- @action
47
- openFlyout() {
48
- this.flyoutOpen = true;
49
- }
50
-
51
- @action
52
- closeFlyout(flyout) {
53
- this.flyoutOpen = false;
54
- }
55
-
56
35
  constructor() {
57
36
  super(...arguments);
58
37
 
59
- this.tabsItems1 = [
38
+ this.tabs = [
60
39
  {
61
40
  id: 'cobalt--id',
62
41
  name: 'Cobalt',
@@ -0,0 +1,86 @@
1
+ ---
2
+ order: 5
3
+ ---
4
+
5
+ # Controlled tabbed content
6
+
7
+ <EuiText>
8
+ <p>You can also use the <code class="euiCode" data-code-language="text">selectedTab</code> and <code class="euiCode" data-code-language="text">onTabClick</code> props to take complete control over tab selection. This can be useful if you want to change tabs based on user interaction with another part of the UI.</p>
9
+ </EuiText>
10
+
11
+ ```hbs template
12
+ <EuiButton
13
+ @color='primary'
14
+ {{on 'click' this.cycleTabs}}
15
+ @iconType='arrowRight'
16
+ @iconSide='right'
17
+ >
18
+ Cycle through tabs
19
+ </EuiButton>
20
+ Outer selected tab:
21
+ {{this.selectedTab.name}}
22
+ <EuiTabbedContent @tabs={{this.tabs}} @selectedTab={{this.selectedTab}}>
23
+ <:selectedTabContent as |selected|>
24
+ <EuiSpacer />
25
+ <EuiText>
26
+ {{selected.content}}
27
+ </EuiText>
28
+ </:selectedTabContent>
29
+ </EuiTabbedContent>
30
+
31
+ <EuiSpacer />
32
+ ```
33
+
34
+ ```js component
35
+ import Component from '@ember/component';
36
+ import { action } from '@ember/object';
37
+ import { tracked } from '@glimmer/tracking';
38
+
39
+ export default class DemoTabsComponent extends Component {
40
+ @tracked selectedTab;
41
+
42
+ constructor() {
43
+ super(...arguments);
44
+
45
+ this.tabs = [
46
+ {
47
+ id: 'cobalt--id',
48
+ name: 'Cobalt',
49
+ content:
50
+ ' Cobalt is a chemical element with symbol Co and atomic number 27. Like nickel, cobalt is found in the Earth&rsquo;s crust only in chemically combined form, save for small deposits found in alloys of natural meteoric iron. The free element, produced by reductive smelting, is a hard, lustrous, silver-gray metal.'
51
+ },
52
+ {
53
+ id: 'dextrose--id',
54
+ name: 'Dextrose',
55
+ content:
56
+ 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
57
+ },
58
+ {
59
+ id: 'hydrogen--id',
60
+ name: 'Hydrogen',
61
+ prepend: 'heatmap',
62
+
63
+ content:
64
+ 'Intravenous sugar solution, also known as dextrose solution, is a mixture of dextrose (glucose) and water. It is used to treat low blood sugar or water loss without electrolyte loss.'
65
+ },
66
+ {
67
+ id: 'monosodium_glutammate--id',
68
+ name: 'Monosodium Glutamate',
69
+ content:
70
+ ' Monosodium glutamate (MSG, also known as sodium glutamate) is the sodium salt of glutamic acid, one of the most abundant naturally occurring non-essential amino acids. Monosodium glutamate is found naturally in tomatoes, cheese and other foods.'
71
+ }
72
+ ];
73
+
74
+ this.selectedTab = this.tabs[0];
75
+ }
76
+
77
+ @action
78
+ cycleTabs() {
79
+ const tabs = this.tabs;
80
+ const selectedTabIndex = tabs.indexOf(this.selectedTab);
81
+ const nextTabIndex =
82
+ selectedTabIndex < tabs.length - 1 ? selectedTabIndex + 1 : 0;
83
+ this.selectedTab = tabs[nextTabIndex];
84
+ }
85
+ }
86
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ember-eui/core",
3
- "version": "5.0.0-alpha.3",
3
+ "version": "5.0.0-alpha.4",
4
4
  "description": "Ember Components for Elastic UI",
5
5
  "keywords": [
6
6
  "ember-addon",
@@ -182,5 +182,5 @@
182
182
  "volta": {
183
183
  "extends": "../../package.json"
184
184
  },
185
- "gitHead": "7cef4c765d72e1182023a9df43570d99007504f9"
185
+ "gitHead": "1b88258ed3a11388d0e4f8557f5744b91ede144e"
186
186
  }
@@ -1,23 +0,0 @@
1
- import { helper } from '@ember/component/helper';
2
- import { assert } from '@ember/debug';
3
-
4
- export function getTabId([tabOrId]: [Tab | string | number]):
5
- | string
6
- | number
7
- | undefined {
8
- if (tabOrId === undefined) {
9
- return;
10
- }
11
-
12
- if (typeof tabOrId === 'string' || typeof tabOrId === 'number') {
13
- return tabOrId;
14
- }
15
-
16
- assert(
17
- 'The passed `tab` object needs to have the `id` property',
18
- tabOrId.id !== undefined
19
- );
20
- return tabOrId.id;
21
- }
22
-
23
- export default helper(getTabId);
@@ -1 +0,0 @@
1
- export { default, getTabId } from '@ember-eui/core/helpers/get-tab-id';