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

add anchor as a new component to support anchor-button scenario #27395

Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "feat(anchor): add anchor to web components",
chrisdholt marked this conversation as resolved.
Show resolved Hide resolved
"packageName": "@fluentui/web-components",
"email": "chhol@microsoft.com",
"dependentChangeType": "patch"
}
4 changes: 4 additions & 0 deletions packages/web-components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
"types": "./dist/esm/accordion-item/define.d.ts",
"default": "./dist/esm/accordion-item/define.js"
},
"./anchor-button": {
"types": "./dist/esm/anchor-button/define.d.ts",
"default": "./dist/esm/anchor-button/define.js"
},
"./avatar": {
"types": "./dist/esm/avatar/define.d.ts",
"default": "./dist/esm/avatar/define.js"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { FluentDesignSystem } from '../fluent-design-system.js';
import { AnchorButton } from './anchor-button.js';
import { styles } from './anchor-button.styles.js';
import { template } from './anchor-button.template.js';

/**
* The Fluent Anchor Button Element. Implements {@link @microsoft/fast-foundation#Anchor },
* {@link @microsoft/fast-foundation#anchorTemplate}
*
* @public
* @remarks
* HTML Element: \<fluent-anchor-button\>
*/
export const definition = AnchorButton.compose({
name: `${FluentDesignSystem.prefix}-anchor-button`,
template,
styles,
shadowOptions: {
delegatesFocus: true,
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { AnchorOptions, ValuesOf } from '@microsoft/fast-foundation';
import { ButtonAppearance, ButtonShape, ButtonSize } from '../button/button.options.js';

/**
* Anchor Button Appearance constants
* @public
*/
export const AnchorButtonAppearance = ButtonAppearance;

/**
* An Anchor Button can be secondary, primary, outline, subtle, transparent
* @public
*/
export type AnchorButtonAppearance = ValuesOf<typeof AnchorButtonAppearance>;

/**
* An Anchor Button can be square, circular or rounded.
* @public
*/
export const AnchorButtonShape = ButtonShape;

/**
* An Anchor Button can be square, circular or rounded
* @public
*/
export type AnchorButtonShape = ValuesOf<typeof AnchorButtonShape>;

/**
* An Anchor Button can be a size of small, medium or large.
* @public
*/
export const AnchorButtonSize = ButtonSize;

/**
* An Anchor Button can be on of several preset sizes.
* @public
*/
export type AnchorButtonSize = ValuesOf<typeof AnchorButtonSize>;

export { AnchorOptions as AnchorButtonOptions };
214 changes: 214 additions & 0 deletions packages/web-components/src/anchor-button/anchor-button.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
import { html } from '@microsoft/fast-element';
import type { Args, Meta } from '@storybook/html';
import { renderComponent } from '../helpers.stories.js';
import type { AnchorButton as FluentAnchorButton } from './anchor-button.js';
import { AnchorButtonAppearance, AnchorButtonShape, AnchorButtonSize } from './anchor-button.options.js';
import './define.js';

type AnchorButtonStoryArgs = Args & FluentAnchorButton;
type AnchorButtonStoryMeta = Meta<AnchorButtonStoryArgs>;

const storyTemplate = html<AnchorButtonStoryArgs>`
<fluent-anchor-button
href="${x => x.href}"
appearance="${x => x.appearance}"
shape="${x => x.shape}"
size="${x => x.size}"
?disabled="${x => x.disabled}"
?disabled-focusable="${x => x.disabledFocusable}"
?icon-only="${x => x.iconOnly}"
>
${x => x.content}
</fluent-anchor-button>
`;

export default {
title: 'Components/Button/Anchor',
args: {
content: 'Anchor',
href: '#',
disabled: false,
disabledFocusable: false,
},
argTypes: {
appearance: {
options: Object.values(AnchorButtonAppearance),
control: {
type: 'select',
},
},
shape: {
options: Object.values(AnchorButtonShape),
control: {
type: 'select',
},
},
size: {
options: Object.values(AnchorButtonSize),
control: {
type: 'select',
},
},
disabled: {
control: 'boolean',
table: {
type: {
summary: 'Sets the disabled state of the component',
},
defaultValue: {
summary: 'false',
},
},
},
disabledFocusable: {
control: 'boolean',
table: {
type: {
summary: 'The component is disabled but still focusable',
},
defaultValue: {
summary: 'false',
},
},
},
href: {
control: 'text',
},
content: {
control: 'Anchor text',
},
},
} as AnchorButtonStoryMeta;

export const AnchorButton = renderComponent(storyTemplate).bind({});

export const Appearance = renderComponent(html<AnchorButtonStoryArgs>`
<fluent-anchor-button href="#">Default</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="primary">Primary</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="outline">Outline</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="subtle">Subtle</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="transparent">Transparent</fluent-anchor-button>
`);

export const Shape = renderComponent(html<AnchorButtonStoryArgs>`
<fluent-anchor-button href="#" shape="rounded">Rounded</fluent-anchor-button>
<fluent-anchor-button href="#" shape="circular">Circular</fluent-anchor-button>
<fluent-anchor-button href="#" shape="square">Square</fluent-anchor-button>
`);

export const Size = renderComponent(html<AnchorButtonStoryArgs>`
<fluent-anchor-button href="#" size="small">Small</fluent-anchor-button>
<fluent-anchor-button href="#" size="small" icon
><svg
fill="currentColor"
slot="start"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
>Small with calendar icon</fluent-anchor-button
>
<fluent-anchor-button href="#" size="small" icon-only aria-label="Small icon only button"
><svg
fill="currentColor"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
></fluent-anchor-button>
<fluent-anchor-button href="#" size="medium">Medium</fluent-anchor-button>
<fluent-anchor-button href="#" size="medium" icon
><svg
fill="currentColor"
slot="start"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
>Medium with calendar icon</fluent-anchor-button
>
<fluent-anchor-button href="#" size="medium" icon-only aria-label="Medium icon only button"
><svg
fill="currentColor"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
></fluent-anchor-button>
<fluent-anchor-button href="#" size="large">Large</fluent-anchor-button>
<fluent-anchor-button href="#" size="large" icon
><svg
fill="currentColor"
slot="start"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
>Large with calendar icon</fluent-anchor-button
>
<fluent-anchor-button href="#" size="large" icon-only aria-label="Large icon only button"
><svg
fill="currentColor"
aria-hidden="true"
width="1em"
height="1em"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.5 3A2.5 2.5 0 0117 5.5v9a2.5 2.5 0 01-2.5 2.5h-9A2.5 2.5 0 013 14.5v-9A2.5 2.5 0 015.5 3h9zm0 1h-9C4.67 4 4 4.67 4 5.5v9c0 .83.67 1.5 1.5 1.5h9c.83 0 1.5-.67 1.5-1.5v-9c0-.83-.67-1.5-1.5-1.5zM7 11a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zM7 7a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2zm3 0a1 1 0 110 2 1 1 0 010-2z"
fill="currentColor"
></path></svg
></fluent-anchor-button>
`);

export const Disabled = renderComponent(html<AnchorButtonStoryArgs>`
<fluent-anchor-button href="#">Enabled state</fluent-anchor-button>
<fluent-anchor-button href="#" disabled>Disabled state</fluent-anchor-button>
<fluent-anchor-button href="#" disabled-focusable>Disabled focusable state</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="primary">Enabled state</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="primary" disabled>Disabled state</fluent-anchor-button>
<fluent-anchor-button href="#" appearance="primary" disabled-focusable>Disabled focusable state</fluent-anchor-button>
`);

export const WithLongText = renderComponent(html<AnchorButtonStoryArgs>`
<style>
.max-width {
width: 280px;
}
</style>
<fluent-anchor-button href="#">Short text</fluent-anchor-button>
<fluent-anchor-button href="#" class="max-width"
>Long text wraps after it hits the max width of the component</fluent-anchor-button
>
`);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { css } from '@microsoft/fast-element';
import { styles as ButtonStyles } from '../button/button.styles.js';

// Need to support icon hover styles
export const styles = css`
${ButtonStyles}

.content {
text-align: center;
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ElementViewTemplate } from '@microsoft/fast-element';
import { anchorTemplate } from '@microsoft/fast-foundation';
import type { AnchorButton } from './anchor-button.js';

/**
* The template for the Button component.
* @public
*/
export const template: ElementViewTemplate<AnchorButton> = anchorTemplate();
Loading