Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add app-bar storybook #582

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/lib/app-bar/help-button/app-bar-help-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ declare global {
*
* @description A utility component with predefined icon and descriptions for use in an app bar `end` slot.
*
* @property {IMenuOption[]} options - The menu options to display when the button is clicked
* @property {string} icon - The name of an alternative icon to display.
* @property {IMenuOption[]} [options=[]] - The menu options to display when the button is clicked
* @property {string} [icon=help] - The name of an alternative icon to display.
*
* @attribute {string} [icon] - The name of an alternative icon to display.
* @attribute {string} [icon=help] - The name of an alternative icon to display.
* @attribute {string} [aria-label] - The aria-label to apply to the button.
* @attribute {string} [aria-labelledby] - The id of an element to use as the aria-labelledby attribute.
*
* @event {CustomEvent<IMenuSelectEventData>} forge-menu-select - Bubbles up the menu select from the internal menu component.
*/
@CustomElement({
name: APP_BAR_HELP_BUTTON_CONSTANTS.elementName,
Expand Down
4 changes: 2 additions & 2 deletions src/lib/app-bar/menu-button/app-bar-menu-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ declare global {
*
* @description A utility component with predefined icon and descriptions for use in an app bar `start` slot.
*
* @property {string} icon - The name of an alternative icon to display.
* @property {string} [icon=menu] - The name of an alternative icon to display.
*
* @attribute {string} [icon] - The name of an alternative icon to display.
* @attribute {string} [icon=menu] - The name of an alternative icon to display.
* @attribute {string} [aria-label] - The aria-label to apply to the button.
* @attribute {string} [aria-labelledby] - The id of an element to use as the aria-labelledby attribute.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ export class AppBarNotificationButtonFoundation implements IAppBarNotificationBu
private _isInitialized = false;
private _icon = 'notifications';

constructor(private _adapter: IAppBarNotificationButtonAdapter) {}
constructor(private _adapter: IAppBarNotificationButtonAdapter) { }

public initialize(): void {
this._adapter.initialize();
this._adapter.setCount(this._count);
this._adapter.setBadgeType(this._dot);
if (!this._dot) {
this._adapter.setCount(this._count);
}
this._adapter.setBadgeTheme(this._theme);
this._adapter.setBadgeVisible(this._showBadge);
this._adapter.setIcon(this._icon);
Expand Down
20 changes: 10 additions & 10 deletions src/lib/app-bar/notification-button/app-bar-notification-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,17 @@ export interface IAppBarNotificationButtonComponent extends IBaseComponent {
/**
* @tag forge-app-bar-notification-button
*
* @property {number | string} count - The number to display in the badge.
* @property {boolean} dot - Whether to display the dot variant of the badge or not.
* @property {boolean} showBadge - Whether to display the badge or not.
* @property {string} theme - The theme to apply to the badge.
* @property {string} icon - The name of an alternative icon to display.
* @property {number | string} [count = 0] - The number to display in the badge.
* @property {boolean} [dot = false] - Whether to display the dot variant of the badge or not.
* @property {boolean} [showBadge = false] - Whether to display the badge or not.
* @property {string} [theme = ""] - The theme to apply to the badge.
* @property {string} [icon = notifications] - The name of an alternative icon to display.
*
* @attribute {string} [count] - The number to display in the badge.
* @attribute {boolean} [dot] - Whether to display the dot variant of the badge or not.
* @attribute {boolean} [show-badge] - Whether to display the badge or not.
* @attribute {string} [theme] - The theme to apply to the badge.
* @attribute {string} [icon] - The name of an alternative icon to display.
* @attribute {string} [count = 0] - The number to display in the badge.
* @attribute {boolean} [dot = false] - Whether to display the dot variant of the badge or not.
* @attribute {boolean} [show-badge = false] - Whether to display the badge or not.
* @attribute {string} [theme = ""] - The theme to apply to the badge.
* @attribute {string} [icon = notifications] - The name of an alternative icon to display.
* @attribute {string} [aria-label] - The aria-label to apply to the button.
* @attribute {string} [aria-labelledby] - The id of an element to use as the aria-labelledby attribute.
*/
Expand Down
27 changes: 15 additions & 12 deletions src/lib/app-bar/profile-button/app-bar-profile-button.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,35 @@ declare global {
* @tag forge-app-bar-profile-button
*
* @property {string} avatarImageUrl - The url of the avatar image to display.
* @property {number} avatarLetterCount - The number of letters to display in the avatar.
* @property {number} [avatarLetterCount=2] - The number of letters to display in the avatar.
* @property {string} avatarText - The text to display in the avatar.
* @property {string} avatarIcon - The name of an alternative icon to display in the avatar.
* @property {string} fullName - The full name.
* @property {string} email - The email address.
* @property {boolean} signOutButton - Whether to display the sign out button or not. Defaults to `true`.
* @property {boolean} profileButton - Whether to display the profile button or not.
* @property {string} signOutButtonText - The text to display in the sign out button.
* @property {string} profileButtonText - The text to display in the profile button.
* @property {boolean} open - Whether the profile card is open or not.
* @property {boolean} [signOutButton=true] - Whether to display the sign out button or not. Defaults to `true`.
* @property {boolean} [profileButton=false] - Whether to display the profile button or not.
* @property {string} [signOutButtonText="Sign out"] - The text to display in the sign out button.
* @property {string} [profileButtonText="Profile"] - The text to display in the profile button.
* @property {boolean} [open=false] - Whether the profile card is open or not.
* @property {IPopoverComponent | undefined} popupElement - The popup element when open.
* @property {AppBarProfileButtonProfileCardBuilder} profileCardBuilder - Sets the profile card builder callback that will be used to add extra content to the profile card.
*
* @attribute {string} [avatar-image-url] - The url of the avatar image to display.
* @attribute {number} [avatar-letter-count] - The number of letters to display in the avatar.
* @attribute {number} [avatar-letter-count=2] - The number of letters to display in the avatar.
* @attribute {string} [avatar-text] - The text to display in the avatar.
* @attribute {string} [avatar-icon] - The name of an alternative icon to display in the avatar.
* @attribute {string} [full-name] - The full name.
* @attribute {string} [email] - The email address.
* @attribute {boolean} [sign-out-button] - Whether to display the sign out button or not. Defaults to `true`.
* @attribute {boolean} [profile-button] - Whether to display the profile button or not.
* @attribute {string} [sign-out-button-text] - The text to display in the sign out button.
* @attribute {string} [profile-button-text] - The text to display in the profile button.
* @attribute {boolean} [open] - Whether the profile card is open or not.
* @attribute {boolean} [sign-out-button=true] - Whether to display the sign out button or not. Defaults to `true`.
* @attribute {boolean} [profile-button=false] - Whether to display the profile button or not.
* @attribute {string} [sign-out-button-text="Sign Out"] - The text to display in the sign out button.
* @attribute {string} [profile-button-text="Profile"] - The text to display in the profile button.
* @attribute {boolean} [open=false] - Whether the profile card is open or not.
* @attribute {string} [aria-label] - The aria-label to apply to the button.
* @attribute {string} [aria-labelledby] - The id of an element to use as the aria-labelledby attribute.
*
* @event {CustomEvent} forge-profile-card-sign-out - Fires when the sign out button is clicked.
* @event {CustomEvent} forge-profile-card-profile - Fires when the profile button is clicked.
*/
@CustomElement({
name: APP_BAR_PROFILE_BUTTON_CONSTANTS.elementName,
Expand Down
10 changes: 10 additions & 0 deletions src/lib/app-bar/search/app-bar-search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ declare global {
* @slot - The default (unnamed) slot is where child `<input>` elements will be placed.
* @slot action - Places actions at the end of the input.
*
* @attribute {boolean} [disabled=false] - A boolean attribute that, if present, indicates that the input should be disabled.
* @attribute {string} value - The value of the input.
* @attribute {string} placeholder - The placeholder text of the input.
*
* @property {boolean} [disabled=false] - A boolean property that, if true, indicates that the input should be disabled.
* @property {string} value - The value of the input.
* @property {string} placeholder - The placeholder text of the input.
*
* @csspart root - The root element
* @csspart container - The input container element.
* @csspart icon-container - The icon container element.
Expand All @@ -52,6 +60,8 @@ declare global {
* @cssproperty --forge-app-bar-search-theme-background-focused - Controls the focused background-color of the container.
* @cssproperty --forge-app-bar-search-theme-hover-opacity - Controls the hover opacity of the outline.
* @cssproperty --forge-app-bar-search-theme-disabled-opacity - Controls the disabled opacity of the component.
*
* @event {CustomEvent<IAppBarSearchInputEventData>} forge-app-bar-search-input - Emits when the users executes the search via pressing the Enter key while the `<input>` has focus.
*/
@CustomElement({
name: APP_BAR_SEARCH_CONSTANTS.elementName,
Expand Down
41 changes: 41 additions & 0 deletions src/stories/components/app-bar/AppBar.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Meta, Title, Canvas } from '@storybook/blocks';
import CustomArgTypes from '../../blocks/CustomArgTypes';
import * as AppBarStories from './AppBar.stories';

<Meta of={AppBarStories} />

<Title />

The app-bar should be used as the header for every page in your application to ensure consistency across our Tyler products and applications. It's the one constant across all applications that helps ensure our applications are perceived as being connected and familiar.

The app-bar itself is nothing more than a container for other add-on components, but it does provide named slots and a common location for branding logo and title.

>For API details regarding any of the app-bar sub-components please see one of the following pages:
>
>- App Bar help button
>- App Bar menu button
>- App Bar notifications
>- App Bar profile
>- App Bar search

## Default

A basic app-bar just contains a title with no other elements.

<Canvas of={AppBarStories.Demo} />

## Full

The following example shows the usage of all of the common app-bar elements placed in their corresponding slots.

<Canvas of={AppBarStories.Full} />

## API

<CustomArgTypes />

## Accessibility
- Ensure that the user can interact with each sub-component of the app bar using only the keyboard.
- The app bar component will use an `<h1>` for the title by default. If you override the title slot content, be sure to use the proper heading element.
- Only **one** `<h1>` should be on a page at any given time (unless a new heading hierarchy is created as a sibling).
- A `<header>` element is built-in to the app bar component.
Empty file.
58 changes: 58 additions & 0 deletions src/stories/components/app-bar/AppBar.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { html } from 'lit';
import { type Meta, type StoryObj } from '@storybook/web-components';
import { customElementStoryRenderer, generateCustomElementArgTypes, standaloneStoryParams } from '../../utils';

import '@tylertech/forge/app-bar';
import '@tylertech/forge/expansion-panel';
import '@tylertech/forge/divider';
import '@tylertech/forge/open-icon';
import './AppBar.scss';

const component = 'forge-app-bar';

const meta = {
title: 'Components/App Bar',
render: args => customElementStoryRenderer(component, args),
component,
parameters: {
actions: { disable: true }
},
argTypes: {
...generateCustomElementArgTypes({
tagName: component,
exclude: ['target'],
controls: {
elevation: { type: 'string', control: 'select', options: ['none', 'raised'] },
theme: { type: 'string', control: 'select', options: ['white', ''] },
}
})
},
args: {
titleText: 'Tyler Forge',
elevation: 'raised',
theme: '',
href: '',
},
} satisfies Meta;

export default meta;

type Story = StoryObj;

export const Demo: Story = {};

export const Full: Story = {
...standaloneStoryParams,
render: () => html`
<forge-app-bar title-text="Tyler Forge">
<forge-app-bar-menu-button slot="start"></forge-app-bar-menu-button>
<forge-app-bar-search slot="center">
<input type="text" placeholder="Search" />
</forge-app-bar-search>
<forge-app-bar-help-button slot="end"></forge-app-bar-help-button>
<forge-app-bar-notification-button slot="end"></forge-app-bar-notification-button>
<forge-app-bar-app-launcher-button slot="end" allow-more="true"></forge-app-bar-app-launcher-button>
<forge-app-bar-profile-button slot="end" avatar-text="First Last" full-name="First Last" email="first.last@tylertech.com"></forge-app-bar-profile-button>
</forge-app-bar>
`
}
31 changes: 31 additions & 0 deletions src/stories/components/app-bar/Search/search.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Meta, Title, Canvas } from '@storybook/blocks';
import CustomArgTypes from '../../../blocks/CustomArgTypes';
import * as SearchStories from './search.stories';

<Meta of={SearchStories} />

<Title />

The app-bar search component is essentially just a strictly-styled `<input>` element that fits in with the app-bar ecosystem. It provides some additional functionality through its public API, but at the very least it gives a common component to use for a familiar search experience for users.

## Default

<Canvas of={SearchStories.Demo} />

## API

<CustomArgTypes />

## Accessibility
- Ensure that you provide a placeholder attribute for the `<input>` element to help give users an idea of what to enter.
- Ensure that you add an aria-label or aria-labelledby attribute to the `<input>`.
- If using a custom theme, make sure proper color contrast ratios are met and adjust using CSS custom properties if not.

## Types
```typescript
interface IAppBarSearchEventData {
value: string;
combined: boolean;
context: string;
}
```
41 changes: 41 additions & 0 deletions src/stories/components/app-bar/Search/search.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { html } from 'lit';
import { type Meta, type StoryObj } from '@storybook/web-components';
import { customElementStoryRenderer, generateCustomElementArgTypes, standaloneStoryParams } from '../../../utils';

import '@tylertech/forge/app-bar';

const component = 'forge-app-bar-search';

const meta = {
title: 'Components/App Bar/Search',
render: args => customElementStoryRenderer(component, args),
component,
parameters: {
actions: { disable: true }
},
argTypes: {
...generateCustomElementArgTypes({
tagName: component,
exclude: ['options', 'icon']
})
},
args: {
},
} satisfies Meta;

export default meta;

type Story = StoryObj;

export const Demo: Story = {
...standaloneStoryParams,
render: () => {
return html`
<forge-app-bar title-text="Search">
<forge-app-bar-search slot="center" >
<input type="text" aria-label="Search for a record" placeholder="Search" />
</forge-app-bar-search>
</forge-app-bar>
`;
},
};
24 changes: 24 additions & 0 deletions src/stories/components/app-bar/help-button/HelpButton.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Meta, Title, Canvas } from '@storybook/blocks';
import CustomArgTypes from '../../../blocks/CustomArgTypes';
import * as HelpButtonStories from './HelpButton.stories';

<Meta of={HelpButtonStories} />

<Title />
For convenience Forge provides the `<forge-app-bar-help-button>` component. This component uses an icon-button (with a predefined icon), and is wrapped in a Forge menu component. The power of this component is that it will ensure a consistent experience for users across all applications that consume it.

>It is expected that you place this component in the `end` slot of the app-bar.

## Default

The following example shows the help button being used in the Forge app-bar.

<Canvas of={HelpButtonStories.Demo} />

## API

<CustomArgTypes />

## Accessibility
- The `<forge-app-bar-help-button>` component handles all accessibility attributes for you, but if you implement this yourself be sure to add the proper aria-label.
- Ensure that the proper color contrast ratio is met, especially if using a custom theme.
44 changes: 44 additions & 0 deletions src/stories/components/app-bar/help-button/HelpButton.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { html } from 'lit';
import { type Meta, type StoryObj } from '@storybook/web-components';
import { customElementStoryRenderer, generateCustomElementArgTypes } from '../../../utils';

import '@tylertech/forge/app-bar';
import '@tylertech/forge/expansion-panel';
import '@tylertech/forge/divider';
import '@tylertech/forge/open-icon';
import { IMenuOption } from '@tylertech/forge';

const component = 'forge-app-bar-help-button';
const options: IMenuOption[] = [{ label: 'Help', value: 'help'}];

const meta = {
title: 'Components/App Bar/Help Button',
render: args => customElementStoryRenderer(component, args),
component,
parameters: {
actions: { disable: true }
},
argTypes: {
...generateCustomElementArgTypes({
tagName: component,
exclude: ['options', 'icon']
})
},
args: {
},
} satisfies Meta;

export default meta;

type Story = StoryObj;

export const Demo: Story = {
render: () => {
return html`
<forge-app-bar title-text="Help Icon">
<forge-app-bar-help-button slot="end" .options=${options}>
</forge-app-bar-help-button>
</forge-app-bar>
`;
}
};
Loading
Loading