• R/O
  • HTTP
  • SSH
  • HTTPS

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javaandroidc++linuxc#objective-ccocoa誰得qtrubybathyscaphegamephpguiwindowsc翻訳pythonomegattwitterframeworkbtronarduinovb.net計画中(planning stage)directxpreviewertestゲームエンジンdom

コミットメタ情報

リビジョン3774f2dca9ddf61aa42ffad2b85d267189caef20 (tree)
日時2017-09-12 22:46:49
作者HMML <hmml3939@gmai...>
コミッターHMML

ログメッセージ

Transit to bootstrap 4 beta!

変更サマリ

差分

--- a/Gemfile
+++ b/Gemfile
@@ -40,7 +40,7 @@ gem 'responders'
4040 gem 'kaminari'
4141 gem 'kaminari-i18n'
4242 gem 'font-awesome-rails'
43-gem 'bootstrap', '4.0.0.alpha6'
43+gem 'bootstrap', '~> 4.0.0.beta'
4444 gem 'lightbox-bootstrap-rails', '5.1.0.1'
4545 gem 'popper_js'
4646 gem 'tether-rails'
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -66,8 +66,9 @@ GEM
6666 bindex (0.5.0)
6767 binding_of_caller (0.7.2)
6868 debug_inspector (>= 0.0.1)
69- bootstrap (4.0.0.alpha6)
69+ bootstrap (4.0.0.beta)
7070 autoprefixer-rails (>= 6.0.3)
71+ popper_js (~> 1.11.1)
7172 sass (>= 3.4.19)
7273 builder (3.2.3)
7374 byebug (9.1.0)
@@ -265,7 +266,7 @@ GEM
265266 cocaine (~> 0.5.5)
266267 mime-types
267268 mimemagic (~> 0.3.0)
268- popper_js (1.12.3)
269+ popper_js (1.11.1)
269270 pry (0.10.4)
270271 coderay (~> 1.1.0)
271272 method_source (~> 0.8.1)
@@ -459,7 +460,7 @@ PLATFORMS
459460
460461 DEPENDENCIES
461462 awesome_print
462- bootstrap (= 4.0.0.alpha6)
463+ bootstrap (~> 4.0.0.beta)
463464 byebug
464465 cancancan
465466 capistrano-bundler
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -6,6 +6,7 @@
66 @import "lightbox-bootstrap";
77
88 @import "awesome_print";
9+@import "bootstrap4-beta-simpleform-workaround";
910 @import "common";
1011
1112 @import "dist_signals";
--- /dev/null
+++ b/app/assets/stylesheets/bootstrap4-beta-simpleform-workaround.scss
@@ -0,0 +1,19 @@
1+
2+@import 'bootstrap/functions';
3+@import 'bootstrap/variables';
4+@import 'bootstrap/mixins';
5+
6+.has-invalid {
7+ .invalid-feedback {
8+ display: block;
9+ }
10+
11+ label {
12+ color: theme-color('danger');
13+ }
14+
15+ .form-control {
16+ background: theme-color-level('danger', -10);
17+ border-color: theme-color('danger');
18+ }
19+}
--- a/app/assets/stylesheets/welcome.scss
+++ b/app/assets/stylesheets/welcome.scss
@@ -22,7 +22,8 @@
2222 }
2323 p a { color: #9cf; }
2424 .image-container {
25- margin-bottom: 2rem;
25+ padding-bottom: 2rem;
26+ height: 100%;
2627 }
2728 @include media-breakpoint-up(lg) {
2829 .image-container {
@@ -30,8 +31,11 @@
3031 }
3132 }
3233 @include media-breakpoint-down(md) {
34+ .carousel-caption h3 {
35+ font-size: 1.6rem;
36+ }
3337 .image-container {
34- margin-bottom: 10rem;
38+ padding-bottom: 10rem;
3539 padding-left: 0px;
3640 }
3741 }
--- a/app/javascript/components/theme_wizard.jsx
+++ b/app/javascript/components/theme_wizard.jsx
@@ -104,7 +104,7 @@ class TW_Login extends React.Component {
104104 return(
105105 <div>
106106 <div className="card">
107- <div className="card-block">
107+ <div className="card-body">
108108 <h3>ログインの確認</h3>
109109 <p>現在ログインしていません。このまま進めた場合、テーマを匿名で公開できますが、公開されたテーマの修正・削除などは一切できません。
110110 </p>
@@ -139,7 +139,7 @@ class TW_ConfirmRights extends React.Component {
139139 return(
140140 <div>
141141 <div className="card">
142- <div className="card-block">
142+ <div className="card-body">
143143 <h3>最初に権利について確認してください</h3>
144144 <p>
145145 公開テーマとして登録すると、データは誰でもダウンロードできるようになります。
@@ -153,8 +153,8 @@ class TW_ConfirmRights extends React.Component {
153153 </li>
154154 </ul>
155155 <div className="form-group">
156- <div className={`form-check ${this.state.valid ? '' : 'has-danger'}`}>
157- <label className="form-check-label">
156+ <div className="form-check">
157+ <label className={`form-check-label ${this.state.valid ? '' : 'text-danger'}`}>
158158 <input className="form-check-input" type="checkbox"
159159 checked={this.props.theme.rights_confirmed}
160160 onChange={(e) => this.props.updateTheme({rights_confirmed: e.target.checked})} />
@@ -220,14 +220,14 @@ class TW_ThemeInfo extends React.Component {
220220 if (attr == 'name' || attr == 'author')
221221 required = <span><abbr title="required">*</abbr>&nbsp;</span>
222222 inputs.push(
223- <div className={`form-group row ${this.state['valid_'+attr] ? '' : 'has-danger'}`} key={`input-group-${attr}`}>
223+ <div className="form-group row">
224224 <label className="col-md-2 form-control-label string" htmlFor={`theme_${attr}`}>
225225 {required}
226226 {I18n.t(`activerecord.attributes.theme.${attr}`)}</label>
227227 <div className="col-md-10">
228- <input className="form-control string" type="text"
228+ <input className={`form-control string ${this.state['valid_'+attr] ? '' : 'is-invalid'}`} key={`input-group-${attr}`}
229229 placeholder={I18n.t(`simple_formn.placeholders.theme.${attr}`, {default: null})}
230- name={`theme[${attr}]`} id={`theme_${attr}`}
230+ name={`theme[${attr}]`} id={`theme_${attr}`} type="text"
231231 value={this.props.theme[attr]}
232232 onChange={(e) => this.props.updateTheme({[attr]: e.target.value})}
233233 />
@@ -239,7 +239,7 @@ class TW_ThemeInfo extends React.Component {
239239 return(
240240 <div>
241241 <div className="card">
242- <div className="card-block">
242+ <div className="card-body">
243243 <h3>テーマ情報を入力して下さい</h3>
244244 {inputs}
245245 </div>
@@ -323,8 +323,8 @@ class TW_License extends React.Component {
323323 for (let key in cc_conds) {
324324 cc_choosers.push(
325325 <div className="form-group" key={`cc-choice-${key}`}>
326- <div className={`form-check ${this.state.valid_cc ? '' : 'has-danger'}`}>
327- <label className="form-check-label">
326+ <div className="form-check">
327+ <label className={`form-check-label ${this.state.valid_cc ? '' : 'text-danger'}`}>
328328 <input className="form-check-input" type="radio" name="cc" value={key}
329329 checked={this.props.theme.license_cc == key}
330330 onChange={(e) => this.props.updateTheme({license_cc: key})}
@@ -346,21 +346,23 @@ class TW_License extends React.Component {
346346 let other_block = null;
347347 if (this.state.other_checked) {
348348 other_block = <div className="other-block">
349- <div className={`form-group row ${this.state.valid_other ? '' : 'has-danger'}`}>
349+ <div className="form-group row">
350350 <label className="col-2 pl-4 form-control-label string" htmlFor="license_oather">
351351 ライセンス名</label>
352352 <div className="col-10">
353- <input className="form-control string" type="text" id="license_other"
354- placeholder="名称を入力して下さい" value={this.props.theme.license_other}
355- onChange={(e) => this.props.updateTheme({license_other: e.target.value})}
356- />
353+ <input className={`form-control string ${this.state.valid_other ? '' : 'is-invalid'}`}
354+ type="text" id="license_other"
355+ placeholder="名称を入力して下さい" value={this.props.theme.license_other}
356+ onChange={(e) => this.props.updateTheme({license_other: e.target.value})}
357+ />
357358 </div>
358359 </div>
359- <div className={`form-group row ${this.state.valid_other_url ? '' : 'has-danger'}`}>
360+ <div className="form-group row">
360361 <label className="col-2 pl-4 form-control-label string" htmlFor="license_other_url">
361362 ライセンス本文URL</label>
362363 <div className="col-10">
363- <input className="form-control string" type="text" id="license_other_url"
364+ <input className={`form-control string ${this.state.valid_other_url ? '' : 'is-invalid'}`}
365+ type="text" id="license_other_url"
364366 placeholder="ライセンスの紹介・本文・など一次情報のURLを入力して下さい"
365367 value={this.props.theme.license_other_url}
366368 onChange={(e) => this.props.updateTheme({license_other_url: e.target.value})}
@@ -373,13 +375,13 @@ class TW_License extends React.Component {
373375 return(
374376 <div>
375377 <div className="card">
376- <div className="card-block">
378+ <div className="card-body">
377379 <h3>ライセンスの選択</h3>
378380 <p>公開したテーマを利用者がどのように扱えるか選択して下さい。</p>
379381
380382 <div className="form-group">
381- <div className={`form-check ${this.state.valid ? '' : 'has-danger'}`}>
382- <label className="form-check-label">
383+ <div className="form-check">
384+ <label className={`form-check-label ${this.state.valid ? '' : 'text-danger'}`}>
383385 <input className="form-check-input" type="checkbox"
384386 checked={this.props.theme.allow_orig_dl}
385387 onChange={(e) => this.props.updateTheme({allow_orig_dl: e.target.checked})} />
@@ -439,7 +441,7 @@ class TW_Publish extends React.Component {
439441 return (
440442 <div>
441443 <div className="card">
442- <div className="card-block">
444+ <div className="card-body">
443445 <h4>最後のステップです</h4>
444446 <p>公開の準備ができました。以下の情報が間違いない事を確認して、公開するボタンを押して下さい。</p>
445447 <ul>
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -5,6 +5,8 @@ class User < ApplicationRecord
55 # :recoverable, :rememberable, :validatable,
66 devise :trackable, :omniauthable
77
8+ validates :name, presence: true
9+
810 has_many :themes
911
1012 def tw_url?
--- a/app/views/drafts/edit.html.haml
+++ b/app/views/drafts/edit.html.haml
@@ -3,16 +3,16 @@
33 .draft-actions.pull-right.text-right
44 %button.btn.btn-secondary{data: {target: '.draft-basic-into', toggle: 'collapse'}}
55 = fa_icon :info
6- %span.hidden-xs-down= t 'draft_info'
7- %span.hidden-sm-up= t 'draft_info_short'
6+ %span.d-none.d-sm-inline= t 'draft_info'
7+ %span.d-sm-none= t 'draft_info_short'
88 %button.btn.btn-secondary{data: {toggle: 'modal', target: '.preview-info-modal'}}
99 = fa_icon :mobile
10- %span.hidden-xs-down= t 'device_preview'
11- %span.hidden-sm-up= t 'device_preview_short'
10+ %span.d-none.d-sm-inline= t 'device_preview'
11+ %span.d-sm-none= t 'device_preview_short'
1212 .btn-group
1313 %button.btn.btn-primary.dropdown-toggle{data: {toggle: :dropdown}}
14- %span.hidden-xs-down= fa_icon('chevron-circle-right')+' '+t('finish_edit')
15- %span.hidden-sm-up= fa_icon('chevron-circle-right')+' '+t('finish_edit_short')
14+ %span.d-none.d-sm-inline= fa_icon('chevron-circle-right')+' '+t('finish_edit')
15+ %span.d-sm-none= fa_icon('chevron-circle-right')+' '+t('finish_edit_short')
1616 .dropdown-menu.dropdown-menu-right
1717 = link_to fa_icon('chevron-circle-right')+' '+t('start_publish_theme'), new_theme_path(draft_key: @draft.key), class: 'dropdown-item'
1818 .dropdown-divider
@@ -24,7 +24,7 @@
2424
2525 .draft-basic-into.collapse.show
2626 .card
27- .card-block
27+ .card-body
2828 %button.btn.btn-secondary.pull-right{data: {target: '.draft-basic-into', toggle: 'collapse'}}
2929 = t 'dismiss'
3030 %p.card-text=t 'draft_edit_desc_html', plus_icon: fa_icon('plus-circle')
--- a/app/views/layouts/_topnav.html.haml
+++ b/app/views/layouts/_topnav.html.haml
@@ -1,8 +1,8 @@
1-%nav.navbar.navbar-light.bg-faded.sticky-top.navbar-toggleable-md#topnav
2- %button.navbar-toggler.navbar-toggler-right{data: {toggle: :collapse, target: '#topnavbar-nav'}}
3- %span.navbar-toggler-icon
1+%nav.navbar.navbar-light.bg-light.sticky-top.navbar-expand-lg#topnav
42 = link_to image_tag('app-icon.png', size: '30x30', class: 'd-inline-block align-top app-icon') + ' ' + t('site_title'),
53 root_path, class: "navbar-brand"
4+ %button.navbar-toggler{data: {toggle: :collapse, target: '#topnavbar-nav'}}
5+ %span.navbar-toggler-icon
66 .collapse.navbar-collapse#topnavbar-nav
77 %ul.navbar-nav.mr-auto
88 %li.nav-item{class: controller_name == "themes" ? 'active' : ''}
--- a/app/views/themes/index.html.haml
+++ b/app/views/themes/index.html.haml
@@ -9,7 +9,7 @@
99 .card-columns.theme-index
1010 - @themes.each do |theme|
1111 .card{class: theme.day_frame_white? ? 'frame-white' : ''}
12- .card-block.p-1
12+ .card-body.p-1
1313 .icons
1414 - 3.times do |idx|
1515 .day-frame.day-frame-80
--- a/app/views/users/show.html.haml
+++ b/app/views/users/show.html.haml
@@ -12,7 +12,7 @@
1212 .card-columns.theme-index
1313 - @user.themes.each do |theme|
1414 .card{class: theme.day_frame_white? ? 'frame-white' : ''}
15- .card-block.p-1
15+ .card-body.p-1
1616 .icons
1717 - 3.times do |idx|
1818 .day-frame.day-frame-80
--- a/app/views/welcome/index.html.haml
+++ b/app/views/welcome/index.html.haml
@@ -1,4 +1,4 @@
1-.pull-right.hidden-sm-down
1+.pull-right.d-none.d-md-block
22 = link_to image_tag('phone-shot.jpg', class: 'img-fluid'),
33 image_path('phone-shot-full.jpg'),
44 'data-toggle' => 'lightbox', 'data-turbolinks' => 'false'
@@ -36,7 +36,7 @@
3636 %w(1 髪飾り @gull08 https://twitter.com/gull08),
3737 ].each_with_index do |tinfo, idx|
3838 .carousel-item{class: "#{idx == 0 ? 'active' : ''} #{tinfo[0] == '3' ? 'item-white-bg' : ''}"}
39- .image-container.text-center.text-lg-left.w-100
39+ .image-container.text-center.text-lg-left.w-100.d-inline-block
4040 = image_tag "theme-#{tinfo[0]}.png", size: '600x300', class: 'img-fluid mx-1'
4141 .carousel-caption.d-block.text-lg-right
4242 %h3= tinfo[1]
@@ -45,7 +45,7 @@
4545 = link_to tinfo[2], tinfo[3]
4646 = link_to fa_icon(:download) + ' 画像のダウンロード',
4747 builtin_theme_download_path(tinfo[0]),
48- class: 'btn btn-secondary btn-sm d-block d-lg-inline-block',
48+ class: 'btn btn-light btn-sm d-block d-lg-inline-block',
4949 'data-turbolinks' => 'false'
5050 %a.carousel-control-prev{href: '#theme-gallery', data: {slide: 'prev'}}
5151 %span.carousel-control-prev-icon
--- a/config/initializers/simple_form_bootstrap.rb
+++ b/config/initializers/simple_form_bootstrap.rb
@@ -4,7 +4,7 @@ SimpleForm.setup do |config|
44 config.button_class = 'btn btn-primary'
55 config.boolean_label_class = nil
66
7- config.wrappers :vertical_form, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
7+ config.wrappers :vertical_form, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
88 b.use :html5
99 b.use :placeholder
1010 b.optional :maxlength
@@ -15,11 +15,11 @@ SimpleForm.setup do |config|
1515 b.use :label, class: 'form-control-label'
1616
1717 b.use :input, class: 'form-control'
18- b.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
18+ b.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
1919 b.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
2020 end
2121
22- config.wrappers :vertical_file_input, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
22+ config.wrappers :vertical_file_input, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
2323 b.use :html5
2424 b.use :placeholder
2525 b.optional :maxlength
@@ -28,11 +28,11 @@ SimpleForm.setup do |config|
2828 b.use :label, class: 'form-control-label'
2929
3030 b.use :input
31- b.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
31+ b.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
3232 b.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
3333 end
3434
35- config.wrappers :vertical_boolean, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
35+ config.wrappers :vertical_boolean, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
3636 b.use :html5
3737 b.optional :readonly
3838
@@ -40,20 +40,20 @@ SimpleForm.setup do |config|
4040 ba.use :label_input
4141 end
4242
43- b.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
43+ b.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
4444 b.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
4545 end
4646
47- config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
47+ config.wrappers :vertical_radio_and_checkboxes, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
4848 b.use :html5
4949 b.optional :readonly
5050 b.use :label, class: 'form-control-label'
5151 b.use :input
52- b.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
52+ b.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
5353 b.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
5454 end
5555
56- config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'has-danger' do |b|
56+ config.wrappers :horizontal_form, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
5757 b.use :html5
5858 b.use :placeholder
5959 b.optional :maxlength
@@ -65,12 +65,12 @@ SimpleForm.setup do |config|
6565
6666 b.wrapper tag: 'div', class: 'col-9' do |ba|
6767 ba.use :input, class: 'form-control'
68- ba.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
68+ ba.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
6969 ba.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
7070 end
7171 end
7272
73- config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group row', error_class: 'has-danger' do |b|
73+ config.wrappers :horizontal_file_input, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
7474 b.use :html5
7575 b.use :placeholder
7676 b.optional :maxlength
@@ -80,12 +80,12 @@ SimpleForm.setup do |config|
8080
8181 b.wrapper tag: 'div', class: 'col-9' do |ba|
8282 ba.use :input
83- ba.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
83+ ba.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
8484 ba.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
8585 end
8686 end
8787
88- config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'has-danger' do |b|
88+ config.wrappers :horizontal_boolean, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
8989 b.use :html5
9090 b.optional :readonly
9191
@@ -94,12 +94,12 @@ SimpleForm.setup do |config|
9494 ba.use :label_input
9595 end
9696
97- wr.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
97+ wr.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
9898 wr.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
9999 end
100100 end
101101
102- config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group row', error_class: 'has-danger' do |b|
102+ config.wrappers :horizontal_radio_and_checkboxes, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
103103 b.use :html5
104104 b.optional :readonly
105105
@@ -107,12 +107,12 @@ SimpleForm.setup do |config|
107107
108108 b.wrapper tag: 'div', class: 'col-9' do |ba|
109109 ba.use :input
110- ba.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
110+ ba.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
111111 ba.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
112112 end
113113 end
114114
115- config.wrappers :inline_form, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
115+ config.wrappers :inline_form, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
116116 b.use :html5
117117 b.use :placeholder
118118 b.optional :maxlength
@@ -123,22 +123,22 @@ SimpleForm.setup do |config|
123123 b.use :label, class: 'sr-only'
124124
125125 b.use :input, class: 'form-control'
126- b.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
126+ b.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
127127 b.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
128128 end
129129
130- config.wrappers :multi_select, tag: 'div', class: 'form-group', error_class: 'has-danger' do |b|
130+ config.wrappers :multi_select, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
131131 b.use :html5
132132 b.optional :readonly
133133 b.use :label, class: 'form-control-label'
134134 b.wrapper tag: 'div', class: 'form-inline' do |ba|
135135 ba.use :input, class: 'form-control'
136- ba.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
136+ ba.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
137137 ba.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
138138 end
139139 end
140140
141- config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'has-danger' do |b|
141+ config.wrappers :horizontal_multi_select, tag: 'div', class: 'form-group row', error_class: 'has-invalid' do |b|
142142 b.use :html5
143143 b.optional :readonly
144144 b.use :label, class: 'col-3 form-control-label'
@@ -146,7 +146,7 @@ SimpleForm.setup do |config|
146146 b.wrapper tag: 'div', class: 'col-9' do |ba|
147147 ba.wrapper tag: 'div', class: 'form-inline' do |bb|
148148 bb.use :input, class: 'form-control'
149- bb.use :error, wrap_with: { tag: 'span', class: 'form-control-feedback' }
149+ bb.use :error, wrap_with: { tag: 'span', class: 'invalid-feedback' }
150150 bb.use :hint, wrap_with: { tag: 'p', class: 'form-text text-muted' }
151151 end
152152 end