diff --git a/core/package-lock.json b/core/package-lock.json index 9c4e9f82fa..4d0b1f0a43 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -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", diff --git a/core/package.json b/core/package.json index c6678605d0..55684b3509 100644 --- a/core/package.json +++ b/core/package.json @@ -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", diff --git a/core/src/components/accordion/accordion.stories.tsx b/core/src/components/accordion/accordion.stories.tsx index 3eb6ba56ad..1fb11b9706 100644 --- a/core/src/components/accordion/accordion.stories.tsx +++ b/core/src/components/accordion/accordion.stories.tsx @@ -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 ( +
+ + + + First Accordion + +
First Content
+
+ + + Second Accordion + +
Second Content
+
+ + + Third Accordion + +
Third Content
+
+
+ + toggleAccordion()}>Toggle Second Accordion +
+ ) + } +} + export const Disabled: Story = { args: { disabled: true, diff --git a/core/src/components/action-sheet/action-sheet.stories.tsx b/core/src/components/action-sheet/action-sheet.stories.tsx new file mode 100644 index 0000000000..e41d67deb5 --- /dev/null +++ b/core/src/components/action-sheet/action-sheet.stories.tsx @@ -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 = { + 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; + +/** + * 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) => ( +
+ + Show Action Sheet +
+ ) +}; + +/** + * 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 ( +
+ { + const actionSheet = document.querySelector('ion-action-sheet')! + actionSheet.isOpen = true + }}>Click Me + { + console.log('Action Sheet dismissed'); + const actionSheet = document.querySelector('ion-action-sheet')! + actionSheet.isOpen = false; + }} + > +
+ ) + } +}; + +/** + * 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) => ( +
+ + Show Action Sheet with Roles +

Check the console to see button handler messages.

+
+ ) +}; + +/** + * 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) => ( +
+ + Show Action Sheet with Icons +
+ ) +}; + +/** + * 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) => ( +
+ { + const { data, role } = e.detail; + console.log(`Dismissed with role: ${role}, data: ${JSON.stringify(data)}`); + }} + > + Show Action Sheet with Data +

Check the console to see dismiss data.

+
+ ) +}; + +/** + * 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) => ( +
+ + Open + +
+ ) +}; diff --git a/core/src/components/badge/badge.stories.tsx b/core/src/components/badge/badge.stories.tsx index 8982f03fef..4130e2d74f 100644 --- a/core/src/components/badge/badge.stories.tsx +++ b/core/src/components/badge/badge.stories.tsx @@ -8,19 +8,7 @@ const meta: Meta = { 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; export const Primary: Story = { - render: (props) => ( -
- {props.text} -
+ render: () => ( + + + 11 + Badge in start slot + + + 22 + Badge in end slot + + ), }; + +export const BadgesInTabButtons: Story = { + render: () => ( + + + + Favorites + + + + + + Music + + + + + Calendar + 47 + + + ) +} + +export const Theming: Story = { + render: () => ( + + + Followers + 22k + + + Likes + 118k + + + Stars + 34k + + + Completed + 80 + + + Warnings + 70 + + + Notifications + 1000 + + + ) +} + +export const CSSProperties: Story = { + render: () => ( +
+ + + Badges styled + 1 + + + + +
+ ) +} \ No newline at end of file diff --git a/core/src/components/breadcrumbs/breadcrumbs.stories.tsx b/core/src/components/breadcrumbs/breadcrumbs.stories.tsx new file mode 100644 index 0000000000..a960f8f1a7 --- /dev/null +++ b/core/src/components/breadcrumbs/breadcrumbs.stories.tsx @@ -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 = { + 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; + +export const Primary: Story = { + render: () => ( + + Home + Electronics + Cameras + Film + + ), +}; + +export const UsingIcons: Story = { + render: () => ( +
+ Icons at Start + + + + Home + + + + Electronics + + + + Cameras + + + + Film + + + + Icons at End + + + Home + + + + Electronics + + + + Cameras + + + + Film + + + +
+ ), +}; + +export const CustomSeparator: Story = { + render: () => ( + + + Home + + + + Electronics + + + + Cameras + + + + Film + + + + ), +}; + +export const CustomCollapse: Story = { + render: () => ( + + Home + Electronics + Photography + Cameras + Film + 35 mm + + ), +}; + +export const ItemsBeforeAfterCollapse: Story = { + render: () => ( +
+
Before Collapse = 2
+ + Home + Electronics + Photography + Cameras + Film + 35 mm + + +
Before Collapse = 0
+ + Home + Electronics + Photography + Cameras + Film + 35 mm + + +
After Collapse = 2
+ + Home + Electronics + Photography + Cameras + Film + 35 mm + + +
Before Collapse = 2, After Collapse = 2
+ + Home + Electronics + Photography + Cameras + Film + 35 mm + +
+ ), +}; + +export const CustomCollapsedIndicator: Story = { + render: () => { + function collapsedIndicator() { + const breadcrumbs = document.querySelector('ion-breadcrumbs') as HTMLIonBreadcrumbsElement; + breadcrumbs.maxItems = undefined; + } + return ( + + Home + Electronics + Photography + Cameras + Film + 35 mm + + ) + }, +}; + +export const CustomCollapsedIndicatorClick: Story = { + render: () => { + function collapsedIndicator(e: CustomEvent) { + 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 += ` + + ${breadcrumb.textContent} + + `; + }); + + popoverList.innerHTML = listHTML; + popover.event = e; + popover.isOpen = true; + } + + function popoverDismiss() { + const popover = document.querySelector('ion-popover') as HTMLIonPopoverElement; + popover.isOpen = false; + } + + return ( +
+ + Home + Electronics + Photography + Cameras + Film + 35 mm + + + + + + +
+ ) + }, +}; + +export const CustomCSSProperties: Story = { + render: () => ( +
+ + Home + Electronics + Cameras + Film + + + +
+ ), +}; \ No newline at end of file diff --git a/core/src/components/button/button.stories.tsx b/core/src/components/button/button.stories.tsx index 0dbd42fbbe..4b95389c0a 100644 --- a/core/src/components/button/button.stories.tsx +++ b/core/src/components/button/button.stories.tsx @@ -8,45 +8,159 @@ const meta: Meta