⭐️

【Polaris和訳】Components/Forms⑥

2021/11/06に公開約59,900字

この記事について

この記事は、Polaris/Components/Formsの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Forms⑥

Inline error

インラインエラーは、マーチャントにフォーム内の 1 つまたは複数の入力項目で何か問題があったことを伝える、簡潔で状況に応じたメッセージです。インラインエラーを使用して、マーチャントがフォームの入力が有効でない理由とその修正方法を理解できるようにします。

Web

Basic inline error

マーチャントがフォーム内の複数のフィールドに有効ではない情報を入力した場合や、フォームレイアウト内の非標準的な位置に表示する必要がある場合に使用します。

React
React
<InlineError message="Store name is required" fieldID="myFieldID" />
HTML
HTML
<div>
  <div id="myFieldIDError" class="Polaris-InlineError">
    <div class="Polaris-InlineError__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
          <path d="M10 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16zM9 9a1 1 0 0 0 2 0V7a1 1 0 1 0-2 0v2zm0 4a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"></path>
        </svg></span></div>Store name is required
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Props

fieldID(Required)
string
メッセージが説明する無効なフォームフィールドの一意の識別子

message(Required)
string | ReactElement | (string | ReactElement)[]
無効なフォームフィールドの入力を解決する方法を簡単に説明したコンテンツです。

アクセシビリティ

  • インラインエラーに一意のidを与えるために、必須のfieldIDprop を使用します。これにより、スクリーンリーダーのユーザーにエラーの内容が伝わるように、aria-describedbyを使ってエラーをフォームフィールドに結びつけます。
  • 必須のmessageprop を使用して、エラーを説明するテキストを提供します。
  • インラインエラーのアイコンは、が見えにくいマーチャントや、ページから色を削除する設定を使用しているマーチャントが、エラーメッセージを視覚的に識別するのに役立ちます。
Android

Basic inline error

マーチャントがフォーム内の複数のフィールドに有効ではない情報を入力した場合や、フォームレイアウト内の非標準的な位置に表示する必要がある場合に使用します。

アクセシビリティ

Android のアクセシビリティについては、Material Design と開発ドキュメントをご覧ください。

iOS

Basic inline error

マーチャントがフォーム内の複数のフィールドに有効ではない情報を入力した場合や、フォームレイアウト内の非標準的な位置に表示する必要がある場合に使用します。

アクセシビリティ

iOS のアクセシビリティについては、Apple の Human Interface Guidelines や API のドキュメントをご覧ください。

ベストプラクティス

インラインエラーは以下のことに注意してください。

  • 短いこと
  • 文語体で書かれていること
  • フォームへの入力が無効な場合、すぐに表示されること
  • 入力が有効になったらすぐに削除し、マーチャントが問題を解決したことをすぐに分かるようにすること
  • マーチャントがフォーム内のタスクを完了できるよう、具体的な解決策を記述すること
  • 説明する入力または入力グループの文脈から外れた場所に配置しない。

エラーメッセージのパターンについて詳しくはこちら

コンテンツガイドライン

インラインエラーメッセージ

エラーメッセージは問題の原因のすぐ下にあるので、コピーはなぜエラーが発生したのかを説明するだけで十分です。必要に応じて、次に何をすべきかを明確にしたり、ワンクリックで修正できる方法を提示することもできます。

インラインエラーメッセージは以下のことに注意してください。

  • 何が悪かったのかを明確に説明し、次のステップを提示するか、ワンクリックで修正できるようにすること
  • 1 文以上の簡潔な文章であること
  • マーチャントがエラーの責任を問われていると感じないように、受動態を使用すること

関連コンポーネント

Keyboard accessories

iOS や Android では、文字入力時にソフトウェアキーボードが画面に表示されます。キーボードアクセサリーは、マーチャントが行っていることに基づいて、追加のコンテンツやアクションを可能にします。例えば、マーチャントが説明文を更新する際に、太字、斜体、下線のコントロールが必要な場合などです。

Android

Keyboard accessories with actions

アクションアクセサリーを使って、マーチャントが画面に入力する内容に関連したアクションを追加します。

Keyboard accessories with text field

メッセージングやチャットベースの製品で、メッセージの入力を容易にするために使用します。

iOS

Keyboard accessories with actions

アクションアクセサリーを使って、マーチャントが画面に入力する内容に関連したアクションを追加します。

Keyboard accessories with text field

メッセージングやチャットベースの製品で、メッセージの入力を容易にするために使用します。

ベストプラクティス

キーボードアクセサリーは以下のことに注意してください。

  • 高さが最大であること。
    • iOS では 44pt
    • Android では 48dp
  • マーチャントが利用できるようにする必要があるコンテンツやアクションの数が多い場合は、水平方向にスワイプ可能なインタラクションを含める。
    • マーチャントがスワイプ操作を認識できるように、簡単なヒントや導入部を提供する。
  • マーチャントの視覚的ノイズや複雑さを軽減するために、可能であればアクションをグループ化し、拡張可能にする。

関連コンポーネント

Radio button

ラジオボタンを使用して、マーチャントが単一の選択をしなければならない選択肢のリストに各アイテムを表示します。

Web

Default radio button

マーチャントが単一の選択をしなければならない場合は、ラジオボタンを使用してください。

React
React
function RadioButtonExample() {
  const [value, setValue] = useState('disabled');

  const handleChange = useCallback(
    (_checked, newValue) => setValue(newValue),
    [],
  );

  return (
    <Stack vertical>
      <RadioButton
        label="Accounts are disabled"
        helpText="Customers will only be able to check out as guests."
        checked={value === 'disabled'}
        id="disabled"
        name="accounts"
        onChange={handleChange}
      />
      <RadioButton
        label="Accounts are optional"
        helpText="Customers will be able to check out with a customer account or as a guest."
        id="optional"
        name="accounts"
        checked={value === 'optional'}
        onChange={handleChange}
      />
    </Stack>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Stack Polaris-Stack--vertical">
    <div class="Polaris-Stack__Item">
      <div><label class="Polaris-Choice" for="disabled"><span class="Polaris-Choice__Control"><span class="Polaris-RadioButton"><input id="disabled" name="accounts" type="radio" class="Polaris-RadioButton__Input" aria-describedby="disabledHelpText" value="" checked=""><span class="Polaris-RadioButton__Backdrop"></span></span></span><span class="Polaris-Choice__Label">Accounts are disabled</span></label>
        <div class="Polaris-Choice__Descriptions">
          <div class="Polaris-Choice__HelpText" id="disabledHelpText">Customers will only be able to check out as guests.</div>
        </div>
      </div>
    </div>
    <div class="Polaris-Stack__Item">
      <div><label class="Polaris-Choice" for="optional"><span class="Polaris-Choice__Control"><span class="Polaris-RadioButton"><input id="optional" name="accounts" type="radio" class="Polaris-RadioButton__Input" aria-describedby="optionalHelpText" value=""><span class="Polaris-RadioButton__Backdrop"></span></span></span><span class="Polaris-Choice__Label">Accounts are optional</span></label>
        <div class="Polaris-Choice__Descriptions">
          <div class="Polaris-Choice__HelpText" id="optionalHelpText">Customers will be able to check out with a customer account or as a guest.</div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Props

ariaDescribedBy
string
ラジオボタンを記述する要素の ID を示す。

checked
boolean
ラジオボタンが選択されているかどうか

disabled
boolean
入力を無効にする

helpText
React.ReactNode
使いやすさを考慮した追加テキスト

id
string
フォーム入力用の ID

label(Required)
React.ReactNode
ラジオボタンのラベル

labelHidden
boolean
ラベルを視覚的に隠す

name
string
フォーム入力用の名前

value
string
フォームの入力値

onBlur
() => void
フォーカスが外された時のコールバック

onChange
(newValue: boolean, id: string) => void
ラジオボタンがトグルされた時のコールバック

onFocus
() => void
ラジオボタンがフォーカスされた時のコールバック

アクセシビリティ

スクリーンリーダーはラジオボタンの状態を自動的に伝えます。

  • disabledprop を使って、HTML のdisabled属性をラジオボタンの<input>に適用します。これにより、マーチャントがラジオボタンを操作することができなくなり、アシスティブテクノロジーにその非アクティブな状態を伝えることができます。
  • idprop を使って、ラジオボタンに一意のid属性値を与えます。idが指定されていない場合は、コンポーネントがidを生成します。アシスティブテクノロジーで正しく動作するためには、すべてのラジオボタンに一意のid値が必要です。

ラベリング

  • 必須のlabelprop は、すべてのマーチャントにラジオボタンの目的を伝えます。
  • labelHiddenprop を使ってラベルを視覚的に隠しますが、アシスティブテクノロジーで利用できるようにします。
  • helpTextprop でヘルプテキストを提供したり、errorprop でインラインエラーメッセージを提供する場合、ヘルプやエラーの内容はaria-describedby属性でスクリーンリーダーのユーザーに伝えられます。

キーボードサポート

  • tabキーでラジオボタングループにフォーカスを移す(逆方向にタブした場合はshifttab)。
  • 上下の矢印キーでどのラジオボタンが選択されているかを変更する。

ベストプラクティス

ラジオボタンは以下のことに注意してください。

  • 必ずラベルコンポーネントと一緒に使用してください。
  • 次のようなラジオボタンのリストを作成してください。
    • 最低でも 2 つ以上の選択肢を含む。
    • マーチャントに 1 つのオプションのみを選択させるために使用します。
    • 相互に排他的な選択肢を含む。つまり、各選択肢はリスト内の他のすべての選択肢から独立していなければなりません。例えば、以下のようなものがあります。赤、青、黄は相互に排他的です。赤、青、黄、赤/青は相互に排他的ではありません。
    • 論理的に意味のある順序で選択肢をリストアップする。
    • 可能な限りデフォルトのオプションを選択してください。

コンテンツガイドライン

ラジオボタンのラベル

ラジオボタンのラベルは以下のことに注意してください。

  • コロンまたは見出しで始まること
  • 大文字で始まる

  • 1 つの文、単語、またはひとかたまりであれば、句読点で終わらない。

トグル(Android と iOS のみ)

トグルラベルは以下のことに注意してください。

  • マーチャントが有効または無効にするものを明確にする。
  • 大文字で始まる

トグルバリューは以下のことに注意してください。

  • ラベルを付けない

関連コンポーネント

Range slider

レンジスライダーは、マーチャントが指定された範囲(最小値と最大値)内の数値を選択するための入力フィールドです。

Web

Default range slider

0 ~ 100 の間の単一の値を選択する必要がある場合に使用します。

React
React
function RangeSliderExample() {
  const [rangeValue, setRangeValue] = useState(32);

  const handleRangeSliderChange = useCallback(
    (value) => setRangeValue(value),
    [],
  );

  return (
    <Card sectioned title="Background color">
      <RangeSlider
        label="Opacity percentage"
        value={rangeValue}
        onChange={handleRangeSliderChange}
        output
      />
    </Card>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Header">
      <h2 class="Polaris-Heading">Background color</h2>
    </div>
    <div class="Polaris-Card__Section">
      <div class="">
        <div class="Polaris-Labelled__LabelWrapper">
          <div class="Polaris-Label"><label id="PolarisRangeSlider2Label" for="PolarisRangeSlider2" class="Polaris-Label__Text">Opacity percentage</label></div>
        </div>
        <div class="Polaris-RangeSlider-SingleThumb" style="--Polaris-RangeSlider-min:0; --Polaris-RangeSlider-max:100; --Polaris-RangeSlider-current:32; --Polaris-RangeSlider-progress:32%; --Polaris-RangeSlider-output-factor:0.18;">
          <div class="Polaris-RangeSlider-SingleThumb__InputWrapper"><input type="range" class="Polaris-RangeSlider-SingleThumb__Input" id="PolarisRangeSlider2" name="PolarisRangeSlider2" min="0" max="100" step="1" aria-valuemin="0" aria-valuemax="100" aria-valuenow="32" aria-invalid="false" value="32"><output for="PolarisRangeSlider2" class="Polaris-RangeSlider-SingleThumb__Output">
              <div class="Polaris-RangeSlider-SingleThumb__OutputBubble"><span class="Polaris-RangeSlider-SingleThumb__OutputText">32</span></div>
            </output></div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Min and max range control

最小値と最大値が指定された数値範囲から、単一の値を選択する必要がある場合に使用します。

React
React
function RangeSliderWithPreciseRangeControlExample() {
  const [rangeValue, setRangeValue] = useState(0);

  const handleRangeSliderChange = useCallback(
    (value) => setRangeValue(value),
    [],
  );

  return (
    <Card sectioned title="Navigation branding">
      <RangeSlider
        output
        label="Logo offset"
        min={-20}
        max={20}
        value={rangeValue}
        onChange={handleRangeSliderChange}
      />
    </Card>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Header">
      <h2 class="Polaris-Heading">Navigation branding</h2>
    </div>
    <div class="Polaris-Card__Section">
      <div class="">
        <div class="Polaris-Labelled__LabelWrapper">
          <div class="Polaris-Label"><label id="PolarisRangeSlider4Label" for="PolarisRangeSlider4" class="Polaris-Label__Text">Logo offset</label></div>
        </div>
        <div class="Polaris-RangeSlider-SingleThumb" style="--Polaris-RangeSlider-min:-20; --Polaris-RangeSlider-max:20; --Polaris-RangeSlider-current:0; --Polaris-RangeSlider-progress:50%; --Polaris-RangeSlider-output-factor:0;">
          <div class="Polaris-RangeSlider-SingleThumb__InputWrapper"><input type="range" class="Polaris-RangeSlider-SingleThumb__Input" id="PolarisRangeSlider4" name="PolarisRangeSlider4" min="-20" max="20" step="1" aria-valuemin="-20" aria-valuemax="20" aria-valuenow="0" aria-invalid="false" value="0"><output for="PolarisRangeSlider4" class="Polaris-RangeSlider-SingleThumb__Output">
              <div class="Polaris-RangeSlider-SingleThumb__OutputBubble"><span class="Polaris-RangeSlider-SingleThumb__OutputText">0</span></div>
            </output></div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Step incremented range control

複数の数値の中から特定の増分の値を選択する必要がある場合に使用します。

React
React
function RangeSliderWithPreciseRangeControlExample() {
  const [rangeValue, setRangeValue] = useState(4);

  const handleRangeSliderChange = useCallback(
    (value) => setRangeValue(value),
    [],
  );

  return (
    <Card sectioned title="Navigation branding">
      <RangeSlider
        output
        label="Logo offset"
        min={-20}
        max={20}
        step={4}
        value={rangeValue}
        onChange={handleRangeSliderChange}
      />
    </Card>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Header">
      <h2 class="Polaris-Heading">Navigation branding</h2>
    </div>
    <div class="Polaris-Card__Section">
      <div class="">
        <div class="Polaris-Labelled__LabelWrapper">
          <div class="Polaris-Label"><label id="PolarisRangeSlider6Label" for="PolarisRangeSlider6" class="Polaris-Label__Text">Logo offset</label></div>
        </div>
        <div class="Polaris-RangeSlider-SingleThumb" style="--Polaris-RangeSlider-min:-20; --Polaris-RangeSlider-max:20; --Polaris-RangeSlider-current:4; --Polaris-RangeSlider-progress:60%; --Polaris-RangeSlider-output-factor:-0.1;">
          <div class="Polaris-RangeSlider-SingleThumb__InputWrapper"><input type="range" class="Polaris-RangeSlider-SingleThumb__Input" id="PolarisRangeSlider6" name="PolarisRangeSlider6" min="-20" max="20" step="4" aria-valuemin="-20" aria-valuemax="20" aria-valuenow="4" aria-invalid="false" value="4"><output for="PolarisRangeSlider6" class="Polaris-RangeSlider-SingleThumb__Output">
              <div class="Polaris-RangeSlider-SingleThumb__OutputBubble"><span class="Polaris-RangeSlider-SingleThumb__OutputText">4</span></div>
            </output></div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Prefix and suffix elements

範囲入力の始点または終点に追加コンテンツが必要な場合に使用します。

range sliderコンポーネントの高さは、labelhelpTextなどの props の有無に応じて変化します。prefixsuffixのプロップに React 要素を設定することで、スペーシングとアライメントの制御が可能になります。

React
React
function RangeSliderWithPrefixAndSuffixExample() {
  const [rangeValue, setRangeValue] = useState(100);

  const handleRangeSliderChange = useCallback(
    (value) => setRangeValue(value),
    [],
  );

  const suffixStyles = {
    minWidth: '24px',
    textAlign: 'right',
  };

  return (
    <Card sectioned title="Text color">
      <RangeSlider
        output
        label="Hue color mix"
        min={0}
        max={360}
        value={rangeValue}
        onChange={handleRangeSliderChange}
        prefix={<p>Hue</p>}
        suffix={<p style={suffixStyles}>{rangeValue}</p>}
      />
    </Card>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Header">
      <h2 class="Polaris-Heading">Text color</h2>
    </div>
    <div class="Polaris-Card__Section">
      <div class="">
        <div class="Polaris-Labelled__LabelWrapper">
          <div class="Polaris-Label"><label id="PolarisRangeSlider8Label" for="PolarisRangeSlider8" class="Polaris-Label__Text">Hue color mix</label></div>
        </div>
        <div class="Polaris-RangeSlider-SingleThumb" style="--Polaris-RangeSlider-min:0; --Polaris-RangeSlider-max:360; --Polaris-RangeSlider-current:100; --Polaris-RangeSlider-progress:27.7778%; --Polaris-RangeSlider-output-factor:0.222222;">
          <div class="Polaris-RangeSlider-SingleThumb__Prefix">
            <p>Hue</p>
          </div>
          <div class="Polaris-RangeSlider-SingleThumb__InputWrapper"><input type="range" class="Polaris-RangeSlider-SingleThumb__Input" id="PolarisRangeSlider8" name="PolarisRangeSlider8" min="0" max="360" step="1" aria-valuemin="0" aria-valuemax="360" aria-valuenow="100" aria-invalid="false" value="100"><output for="PolarisRangeSlider8" class="Polaris-RangeSlider-SingleThumb__Output">
              <div class="Polaris-RangeSlider-SingleThumb__OutputBubble"><span class="Polaris-RangeSlider-SingleThumb__OutputText">100</span></div>
            </output></div>
          <div class="Polaris-RangeSlider-SingleThumb__Suffix">
            <p style="min-width: 24px; text-align: right;">100</p>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Dual thumb range slider

数値の範囲から 2 つの値を選択する必要がある場合に使用します。

React
React
function DualThumbRangeSliderExample() {
  const initialValue = [900, 1000];
  const prefix = '$';
  const min = 0;
  const max = 2000;
  const step = 10;

  const [intermediateTextFieldValue, setIntermediateTextFieldValue] =
    useState(initialValue);
  const [rangeValue, setRangeValue] = useState(initialValue);

  const handleRangeSliderChange = useCallback((value) => {
    setRangeValue(value);
    setIntermediateTextFieldValue(value);
  }, []);

  const handleLowerTextFieldChange = useCallback(
    (value) => {
      const upperValue = rangeValue[1];
      setIntermediateTextFieldValue([parseInt(value, 10), upperValue]);
    },
    [rangeValue],
  );

  const handleUpperTextFieldChange = useCallback(
    (value) => {
      const lowerValue = rangeValue[0];
      setIntermediateTextFieldValue([lowerValue, parseInt(value, 10)]);
    },
    [rangeValue],
  );

  const handleLowerTextFieldBlur = useCallback(() => {
    const upperValue = rangeValue[1];
    const value = intermediateTextFieldValue[0];

    setRangeValue([parseInt(value, 10), upperValue]);
  }, [intermediateTextFieldValue, rangeValue]);

  const handleUpperTextFieldBlur = useCallback(() => {
    const lowerValue = rangeValue[0];
    const value = intermediateTextFieldValue[1];

    setRangeValue([lowerValue, parseInt(value, 10)]);
  }, [intermediateTextFieldValue, rangeValue]);

  const handleEnterKeyPress = useCallback(
    (event) => {
      const newValue = intermediateTextFieldValue;
      const oldValue = rangeValue;

      if (event.keyCode === Key.Enter && newValue !== oldValue) {
        setRangeValue(newValue);
      }
    },
    [intermediateTextFieldValue, rangeValue],
  );

  const lowerTextFieldValue =
    intermediateTextFieldValue[0] === rangeValue[0]
      ? rangeValue[0]
      : intermediateTextFieldValue[0];

  const upperTextFieldValue =
    intermediateTextFieldValue[1] === rangeValue[1]
      ? rangeValue[1]
      : intermediateTextFieldValue[1];

  return (
    <Card sectioned title="Minimum requirements">
      <div onKeyDown={handleEnterKeyPress}>
        <RangeSlider
          output
          label="Money spent is between"
          value={rangeValue}
          prefix={prefix}
          min={min}
          max={max}
          step={step}
          onChange={handleRangeSliderChange}
        />
        <Stack distribution="equalSpacing" spacing="extraLoose">
          <TextField
            label="Min money spent"
            type="number"
            value={`${lowerTextFieldValue}`}
            prefix={prefix}
            min={min}
            max={max}
            step={step}
            onChange={handleLowerTextFieldChange}
            onBlur={handleLowerTextFieldBlur}
            autoComplete="off"
          />
          <TextField
            label="Max money spent"
            type="number"
            value={`${upperTextFieldValue}`}
            prefix={prefix}
            min={min}
            max={max}
            step={step}
            onChange={handleUpperTextFieldChange}
            onBlur={handleUpperTextFieldBlur}
            autoComplete="off"
          />
        </Stack>
      </div>
    </Card>
  );
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Header">
      <h2 class="Polaris-Heading">Minimum requirements</h2>
    </div>
    <div class="Polaris-Card__Section">
      <div>
        <div class="">
          <div class="Polaris-Labelled__LabelWrapper">
            <div class="Polaris-Label"><label id="PolarisRangeSlider10Label" for="PolarisRangeSlider10" class="Polaris-Label__Text">Money spent is between</label></div>
          </div>
          <div class="Polaris-RangeSlider-DualThumb__Wrapper">
            <div class="Polaris-RangeSlider-DualThumb__Prefix">$</div>
            <div class="Polaris-RangeSlider-DualThumb__TrackWrapper">
              <div class="Polaris-RangeSlider-DualThumb__Track" style="--Polaris-RangeSlider-progress-lower:288.802px; --Polaris-RangeSlider-progress-upper:320.891px;"></div>
              <div class="Polaris-RangeSlider-DualThumb--trackDashed"></div>
              <div id="PolarisRangeSlider10" class="Polaris-RangeSlider-DualThumb__Thumbs" role="slider" aria-valuemin="0" aria-valuemax="2000" aria-valuenow="900" aria-invalid="false" aria-labelledby="PolarisRangeSlider10Label" tabindex="0" style="left: 288.802px;"></div><output for="PolarisRangeSlider10" class="Polaris-RangeSlider-DualThumb__Output" style="left: 288.802px;">
                <div class="Polaris-RangeSlider-DualThumb__OutputBubble"><span class="Polaris-RangeSlider-DualThumb__OutputText">900</span></div>
              </output>
              <div id="PolarisRangeSlider10Upper" class="Polaris-RangeSlider-DualThumb__Thumbs" role="slider" aria-valuemin="0" aria-valuemax="2000" aria-valuenow="1000" aria-invalid="false" aria-labelledby="PolarisRangeSlider10Label" tabindex="0" style="left: 320.891px;"></div><output for="PolarisRangeSlider10Upper" class="Polaris-RangeSlider-DualThumb__Output" style="left: 320.891px;">
                <div class="Polaris-RangeSlider-DualThumb__OutputBubble"><span class="Polaris-RangeSlider-DualThumb__OutputText">1000</span></div>
              </output>
            </div>
          </div>
        </div>
        <div class="Polaris-Stack Polaris-Stack--spacingExtraLoose Polaris-Stack--distributionEqualSpacing">
          <div class="Polaris-Stack__Item">
            <div class="">
              <div class="Polaris-Labelled__LabelWrapper">
                <div class="Polaris-Label"><label id="PolarisTextField3Label" for="PolarisTextField3" class="Polaris-Label__Text">Min money spent</label></div>
              </div>
              <div class="Polaris-Connected">
                <div class="Polaris-Connected__Item Polaris-Connected__Item--primary">
                  <div class="Polaris-TextField Polaris-TextField--hasValue">
                    <div class="Polaris-TextField__Prefix" id="PolarisTextField3Prefix">$</div><input id="PolarisTextField3" autocomplete="off" class="Polaris-TextField__Input" min="0" max="2000" step="10" type="number" aria-labelledby="PolarisTextField3Label PolarisTextField3Prefix" aria-invalid="false" value="900">
                    <div class="Polaris-TextField__Spinner" aria-hidden="true">
                      <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                        <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                              <path d="m15 12-5-5-5 5h10z"></path>
                            </svg></span></div>
                      </div>
                      <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                        <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                              <path d="m5 8 5 5 5-5H5z"></path>
                            </svg></span></div>
                      </div>
                    </div>
                    <div class="Polaris-TextField__Backdrop"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
          <div class="Polaris-Stack__Item">
            <div class="">
              <div class="Polaris-Labelled__LabelWrapper">
                <div class="Polaris-Label"><label id="PolarisTextField4Label" for="PolarisTextField4" class="Polaris-Label__Text">Max money spent</label></div>
              </div>
              <div class="Polaris-Connected">
                <div class="Polaris-Connected__Item Polaris-Connected__Item--primary">
                  <div class="Polaris-TextField Polaris-TextField--hasValue">
                    <div class="Polaris-TextField__Prefix" id="PolarisTextField4Prefix">$</div><input id="PolarisTextField4" autocomplete="off" class="Polaris-TextField__Input" min="0" max="2000" step="10" type="number" aria-labelledby="PolarisTextField4Label PolarisTextField4Prefix" aria-invalid="false" value="1000">
                    <div class="Polaris-TextField__Spinner" aria-hidden="true">
                      <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                        <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                              <path d="m15 12-5-5-5 5h10z"></path>
                            </svg></span></div>
                      </div>
                      <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                        <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                              <path d="m5 8 5 5 5-5H5z"></path>
                            </svg></span></div>
                      </div>
                    </div>
                    <div class="Polaris-TextField__Backdrop"></div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Props

disabled
boolean
入力を無効にする

error
string | ReactElement | (string | ReactElement)[]
エラーメッセージを表示する

helpText
React.ReactNode
使いやすさを考慮した追加テキスト

id
string
レンジインプットの ID

label(Required)
React.ReactNode
レンジインプットのラベル

labelAction
Action
ラベルにアクションを追加する

labelHidden
boolean
視覚的にラベルを隠す

max
number
レンジインプットの最大値

min
number
レンジインプットの最小値

output
boolean
スライド時に、現在の値を示すツールチップを提供する

prefix
React.ReactNode
インプットの前に表示する要素

step
number
レンジインプット変更時のインクリメント値

suffix
React.ReactNode
インプットの後に表示する要素

value(Required)
number | DualValue
レンジインプットの初期値

onBlur
() => void
フォーカスが外された時のコールバック

onChange(Required)
(value: number | DualValue, id: string) => void
レンジインプット変更時のコールバック

onFocus
() => void
レンジインプットがフォーカスされた時のコールバック

アクセシビリティ

レンジスライダーでは、スライダーサムのクリックやタップのターゲットが大きく表示されます。また、マーチャントはスライダートラックをタップまたはクリックすることで、最も近いスライダーサムを移動させることができます。

シングルサムスライダー

デフォルトのレンジスライダーコンポーネントは、ARIA 1.1 のスライダーパターンを使用して、デフォルトの HTML の<input type="range">をベースにしています。必須のlabelprop は、フォーカスを受けたときにアシスティブテクノロジーに伝達されるフィールドのラベルを提供します。スライダーが使用されると、valueprop が視覚的およびプログラム的に更新され、現在の値が反映されます。

現在の値を支援技術に一貫して提供するには、minprop およびmaxprop を使用して、スライダの最小値と最大値を指定します。

デュアルサムスライダー

デュアルサムレンジスライダーコンポーネントは、ARIA 1.1 のスライダー(マルチサム)パターンを使用しています。しかし、このパターンはスクリーンリーダー、特にモバイルデバイスでは一貫してサポートされていません。このため、デュアルサムスライダーと各値のテキストフィールドを組み合わせるか、または他のアクセス可能な入力方法を提供するのが最善です。

キーボード

  • スライダーのサムにフォーカスを移すには、前進させるにtabはキーを、後退させるにはshifttabを押します。
  • サムがフォーカスされているときは、上下または左右の矢印キーでサムを動かし、関連する値を更新します。

ベストプラクティス

レンジスライダーは以下のことに注意してください。

  • ラベルがhiddenの場合でも、常にラベルを付けて使用すること。
  • ラベルが表示されている場合は、範囲入力の目的とその値(minmaxstepvalue)を明確に伝える必要があります。
  • 必須ではない入力を要求する必要がある場合には、Optionalというラベルを付けること
  • マーチャントがフィールドでの操作を終えるとすぐに入力を検証すること(それ以前は不可)
  • レンジスライダーの親指が 2 つある場合は、必ず 2 つのテキストフィールドコンポーネントと一緒に使用し、下と上の両方の親指にアクセシブルな代替手段を提供します。

コンテンツガイドライン

Range label

ラベルとは、要求された入力の短い説明のことです。ラベルは指示文ではありませんが、意味があり、何が求められているかを明確に示す必要があります。ラベルは以下のようにします。

  • フォームフィールドの上に配置
  • 短く、簡潔に(1 ~ 3 語)
  • 文語体(最初の単語は大文字、残りは小文字)で書かれている。

Designating optional fields

必須の情報だけを入力してもらうようにしましょう。任意の情報を提供してもらう必要がある場合は、フィールドのラベルの最後に (optional) というテキストを入れて、任意のフィールドをマークしてください。必須項目にはアスタリスクを付けないでください。

Help text

ヘルプテキストは、フォームフィールドに入力する人に追加のガイダンスや指示を与えるものです。また、その情報がどのように使用されるかを明確にするためにも使用されます。他のフォームコンテンツと同様に、ヘルプテキストは簡潔で読みやすいものでなければなりません。

Validation error messages

エラーメッセージは以下のことに注意してください。

  • 何が悪かったのか、どうすれば解決できるのかを明確に説明する。
  • 簡潔な文章で、一文以上は書かない.
  • お客さまがエラーの責任を問われていると感じないように、受動態を使用する。

関連コンポーネント

Select

セレクトは、マーチャントがオプションメニューから 1 つのオプションを選択するためのものです。選択肢が 4 つ以上ある場合は、インターフェースが煩雑にならないように、セレクトを検討してください。

Web

Default select

クラシックなドロップダウンメニュー、またはマーチャントのブラウザで判断される同等のピッカーを表示します。

React
React
function SelectExample() {
  const [selected, setSelected] = useState('today');

  const handleSelectChange = useCallback((value) => setSelected(value), []);

  const options = [
    {label: 'Today', value: 'today'},
    {label: 'Yesterday', value: 'yesterday'},
    {label: 'Last 7 days', value: 'lastWeek'},
  ];

  return (
    <Select
      label="Date range"
      options={options}
      onChange={handleSelectChange}
      value={selected}
    />
  );
}
HTML
HTML
<div>
  <div class="">
    <div class="Polaris-Labelled__LabelWrapper">
      <div class="Polaris-Label"><label id="PolarisSelect2Label" for="PolarisSelect2" class="Polaris-Label__Text">Date range</label></div>
    </div>
    <div class="Polaris-Select"><select id="PolarisSelect2" class="Polaris-Select__Input" aria-invalid="false">
        <option value="today">Today</option>
        <option value="yesterday">Yesterday</option>
        <option value="lastWeek">Last 7 days</option>
      </select>
      <div class="Polaris-Select__Content" aria-hidden="true"><span class="Polaris-Select__SelectedOption">Today</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
            </svg></span></span></div>
      <div class="Polaris-Select__Backdrop"></div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Select with inline label

ツールバーなど、セレクトが 1 行に収まる必要がある場合にのみ使用します。

React
React
function InlineLabelExample() {
  const [selected, setSelected] = useState('newestUpdate');

  const handleSelectChange = useCallback((value) => setSelected(value), []);

  const options = [
    {label: 'Newest update', value: 'newestUpdate'},
    {label: 'Oldest update', value: 'oldestUpdate'},
    {label: 'Most spent', value: 'mostSpent'},
    {label: 'Most orders', value: 'mostOrders'},
    {label: 'Last name A–Z', value: 'lastNameAlpha'},
    {label: 'Last name Z–A', value: 'lastNameReverseAlpha'},
  ];

  return (
    <Select
      label="Sort by"
      labelInline
      options={options}
      onChange={handleSelectChange}
      value={selected}
    />
  );
}
HTML
HTML
<div>
  <div class="Polaris-Labelled--hidden">
    <div class="Polaris-Labelled__LabelWrapper">
      <div class="Polaris-Label"><label id="PolarisSelect8Label" for="PolarisSelect8" class="Polaris-Label__Text">Sort by</label></div>
    </div>
    <div class="Polaris-Select"><select id="PolarisSelect8" class="Polaris-Select__Input" aria-invalid="false">
        <option value="newestUpdate">Newest update</option>
        <option value="oldestUpdate">Oldest update</option>
        <option value="mostSpent">Most spent</option>
        <option value="mostOrders">Most orders</option>
        <option value="lastNameAlpha">Last name A–Z</option>
        <option value="lastNameReverseAlpha">Last name Z–A</option>
      </select>
      <div class="Polaris-Select__Content" aria-hidden="true"><span class="Polaris-Select__InlineLabel">Sort by</span><span class="Polaris-Select__SelectedOption">Newest update</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
            </svg></span></span></div>
      <div class="Polaris-Select__Backdrop"></div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Disabled select

現在利用できない選択項目に使用します。周囲のインターフェイスでは、セレクトボックスが無効になっている理由と、有効にする方法を明確にする必要があります。

React
React
<Select
  label="Date range"
  disabled
  options={[
    {label: 'Today', value: 'today'},
    {label: 'Yesterday', value: 'yesterday'},
    {label: 'Last 7 days', value: 'lastWeek'},
  ]}
/>
HTML
HTML
<div>
  <div class="">
    <div class="Polaris-Labelled__LabelWrapper">
      <div class="Polaris-Label"><label id="PolarisSelect10Label" for="PolarisSelect10" class="Polaris-Label__Text">Date range</label></div>
    </div>
    <div class="Polaris-Select Polaris-Select--disabled"><select id="PolarisSelect10" class="Polaris-Select__Input" disabled="" aria-invalid="false">
        <option value="today">Today</option>
        <option value="yesterday">Yesterday</option>
        <option value="lastWeek">Last 7 days</option>
      </select>
      <div class="Polaris-Select__Content" aria-hidden="true" aria-disabled="true"><span class="Polaris-Select__SelectedOption">Today</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
            </svg></span></span></div>
      <div class="Polaris-Select__Backdrop"></div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Select with prefix

任意の React 要素を個々の選択オプションの左側にレンダリングします。ドロップダウンには表示されません。

React
React
function PrefixExample() {
  const [selected, setSelected] = useState('enabled');

  const handleSelectChange = useCallback((value) => setSelected(value), []);

  const options = [
    {
      label: 'Increase',
      value: 'Increase',
      prefix: <Icon source={CaretUpMinor} />,
    },
    {
      label: 'Decrease',
      value: 'Decrease',
      prefix: <Icon source={CaretDownMinor} />,
    },
  ];

  return (
    <Select
      label="Permission"
      options={options}
      onChange={handleSelectChange}
      value={selected}
    />
  );
}
HTML
HTML
<div>
  <div class="">
    <div class="Polaris-Labelled__LabelWrapper">
      <div class="Polaris-Label"><label id="PolarisSelect12Label" for="PolarisSelect12" class="Polaris-Label__Text">Permission</label></div>
    </div>
    <div class="Polaris-Select"><select id="PolarisSelect12" class="Polaris-Select__Input" aria-invalid="false">
        <option value="Increase">Increase</option>
        <option value="Decrease">Decrease</option>
      </select>
      <div class="Polaris-Select__Content" aria-hidden="true">
        <div class="Polaris-Select__Prefix"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m15 12-5-5-5 5h10z"></path>
            </svg></span></div><span class="Polaris-Select__SelectedOption">Increase</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
            </svg></span></span>
      </div>
      <div class="Polaris-Select__Backdrop"></div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Select with validation error

マーチャントの選択に問題があることを知らせるために使用します。セレクトについては、通常、プレースホルダーオプション(“Select”)を使用していて、他の選択が行われていない場合にのみ、セレクションが無効になります。

React
React
function ValidationErrorExample() {
  const [selected, setSelected] = useState('');

  const handleSelectChange = useCallback((value) => setSelected(value), []);

  return (
    <Select
      label="Province"
      options={['Alberta']}
      value={selected}
      onChange={handleSelectChange}
      error="Province is required"
    />
  );
}
HTML
HTML
<div>
  <div class="">
    <div class="Polaris-Labelled__LabelWrapper">
      <div class="Polaris-Label"><label id="PolarisSelect14Label" for="PolarisSelect14" class="Polaris-Label__Text">Province</label></div>
    </div>
    <div class="Polaris-Select Polaris-Select--error"><select id="PolarisSelect14" class="Polaris-Select__Input" aria-invalid="true" aria-describedby="PolarisSelect14Error">
        <option value="Alberta">Alberta</option>
      </select>
      <div class="Polaris-Select__Content" aria-hidden="true"><span class="Polaris-Select__SelectedOption">Alberta</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
            </svg></span></span></div>
      <div class="Polaris-Select__Backdrop"></div>
    </div>
    <div class="Polaris-Labelled__Error">
      <div id="PolarisSelect14Error" class="Polaris-InlineError">
        <div class="Polaris-InlineError__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="M10 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16zM9 9a1 1 0 0 0 2 0V7a1 1 0 1 0-2 0v2zm0 4a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"></path>
            </svg></span></div>Province is required
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Select with separate validation error

セレクトが依存しているフォームインプットのグループのコンテキストで、セレクトの入力が無効な場合にマーチャントに知らせるために使用します。

errorprop がtrueboolean値を持つ場合、セレクトコンポーネントはマーチャントに入力が無効であることを、エラーメッセージを直下に表示することなく示します。これは、フォーム内にインラインのエラーコンポーネントが別途存在することを想定しています。

無効な select とその検証エラーを別々に表示するには、以下のようにします。

  • セレクトコンポーネントのidprop に一意の識別子を設定します。
  • セレクトコンポーネントのerrorprop にboolean値を設定する。
  • 無効なセレクト入力を記述するためにインラインエラーコンポーネントを使用し、そのfieldIDprop にテキストフィールドidに使用されるのと同じ一意の識別子を設定する

React
React
function SeparateValidationErrorExample() {
  const [weight, setWeight] = useState('12');
  const [unit, setUnit] = useState('');

  const handleWeightChange = useCallback((value) => setWeight(value), []);
  const handleUnitChange = useCallback((value) => setUnit(value), []);

  const unitSelectID = 'unit';
  const errorMessage = generateErrorMessage();
  const formGroupMarkup = (
    <Stack vertical spacing="extraTight">
      <FormLayout>
        <FormLayout.Group condensed>
          <TextField
            label="Product weight"
            type="number"
            value={weight}
            onChange={handleWeightChange}
            error={Boolean(!weight && unit)}
            autoComplete="off"
          />
          <Select
            id={unitSelectID}
            label="Unit of measure"
            placeholder="Select"
            options={['oz', 'g', 'kg', 'lb']}
            value={unit}
            onChange={handleUnitChange}
            error={Boolean(!unit && weight)}
          />
        </FormLayout.Group>
      </FormLayout>
      <InlineError message={errorMessage} fieldID={unitSelectID} />
    </Stack>
  );

  return <Card sectioned>{formGroupMarkup}</Card>;

  function generateErrorMessage() {
    const weightError =
      !weight && unit ? 'The numeric weight of the product ' : '';
    const unitError =
      !unit && weight ? 'The unit of measure for the product weight' : '';

    if (!weightError && !unitError) {
      return '';
    }

    return (
      <span>
        <TextStyle variation="negative">
          <p>
            {`${weightError}${unitError} is required when weight based shipping rates are enabled. `}
            <Link>Manage shipping</Link>
          </p>
        </TextStyle>
      </span>
    );
  }
}
HTML
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-Card__Section">
      <div class="Polaris-Stack Polaris-Stack--vertical Polaris-Stack--spacingExtraTight">
        <div class="Polaris-Stack__Item">
          <div class="Polaris-FormLayout">
            <div role="group" class="Polaris-FormLayout--condensed">
              <div class="Polaris-FormLayout__Items">
                <div class="Polaris-FormLayout__Item">
                  <div class="">
                    <div class="Polaris-Labelled__LabelWrapper">
                      <div class="Polaris-Label"><label id="PolarisTextField2Label" for="PolarisTextField2" class="Polaris-Label__Text">Product weight</label></div>
                    </div>
                    <div class="Polaris-Connected">
                      <div class="Polaris-Connected__Item Polaris-Connected__Item--primary">
                        <div class="Polaris-TextField Polaris-TextField--hasValue"><input id="PolarisTextField2" autocomplete="off" class="Polaris-TextField__Input" type="number" aria-labelledby="PolarisTextField2Label" aria-invalid="false" value="12">
                          <div class="Polaris-TextField__Spinner" aria-hidden="true">
                            <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                              <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                                    <path d="m15 12-5-5-5 5h10z"></path>
                                  </svg></span></div>
                            </div>
                            <div role="button" class="Polaris-TextField__Segment" tabindex="-1">
                              <div class="Polaris-TextField__SpinnerIcon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                                    <path d="m5 8 5 5 5-5H5z"></path>
                                  </svg></span></div>
                            </div>
                          </div>
                          <div class="Polaris-TextField__Backdrop"></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
                <div class="Polaris-FormLayout__Item">
                  <div class="">
                    <div class="Polaris-Labelled__LabelWrapper">
                      <div class="Polaris-Label"><label id="unitLabel" for="unit" class="Polaris-Label__Text">Unit of measure</label></div>
                    </div>
                    <div class="Polaris-Select Polaris-Select--error"><select id="unit" class="Polaris-Select__Input" aria-invalid="true" aria-describedby="unitError">
                        <option value="" disabled="">Select</option>
                        <option value="oz">oz</option>
                        <option value="g">g</option>
                        <option value="kg">kg</option>
                        <option value="lb">lb</option>
                      </select>
                      <div class="Polaris-Select__Content" aria-hidden="true"><span class="Polaris-Select__SelectedOption">Select</span><span class="Polaris-Select__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path>
                            </svg></span></span></div>
                      <div class="Polaris-Select__Backdrop"></div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="Polaris-Stack__Item">
          <div id="unitError" class="Polaris-InlineError">
            <div class="Polaris-InlineError__Icon"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
                  <path d="M10 18a8 8 0 1 1 0-16 8 8 0 0 1 0 16zM9 9a1 1 0 0 0 2 0V7a1 1 0 1 0-2 0v2zm0 4a1 1 0 1 0 2 0 1 1 0 0 0-2 0z"></path>
                </svg></span></div><span><span class="Polaris-TextStyle--variationNegative">
                <p>The unit of measure for the product weight is required when weight based shipping rates are enabled. <button type="button" class="Polaris-Link">Manage shipping</button></p>
              </span></span>
          </div>
        </div>
      </div>
    </div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Props

disabled
boolean
入力を無効にする

error
string | ReactElement | (string | ReactElement)[] | boolean
エラー state を表示する

helpText
React.ReactNode
使用時の補助のための追加テキスト

id
string
フォームインプットの ID

label(Required)
React.ReactNode
セレクトのラベル

labelAction
Action
ラベルにアクションを追加する

labelHidden
boolean
ラベルを視覚的に隠す

labelInline
boolean
コントロール内で、値の左側にラベルを表示する

name
string
フォームインプットの名前

options
(string | StrictOption | SelectGroup)[]
選択できるオプションまたはオプショングループのリスト

placeholder
string
プレースホルダーとして表示するテキストの例

requiredIndicator
boolean
視覚的に必要なインジケータ、ラベルにアスタリスクを追加

value
string
フォームインプットの値

onBlur
() => void
フォーカスが外された時のコールバック

onChange
(selected: string, id: string) => void
選択肢が変更された時のコールバック

onFocus
() => void
セレクトがフォーカスされた時のコールバック

Android

Default select

Android のメニューは、ウェブのドロップダウンと似たような動作をします。

Disabled select

現在利用できない選択項目に使用します。周囲のインターフェイスでは、セレクトボックスが無効になっている理由と、有効にする方法を明確にする必要があります。

iOS

Default select

iOS のピッカーはインラインで展開します。マーチャントはスクロールして欲しい商品を選ぶ。

Disabled select

現在利用できない選択項目に使用します。周囲のインターフェイスでは、セレクトボックスが無効になっている理由と、有効にする方法を明確にする必要があります。

ベストプラクティス

セレクトコンポーネントは以下のことに注意してください。

  • あらかじめ定義された 4 つ以上のオプションを選択するために使用される。
  • 可能な限りデフォルトのオプションを選択する。
  • 論理的なデフォルト・オプションがない場合にのみ、プレースホルダー・オプションとしてSelectを使用する。

コンテンツガイドライン

セレクトラベル

ラベルは以下のことに注意してください。

  • 要求された入力内容を簡単に説明してください(1 ~ 3 語)。
  • 文語体(最初の単語は大文字、残りの単語は小文字)で書いてください。
  • 句読点や冠詞("the"、"an"、"a")は避けてください。
  • 独立した文章であること。国際化に対応するため、コンポーネントのオプションで終了する文の最初の部分として機能してはいけません。
  • 説明的ではなく、記述的であること。選択肢の説明が必要な場合は、フィールドの下にヘルプテキストを使用してください。

セレクトオプション

オプションは以下のことに注意してください。

  • デフォルトのオプションがない場合は、Selectで始まります。
  • お客様が必要なオプションを簡単に見つけられるよう、アルファベット順またはその他の論理的な順序で記載する。
  • 文語体(最初の単語は大文字、残りは小文字)で記述し、各オプションの最後にカンマやセミコロンを使用しないでください。
  • オプションが何をするものかを明確に表示する。

関連コンポーネント

  • 選択肢が 4 つ以下のリストからマーチャントに 1 つの選択肢を選ばせるには、choice list コンポーネントを使用します。
  • マーチャントが複数の選択肢を選択できるようにしたり、オプションテキストの高度なフォーマットを可能にするには、popoverの中にoption listを使用します。

Stepper

ステッパーを使って、カウンターフィールドの値を増減させる。

Android

Default stepper

ステッパーには、マイナスボタンとプラスボタンの 2 つのボタンがあります。テキストフィールドにもタップできるようになっています。

Disabled stepper

一番下または一番上の値に達した場合、該当するボタンは無効になります。

ベストプラクティス

  • 値を増減させるものを、変化させる値と密接な関係に置くことで明確にする。
  • 最大値を示す数値表示をステッパーの外側に設けることで、マーチャントが値を覚える必要がなくなります。

コンテンツガイドライン

値を切り捨てないようにしてください。

値を省略することは避け(10k、1m)、代わりにスペースに合わせて文字を小さくする。

関連コンポーネント

Tag

タグは、マーチャントが提供するインタラクティブなキーワードのセットで、オブジェクトのラベル付け、整理、分類に役立ちます。タグはマーチャントがオブジェクトに追加したり削除したりすることができます。

Web

Default tag

オブジェクトの属性を示すために使用します。

React
React
<Tag>Wholesale</Tag>
HTML
HTML
<div><span class="Polaris-Tag"><span title="Wholesale" class="Polaris-Tag__TagText">Wholesale</span></span>
  <div id="PolarisPortalsContainer"></div>
</div>

Removable tag

マーチャントがオブジェクトから属性を削除するために使用します。

React
React
function RemovableTagExample() {
  const [selectedTags, setSelectedTags] = useState([
    'Rustic',
    'Antique',
    'Vinyl',
    'Refurbished',
  ]);

  const removeTag = useCallback(
    (tag) => () => {
      setSelectedTags((previousTags) =>
        previousTags.filter((previousTag) => previousTag !== tag),
      );
    },
    [],
  );

  const tagMarkup = selectedTags.map((option) => (
    <Tag key={option} onRemove={removeTag(option)}>
      {option}
    </Tag>
  ));

  return <Stack spacing="tight">{tagMarkup}</Stack>;
}
HTML
HTML
<div>
  <div class="Polaris-Stack Polaris-Stack--spacingTight">
    <div class="Polaris-Stack__Item"><span class="Polaris-Tag Polaris-Tag--removable"><span title="Rustic" class="Polaris-Tag__TagText">Rustic</span><button type="button" aria-label="Remove Rustic" class="Polaris-Tag__Button"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m11.414 10 4.293-4.293a.999.999 0 1 0-1.414-1.414L10 8.586 5.707 4.293a.999.999 0 1 0-1.414 1.414L8.586 10l-4.293 4.293a.999.999 0 1 0 1.414 1.414L10 11.414l4.293 4.293a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414L11.414 10z"></path>
            </svg></span></button></span></div>
    <div class="Polaris-Stack__Item"><span class="Polaris-Tag Polaris-Tag--removable"><span title="Antique" class="Polaris-Tag__TagText">Antique</span><button type="button" aria-label="Remove Antique" class="Polaris-Tag__Button"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m11.414 10 4.293-4.293a.999.999 0 1 0-1.414-1.414L10 8.586 5.707 4.293a.999.999 0 1 0-1.414 1.414L8.586 10l-4.293 4.293a.999.999 0 1 0 1.414 1.414L10 11.414l4.293 4.293a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414L11.414 10z"></path>
            </svg></span></button></span></div>
    <div class="Polaris-Stack__Item"><span class="Polaris-Tag Polaris-Tag--removable"><span title="Vinyl" class="Polaris-Tag__TagText">Vinyl</span><button type="button" aria-label="Remove Vinyl" class="Polaris-Tag__Button"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m11.414 10 4.293-4.293a.999.999 0 1 0-1.414-1.414L10 8.586 5.707 4.293a.999.999 0 1 0-1.414 1.414L8.586 10l-4.293 4.293a.999.999 0 1 0 1.414 1.414L10 11.414l4.293 4.293a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414L11.414 10z"></path>
            </svg></span></button></span></div>
    <div class="Polaris-Stack__Item"><span class="Polaris-Tag Polaris-Tag--removable"><span title="Refurbished" class="Polaris-Tag__TagText">Refurbished</span><button type="button" aria-label="Remove Refurbished" class="Polaris-Tag__Button"><span class="Polaris-Icon"><span class="Polaris-VisuallyHidden"></span><svg viewBox="0 0 20 20" class="Polaris-Icon__Svg" focusable="false" aria-hidden="true">
              <path d="m11.414 10 4.293-4.293a.999.999 0 1 0-1.414-1.414L10 8.586 5.707 4.293a.999.999 0 1 0-1.414 1.414L8.586 10l-4.293 4.293a.999.999 0 1 0 1.414 1.414L10 11.414l4.293 4.293a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414L11.414 10z"></path>
            </svg></span></button></span></div>
  </div>
  <div id="PolarisPortalsContainer"></div>
</div>

Clickable tag

マーチャントがオブジェクトに属性を追加するために使用します。

React
React
<Tag onClick={() => console.log('Clicked')}>Wholesale</Tag>
HTML
HTML
<div><button type="button" class="Polaris-Tag Polaris-Tag--clickable">Wholesale</button>
  <div id="PolarisPortalsContainer"></div>
</div>

Props

children
string
タグに表示するコンテンツ

disabled
boolean
タグを無効にする

onClick
() => void
タグがクリックされたとき、またはキーが押されたときにコールバックします。設定されている場合は、削除ボタンなしでレンダリングされます。

onRemove
() => void
削除ボタンがクリックされたとき、またはキーが押されたときのコールバックです。

アクセシビリティ

ラベリング

タグを削除するボタンには、aria-labelを用いたラベルが自動的に付与され、スクリーンリーダーのユーザーがどのタグが削除されるかを識別できるようになっています。

キーボード対応

タグを削除するコントロールは、標準的なキーボードサポートを備えたボタンとして実装されています。

  • ボタンにキーボードフォーカスを与えるには、tabキー(逆方向にタブする場合はshifttab)を押します。
  • ボタンを有効にするには、enter/returnまたはspaceキーを押します。

マーチャントがタグを削除するボタンを使用する際には、キーボードフォーカスが管理されていることを確認することが重要です。ページ内の次の要素にフォーカスを移すことが推奨されます。

Android

Default tag

オブジェクトの属性を示すために使用します。

Removable tag

マーチャントがオブジェクトから属性を削除するために使用します。

Clickable tag

マーチャントがオブジェクトに属性を追加するために使用します。

アクセシビリティ

Android のアクセシビリティについては、Material Design と開発ドキュメントをご覧ください。

iOS

Default tag

オブジェクトの属性を示すために使用します。

Removable tag

マーチャントがオブジェクトから属性を削除するために使用します。

Clickable tag

マーチャントがオブジェクトに属性を追加するために使用します。

アクセシビリティ

iOS のアクセシビリティについては、Apple の Human Interface Guidelines や API のドキュメントをご覧ください。

ベストプラクティス

タグは以下のことに注意してください。

  • マーチャントがタグを追加・削除できる入力コントロールの近くまたは内側に表示されること

関連コンポーネント

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Discussion

ログインするとコメントできます