tag:crieit.net,2005:https://crieit.net/tags/SemanticUI/feed 「SemanticUI」の記事 - Crieit Crieitでタグ「SemanticUI」に投稿された最近の記事 2020-07-06T22:33:40+09:00 https://crieit.net/tags/SemanticUI/feed tag:crieit.net,2005:PublicArticle/15996 2020-07-05T23:38:19+09:00 2020-07-06T22:33:40+09:00 https://crieit.net/posts/Semantic-UI-React-Form-Input Semantic UI ReactのForm.Inputとはなんなのか <p><a target="_blank" rel="nofollow noopener" href="https://react.semantic-ui.com/">Semantic UI React</a> を使っていて <code>Input</code> と <code>Form.Input</code> の違いがよくわかっていなかったので、ちゃんと調べてみました。</p> <p>バージョンは次のとおりです。</p> <ul> <li>React: 16.13.1</li> <li>Semantic UI React: 0.88.2</li> </ul> <h2 id="はじめに"><a href="#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB">はじめに</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://react.semantic-ui.com/collections/form/">リファレンス</a> で <code>Form.Input</code> を選択すると書かれている通り、 <code>Form.Input</code> は <code><Form.Field control={Input} /></code> のシンタックスシュガーです。</p> <blockquote> <p>Sugar for <code><Form.Field control={Input} /></code>.</p> </blockquote> <p>さらに <code>From.Field</code> の項目を読むと、次のように書かれています。</p> <blockquote> <p>A field is a form element containing a label and an input.</p> </blockquote> <p>しかし、バリデーションエラー用のLabelも重要な役割を担っているので、 <code>From.Field</code> は次の3つを含む複合コンポーネントだと捉えた方が良いでしょう <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> 。</p> <ul> <li>項目名を表すlabel</li> <li>メインの入力欄であるInput</li> <li>バリデーションエラー用のLabel</li> </ul> <p>さて、 <code>Form.Field</code> の中身を記述する方法は、大きく分けて次の2つがあります。</p> <ul> <li><code>control</code> を指定する方法( <code>Form.Input</code> を使ったときに発生)</li> <li><code>children</code> (子要素)を指定する方法</li> </ul> <p>個人的には後者の方が暗黙的な挙動が少なくて好きですが、前者の方が記述は楽です。<br /> この記事では、同じDOM構造を実現するための2種類の書き方を比較することで、 <code>Form.Input</code> を使った場合に行われることを理解します。</p> <h2 id="2種類の記述方法を比較する"><a href="#2%E7%A8%AE%E9%A1%9E%E3%81%AE%E8%A8%98%E8%BF%B0%E6%96%B9%E6%B3%95%E3%82%92%E6%AF%94%E8%BC%83%E3%81%99%E3%82%8B">2種類の記述方法を比較する</a></h2> <p>ここでは次の2つの記述方法でほぼ同じDOM構造を実現します。</p> <ol> <li><code>Form.Input</code> のみを使う</li> <li><code>Form.Field</code> の子要素に <code>Input</code> を含める</li> </ol> <p>ソースコードは次の通りです。</p> <pre><code class="js">import React, { useState } from "react"; import { Form, Input, Label } from "semantic-ui-react"; const FormExampleFieldError = () => { const [firstName, setFirstName] = useState(""); const handleChange = e => { setFirstName(e.target.value); }; const error = firstName === "" ? "First name is required" : undefined; return ( <Form> {/* 1. Form.Inputのみを使う */} <Form.Input type="text" name="firstName" id="input1-firstName" placeholder="First name" value={firstName} onChange={handleChange} label="First name" error={error} /> {/* 2. Form.Fieldの子要素にInputを含める */} <Form.Field error={!!error}> <label htmlFor="input2-firstName">First name</label> <Input type="text" name="firstName" id="input2-firstName" placeholder="First name" value={firstName} onChange={handleChange} aria-describedby={error && "input2-firstName-error-message"} aria-invalid={!!error} /> {error && ( <Label prompt pointing="above" id="input2-firstName-error-message" role="alert" aria-atomic > {error} </Label> )} </Form.Field> </Form> ); }; export default FormExampleFieldError; </code></pre> <h3 id="レンダリング結果: エラー無しの場合"><a href="#%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E7%B5%90%E6%9E%9C%3A+%E3%82%A8%E3%83%A9%E3%83%BC%E7%84%A1%E3%81%97%E3%81%AE%E5%A0%B4%E5%90%88">レンダリング結果: エラー無しの場合</a></h3> <p>エラーが無い場合、レンダリング結果は次のようになりました。同等のDOM構造になっていることがわかります。なお <code>aria-invalid="false"</code> はデフォルト値なので、属性が無いのと同じ意味です。</p> <pre><code class="html"><form class="ui form"> <!-- 1. Form.Inputのみを使う --> <div class="field"><label for="input1-firstName">First name</label> <div class="ui input"><input name="firstName" placeholder="First name" id="input1-firstName" type="text" value="a"></div> </div> <!-- 2. Form.Fieldの子要素にInputを含める --> <div class="field"><label for="input2-firstName">First name</label> <div class="ui input"><input name="firstName" id="input2-firstName" placeholder="First name" aria-invalid="false" type="text" value="a"></div> </div> </form> </code></pre> <h3 id="レンダリング結果: エラー有りの場合"><a href="#%E3%83%AC%E3%83%B3%E3%83%80%E3%83%AA%E3%83%B3%E3%82%B0%E7%B5%90%E6%9E%9C%3A+%E3%82%A8%E3%83%A9%E3%83%BC%E6%9C%89%E3%82%8A%E3%81%AE%E5%A0%B4%E5%90%88">レンダリング結果: エラー有りの場合</a></h3> <p>エラーが有る場合、レンダリング結果は次のようになりました。こちらも同等のDOM構造になっています。 <code>Form.Input</code> を使うと、 <code>aria-invalid</code> や <code>aria-describedby</code> などのアクセシビリティ関連の属性が自動で追加されていることがわかります。</p> <pre><code class="html"><form class="ui form"> <!-- 1. Form.Inputのみを使う --> <div class="error field"><label for="input1-firstName">First name</label> <div class="ui input"><input aria-describedby="input1-firstName-error-message" aria-invalid="true" name="firstName" placeholder="First name" id="input1-firstName" type="text" value=""></div> <div class="ui pointing above prompt label" id="input1-firstName-error-message" role="alert" aria-atomic="true"> First name is required</div> </div> <!-- 2. Form.Fieldの子要素にInputを含める --> <div class="error field"><label for="input2-firstName">First name</label> <div class="ui input"><input name="firstName" id="input2-firstName" placeholder="First name" aria-describedby="input2-firstName-error-message" aria-invalid="true" type="text" value=""></div> <div id="input2-firstName-error-message" role="alert" aria-atomic="true" class="ui pointing above prompt label"> First name is required</div> </div> </form> </code></pre> <h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2> <p>Semantic UI Reactでは、 <code>Form.Input</code> を使うことで、少ない記述で次の3要素を持つ入力欄を作成できます。</p> <ul> <li>項目名を表すlabel</li> <li>メインの入力欄であるInput</li> <li>バリデーションエラー用のLabel</li> </ul> <p>特にバリデーションエラーの表示は自前で記述するとそれなりに大変なので、積極的に使っていきたいです。</p> <h2 id="参考"><a href="#%E5%8F%82%E8%80%83">参考</a></h2> <ul> <li><a target="_blank" rel="nofollow noopener" href="https://github.com/Semantic-Org/Semantic-UI-React/blob/v0.88.2/src/collections/Form/FormField.js">Form.Fieldのソースコード</a></li> </ul> <h2 id="おまけ: 子要素にinputを含めた場合"><a href="#%E3%81%8A%E3%81%BE%E3%81%91%3A+%E5%AD%90%E8%A6%81%E7%B4%A0%E3%81%ABinput%E3%82%92%E5%90%AB%E3%82%81%E3%81%9F%E5%A0%B4%E5%90%88">おまけ: 子要素にinputを含めた場合</a></h2> <p><a target="_blank" rel="nofollow noopener" href="https://react.semantic-ui.com/collections/form/">リファレンス</a> に書かれているように、 <code>Form.Field</code> には <code>Input</code> の代わりに、HTMLの <code>input</code> 要素を含めることもできます。この場合、若干異なるDOM構造が生成されるものの、見た目は同じになりました。DOM構造の差異は、inputが <code><div class="ui input"></code> によって囲まれない点だけです。</p> <p>ソース</p> <pre><code class="js"> {/* 3. Form.Fieldの子要素にhtmlのinputを含める */} <Form.Field error={error}> <label htmlFor="input3-firstName">First name</label> <input type="text" name="firstName" id="input3-firstName" placeholder="First name" value={firstName} onChange={handleChange} aria-describedby={error && "input3-firstName-error-message"} aria-invalid={!!error} /> {error && ( <Label prompt pointing="above" id="input3-firstName-error-message" role="alert" aria-atomic > {error} </Label> )} </Form.Field> </code></pre> <p>レンダリング結果: エラー無しの場合</p> <pre><code class="html"> <!-- 3. Form.Fieldの子要素にhtmlのinputを含める --> <div class="field"><label for="input3-firstName">First name</label><input type="text" name="firstName" id="input3-firstName" placeholder="First name" aria-invalid="false" value="a"></div> </code></pre> <p>レンダリング結果: エラー有りの場合</p> <pre><code class="html"> <!-- 3. Form.Fieldの子要素にhtmlのinputを含める --> <div class="error field"><label for="input3-firstName">First name</label><input type="text" name="firstName" id="input3-firstName" placeholder="First name" aria-describedby="input3-firstName-error-message" aria-invalid="true" value=""> <div id="input3-firstName-error-message" role="alert" aria-atomic="true" class="ui pointing above prompt label"> First name is required</div> </div> </code></pre> <p>エラーの有無にかかわらず、見た目では区別がつきません。</p> <p><a href="https://crieit.now.sh/upload_images/5a11f6f3844392eef8bb653508a390ab5f01e4095de34.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5a11f6f3844392eef8bb653508a390ab5f01e4095de34.png?mw=700" alt="エラーが無い場合の見た目" /></a></p> <p><a href="https://crieit.now.sh/upload_images/5a11f6f3844392eef8bb653508a390ab5f01e43621baf.png" target="_blank" rel="nofollow noopener"><img src="https://crieit.now.sh/upload_images/5a11f6f3844392eef8bb653508a390ab5f01e43621baf.png?mw=700" alt="エラーが有る場合の見た目" /></a></p> <hr /> <div class="footnotes" role="doc-endnotes"> <hr /> <ol> <li id="fn:1" role="doc-endnote"> <p>Material UIの <a target="_blank" rel="nofollow noopener" href="https://material-ui.com/components/text-fields/">TextField</a> と同じようなイメージです。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p> </li> </ol> </div> かと tag:crieit.net,2005:PublicArticle/14718 2019-01-12T16:24:34+09:00 2019-01-29T00:13:24+09:00 https://crieit.net/posts/SemanticUI SemanticUIでイマドキの横スクロールを実現する <p><a target="_blank" rel="nofollow noopener" href="https://semantic-ui.com">SemanticUI</a>が好きでずっと使っています。</p> <p>特に<a target="_blank" rel="nofollow noopener" href="https://semantic-ui.com/views/card.html">Card component</a>は使い勝手がよく、しょっちゅうお世話になるのですが、これをイマドキの横スクロールで使いたい。</p> <p>というわけで数行のCSS魔改造で実現してみるという小ネタです。</p> <hr /> <h2 id="完成品はこちら"><a href="#%E5%AE%8C%E6%88%90%E5%93%81%E3%81%AF%E3%81%93%E3%81%A1%E3%82%89">完成品はこちら</a></h2> <p>CodePENに上げてるのでよければ見てみてください。</p> <p data-height="329" data-theme-id="0" data-slug-hash="PXxJyd" data-default-tab="css,result" data-user="tomomichi" data-pen-title="Horizontal Scrollable Cards with Semantic UI " data-preview="true" class="codepen">See the Pen <a target="_blank" rel="nofollow noopener" href="https://codepen.io/tomomichi/pen/PXxJyd/">Horizontal Scrollable Cards with Semantic UI </a> by o_tomomichi (<a target="_blank" rel="nofollow noopener" href="https://codepen.io/tomomichi">@tomomichi</a>) on <a target="_blank" rel="nofollow noopener" href="https://codepen.io">CodePen</a>.</p> <h2 id="やってること"><a href="#%E3%82%84%E3%81%A3%E3%81%A6%E3%82%8B%E3%81%93%E3%81%A8">やってること</a></h2> <p>デフォルトのCards componentに、独自のscrollingクラスをつけています。<br /> HTML側でいじってるのはこれだけ。</p> <p>あとはスマホサイズのときのみscrolling内のcardが横スクロールするよう、CSSを上書きしています。<br /> 元のCSSがflexを設定してるので、no-wrapにしてる感じです。</p> <hr /> <h2 id="まとめ"><a href="#%E3%81%BE%E3%81%A8%E3%82%81">まとめ</a></h2> <p>という感じでイマドキの横スクロールUIができました。</p> <p>これが本当に使いやすいかどうかは議論の余地ありですが、個人的にはけっこう好きです。<br /> (あんまり数が多いと絶対見ないので、多くても5〜6個くらいまでが使いどころじゃないかと)</p> <p>SemanticUI、とてもよいのでよければ使ってみてください。<br /> おしまい。</p> ほげにし