feat(segment): add segment view and content components

This commit is contained in:
Brandy Carney
2024-09-17 13:51:51 -04:00
parent fa74077820
commit 0324a78c2b
12 changed files with 326 additions and 0 deletions

View File

@ -0,0 +1,20 @@
// Segment View
// --------------------------------------------------
:host {
display: flex;
overflow-x: scroll;
scroll-snap-type: x mandatory;
/* Hide scrollbar in Firefox */
scrollbar-width: none;
/* Hide scrollbar in IE and Edge */
-ms-overflow-style: none;
}
/* Hide scrollbar in webkit */
:host::-webkit-scrollbar {
display: none;
}

View File

@ -0,0 +1,90 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Listen, h } from '@stencil/core';
import { addEventListener, removeEventListener } from '@utils/helpers';
@Component({
tag: 'ion-segment-view',
styleUrl: 'segment-view.scss',
shadow: true,
})
export class SegmentView implements ComponentInterface {
private segmentEl: HTMLIonSegmentElement | null = null;
@Element() el!: HTMLElement;
@Listen('scroll')
segmentViewScroll(ev: any) {
const { segmentEl } = this;
const atSnappingPoint = ev.target.scrollLeft % ev.target.offsetWidth === 0;
if (atSnappingPoint) {
const index = Math.round(ev.target.scrollLeft / ev.target.offsetWidth);
const segmentButton = this.getSegmentButtonAtIndex(index);
if (segmentEl) {
segmentEl.value = segmentButton.value;
}
}
}
connectedCallback() {
const segmentEl = (this.segmentEl = document.querySelector(`ion-segment[view=${this.el.id}]`));
if (segmentEl) {
addEventListener(segmentEl, 'ionChange', this.updateSection);
}
}
disconnectedCallback() {
const segmentEl = this.segmentEl;
if (segmentEl) {
removeEventListener(segmentEl, 'ionChange', this.updateSection);
this.segmentEl = null;
}
}
private updateSection = () => {
const { segmentEl } = this;
if (segmentEl) {
const value = segmentEl.value;
const index = this.getSegmentButtonIndexWithValue(value);
this.setSection(index);
}
};
private setSection = (index: number) => {
const sectionWidth = this.el.offsetWidth;
this.el.scrollTo({
top: 0,
left: index * sectionWidth,
behavior: 'smooth',
});
};
private getSegmentButtons(): HTMLIonSegmentButtonElement[] {
const { segmentEl } = this;
if (!segmentEl) {
return [];
}
return Array.from(segmentEl.querySelectorAll('ion-segment-button'));
}
private getSegmentButtonAtIndex(index: number) {
return this.getSegmentButtons()[index];
}
private getSegmentButtonIndexWithValue(value: any) {
return this.getSegmentButtons().findIndex((b) => b.value === value);
}
render() {
return (
<Host>
<slot></slot>
</Host>
);
}
}

View File

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8" />
<title>Segment View - Basic</title>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
/>
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
<script src="../../../../../scripts/testing/scripts.js"></script>
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
</head>
<body onload="listenForEvent()">
<ion-app>
<ion-header>
<ion-toolbar>
<ion-title>Segment View - Basic</ion-title>
</ion-toolbar>
<ion-toolbar>
<ion-segment view="myView" value="Paid">
<ion-segment-button value="Paid">
<ion-label>Paid</ion-label>
</ion-segment-button>
<ion-segment-button value="Free">
<ion-label>Free</ion-label>
</ion-segment-button>
<ion-segment-button value="Top">
<ion-label>Top</ion-label>
</ion-segment-button>
</ion-segment>
</ion-toolbar>
</ion-header>
<ion-content>
<ion-segment-view id="myView">
<ion-segment-content>
Paid
</ion-segment-content>
<ion-segment-content>
Free
</ion-segment-content>
<ion-segment-content>
Top
</ion-segment-content>
</ion-segment-view>
</ion-content>
</ion-app>
</body>
</html>