more stories

This commit is contained in:
Christian Bromann
2025-04-29 22:32:48 -07:00
parent f0f9bf9250
commit 84fb25ff23
8 changed files with 1003 additions and 66 deletions

30
core/package-lock.json generated
View File

@ -28,7 +28,7 @@
"@stencil/core": "^4.30.0",
"@stencil/react-output-target": "0.5.3",
"@stencil/sass": "^3.0.9",
"@stencil/storybook-plugin": "^0.0.11",
"@stencil/storybook-plugin": "^0.0.12",
"@stencil/vue-output-target": "0.10.7",
"@storybook/addon-essentials": "^8.6.12",
"@storybook/addon-interactions": "^8.6.12",
@ -2608,9 +2608,9 @@
}
},
"node_modules/@stencil/storybook-plugin": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/@stencil/storybook-plugin/-/storybook-plugin-0.0.11.tgz",
"integrity": "sha512-sfTgNBGtIru0CvZ5243t4Ew2wrdvnd6iWDRWLrr2R17lUs3RWEh2/W8E1SX/lXFJVwCqENwPh95W6jS4eyJOUA==",
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@stencil/storybook-plugin/-/storybook-plugin-0.0.12.tgz",
"integrity": "sha512-mBz6wYE/getEnDn9TkciyOTR2ZO+mz5bBAjN4YEAG/sjesgBGvxB0NKVHTtLTqLGEv/wtQo/nh/zjsPmwoHqxw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -2624,7 +2624,7 @@
"@storybook/types": "^8.6.12",
"preact-render-to-string": "^6.5.13",
"react-docgen-typescript": "^2.2.2",
"unplugin-stencil": "^0.2.5"
"unplugin-stencil": "^0.2.6"
},
"engines": {
"node": ">=20"
@ -2916,9 +2916,9 @@
}
},
"node_modules/@stencil/storybook-plugin/node_modules/unplugin-stencil": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/unplugin-stencil/-/unplugin-stencil-0.2.5.tgz",
"integrity": "sha512-4/wufyqIRkcYfWlWvfUBtPm2/z0EuhWfHbBUKSL0dcAGpgC65LhH05jfwVpfrlSuc44Tp1rFx3ciaIFsjpXDsg==",
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/unplugin-stencil/-/unplugin-stencil-0.2.6.tgz",
"integrity": "sha512-buLzEBcTLE9B+6/5N0OjFItEFifK19QBj80a4oPuX82K6+/kb3ooHmQiklcam9Y6L8/tyAfjj2ADQbhg0GaM2Q==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -15288,9 +15288,9 @@
"requires": {}
},
"@stencil/storybook-plugin": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/@stencil/storybook-plugin/-/storybook-plugin-0.0.11.tgz",
"integrity": "sha512-sfTgNBGtIru0CvZ5243t4Ew2wrdvnd6iWDRWLrr2R17lUs3RWEh2/W8E1SX/lXFJVwCqENwPh95W6jS4eyJOUA==",
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@stencil/storybook-plugin/-/storybook-plugin-0.0.12.tgz",
"integrity": "sha512-mBz6wYE/getEnDn9TkciyOTR2ZO+mz5bBAjN4YEAG/sjesgBGvxB0NKVHTtLTqLGEv/wtQo/nh/zjsPmwoHqxw==",
"dev": true,
"requires": {
"@storybook/addon-actions": "^8.6.12",
@ -15303,7 +15303,7 @@
"@storybook/types": "^8.6.12",
"preact-render-to-string": "^6.5.13",
"react-docgen-typescript": "^2.2.2",
"unplugin-stencil": "^0.2.5"
"unplugin-stencil": "^0.2.6"
},
"dependencies": {
"@rollup/rollup-darwin-arm64": {
@ -15462,9 +15462,9 @@
}
},
"unplugin-stencil": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/unplugin-stencil/-/unplugin-stencil-0.2.5.tgz",
"integrity": "sha512-4/wufyqIRkcYfWlWvfUBtPm2/z0EuhWfHbBUKSL0dcAGpgC65LhH05jfwVpfrlSuc44Tp1rFx3ciaIFsjpXDsg==",
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/unplugin-stencil/-/unplugin-stencil-0.2.6.tgz",
"integrity": "sha512-buLzEBcTLE9B+6/5N0OjFItEFifK19QBj80a4oPuX82K6+/kb3ooHmQiklcam9Y6L8/tyAfjj2ADQbhg0GaM2Q==",
"dev": true,
"requires": {
"mlly": "^1.7.4",

View File

@ -50,7 +50,7 @@
"@stencil/core": "^4.30.0",
"@stencil/react-output-target": "0.5.3",
"@stencil/sass": "^3.0.9",
"@stencil/storybook-plugin": "^0.0.11",
"@stencil/storybook-plugin": "^0.0.12",
"@stencil/vue-output-target": "0.10.7",
"@storybook/addon-essentials": "^8.6.12",
"@storybook/addon-interactions": "^8.6.12",

View File

@ -77,6 +77,46 @@ export const Default: Story = {
),
};
export const CustomToggle: Story = {
render: () => {
function toggleAccordion() {
const accordionGroup = document.querySelector('ion-accordion-group') as HTMLIonAccordionGroupElement
if (accordionGroup.value === 'second') {
accordionGroup.value = undefined;
} else {
accordionGroup.value = 'second';
}
}
return (
<div>
<ion-accordion-group>
<ion-accordion value="first">
<ion-item slot="header" color="light">
<ion-label>First Accordion</ion-label>
</ion-item>
<div class="ion-padding" slot="content">First Content</div>
</ion-accordion>
<ion-accordion value="second">
<ion-item slot="header" color="light">
<ion-label>Second Accordion</ion-label>
</ion-item>
<div class="ion-padding" slot="content">Second Content</div>
</ion-accordion>
<ion-accordion value="third">
<ion-item slot="header" color="light">
<ion-label>Third Accordion</ion-label>
</ion-item>
<div class="ion-padding" slot="content">Third Content</div>
</ion-accordion>
</ion-accordion-group>
<ion-button class="ion-margin-top" onClick={() => toggleAccordion()}>Toggle Second Accordion</ion-button>
</div>
)
}
}
export const Disabled: Story = {
args: {
disabled: true,

View File

@ -0,0 +1,368 @@
import { h } from '@stencil/core';
import type { Meta, StoryObj } from '@stencil/storybook-plugin';
import { ActionSheet } from './action-sheet';
const meta: Meta<ActionSheet> = {
title: 'Action Sheet',
component: ActionSheet,
parameters: {
layout: 'centered',
},
argTypes: {
header: {
control: 'text',
description: 'Title for the action sheet',
},
subHeader: {
control: 'text',
description: 'Subtitle for the action sheet',
},
buttons: {
control: 'object',
description: 'An array of buttons for the action sheet',
},
backdropDismiss: {
control: 'boolean',
description: 'If true, the action sheet will be dismissed when the backdrop is clicked',
},
translucent: {
control: 'boolean',
description: 'If true, the action sheet will be translucent in iOS mode',
},
animated: {
control: 'boolean',
description: 'If true, the action sheet will animate',
},
cssClass: {
control: 'text',
description: 'Additional classes to apply for custom CSS',
},
isOpen: {
control: 'boolean',
description: 'If true, the action sheet will open. If false, the action sheet will close',
},
},
args: {
backdropDismiss: true,
animated: true,
isOpen: false,
},
};
export default meta;
type Story = StoryObj<ActionSheet>;
/**
* Basic inline action sheet example as shown in the documentation
*/
export const InlineActionSheet: Story = {
args: {
header: 'Actions',
buttons: [
{
text: 'Delete',
role: 'destructive',
data: {
action: 'delete',
},
},
{
text: 'Share',
data: {
action: 'share',
},
},
{
text: 'Cancel',
role: 'cancel',
data: {
action: 'cancel',
},
},
],
},
render: (props) => (
<div>
<ion-action-sheet {...props} trigger="open-action-sheet"></ion-action-sheet>
<ion-button id="open-action-sheet">Show Action Sheet</ion-button>
</div>
)
};
/**
* Example of using isOpen property to control the action sheet state
*/
export const UsingIsOpen: Story = {
args: {
header: 'Actions',
buttons: [
{
text: 'Delete',
role: 'destructive',
data: {
action: 'delete',
},
},
{
text: 'Share',
data: {
action: 'share',
},
},
{
text: 'Cancel',
role: 'cancel',
data: {
action: 'cancel',
},
},
],
isOpen: true
},
render: () => {
return (
<div>
<ion-button onClick={() => {
const actionSheet = document.querySelector('ion-action-sheet')!
actionSheet.isOpen = true
}}>Click Me</ion-button>
<ion-action-sheet
overlayIndex={1000}
buttons={[
{
text: 'Delete',
role: 'destructive',
data: {
action: 'delete',
},
},
{
text: 'Share',
data: {
action: 'share',
},
},
{
text: 'Cancel',
role: 'cancel',
data: {
action: 'cancel',
},
},
]}
header="Actions"
onIonActionSheetDidDismiss={() => {
console.log('Action Sheet dismissed');
const actionSheet = document.querySelector('ion-action-sheet')!
actionSheet.isOpen = false;
}}
></ion-action-sheet>
</div>
)
}
};
/**
* Example with role buttons, showing destructive and cancel roles
*/
export const ButtonsWithRoles: Story = {
args: {
header: 'Actions',
buttons: [
{
text: 'Delete',
role: 'destructive',
handler: () => {
console.log('Delete clicked');
}
},
{
text: 'Share',
handler: () => {
console.log('Share clicked');
}
},
{
text: 'Play',
handler: () => {
console.log('Play clicked');
}
},
{
text: 'Favorite',
handler: () => {
console.log('Favorite clicked');
}
},
{
text: 'Cancel',
role: 'cancel',
handler: () => {
console.log('Cancel clicked');
}
}
]
},
render: (props) => (
<div>
<ion-action-sheet {...props} trigger="open-buttons-action-sheet"></ion-action-sheet>
<ion-button id="open-buttons-action-sheet">Show Action Sheet with Roles</ion-button>
<p>Check the console to see button handler messages.</p>
</div>
)
};
/**
* Example with icons and handler functions
*/
export const WithIcons: Story = {
args: {
header: 'Albums',
buttons: [
{
text: 'Delete',
role: 'destructive',
icon: 'trash',
handler: () => {
console.log('Delete clicked');
}
},
{
text: 'Share',
icon: 'share',
handler: () => {
console.log('Share clicked');
}
},
{
text: 'Play',
icon: 'play-circle',
handler: () => {
console.log('Play clicked');
}
},
{
text: 'Favorite',
icon: 'heart',
handler: () => {
console.log('Favorite clicked');
}
},
{
text: 'Cancel',
role: 'cancel',
icon: 'close',
handler: () => {
console.log('Cancel clicked');
}
}
]
},
render: (props) => (
<div>
<ion-action-sheet {...props} trigger="open-icons-action-sheet"></ion-action-sheet>
<ion-button id="open-icons-action-sheet">Show Action Sheet with Icons</ion-button>
</div>
)
};
/**
* Example showing how to collect data from action sheet dismissal
*/
export const CollectingDismissData: Story = {
args: {
header: 'Actions',
buttons: [
{
text: 'Delete',
role: 'destructive',
data: {
action: 'delete'
}
},
{
text: 'Share',
data: {
action: 'share'
}
},
{
text: 'Cancel',
role: 'cancel',
data: {
action: 'cancel'
}
}
]
},
render: (props) => (
<div>
<ion-action-sheet
{...props}
trigger="open-data-action-sheet"
onIonActionSheetDidDismiss={(e) => {
const { data, role } = e.detail;
console.log(`Dismissed with role: ${role}, data: ${JSON.stringify(data)}`);
}}
></ion-action-sheet>
<ion-button id="open-data-action-sheet">Show Action Sheet with Data</ion-button>
<p>Check the console to see dismiss data.</p>
</div>
)
};
/**
* Example with custom CSS class for styling
*/
export const WithCustomStyling: Story = {
args: {
overlayIndex: 1000,
trigger: 'open-action-sheet',
header: 'Example header',
subHeader: 'Example subheader',
buttons: [
{
text: 'Delete',
role: 'destructive',
data: {
action: 'delete',
},
},
{
text: 'Share',
data: {
action: 'share',
},
},
{
text: 'Cancel',
role: 'cancel',
data: {
action: 'cancel',
},
},
],
translucent: false
},
render: (props) => (
<div>
<style>
{`
ion-action-sheet.my-custom-class {
--background: #f58840;
--backdrop-opacity: 0.6;
--button-background-selected: #e97223;
--button-color: #000000;
--color: #fff;
/* role: "destructive" button iOS styling override */
--ion-color-danger: #000000;
}
`}
</style>
<ion-button id="open-action-sheet">Open</ion-button>
<ion-action-sheet class="my-custom-class" {...props}></ion-action-sheet>
</div>
)
};

View File

@ -8,19 +8,7 @@ const meta: Meta<Badge & { text: string }> = {
component: Badge,
parameters: {
layout: 'centered',
},
argTypes: {
color: {
control: 'select',
options: ['primary', 'secondary', 'tertiary', 'success', 'warning', 'danger', 'light', 'medium', 'dark'],
},
text: {
control: 'text',
},
},
args: {
text: 'NEW',
},
}
};
export default meta;
@ -28,9 +16,92 @@ export default meta;
type Story = StoryObj<Badge & { text: string }>;
export const Primary: Story = {
render: (props) => (
<div>
<ion-badge {...props}>{props.text}</ion-badge>
</div>
render: () => (
<ion-list style={{ width: '300px' }}>
<ion-item>
<ion-badge slot="start">11</ion-badge>
<ion-label>Badge in start slot</ion-label>
</ion-item>
<ion-item>
<ion-badge slot="end">22</ion-badge>
<ion-label>Badge in end slot</ion-label>
</ion-item>
</ion-list>
),
};
export const BadgesInTabButtons: Story = {
render: () => (
<ion-tab-bar color="light" style={{ width: '500px' }}>
<ion-tab-button tab="1">
<ion-icon name="heart"></ion-icon>
<ion-label>Favorites</ion-label>
<ion-badge color="danger"></ion-badge>
</ion-tab-button>
<ion-tab-button tab="2">
<ion-icon name="musical-note"></ion-icon>
<ion-label>Music</ion-label>
</ion-tab-button>
<ion-tab-button tab="3">
<ion-icon name="calendar"></ion-icon>
<ion-label>Calendar</ion-label>
<ion-badge color="danger">47</ion-badge>
</ion-tab-button>
</ion-tab-bar>
)
}
export const Theming: Story = {
render: () => (
<ion-list style={{ width: '300px' }}>
<ion-item>
<ion-label>Followers</ion-label>
<ion-badge color="primary">22k</ion-badge>
</ion-item>
<ion-item>
<ion-label>Likes</ion-label>
<ion-badge color="secondary">118k</ion-badge>
</ion-item>
<ion-item>
<ion-label>Stars</ion-label>
<ion-badge color="tertiary">34k</ion-badge>
</ion-item>
<ion-item>
<ion-label>Completed</ion-label>
<ion-badge color="success">80</ion-badge>
</ion-item>
<ion-item>
<ion-label>Warnings</ion-label>
<ion-badge color="warning">70</ion-badge>
</ion-item>
<ion-item>
<ion-label>Notifications</ion-label>
<ion-badge color="danger">1000</ion-badge>
</ion-item>
</ion-list>
)
}
export const CSSProperties: Story = {
render: () => (
<div style={{ width: '300px' }}>
<ion-list>
<ion-item>
<ion-label>Badges styled</ion-label>
<ion-badge>1</ion-badge>
</ion-item>
</ion-list>
<style>{`
ion-badge {
--background: purple;
--color: white;
--padding-end: 20px;
--padding-start: 20px;
}
`}</style>
</div>
)
}

View File

@ -0,0 +1,262 @@
import { h } from '@stencil/core';
import type { Meta, StoryObj } from '@stencil/storybook-plugin';
import type { BreadcrumbCollapsedClickEventDetail } from '../breadcrumb/breadcrumb-interface';
import { Breadcrumbs } from './breadcrumbs';
const meta: Meta<Breadcrumbs & { text: string }> = {
title: 'Breadcrumbs',
component: Breadcrumbs,
parameters: {
layout: 'centered',
}
};
const breadcrumbProps = {
last: false,
showCollapsedIndicator: false
} as const;
const lastBreadcrumbProps = {
...breadcrumbProps,
last: true
} as const;
export default meta;
type Story = StoryObj<Breadcrumbs & { text: string }>;
export const Primary: Story = {
render: () => (
<ion-breadcrumbs style={{ width: '500px' }}>
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...lastBreadcrumbProps}>Film</ion-breadcrumb>
</ion-breadcrumbs>
),
};
export const UsingIcons: Story = {
render: () => (
<div style={{ width: '500px', display: 'flex', flexDirection: 'column', gap: '16px' }}>
<ion-label style={{ marginInline: 'auto' }}>Icons at Start</ion-label>
<ion-breadcrumbs>
<ion-breadcrumb href="#home" {...breadcrumbProps}>
<ion-icon slot="start" name="home"></ion-icon>
Home
</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>
<ion-icon slot="start" name="flash"></ion-icon>
Electronics
</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>
<ion-icon slot="start" name="camera"></ion-icon>
Cameras
</ion-breadcrumb>
<ion-breadcrumb href="#film" {...lastBreadcrumbProps}>
<ion-icon slot="start" name="film"></ion-icon>
Film
</ion-breadcrumb>
</ion-breadcrumbs>
<ion-label style={{ marginInline: 'auto' }}>Icons at End</ion-label>
<ion-breadcrumbs>
<ion-breadcrumb href="#home" {...breadcrumbProps}>
Home
<ion-icon slot="end" name="home"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>
Electronics
<ion-icon slot="end" name="flash"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>
Cameras
<ion-icon slot="end" name="camera"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#film" {...lastBreadcrumbProps}>
Film
<ion-icon slot="end" name="film"></ion-icon>
</ion-breadcrumb>
</ion-breadcrumbs>
</div>
),
};
export const CustomSeparator: Story = {
render: () => (
<ion-breadcrumbs>
<ion-breadcrumb href="#home" {...breadcrumbProps}>
Home
<ion-icon slot="separator" name="arrow-forward-circle"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>
Electronics
<ion-icon slot="separator" name="arrow-forward-circle"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>
Cameras
<ion-icon slot="separator" name="arrow-forward-circle"></ion-icon>
</ion-breadcrumb>
<ion-breadcrumb href="#film" {...lastBreadcrumbProps}>
Film
<ion-icon slot="separator" name="arrow-forward-circle"></ion-icon>
</ion-breadcrumb>
</ion-breadcrumbs>
),
};
export const CustomCollapse: Story = {
render: () => (
<ion-breadcrumbs max-items="4">
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
),
};
export const ItemsBeforeAfterCollapse: Story = {
render: () => (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
<div style={{ marginInline: 'auto' }}>Before Collapse = 2</div>
<ion-breadcrumbs max-items="4" items-before-collapse="2">
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
<div style={{ marginInline: 'auto' }}>Before Collapse = 0</div>
<ion-breadcrumbs max-items="4" items-before-collapse="0">
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
<div style={{ marginInline: 'auto' }}>After Collapse = 2</div>
<ion-breadcrumbs max-items="4" items-after-collapse="2">
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
<div style={{ marginInline: 'auto' }}>Before Collapse = 2, After Collapse = 2</div>
<ion-breadcrumbs max-items="4" items-before-collapse="2" items-after-collapse="2">
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
</div>
),
};
export const CustomCollapsedIndicator: Story = {
render: () => {
function collapsedIndicator() {
const breadcrumbs = document.querySelector('ion-breadcrumbs') as HTMLIonBreadcrumbsElement;
breadcrumbs.maxItems = undefined;
}
return (
<ion-breadcrumbs max-items="4" onIonCollapsedClick={collapsedIndicator}>
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
)
},
};
export const CustomCollapsedIndicatorClick: Story = {
render: () => {
function collapsedIndicator(e: CustomEvent<BreadcrumbCollapsedClickEventDetail>) {
const popover = document.querySelector('ion-popover') as HTMLIonPopoverElement;
const popoverList = document.querySelector('ion-popover ion-list') as HTMLIonListElement;
if (!e.detail.collapsedBreadcrumbs) {
return;
}
let listHTML = ``;
e.detail.collapsedBreadcrumbs.forEach((breadcrumb, i) => {
if (!e.detail.collapsedBreadcrumbs) {
return;
}
listHTML += `
<ion-item
${i === e.detail.collapsedBreadcrumbs.length - 1 ? `lines="none"` : ''}
href="${breadcrumb.href}"
>
<ion-label>${breadcrumb.textContent}</ion-label>
</ion-item>
`;
});
popoverList.innerHTML = listHTML;
popover.event = e;
popover.isOpen = true;
}
function popoverDismiss() {
const popover = document.querySelector('ion-popover') as HTMLIonPopoverElement;
popover.isOpen = false;
}
return (
<div>
<ion-breadcrumbs max-items="4" onIonCollapsedClick={collapsedIndicator}>
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#photography" {...breadcrumbProps}>Photography</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...breadcrumbProps}>Film</ion-breadcrumb>
<ion-breadcrumb href="#35mm" {...lastBreadcrumbProps}>35 mm</ion-breadcrumb>
</ion-breadcrumbs>
<ion-popover overlayIndex={1000} onDidDismiss={popoverDismiss}>
<ion-content>
<ion-list></ion-list>
</ion-content>
</ion-popover>
</div>
)
},
};
export const CustomCSSProperties: Story = {
render: () => (
<div>
<ion-breadcrumbs>
<ion-breadcrumb href="#home" {...breadcrumbProps}>Home</ion-breadcrumb>
<ion-breadcrumb href="#electronics" {...breadcrumbProps}>Electronics</ion-breadcrumb>
<ion-breadcrumb href="#cameras" {...breadcrumbProps}>Cameras</ion-breadcrumb>
<ion-breadcrumb href="#film" {...lastBreadcrumbProps}>Film</ion-breadcrumb>
</ion-breadcrumbs>
<style>{`
ion-breadcrumb {
--color: rgb(81, 155, 198);
--color-active: rgb(150, 112, 220);
--color-hover: rgb(103, 61, 180);
}
`}</style>
</div>
),
};

View File

@ -8,45 +8,159 @@ const meta: Meta<Button> = {
component: Button,
parameters: {
layout: 'centered',
},
argTypes: {
fill: {
control: 'select',
options: ['solid', 'outline', 'clear']
},
expand: {
control: 'select',
options: ['full', 'block']
},
size: {
control: 'select',
options: ['small', 'default', 'large']
},
},
args: { fill: 'outline', expand: 'full', size: 'small' },
}
};
export default meta;
type Story = StoryObj<Button>;
export const Primary: Story = {
args: {
fill: 'outline',
expand: 'full',
size: 'small',
},
render: (props) => <ion-button {...props}>Primary Button</ion-button>,
export const BasicUsage: Story = {
render: () => (<div>
<ion-button>Default</ion-button>
<ion-button disabled={true}>Disabled</ion-button>
</div>),
};
/**
* Storybook story without custom render function
*/
export const Secondary: Story = {
args: {
fill: 'solid',
expand: 'block',
size: 'large',
},
render: (props) => <ion-button {...props}>Secondary Button</ion-button>,
export const Expand: Story = {
render: () => <div style={{ width: '500px' }}>
<ion-button expand="block">Block</ion-button>
<ion-button expand="full">Full</ion-button>
</div>,
};
export const Shape: Story = {
render: () => <div>
<ion-button>Default</ion-button>
<ion-button shape="round">Round</ion-button>
<ion-button>
<ion-icon slot="icon-only" name="heart"></ion-icon>
</ion-button>
<ion-button shape="round">
<ion-icon slot="icon-only" name="heart"></ion-icon>
</ion-button>
</div>,
};
export const Fill: Story = {
render: () => <div>
<ion-button>Default</ion-button>
<ion-button fill="clear">Clear</ion-button>
<ion-button fill="outline">Outline</ion-button>
<ion-button fill="solid">Solid</ion-button>
</div>,
};
export const Size: Story = {
render: () => <div>
<ion-button size="small">Small</ion-button>
<ion-button size="default">Default</ion-button>
<ion-button size="large">Large</ion-button>
</div>,
};
export const Icons: Story = {
render: () => <div style={{
display: 'grid',
gridTemplateColumns: 'repeat(3, auto)',
justifyItems: 'center',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
}}>
<ion-button size="small">
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
</ion-button>
<ion-button>
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
</ion-button>
<ion-button size="large">
<ion-icon slot="icon-only" ios="logo-apple" md="settings-sharp"></ion-icon>
</ion-button>
<ion-button size="small">
<ion-icon slot="start" name="star"></ion-icon>
Left Icon
</ion-button>
<ion-button>
<ion-icon slot="start" name="star"></ion-icon>
Left Icon
</ion-button>
<ion-button size="large">
<ion-icon slot="start" name="star"></ion-icon>
Left Icon
</ion-button>
<ion-button size="small">
Right Icon
<ion-icon slot="end" name="heart"></ion-icon>
</ion-button>
<ion-button>
Right Icon
<ion-icon slot="end" name="heart"></ion-icon>
</ion-button>
<ion-button size="large">
Right Icon
<ion-icon slot="end" name="heart"></ion-icon>
</ion-button>
</div>,
};
export const Theming: Story = {
render: () => <div style={{
flexWrap: 'wrap',
width: '350px',
margin: '0 auto',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
}}>
<ion-button>Default</ion-button>
<ion-button color="primary">Primary</ion-button>
<ion-button color="secondary">Secondary</ion-button>
<ion-button color="tertiary">Tertiary</ion-button>
<ion-button color="success">Success</ion-button>
<ion-button color="warning">Warning</ion-button>
<ion-button color="danger">Danger</ion-button>
<ion-button color="light">Light</ion-button>
<ion-button color="medium">Medium</ion-button>
<ion-button color="dark">Dark</ion-button>
</div>,
};
export const CustomCSSProperties: Story = {
render: () => <div>
<style>{`
ion-button {
--background: #93e9be;
--background-hover: #9ce0be;
--background-activated: #88f4be;
--background-focused: #88f4be;
--color: blue;
--border-radius: 0;
--border-color: #000;
--border-style: solid;
--border-width: 1px;
--box-shadow: 0 2px 6px 0 rgb(0, 0, 0, 0.25);
--ripple-color: deeppink;
--padding-top: 10px;
--padding-bottom: 10px;
}
`}</style>
<ion-button>Custom Button</ion-button>
</div>,
};

View File

@ -0,0 +1,82 @@
import { h } from '@stencil/core';
import type { Meta, StoryObj } from '@stencil/storybook-plugin';
import type { BreadcrumbCollapsedClickEventDetail } from '../breadcrumb/breadcrumb-interface';
import { RippleEffect } from './ripple-effect';
const meta: Meta<RippleEffect> = {
title: 'Ripple Effect',
component: RippleEffect,
parameters: {
layout: 'centered',
}
};
export default meta;
type Story = StoryObj<RippleEffect>;
export const BasicUsage: Story = {
render: () => (<div>
<div class="wrapper">
<b>Click on a shape to see the ripple</b>
<div class="ion-activatable ripple-parent rectangle">
<ion-ripple-effect></ion-ripple-effect>
</div>
<div class="ion-activatable ripple-parent rounded-rectangle">
<ion-ripple-effect></ion-ripple-effect>
</div>
<div class="ion-activatable ripple-parent circle">
<ion-ripple-effect></ion-ripple-effect>
</div>
</div>
<style>{`
.wrapper {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
text-align: center;
height: 300px;
width: 300px;
margin: 0 auto;
}
b {
width: 100%;
}
.ripple-parent {
position: relative;
overflow: hidden;
border: 1px solid #ddd;
}
.rectangle {
width: 300px;
height: 150px;
}
.rounded-rectangle {
width: 185px;
height: 65px;
border-radius: 8px;
}
.circle {
width: 90px;
height: 90px;
border-radius: 50%;
}
`}</style>
</div>),
};