Skip to content

Commit

Permalink
Merge pull request #1702 from hashicorp/selected-tab-condition-part2-…
Browse files Browse the repository at this point in the history
…documentation

`Tabs` - Update documentation
  • Loading branch information
didoo committed Oct 11, 2023
2 parents 8fd10b9 + f3de67e commit 0eada7c
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 31 deletions.
5 changes: 5 additions & 0 deletions website/app/controllers/show.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,18 @@ export default class ShowController extends Controller {
{
selectedTab: 'tab',
},
// see: https://github.com/DockYard/ember-router-scroll#preservescrollposition-with-queryparams
'preserveScrollPosition',
// these are used for the searches/filters in the website
'searchQuery',
'selectedIconSize',
// these are used in the "pagination > how to use" demos
'demoCurrentPage',
'demoCurrentPageSize',
'demoCurrentCursor',
'demoExtraParam',
// these are used in the "tabs > how to use" demos
'demoSelectedTab',
];

@service fastboot;
Expand Down
1 change: 1 addition & 0 deletions website/app/styles/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
@import "pages/components/radio-card";
@import "pages/components/side-nav";
@import "pages/components/table";
@import "pages/components/tabs";
@import "pages/layouts/app-frame";

// Third-party declarations
Expand Down
18 changes: 18 additions & 0 deletions website/app/styles/pages/components/tabs.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/


// COMPONENTS > APP-FOOTER

#show-content-components-tabs {
.doc-tabs-demo-overflow {
.hds-tabs__panel {
@include doc-font-style-body-small();
padding: 16px;

em { display: block; }
}
}
}
10 changes: 8 additions & 2 deletions website/docs/components/pagination/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ const getNewPrevNextCursors = (cursor, pageSize, records) => {
export default class Index extends Component {
@service router;

debugger;

@tracked demoPageSizes = [5, 10, 30];

// ----------------------------
Expand Down Expand Up @@ -347,8 +345,12 @@ export default class Index extends Component {
get demoQueryFunctionNumbered() {
return (page, pageSize) => {
return {
// important: in order for this to work, the query param name needs to be added to the list of query params in the controller:
// see: https://github.com/hashicorp/design-system/blob/main/website/app/controllers/show.js#L42-L53
demoCurrentPage: page,
demoCurrentPageSize: pageSize,
// see: https://github.com/DockYard/ember-router-scroll#preservescrollposition-with-queryparams
preserveScrollPosition: true,
};
};
}
Expand All @@ -369,8 +371,12 @@ export default class Index extends Component {
let { newPrevCursor, newNextCursor } = this.demoNewPrevNextCursors;
return (page) => {
return {
// important: in order for this to work, the query param name needs to be added to the list of query params in the controller:
// see: https://github.com/hashicorp/design-system/blob/main/website/app/controllers/show.js#L42-L53
demoCurrentCursor: page === 'prev' ? newPrevCursor : newNextCursor,
demoExtraParam: 'hello',
// see: https://github.com/DockYard/ember-router-scroll#preservescrollposition-with-queryparams
preserveScrollPosition: true,
};
};
}
Expand Down
37 changes: 37 additions & 0 deletions website/docs/components/tabs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,45 @@

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';

export default class Index extends Component {
@service router;

// ----------------------------
// since this is techically a component and not a controller
// we can't directly access the query parameters values (and then track them)
// using the `queryParams` declaration, so we need to access them directly
// via the router, and provide them as getter to the code snippets so they're
// kept in sync with the URL whenever the user interacts with the demo component

get demoSelectedTab() {
return parseInt(
this.router?.currentRoute?.queryParams?.demoSelectedTab ?? 0
);
}

get demoRouteName() {
// eg. 'components.pagination';
return this.router.currentRouteName;
}

@action
async demoUpdateSelectedTabQueryParam(_element, index) {
const routeQueryParams = this?.router?.currentRoute?.queryParams ?? {};
let queryParams = Object.assign({}, routeQueryParams);
if (index !== undefined) {
// important: in order for this to work, the query param name needs to be added to the list of query params in the controller:
// see: https://github.com/hashicorp/design-system/blob/main/website/app/controllers/show.js#L42-L53
queryParams.demoSelectedTab = index;
// see: https://github.com/DockYard/ember-router-scroll#preservescrollposition-with-queryparams
queryParams.preserveScrollPosition = true;

// navigate to the new URL (notice: the anchor/fragment `#...` is not preserved unfortunately)
await this.router.transitionTo({ queryParams });
}
}

@action
logClickedTab(event) {
const tabId = event.target.id;
Expand Down
18 changes: 14 additions & 4 deletions website/docs/components/tabs/partials/code/component-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,17 @@ The Tabs component is composed of different parts, with their own APIs:
### Tabs API

<Doc::ComponentApi as |C|>
<C.Property @name="onClickTab" @type="function"/>
<C.Property @name="onClickTab" @type="function">
Callback function invoked when the one of the tabs is clicked, if provided. The function receives the DOM `event` and the tab's `index` (integer number) as arguments.
</C.Property>
<C.Property @name="selectedTabIndex" @type="integer">
This argument can be used to select the initial tab and control the component state bypassing its default internal state (usually via query parameters).
<br/>
_Notice: when the initial tab is set using this parameter instead of using the `@isSelected` argument on the `Tab` sub-component, the consumer is responsible for updating the index whenever the user clicks on one of the tabs (via `onClickTab`)._
</C.Property>
<C.Property @name="isParentVisible" @type="boolean" default="false">
Special argument used to control nested tabs. See ["How to use / Nested tabs"](/components/tabs?tab=code#nested-tabs) for details.
</C.Property>
<C.Property @name="...attributes">
This component supports use of [`...attributes`](https://guides.emberjs.com/release/in-depth-topics/patterns-for-components/#toc_attribute-ordering).
</C.Property>
Expand All @@ -18,12 +28,12 @@ The Tabs component is composed of different parts, with their own APIs:
### Tabs::Tab API

<Doc::ComponentApi as |C|>
<C.Property @name="count" @type="string">
Displays an optional `count` indicator in the tab. Accepts the text value that should go in [Badge Count](/components/badge-count).
</C.Property>
<C.Property @name="icon">
Displays an optional icon in the tab. Accepts any [icon](/icons/library) name.
</C.Property>
<C.Property @name="count" @type="string">
Displays an optional `count` indicator in the tab. Accepts the text value that should go in [Badge Count](/components/badge-count).
</C.Property>
<C.Property @name="isSelected" @type="boolean" @default="false">
Customizes the initial tab to display when the page is loaded. The first tab is selected on page load by default.
</C.Property>
Expand Down
55 changes: 53 additions & 2 deletions website/docs/components/tabs/partials/code/how-to-use.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@
</Hds::Tabs>
```

### Custom starting tab
### Pre-selecting a tab

Customize the starting tab to display on page load. The first tab is selected by default.
While the first tab is selected by default, it is possible to customize the starting tab to display on page load in two different ways (depending on how the tabs' state is controlled/persisted).

#### Using `@isSelected` argument applied to one of the `Tab` elements

Declare which tab is selected when the component is first rendered by providing `@isSelected` argument to one of the `Tab` elements. From that moment on, the tab selection is controlled internally by the component.

```handlebars
<Hds::Tabs as |T|>
Expand All @@ -28,6 +32,22 @@ Customize the starting tab to display on page load. The first tab is selected by
</Hds::Tabs>
```

#### Using `@selectedTabIndex` argument applied to the `Tabs` component

If you want to control the internal "selected tab" state of the component, and possibly persist it in a query parameter, you need to provide a `@selectedTabIndex` argument to the main `Tabs` component. You also need to handle the change of state using the `@onClickTab` callback function, invoked whenever a user clicks/selects one of the tabs.

```handlebars
<Hds::Tabs @selectedTabIndex={{this.demoSelectedTab}} @onClickTab={{this.demoUpdateSelectedTabQueryParam}} as |T|>
<T.Tab>One</T.Tab>
<T.Tab>Two</T.Tab>
<T.Tab >Three</T.Tab>
<T.Panel>Content 1</T.Panel>
<T.Panel>Content 2</T.Panel>
<T.Panel>Content 3</T.Panel>
</Hds::Tabs>
```

### Count and icon

```handlebars
Expand Down Expand Up @@ -57,3 +77,34 @@ Use the `@onClickTab` handler to pass in a custom function. For example, to stor
<T.Panel>Content three</T.Panel>
</Hds::Tabs>
```

### Nested tabs

[We don’t recommend nesting tabs](/components/tabs#nested), but in case it’s necessary to implement such a feature a special code implementation needs to be used: the `T.Panel` needs to be exposed and its `P.isVisible` property needs to be provided to the nested tab using the `@isParentVisible` argument, so that when the parent visibility changes the nested tab can be initialized accordingly.

```handlebars
<Hds::Tabs as |T|>
<T.Tab>🐤 Birds</T.Tab>
<T.Tab>🐠 Fishes</T.Tab>
<T.Tab>🐙 Cephalopods</T.Tab>
<T.Panel as |P|>
<Hds::Tabs @isParentVisible={{P.isVisible}} as |NT|>
<NT.Tab>🦜 Parrots</NT.Tab>
<NT.Tab>🦅 Eagles</NT.Tab>
<NT.Tab>🦉 Owls</NT.Tab>
<NT.Panel><Doc::Placeholder @text="🦜 Content for Parrots" @height="50" /></NT.Panel>
<NT.Panel><Doc::Placeholder @text="🦅 Content for Eagles" @height="50" /></NT.Panel>
<NT.Panel><Doc::Placeholder @text="🦉 Content for Owls" @height="50" /></NT.Panel>
</Hds::Tabs>
</T.Panel>
<T.Panel as |P|>
<Hds::Tabs @isParentVisible={{P.isVisible}} as |NT|>
<NT.Tab>🐬 Dolphins</NT.Tab>
<NT.Tab>🦈 Sharks</NT.Tab>
<NT.Panel><Doc::Placeholder @text="🐬 Content for Dolphins" @height="50" /></NT.Panel>
<NT.Panel><Doc::Placeholder @text="🦈 Content for Sharks" @height="50" /></NT.Panel>
</Hds::Tabs>
</T.Panel>
<T.Panel><Doc::Placeholder @text="🐙 Content for Cephalopods" @height="50" /></T.Panel>
</Hds::Tabs>
```
66 changes: 43 additions & 23 deletions website/docs/components/tabs/partials/guidelines/guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ Don’t use Tabs for sequential content.

!!! Dont

We don’t recommend using a singular Tab; instead consider using a heading.
We don’t recommend using a singular Tab; instead consider using a heading.

![Tabs with only one tab](/assets/components/tabs/tab-behavior-single-button.png)
!!!

!!! Dont

Don’t trigger a Tab change via an external action, such as a submit or next button. Tab changes should only be triggered by the Tab itself as that is the expected user interaction.
Don’t trigger a Tab change via an external action, such as a submit or next button. Tab changes should only be triggered by the Tab itself as that is the expected user interaction.

![Tabs with external trigger](/assets/components/tabs/tabs-external-trigger.png)
!!!
Expand Down Expand Up @@ -90,27 +90,47 @@ When the content area does not consist of a contained component (ie. text block,

Tabs will fill 100% of the parent container, unless explicitly set to something else. When there are too many tabs to fit within the TabList, a horizontal scrollbar will help the user navigation hidden tabs.

<Hds::Tabs as |T|>
<T.Tab>One one-thousand</T.Tab>
<T.Tab>Two one-thousand</T.Tab>
<T.Tab>Three one-thousand</T.Tab>
<T.Tab>Four one-thousand</T.Tab>
<T.Tab>Five one-thousand</T.Tab>
<T.Tab>Six one-thousand</T.Tab>
<T.Tab>Seven one-thousand</T.Tab>
<T.Tab>Eight one-thousand</T.Tab>
<T.Tab>Nine one-thousand</T.Tab>
<T.Tab>Ten one-thousand</T.Tab>
<T.Panel>Content one</T.Panel>
<T.Panel>Content two</T.Panel>
<T.Panel>Content three</T.Panel>
<T.Panel>Content four</T.Panel>
<T.Panel>Content five</T.Panel>
<T.Panel>Content six</T.Panel>
<T.Panel>Content seven</T.Panel>
<T.Panel>Content eight</T.Panel>
<T.Panel>Content nine</T.Panel>
<T.Panel>Content ten</T.Panel>
<Hds::Tabs class="doc-tabs-demo-overflow" as |T|>
<T.Tab>The Wonderful Wizard of Oz</T.Tab>
<T.Tab>The Bell Jar</T.Tab>
<T.Tab>The Little Prince</T.Tab>
<T.Tab>Alice in Wonderland</T.Tab>
<T.Tab>Lady Windermere’s Fan</T.Tab>
<T.Tab>Dune</T.Tab>
<T.Tab>The Handmaid’s Tale</T.Tab>
<T.Tab>To Kill a Mockingbird</T.Tab>
<T.Tab>Fahrenheit 451</T.Tab>
<T.Tab>Slaughterhouse-Five</T.Tab>
<T.Tab>Handle With Care</T.Tab>
<T.Tab>Oh, the Places You’ll Go!</T.Tab>
<T.Tab>Barrel Fever</T.Tab>
<T.Tab>I am No One You Know</T.Tab>
<T.Tab>Harry Potter and the Goblet of Fire</T.Tab>
<T.Tab>Twilight of the Idols</T.Tab>
<T.Tab>Song of Myself</T.Tab>
<T.Tab>This is My Story</T.Tab>
<T.Tab>The Secret History</T.Tab>
<T.Tab>Poems of Arthur O’Shaughnessy</T.Tab>
<T.Panel>“A heart is not judged by how much you love; but by how much you are loved by others” – <em>L. Frank Baum, The Wonderful Wizard of Oz</em></T.Panel>
<T.Panel>“I took a deep breath and listened to the old brag of my heart. I am, I am, I am.” – <em>Sylvia Plath, The Bell Jar</em></T.Panel>
<T.Panel>“The most beautiful things in the world cannot be seen or touched, they are felt with the heart.” – <em>Antoine de Saint-Exupéry, The Little Prince</em></T.Panel>
<T.Panel>“Why, sometimes I’ve believed as many as six impossible things before breakfast.” – <em>Lewis Carroll, Alice in Wonderland</em></T.Panel>
<T.Panel>“We are all in the gutter, but some of us are looking at the stars.” – <em>Oscar Wilde, Lady Windermere’s Fan</em></T.Panel>
<T.Panel>“I must not fear. Fear is the mind-killer. Fear is the little-death that brings total obliteration. I will face my fear. I will permit it to pass over me and through me. And when it has gone past I will turn the inner eye to see its path. Where the fear has gone there will be nothing. Only I will remain.” – <em>Frank Herbert, Dune</em></T.Panel>
<T.Panel>“Nolite te bastardes carborundorum.” (Don’t let the bastards grind you down) – <em>Margaret Atwood, The Handmaid’s Tale</em></T.Panel>
<T.Panel>“Atticus said to Jem one day, “I’d rather you shot at tin cans in the backyard, but I know you’ll go after birds. Shoot all the blue jays you want, if you can hit ‘em, but remember it’s a sin to kill a mockingbird.” That was the only time I ever heard Atticus say it was a sin to do something, and I asked Miss Maudie about it. “Your father’s right,” she said. “Mockingbirds don’t do one thing except make music for us to enjoy. They don’t eat up people’s gardens, don’t nest in corn cribs, they don’t do one thing but sing their hearts out for us. That’s why it’s a sin to kill a mockingbird.” – <em>Harper Lee, To Kill a Mockingbird</em></T.Panel>
<T.Panel>“Stuff your eyes with wonder, he said, live as if you’d drop dead in ten seconds. See the world. It’s more fantastic than any dream made or paid for in factories.” – <em>Ray Bradbury, Fahrenheit 451</em></T.Panel>
<T.Panel>“And so it goes…” – <em>Kurt Vonnegut, Slaughterhouse-Five</em></T.Panel>
<T.Panel>“You can tell yourself that you would be willing to lose everything you have in order to get something you want. But it’s a catch-22: all of those things you’re willing to lose are what make you recognizable. Lose them, and you’ve lost yourself.” – <em>Jodi Picoult, Handle With Care</em></T.Panel>
<T.Panel>“You have brains in your head. You have feet in your shoes. You can steer yourself any direction you choose. You’re on your own. And you know what you know. And YOU are the one who’ll decide where to go…” – <em>Dr. Seuss, Oh, the Places You’ll Go!</em></T.Panel>
<T.Panel>“If you’re looking for sympathy you’ll find it between shit and syphilis in the dictionary.” – <em>David Sedaris, Barrel Fever</em></T.Panel>
<T.Panel>“I had forgotten that time wasn’t fixed like concrete but in fact was fluid as sand, or water. I had forgotten that even misery can end. ” – <em>Joyce Carol Oates, I am No One You Know</em></T.Panel>
<T.Panel>“If you want to know what a man’s like, take a good look at how he treats his inferiors, not his equals.” – <em>J.K. Rowling, Harry Potter and the Goblet of Fire</em></T.Panel>
<T.Panel>“Without music, life would be a mistake.” – <em>Friedrich Nietzsche, Twilight of the Idols</em></T.Panel>
<T.Panel>“This is what you shall do; Love the earth and sun and the animals, despise riches, give alms to every one that asks, stand up for the stupid and crazy, devote your income and labor to others, hate tyrants, argue not concerning God, have patience and indulgence toward the people, take off your hat to nothing known or unknown or to any man or number of men, go freely with powerful uneducated persons and with the young and with the mothers of families, read these leaves in the open air every season of every year of your life, re-examine all you have been told at school or church or in any book, dismiss whatever insults your own soul, and your very flesh shall be a great poem and have the richest fluency not only in its words but in the silent lines of its lips and face and between the lashes of your eyes and in every motion and joint of your body.” – <em>Walt Whitman, Song of Myself</em></T.Panel>
<T.Panel>“No one can make you feel inferior without your consent.” – <em>Eleanor Roosevelt, This is My Story</em></T.Panel>
<T.Panel>“It’s a very Greek idea, and a very profound one. Beauty is terror. Whatever we call beautiful, we quiver before it. And what could be more terrifying and beautiful, to souls like the Greeks or our own, than to lose control completely? To throw off the chains of being for an instant, to shatter the accident of our mortal selves? Euripides speaks of the Maenads: head thrown I back, throat to the stars, “more like deer than human being.” To be absolutely free! One is quite capable, of course, of working out these destructive passions in more vulgar and less efficient ways. But how glorious to release them in a single burst! To sing, to scream, to dance barefoot in the woods in the dead of night, with no more awareness of mortality than an animal! These are powerful mysteries. The bellowing of bulls. Springs of honey bubbling from the ground. If we are strong enough in our souls we can rip away the veil and look that naked, terrible beauty right in the face; let God consume us, devour us, unstring our bones. Then spit us out reborn.” – <em>Donna Tartt, The Secret History</em></T.Panel>
<T.Panel>“We are the music-makers, And we are the dreamers of dreams, Wandering by lone sea-breakers, And sitting by desolate streams. World-losers and world-forsakers, Upon whom the pale moon gleams; Yet we are the movers and shakers, Of the world forever, it seems.” – <em>Arthur O’Shaughnessy, Poems of Arthur O’Shaughnessy</em></T.Panel>
</Hds::Tabs>

!!! Insight
Expand Down

0 comments on commit 0eada7c

Please sign in to comment.