React Stepper (ステッパー) の概要
React ステッパー コンポーネントは、ウィザードのようなワークフローを提供し、番号付きのステップの進行状況を示すために使用されます。これにより、開発者は長いコンテンツを一連の論理的なステップに分割できるため、エンド ユーザーはプロセス全体をより簡単にナビゲートできます。React ステッパーは、垂直または水平な線で表示されます。React ステッパーには、ステップの検証、スタイル設定、向き、キーボード ナビゲーションなどの複数の機能があります。
React ステッパーの例
次の Ignite UI for React ステッパーの例は、動作中のコンポーネントを示しています。これは、エンドユーザーが注文の詳細を構成するために通過しなければならないプロセスを、いくつかの連続したステップに従って視覚化します。
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import {
IgrStepper,
IgrStep,
IgrRadio,
IgrRadioGroup,
IgrButton,
IgrSwitch,
IgrCheckboxChangeEventArgs,
IgrComponentValueChangedEventArgs,
IgrInput,
} from "@infragistics/igniteui-react";
import "igniteui-webcomponents/themes/light/bootstrap.css";
export default class LinearStepper extends React.Component<any, any> {
private stepperRef = React.createRef<IgrStepper>();
private InfoForm = React.createRef<any>();
private AddressForm = React.createRef<any>();
private activeStepIndex = 0;
constructor(props: any) {
super(props);
this.state = {
linear: false,
firstStepInvalid: true,
secondStepInvalid: true,
};
this.onSwitchChange = this.onSwitchChange.bind(this);
}
componentDidMount() {
this.InfoForm.current.addEventListener("igcInput", this.onInput.bind(this));
this.AddressForm.current.addEventListener(
"igcInput",
this.onInput.bind(this)
);
}
public render(): JSX.Element {
return (
<div className="container sample">
<IgrSwitch onChange={this.onSwitchChange}>
<span>Linear</span>
</IgrSwitch>
<IgrStepper ref={this.stepperRef} linear={this.state.linear}>
<IgrStep
invalid={this.state.linear && this.state.firstStepInvalid}
>
<span slot="title">
Personal Info
</span>
<form ref={this.InfoForm}>
<IgrInput
required
label="Full Name"
type="text"
name="fullName"
></IgrInput>
<IgrInput
required
label="Email"
type="email"
name="email"
></IgrInput>
<IgrButton
disabled={this.state.linear && this.state.firstStepInvalid}
onClick={() => {
this.stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep
invalid={this.state.linear && this.state.secondStepInvalid}
>
<span slot="title">
Delivery address
</span>
<form ref={this.AddressForm}>
<IgrInput
required
label="City"
type="text"
name="city"
></IgrInput>
<IgrInput
required
label="Street"
type="text"
name="street"
></IgrInput>
<IgrButton
onClick={() => {
this.stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
disabled={this.state.linear && this.state.secondStepInvalid}
onClick={() => {
this.stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep optional>
<span slot="title">
Billing address
</span>
<span slot="subtitle">
(optional)
</span>
<form>
<IgrInput
required
label="City"
type="text"
name="bill-city"
></IgrInput>
<IgrInput
required
label="Street"
type="text"
name="bill-street"
></IgrInput>
<IgrButton
onClick={() => {
this.stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
this.stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep>
<span slot="title">
Payment
</span>
<IgrRadioGroup>
<IgrRadio name="payment" checked>
<span>PayPal (n@mail.com; 18/02/2021)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>Visa (**** **** **** 1234; 12/23)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>
MasterCard (**** **** **** 5678; 12/24)
</span>
</IgrRadio>
</IgrRadioGroup>
<IgrButton
onClick={() => {
this.stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
this.stepperRef.current.next();
}}
>
<span>SUBMIT</span>
</IgrButton>
</IgrStep>
<IgrStep>
<span slot="title">
Delivery status
</span>
<p>
Your order is on its way. Expect delivery on 25th September 2021.
Delivery address: San Jose, CA 94243.
</p>
<IgrButton
onClick={() => {
this.stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
this.stepperRef.current.reset();
}}
>
<span>RESET</span>
</IgrButton>
</IgrStep>
</IgrStepper>
</div>
);
}
public onSwitchChange(e: IgrCheckboxChangeEventArgs) {
this.setState({ linear: e.detail.checked });
if (e.detail.checked) {
this.checkActiveStepValidity();
}
}
public onInput(s: IgrInput, e: IgrComponentValueChangedEventArgs) {
if (!this.state.linear) return;
this.checkActiveStepValidity();
}
private checkActiveStepValidity() {
const activeStep = this.activeStep;
if (activeStep && this.activeStepIndex === 0) {
const isInvalidForm = this.checkFormValidity(this.InfoForm);
this.setState({ firstStepInvalid: isInvalidForm });
}
if (activeStep && this.activeStepIndex === 1) {
const isInvalidForm = this.checkFormValidity(this.AddressForm);
this.setState({ secondStepInvalid: isInvalidForm });
}
}
private checkFormValidity(form: any) {
let isInvalidForm = false;
for (const element of form.current.children) {
if (
element.tagName.toLowerCase() === "igc-input" &&
element.value === ""
) {
const oldInvalid = element.invalid;
const isElementInvalid = !element.checkValidity();
element.invalid = oldInvalid;
if (isElementInvalid) {
isInvalidForm = true;
break;
}
}
}
return isInvalidForm;
}
private get activeStep(): IgrStep | undefined {
return this.stepperRef.current.steps.find(
(step: IgrStep, index: number) => {
this.activeStepIndex = index;
return step.active;
}
);
}
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<LinearStepper />);
tsx
.radio-groups {
display: flex;
align-items: center;
margin-bottom: 1rem;
}
.radio-group {
margin-right: 2rem;
}
.radio-group-container {
padding: 0.5rem;
border: 1px solid gainsboro;
}
igc-switch {
margin: 0.5rem;
}
igc-button {
margin: 1rem 0.5rem 0 0;
}
css
このサンプルが気に入りましたか? 完全な Ignite UI for Reactツールキットにアクセスして、すばやく独自のアプリの作成を開始します。無料でダウンロードできます。
React ステッパーを使用した作業の開始
まず、次のコマンドを実行して、対応する Ignite UI for React npm パッケージをインストールする必要があります:
npm install igniteui-react
cmd
次に、以下のように、IgrStepper
と必要な CSS をインポートする必要があります:
import { IgrStepper, IgrStep } from 'igniteui-react';
import 'igniteui-webcomponents/themes/light/bootstrap.css';
tsx
これで、React IgrStepper
とそのパネルの基本構成から始めることができます。
React ステッパーの使用方法
IgrStep
は、IgrStepper
に属するすべてのステップの表現です。ステップは invalid
、active
、optional
、disabled
、complete
プロパティを提供し、ビジネス要件に応じてステップの状態を構成できます。
React ステッパーの宣言
ステップは、以下の方法のいずれかを使用して宣言できます。
<IgrStepper>
{this.StepsData.map(item =>
<IgrStep key={item.title} disabled={item.disabled}>
<p slot="title">{item.title}</p>
</IgrStep>
}
</IgrStepper>
tsx
<IgrStepper>
<IgrStep>
<p slot="title">Step 1</p>
</IgrStep>
<IgrStep>
<p slot="title">Step 2</p>
</IgrStep>
</IgrStepper>
tsx
各ステップで、Indicator
、Title
、および Subtitle
スロットを使用してインジケーター、タイトル、およびサブタイトルを構成できます。
Default の IgrStep スロットは、ステップのコンテンツを描画します。
<IgrStepper>
<IgrStep>
<IgrIcon slot="indicator" name="home" collection="material" />
<p slot="title">Home</p>
<p slot="subtitle">Home Sub Title</p>
<div>
Step Content
...
</div>
</IgrStep>
</IgrStepper>
tsx
React ステッパーの向きの変更
公開された orientation
プロパティでステッパーの向きをカスタマイズできます。horizontal (デフォルト値) また vertical に設定できます。
水平方向の React ステッパー
IgrStepper
の orientation プロパティのデフォルト値は horizontal です。
React ステッパーが水平方向の場合、ステップのコンテンツをステップのヘッダーの上または下に表示するかどうかを決定できます。これは、IgrStepper
の contentTop
ブール型プロパティを設定することで実現できます。デフォルト値は false です。有効な場合、ステップのコンテンツはステップのヘッダーの上に表示されます。
垂直方向の React ステッパー
水平レイアウトから垂直レイアウトに簡単に切り替えることができます。デフォルトの方向を変更するには、orientation
プロパティを vertical に設定します。
以下のサンプルは、実行時にステッパーの向きとタイトルの位置を変更する方法を示しています。
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import {
IgrButton,
IgrRadio,
IgrRadioChangeEventArgs,
IgrRadioGroup,
IgrStep,
IgrStepper,
StepperOrientation,
StepperTitlePosition,
} from "@infragistics/igniteui-react";
import 'igniteui-webcomponents/themes/light/bootstrap.css';
export interface StepperOrientationProps {
orientation: StepperOrientation;
titlePosition: StepperTitlePosition;
}
export default class StepperOrientationSample extends React.Component<any, StepperOrientationProps> {
private stepperRef = React.createRef<IgrStepper>();
constructor(props: StepperOrientationProps) {
super(props);
this.state = { orientation: "horizontal", titlePosition: "auto" };
this.handleTitlePositionChange = this.handleTitlePositionChange.bind(this);
this.handleOrientationChange = this.handleOrientationChange.bind(this);
}
public render(): JSX.Element {
return (
<div className="container sample">
<div className="radio-groups">
<div className="radio-group">
<label>Title position</label>
<div className="radio-group-container">
<IgrRadioGroup alignment="horizontal" onChange={this.handleTitlePositionChange} value={this.state.titlePosition}>
<IgrRadio name="title" value="top"><span>Top</span></IgrRadio>
<IgrRadio name="title" value="bottom"><span>Bottom</span></IgrRadio>
<IgrRadio name="title" value="start"><span>Start</span></IgrRadio>
<IgrRadio name="title" value="end"><span>End</span></IgrRadio>
<IgrRadio name="title" value="auto"><span>Auto (default)</span></IgrRadio>
</IgrRadioGroup>
</div>
</div>
<div className="radio-group">
<label>Orientation</label>
<div className="radio-group-container">
<IgrRadioGroup alignment="horizontal" onChange={this.handleOrientationChange} value={this.state.orientation}>
<IgrRadio name="orientation" value="horizontal"><span>Horizontal</span></IgrRadio>
<IgrRadio name="orientation" value="vertical"><span>Vertical</span></IgrRadio>
</IgrRadioGroup>
</div>
</div>
</div>
<IgrStepper ref={this.stepperRef} orientation={this.state.orientation} titlePosition={this.state.titlePosition}>
<IgrStep>
<span slot="title">Order</span>
<IgrButton onClick={() => { this.stepperRef.current.next(); }}><span>NEXT</span></IgrButton>
</IgrStep>
<IgrStep>
<span slot="title">Payment</span>
<IgrButton onClick={() => { this.stepperRef.current.prev(); }}><span>PREVIOUS</span></IgrButton>
<IgrButton onClick={() => { this.stepperRef.current.next(); }}><span>NEXT</span></IgrButton>
</IgrStep>
<IgrStep>
<span slot="title">Confirmation</span>
<IgrButton onClick={() => { this.stepperRef.current.prev(); }}><span>PREVIOUS</span></IgrButton>
<IgrButton onClick={() => { this.stepperRef.current.reset(); }}><span>RESET</span></IgrButton>
</IgrStep>
</IgrStepper>
</div>
);
}
public handleTitlePositionChange(e: IgrRadioChangeEventArgs) {
const newTitlePosition = e.detail.value as StepperTitlePosition;
this.setState({ titlePosition: newTitlePosition });
}
public handleOrientationChange(e: IgrRadioChangeEventArgs) {
const newOrientation = e.detail.value as StepperOrientation;
this.setState({ orientation: newOrientation, titlePosition: "auto" });
}
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<StepperOrientationSample />);
tsx
.radio-groups {
display: flex;
align-items: center;
margin-bottom: 1rem;
}
.radio-group {
margin-right: 2rem;
}
.radio-group-container {
padding: 0.5rem;
border: 1px solid gainsboro;
}
css
ステップ状態
React IgrStepper
は 5 つのステップ状態をサポートし、それぞれがデフォルトで異なるスタイルを適用します。
- active - ステップが現在表示されているかどうかを決定します。設計上、ユーザーが明示的にステップの active 属性を true に設定しない場合、最初の有効なステップがアクティブになります。
- disabled - ステップが操作可能かどうかを決定します。デフォルトでは、ステップの disabled 属性は false に設定されています。
- invalid - ステップが有効かどうかを決定します。その値に基づいて、ユーザーがリニア ステッパー モードで前に進むことができるかどうかが決定されます。デフォルト値は false です。
- optional - デフォルトで、ステップの optional 属性は false に設定されます。リニア ステッパーのステップの有効性が必要ない場合、オプションの属性を有効にして、ステップの有効性とは関係なく前進できます。
- complete - デフォルトでは、ステップの complete 属性は false を返します。ユーザーは、complete 属性を必要に応じて設定することにより、このデフォルトの complete 動作をオーバーライドできます。ステップが complete (完了済み) としてマークされると、ステップ ヘッダーのスタイルがデフォルトで変更されるだけでなく、完了したステップと次のステップの間の進捗線のスタイルも変更されます。
リニア React ステッパー
React IgrStepper
は、linear
プロパティを使用してステップ フローを設定できます。デフォルトで、linear は false に設定され、ユーザーは IgrStepper
で無効にされていないステップを選択できます。
<IgrStepper linear={true}>
<IgrStep>
<p slot="title">Step 1</p>
</IgrStep>
<IgrStep>
<p slot="title">Step 2</p>
</IgrStep>
</IgrStepper>
tsx
linear プロパティが true に設定されている場合、ステッパーは次のステップに進む前に現在のオプションではないステップを有効にする必要があります。
現在のオプションではないステップが有効でない場合、現在のステップを検証するまで次のステップに進むことができません。
ステップ操作
IgrStepper
は、ステップ操作に以下の API メソッドを提供します。
- navigateTo – 指定したインデックスでステップをアクティブ化します。
- next - 次の無効化されていないステップをアクティブ化します。
- prev – 前の無効化されていないステップをアクティブ化します。
- reset – ステッパーを初期状態にリセットします。
reset メソッドは、ステッパーを初期状態にリセットします。つまり、最初のステップをアクティブにします。reset メソッドはステップの内容をクリアしません。これは手動で行う必要があります。
ステップのカスタマイズ
Ignite UI for React ステッパーでは、タイトル、インジケーターなどのさまざまなオプションを構成できます。
これは、IgrStepper
の stepType
プロパティで実現できます。プロパティは以下の値を含みます:
- Full (フル、デフォルト値)
- Indicator (インジケーター)
- Title (タイトル)
Full (フル)
タイトルとサブタイトルが定義されている場合、この設定ではインジケーターとタイトルの両方が描画されます。
また、ユーザーはステップのタイトルの位置を定義できるため、ステップ インジケーターの前、後、上、または下に配置できます。
ユーザーは titlePosition
プロパティを使用してタイトル位置を構成できます。プロパティは以下の値を含みます:
- undefined (デフォルト値)
- end
- start
- bottom
- top
React IgrStepper
が水平方向で、タイトルの位置が定義されていない場合、タイトルはインジケーターの下に表示されます。
向きが垂直に設定され、タイトルの位置が定義されていない場合、タイトルはインジケーターの後に表示されます。
titlePosition プロパティは、ステッパーの stepType プロパティが full に設定されている場合にのみ適用できます。
Indicator (インジケーター)
ステップのインジケーターのみを表示する場合は、stepType オプションを indicator に設定します。
ステップ インジケーターはすべてのコンテンツをサポートしますが、サイズが常に 24 ピクセルになるという制限があります。この点に注意して、ステップ インジケーターとして IgrIcon
または IgrAvatar
を使用することをお勧めします。
Title (タイトル)
ステップのタイトルのみを表示する場合は、stepType オプションを title に設定します。
このように、サブタイトルが定義されている場合、それらもステップ タイトルの下に描画されます。
このコンテナーは、サイズ制限なしで要件に応じて再テンプレート化できます。たとえば、サイズが 24 ピクセルより大きいインジケーターを中に追加できます。
以下のサンプルは公開されたすべてのステップ タイプと変更方法を示しています。
import React, { useState } from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import { IgrStepper, IgrStep, IgrRadio, IgrRadioGroup, StepperStepType, IgrRadioChangeEventArgs } from "@infragistics/igniteui-react";
import 'igniteui-webcomponents/themes/light/bootstrap.css';
export default function StepperStepTypes() {
const [stepType, setStepType] = useState<StepperStepType>("full");
const onStepTypeChange = (e: IgrRadioChangeEventArgs) => {
const newStepType = e.detail.value as StepperStepType;
setStepType(newStepType);
}
return (
<div className="container sample">
<label>Step type</label>
<div className="radio-group-container">
<IgrRadioGroup alignment="horizontal">
<IgrRadio name="type" value="indicator" onChange={onStepTypeChange}><span>Indicator</span></IgrRadio>
<IgrRadio name="type" value="title" onChange={onStepTypeChange}><span>Title</span></IgrRadio>
<IgrRadio name="type" value="full" onChange={onStepTypeChange} checked={stepType === 'full'}><span>Full</span></IgrRadio>
</IgrRadioGroup>
</div>
<IgrStepper stepType={stepType}>
<IgrStep>
<span slot="title">Pricing Plan</span>
</IgrStep>
<IgrStep>
<span slot="title">Car Details</span>
</IgrStep>
<IgrStep>
<span slot="title">Payment</span>
</IgrStep>
</IgrStepper>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<StepperStepTypes />);
tsx
.radio-group-container {
width: fit-content;
padding: 0.5rem;
border: 1px solid gainsboro;
margin-bottom: 1rem;
}
css
Stepper のアニメーション
React の IgrStepper
のアニメーションにより、エンドユーザーは、定義されたステップを操作しているときに美しいユーザー操作体験を得ることができます。使用可能なアニメーション オプションは、ステッパーの向きによって異なります。
ステッパーが水平方向の場合、デフォルトでは slide
アニメーションを使用するように設定されています。その他に fade
アニメーションもサポートされます。アニメーションは、horizontalAnimation
入力を介して構成されます。
垂直方向のレイアウトでは、アニメーション タイプは verticalAnimation
プロパティを使用して定義できます。デフォルトでは、その値は grow
に設定されており、ユーザーはそれを fade
に設定することもできます。
両方のアニメーション タイプ入力に none
を設定すると、ステッパー アニメーションが無効になります。
IgrStepper
コンポーネントを使用すると、ステップ間の遷移にかかる時間を設定することもできます。これは、数値を受け取る animationDuration
プロパティで設定でき、いずれのレイアウト方向でも共通の設定です。デフォルト値は 320ms に設定されています。
import React, { useRef, useState } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import {
IgrStepper,
IgrStep,
IgrRadio,
IgrRadioGroup,
IgrButton,
IgrInput,
IgrSelect,
IgrSelectItem,
IgrSelectItemComponentEventArgs,
IgrComponentValueChangedEventArgs,
StepperOrientation,
HorizontalTransitionAnimation,
StepperVerticalAnimation,
} from "@infragistics/igniteui-react";
import "igniteui-webcomponents/themes/light/bootstrap.css";
export default function StepperAnimations() {
const stepperRef = useRef<IgrStepper>(null);
const [orientation, setOrientation] = useState<StepperOrientation>("horizontal");
const [horizontalAnimation, setHorizontalAnimation] = useState<HorizontalTransitionAnimation>("slide");
const [verticalAnimation, setVerticalAnimation] = useState<StepperVerticalAnimation>("grow");
const [animationDuration, setAnimationDuration] = useState("320");
const orientationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as StepperOrientation;
setOrientation(selectedValue);
}
const horizontalAnimationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as HorizontalTransitionAnimation;
setHorizontalAnimation(selectedValue);
}
const verticalAnimationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as StepperVerticalAnimation;
setVerticalAnimation(selectedValue);
}
const animationDurationChange = (e: IgrComponentValueChangedEventArgs) => {
const animationDuration = e.detail;
setAnimationDuration(animationDuration);
}
return (
<div className="container sample">
<article className="settings">
<IgrSelect label="Orienation" onChange={orientationChange}>
<IgrSelectItem value="horizontal" selected={orientation === 'horizontal'}>
<span>Horizontal</span>
</IgrSelectItem>
<IgrSelectItem value="vertical">
<span>Vertical</span>
</IgrSelectItem>
</IgrSelect>
<IgrSelect
label="Vertical Animation"
onChange={verticalAnimationChange}
>
<IgrSelectItem value="grow" selected={verticalAnimation === 'grow'}>
<span>Grow</span>
</IgrSelectItem>
<IgrSelectItem value="fade">
<span>Fade</span>
</IgrSelectItem>
<IgrSelectItem value="none">
<span>None</span>
</IgrSelectItem>
</IgrSelect>
<IgrSelect
label="Horizontal Animation"
onChange={horizontalAnimationChange}
>
<IgrSelectItem value="slide" selected={horizontalAnimation === 'slide'}>
<span>Slide</span>
</IgrSelectItem>
<IgrSelectItem value="fade">
<span>Fade</span>
</IgrSelectItem>
<IgrSelectItem value="none">
<span>None</span>
</IgrSelectItem>
</IgrSelect>
<IgrInput
type="number"
value={animationDuration}
label="Duration"
onChange={animationDurationChange}
>
<span slot="suffix">ms</span>
</IgrInput>
</article>
<IgrStepper
ref={stepperRef}
orientation={orientation}
horizontalAnimation={horizontalAnimation}
verticalAnimation={verticalAnimation}
animationDuration={+animationDuration}
>
<IgrStep>
<span slot="title">Personal Info</span>
<form>
<IgrInput
label="Full Name"
type="text"
name="fullName"
></IgrInput>
<IgrInput label="Email" type="email" name="email"></IgrInput>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep>
<span slot="title">Delivery address</span>
<form>
<IgrInput label="City" type="text" name="city"></IgrInput>
<IgrInput label="Street" type="text" name="street"></IgrInput>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep>
<span slot="title">Payment</span>
<IgrRadioGroup>
<IgrRadio name="payment" checked>
<span>PayPal (n@mail.com; 18/02/2021)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>Visa (**** **** **** 1234; 12/23)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>MasterCard (**** **** **** 5678; 12/24)</span>
</IgrRadio>
</IgrRadioGroup>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>SUBMIT</span>
</IgrButton>
</IgrStep>
<IgrStep>
<span slot="title">Delivery status</span>
<p>
Your order is on its way. Expect delivery on 25th September 2021.
Delivery address: San Jose, CA 94243.
</p>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.reset();
}}
>
<span>RESET</span>
</IgrButton>
</IgrStep>
</IgrStepper>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<StepperAnimations />);
tsx
.settings {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.125rem;
background: hsl(var(--ig-gray-100));
padding: 1.125rem;
border: 1px solid hsl(var(--ig-gray-300));
border-radius: .25rem;
margin-bottom: 2rem;
}
igc-button {
margin: 1rem 0.5rem 0 0;
}
css
キーボード ナビゲーション
Ignite UI for React ステッパーは、さまざまなキーボード操作をエンドユーザーに提供します。この機能はデフォルトで有効になっており、エンドユーザーは簡単にステップを移動できます。
React IgrStepper
ナビゲーションは W3 アクセシビリティ標準に準拠しており、便利に使用できます。
キーの組み合わせ
- Tab - 次の移動可能な要素にフォーカスを移動します。
- Shift + Tab - 前移動可能な要素にフォーカスを移動します。
- ↓ - ステッパーが垂直方向の場合、次のアクセス可能なステップのヘッダーにフォーカスを移動します。
- ↑ - ステッパーが垂直方向の場合、前のアクセス可能なステップのヘッダーにフォーカスを移動します。
- ← - 両方の方向で前のアクセス可能なステップのヘッダーにフォーカスを移動します。
- → - 両方の方向で次にアクセス可能なステップのヘッダーにフォーカスを移動します。
- Home - ステッパーの最初の有効なステップのヘッダーにフォーカスを移動します。
- End - ステッパーの最後の有効なステップのヘッダーにフォーカスを移動します。
- Enter / Space - 現在フォーカスされているステップをアクティブ化します。
スタイル設定
以下にリストされている公開された CSS パーツのいくつかを使用して、IgrStep
の外観を変更できます:
パーツ名 |
説明 |
header-container |
ステップのヘッダーとそのセパレーターのラッパー。 |
disabled |
使用不可な状態を示します。ヘッダー コンテナーに適用されます。 |
complete-start |
現在のステップの完了状態を示します。ヘッダー コンテナーに適用されます。 |
complete-end |
前のステップの完了状態を示します。ヘッダー コンテナーに適用されます。 |
optional |
オプションの状態を示します。ヘッダー コンテナーに適用されます。 |
invalid |
オプションの状態を示します。ヘッダー コンテナーに適用されます。 |
top |
タイトルがインジケーターの上にあることを示します。ヘッダー コンテナーに適用されます。 |
bottom |
タイトルがインジケーターの下にあることを示します。ヘッダー コンテナーに適用されます。 |
start |
タイトルがインジケーターの前にあることを示します。ヘッダー コンテナーに適用されます。 |
end |
タイトルがインジケーターの後にあることを示します。ヘッダー コンテナーに適用されます。 |
header |
ステップのインジケーターとテキストのラッパー。 |
indicator |
Tステップのインジケーター。 |
text |
ステップのタイトルとサブタイトルのラッパー。 |
empty |
ステップにタイトルとサブタイトルが提供されていないことを示します。テキストに適用されます。 |
title |
ステップのタイトル。 |
subtitle |
ステップのサブタイトル。 |
body |
ステップのコンテンツのラッパー。 |
content |
ステップのコンテンツ。 |
これらの CSS パーツを使用して、次のように IgrStepper
コンポーネントの外観をカスタマイズできます:
igc-step::part(title) {
color: var(--ig-primary-500);
}
igc-step[active]::part(indicator) {
background-color: var(--ig-primary-500);
}
igc-step::part(indicator) {
background-color: var(--ig-surface-500);
}
css
import React, { useEffect, useRef, useState } from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
import {
IgrStepper,
IgrStep,
IgrRadio,
IgrRadioGroup,
IgrButton,
IgrInput,
IgrSelect,
IgrSelectItem,
IgrSelectItemComponentEventArgs,
IgrComponentValueChangedEventArgs,
StepperOrientation,
HorizontalTransitionAnimation,
StepperVerticalAnimation,
IgrIcon,
registerIconFromText,
} from "@infragistics/igniteui-react";
import "igniteui-webcomponents/themes/light/bootstrap.css";
const personalInfoIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 12c2.7 0 4.8-2.1 4.8-4.8S14.7 2.4 12 2.4 7.2 4.5 7.2 7.2 9.3 12 12 12zm0 2.4c-3.2 0-9.6 1.6-9.6 4.8v2.4h19.2v-2.4c0-3.2-6.4-4.8-9.6-4.8z"/></svg>';
const addressIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M12 2C8.1 2 5 5.1 5 9c0 5.3 7 13 7 13s7-7.7 7-13c0-3.9-3.1-7-7-7zm0 9.5c-1.4 0-2.5-1.1-2.5-2.5S10.6 6.5 12 6.5s2.5 1.1 2.5 2.5S13.4 11.5 12 11.5z"/></svg>';
const paymentIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v2h20V6c0-1.1-.9-2-2-2zM2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2v-8H2v8zm4-3h4v2H6v-2z"/></svg>';
const deliveryStatusIcon =
'<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M20 8h-3V4H3c-1.1 0-2 .9-2 2v11h2a2 2 0 1 0 4 0h8a2 2 0 1 0 4 0h3v-5l-4-4zm-5 5H4V6h11v7zm2-4.17L19.17 13H17V8.83zM6 18a1 1 0 1 1 0-2 1 1 0 0 1 0 2zm12 0a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>';
export default function StepperStyling() {
const stepperRef = useRef<IgrStepper>(null);
const [orientation, setOrientation] =
useState<StepperOrientation>("horizontal");
const [horizontalAnimation, setHorizontalAnimation] =
useState<HorizontalTransitionAnimation>("slide");
const [verticalAnimation, setVerticalAnimation] =
useState<StepperVerticalAnimation>("grow");
const [animationDuration, setAnimationDuration] = useState("320");
useEffect(() => {
registerIconFromText("personal", personalInfoIcon, "material");
registerIconFromText("address", addressIcon, "material");
registerIconFromText("payment", paymentIcon, "material");
registerIconFromText("delivery", deliveryStatusIcon, "material");
}, []);
const orientationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as StepperOrientation;
setOrientation(selectedValue);
};
const horizontalAnimationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as HorizontalTransitionAnimation;
setHorizontalAnimation(selectedValue);
};
const verticalAnimationChange = (e: IgrSelectItemComponentEventArgs) => {
const selectedValue = e.detail.value as StepperVerticalAnimation;
setVerticalAnimation(selectedValue);
};
const animationDurationChange = (e: IgrComponentValueChangedEventArgs) => {
const animationDuration = e.detail;
setAnimationDuration(animationDuration);
};
return (
<div className="container sample">
<article className="settings">
<IgrSelect label="Orienation" onChange={orientationChange}>
<IgrSelectItem
value="horizontal"
selected={orientation === "horizontal"}
>
<span>Horizontal</span>
</IgrSelectItem>
<IgrSelectItem value="vertical">
<span>Vertical</span>
</IgrSelectItem>
</IgrSelect>
<IgrSelect
label="Vertical Animation"
onChange={verticalAnimationChange}
>
<IgrSelectItem value="grow" selected={verticalAnimation === "grow"}>
<span>Grow</span>
</IgrSelectItem>
<IgrSelectItem value="fade">
<span>Fade</span>
</IgrSelectItem>
<IgrSelectItem value="none">
<span>None</span>
</IgrSelectItem>
</IgrSelect>
<IgrSelect
label="Horizontal Animation"
onChange={horizontalAnimationChange}
>
<IgrSelectItem
value="slide"
selected={horizontalAnimation === "slide"}
>
<span>Slide</span>
</IgrSelectItem>
<IgrSelectItem value="fade">
<span>Fade</span>
</IgrSelectItem>
<IgrSelectItem value="none">
<span>None</span>
</IgrSelectItem>
</IgrSelect>
<IgrInput
type="number"
value={animationDuration}
label="Duration"
onChange={animationDurationChange}
>
<span slot="suffix">ms</span>
</IgrInput>
</article>
<IgrStepper
ref={stepperRef}
orientation={orientation}
horizontalAnimation={horizontalAnimation}
verticalAnimation={verticalAnimation}
animationDuration={+animationDuration}
>
<IgrStep>
<IgrIcon slot="indicator" name="personal" collection="material" />
<p slot="title">Personal Info</p>
<form>
<IgrInput label="Full Name" type="text" name="fullName"></IgrInput>
<IgrInput label="Email" type="email" name="email"></IgrInput>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep>
<IgrIcon slot="indicator" name="address" collection="material" />
<span slot="title">Delivery address</span>
<form>
<IgrInput label="City" type="text" name="city"></IgrInput>
<IgrInput label="Street" type="text" name="street"></IgrInput>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>NEXT</span>
</IgrButton>
</form>
</IgrStep>
<IgrStep>
<IgrIcon slot="indicator" name="payment" collection="material" />
<span slot="title">Payment</span>
<IgrRadioGroup>
<IgrRadio name="payment" checked>
<span>PayPal (n@mail.com; 18/02/2021)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>Visa (**** **** **** 1234; 12/23)</span>
</IgrRadio>
<IgrRadio name="payment">
<span>MasterCard (**** **** **** 5678; 12/24)</span>
</IgrRadio>
</IgrRadioGroup>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.next();
}}
>
<span>SUBMIT</span>
</IgrButton>
</IgrStep>
<IgrStep>
<IgrIcon slot="indicator" name="delivery" collection="material" />
<span slot="title">Delivery status</span>
<p>
Your order is on its way. Expect delivery on 25th September 2021.
Delivery address: San Jose, CA 94243.
</p>
<IgrButton
onClick={() => {
stepperRef.current.prev();
}}
>
<span>PREVIOUS</span>
</IgrButton>
<IgrButton
onClick={() => {
stepperRef.current.reset();
}}
>
<span>RESET</span>
</IgrButton>
</IgrStep>
</IgrStepper>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<StepperStyling />);
tsx
.settings {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1.125rem;
background: hsl(var(--ig-gray-100));
padding: 1.125rem;
border: 1px solid hsl(var(--ig-gray-300));
border-radius: .25rem;
margin-bottom: 2rem;
}
:root {
--color-teal: rgba(77, 182, 172, 1);
--color-dark-navy: rgba(26, 35, 126, 1);
--color-aqua-gray: rgba(208, 236, 236, 1);
--color-white: rgba(255, 255, 255, 1);
--color-teal-hover: rgba(26, 35, 126, 1);
--color-teal-shadow: rgba(77, 182, 172, 0.5);
}
igc-button::part(base) {
margin: 1rem 0.5rem 0 0;
background-color: var(--color-teal);
color: var(--color-white);
font-weight: 600;
transition: background-color 0.25s ease, transform 0.1s ease;
}
igc-button:hover::part(base) {
background-color: var(--color-dark-navy);
}
igc-button:active::part(base) {
transform: scale(0.96);
}
igc-step::part(title) {
color: var(--color-dark-navy);
font-variant: small-caps;
font-weight: bold;
}
igc-step::part(indicator) {
border-radius: 12px 6px 12px 6px;
background-color: var(--color-aqua-gray);
color: var(--color-dark-navy);
transition: all 0.2s ease;
}
igc-step[active]::part(indicator) {
background-color: var(--color-teal);
box-shadow: 0 2px 8px var(--color-teal-shadow);
transform: scale(1.04);
}
igc-step[active]:active::part(indicator) {
transform: scale(1.08);
}
css
API リファレンス
その他のリソース