sdr_view_components 0.1.14 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +55 -38
- data/app/assets/sdr_view_components.css +110 -0
- data/app/components/sdr_view_components/elements/heading_component.rb +3 -1
- data/app/components/sdr_view_components/elements/icon_button_component.rb +10 -0
- data/app/components/sdr_view_components/elements/spinner_component.html.erb +2 -2
- data/app/components/sdr_view_components/elements/spinner_component.rb +5 -4
- data/app/components/sdr_view_components/elements/tabs/pane_component.html.erb +3 -0
- data/app/components/sdr_view_components/elements/tabs/pane_component.rb +27 -0
- data/app/components/sdr_view_components/elements/tabs/tab_component.html.erb +3 -0
- data/app/components/sdr_view_components/elements/tabs/tab_component.rb +42 -0
- data/app/components/sdr_view_components/elements/tabs/tab_list_component.html.erb +9 -0
- data/app/components/sdr_view_components/elements/tabs/tab_list_component.rb +33 -0
- data/app/components/sdr_view_components/elements/toast_component.rb +1 -1
- data/app/components/sdr_view_components/tables/base_table_component.html.erb +32 -0
- data/app/components/sdr_view_components/tables/base_table_component.rb +69 -0
- data/app/components/sdr_view_components/tables/cell_component.html.erb +3 -0
- data/app/components/sdr_view_components/tables/cell_component.rb +21 -0
- data/app/components/sdr_view_components/tables/header_component.html.erb +4 -0
- data/app/components/sdr_view_components/tables/header_component.rb +22 -0
- data/app/components/sdr_view_components/tables/list_cell_component.html.erb +5 -0
- data/app/components/sdr_view_components/tables/list_cell_component.rb +22 -0
- data/app/components/sdr_view_components/tables/raw_table_component.rb +10 -0
- data/app/components/sdr_view_components/tables/row_component.html.erb +24 -0
- data/app/components/sdr_view_components/tables/row_component.rb +32 -0
- data/app/components/sdr_view_components/tables/table_component.rb +10 -0
- data/app/views/layouts/lookbook.html.erb +46 -0
- data/lib/sdr_view_components/configuration.rb +22 -0
- data/lib/sdr_view_components/engine.rb +17 -7
- data/lib/sdr_view_components/error.rb +7 -0
- data/lib/sdr_view_components/version.rb +1 -1
- data/lib/sdr_view_components.rb +2 -0
- metadata +25 -6
- data/app/assets/stylesheets/styles.scss +0 -118
- data/app/components/component_support/file_hierarchy.rb +0 -22
- data/app/components/sdr_view_components/forms/button_component.rb +0 -42
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cbfc52ae67fecdff708f4696aaa7092396da6dff749264858c11dbbfbe8a4382
|
|
4
|
+
data.tar.gz: 32a60c51ecd3fdb27a1ef011ad8fbaee64053f956e66d0d3d42c51fd36801f78
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0f7f24fc7019c867299b390b5ae6dff1a93fc7b41f66a5075f473b5ebd69061d7cd4f44f92480b6e3337f26ac2683b5b48260580bbc11aa72b9007a910884c11
|
|
7
|
+
data.tar.gz: bbca5c2fc24924a8df4e40a706140b568502bf4816b3e2a43840614d201c28d849d1e2374febb56d9b4656f4ae6a0d8cd28e13750fcc5c94da0685dc78305161
|
data/README.md
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
# SdrViewComponents
|
|
6
6
|
|
|
7
|
-
A rails gem to provide reusable view components used throughout the SDR applications and implement
|
|
8
|
-
component library assets.
|
|
7
|
+
A rails gem to provide reusable view components used throughout the SDR applications and implement component library assets.
|
|
9
8
|
|
|
10
9
|
# Installation
|
|
11
10
|
|
|
@@ -21,48 +20,13 @@ This set of components relies on the component library stylesheets, add:
|
|
|
21
20
|
|
|
22
21
|
```
|
|
23
22
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/sul-dlss/component-library@v2025-09-11/styles/sul.css">
|
|
23
|
+
<%= stylesheet_link_tag "sdr_view_components", "data-turbo-track": "reload" %>
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
with the most recent date tagged release to your `application.html.erb` layout file.
|
|
27
27
|
|
|
28
28
|
## Usage
|
|
29
29
|
|
|
30
|
-
### Add the SUL Header to your application
|
|
31
|
-
|
|
32
|
-
Supported header variations are `:dark`, `:light`, and `:white` (default is `:light`)
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
<%= render SdrViewComponents::Structure::HeaderComponent.new(title: 'Test Header', subtitle: 'Test Subtitle', variant: :dark) do |header| %>
|
|
36
|
-
<% header.with_primary_navigation_link do %>
|
|
37
|
-
<%= render SdrViewComponents::Elements::Navigation::NavItemComponent.new(text: 'Home', path: '#') %>
|
|
38
|
-
<% end %>
|
|
39
|
-
<% header.with_primary_navigation_link do %>
|
|
40
|
-
<%= render SdrViewComponents::Elements::Navigation::DropdownMenuComponent.new(text: 'Logged in: amcollie-preview-dropdown') do |dropdown| %>
|
|
41
|
-
<% dropdown.with_item do %>
|
|
42
|
-
<%= link_to 'Logout', '/Shibboleth.sso/Logout', class: 'dropdown-item' %>
|
|
43
|
-
<% end %>
|
|
44
|
-
<% end %>
|
|
45
|
-
<%# ... all primary nav links %>
|
|
46
|
-
<% end %>
|
|
47
|
-
<% header.with_secondary_navigation_link do %>
|
|
48
|
-
<%= render SdrViewComponents::Elements::Navigation::NavItemComponent.new(text: 'Option', path: '/item1') %>
|
|
49
|
-
<%# ... all secondary nav links>
|
|
50
|
-
<% end %>
|
|
51
|
-
<% end %>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
The `:dark` variation supports providing an rgb value via the `background_color` param in order to override the default dark background, for example:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
<%= render SdrViewComponents::Structure::HeaderComponent.new(title: 'Test Header', subtitle: 'Test Subtitle', variant: :dark, rgb_color_str: '1, 104, 149') do |header| %>
|
|
58
|
-
|
|
59
|
-
...
|
|
60
|
-
|
|
61
|
-
<% end %>
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
By default, the SUL Rosette is included in the header, this can be disabled by setting `rosette: false` in the parameter list when instantiating the header.
|
|
65
|
-
|
|
66
30
|
### Form components
|
|
67
31
|
|
|
68
32
|
SdrViewComponents provides a wrapper for several [ActionView::Helper::Tags](https://api.rubyonrails.org/v8.1.1/classes/ActionView/Helpers/Tags.html).
|
|
@@ -113,3 +77,56 @@ At a minimum, each of these components must be provided wih the `form:` and `fie
|
|
|
113
77
|
```
|
|
114
78
|
<% render SdrViewComponent::....>
|
|
115
79
|
```
|
|
80
|
+
|
|
81
|
+
## Component library version
|
|
82
|
+
The [component-library](https://github.com/sul-dlss/component-library/) version is set in `lib/sdr_view_components/configuration.rb`.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
def initialize
|
|
86
|
+
# Default URL for the component library assets
|
|
87
|
+
@component_library_url = 'https://cdn.jsdelivr.net/gh/sul-dlss/component-library@v2026-01-27'
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Lookbook
|
|
92
|
+
|
|
93
|
+
[Lookbook](https://lookbook.build/) provides a component browser for the components.
|
|
94
|
+
|
|
95
|
+
### Creating previews
|
|
96
|
+
For a component to appear in Lookbook, it must have a preview. See `spec/components/previews/sdr_view_components`
|
|
97
|
+
|
|
98
|
+
Previews can easily be created with the `viewComponentPreview` prompt. For example: `/viewComponentPreview SpinnerComponent`.
|
|
99
|
+
|
|
100
|
+
### Running locally
|
|
101
|
+
|
|
102
|
+
`bin/rails s`
|
|
103
|
+
|
|
104
|
+
Lookbook will then be available at: http://localhost:3000/lookbook
|
|
105
|
+
|
|
106
|
+
### Adding to another app
|
|
107
|
+
|
|
108
|
+
When performing development in an app that is using SdrViewComponents, it may be helpful to be running Lookbook in that app (instead of having to run a separate local instance of it).
|
|
109
|
+
|
|
110
|
+
To run Lookbook in that app:
|
|
111
|
+
1. Add Lookbook to `Gemfile.rb`:
|
|
112
|
+
```
|
|
113
|
+
group :development do
|
|
114
|
+
gem 'lookbook'
|
|
115
|
+
end
|
|
116
|
+
```
|
|
117
|
+
2. Add routes to `routes.rb`:
|
|
118
|
+
```
|
|
119
|
+
if Rails.env.development?
|
|
120
|
+
mount SdrViewComponents::Engine => '/sdr_view_components'
|
|
121
|
+
mount Lookbook::Engine, at: '/lookbook'
|
|
122
|
+
end
|
|
123
|
+
```
|
|
124
|
+
3. Add `config/initializers/sdr_view_components.rb`:
|
|
125
|
+
```
|
|
126
|
+
SdrViewComponents.configure do |config|
|
|
127
|
+
config.component_library_url = Settings.component_library.url
|
|
128
|
+
end
|
|
129
|
+
```
|
|
130
|
+
It is recommended to change the component library URL to a configuration in the app instead of hardcoding in layouts.
|
|
131
|
+
|
|
132
|
+
When your app is running locally, Lookbook will be available at: http://localhost:3000/lookbook
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/* Header */
|
|
2
|
+
.masthead {
|
|
3
|
+
color: white;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.masthead h1,
|
|
7
|
+
.masthead .h1 {
|
|
8
|
+
font-size: 2.25rem;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/* Toggle */
|
|
12
|
+
.btn-group-toggle label.btn {
|
|
13
|
+
--bs-btn-focus-box-shadow: 0 0 0 0.25rem rgb(var(--bs-btn-focus-shadow-rgb), .5);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.btn-group-toggle input:checked + label {
|
|
17
|
+
background-color: var(--bs-primary);
|
|
18
|
+
border-color: var(--bs-primary);
|
|
19
|
+
color: #fff;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.btn-group-toggle input:not(:checked) + label {
|
|
23
|
+
background-color: transparent;
|
|
24
|
+
border-color: var(--bs-primary);
|
|
25
|
+
color: var(--bs-primary);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.btn-group-toggle .btn-check:checked + .btn {
|
|
29
|
+
background-color: var(--stanford-digital-blue);
|
|
30
|
+
border-color: var(--stanford-digital-blue);
|
|
31
|
+
color: #fff;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.btn-group-toggle :not(.btn-check:checked) + .btn {
|
|
35
|
+
color: var(--stanford-digital-blue);
|
|
36
|
+
border-color: var(--stanford-digital-blue);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.btn-group-toggle input:checked + label::before {
|
|
40
|
+
display: inline-block;
|
|
41
|
+
margin-right: 3px;
|
|
42
|
+
font-family: bootstrap-icons;
|
|
43
|
+
vertical-align: -15%;
|
|
44
|
+
content: "\F633";
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/* Banner */
|
|
48
|
+
.banner.alert a.btn-primary {
|
|
49
|
+
color: white;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Forms */
|
|
53
|
+
.form-control,
|
|
54
|
+
.form-select,
|
|
55
|
+
.form-check-input {
|
|
56
|
+
border-color: var(--stanford-60-black);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* Tabs */
|
|
60
|
+
.nav-underline {
|
|
61
|
+
border-bottom: 1px solid black;
|
|
62
|
+
margin-bottom: 10px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.nav-underline .nav-link {
|
|
66
|
+
width: 10.5rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.nav-underline .nav-link:not(.active) {
|
|
70
|
+
color: rgba(var(--bs-link-color-rgb), var(--bs-link-opacity, 1));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.nav-underline .nav-link.active {
|
|
74
|
+
border-bottom: 3px solid #B1040E;
|
|
75
|
+
color: #B1040E;
|
|
76
|
+
font-weight: bold;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Tables */
|
|
80
|
+
table.table-h3 caption {
|
|
81
|
+
padding: .25rem;
|
|
82
|
+
font-size: 1.5rem;
|
|
83
|
+
font-weight: 600;
|
|
84
|
+
line-height: 1.5;
|
|
85
|
+
color: var(--stanford-black);
|
|
86
|
+
caption-side: top;
|
|
87
|
+
border-bottom: 1px solid var(--stanford-black);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
table.table-h3 th {
|
|
91
|
+
font-size: 1.0rem;
|
|
92
|
+
font-weight: 600;
|
|
93
|
+
color: var(--stanford-black);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
table.table-h3 tr {
|
|
97
|
+
border-color: var(--stanford-30-black);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/* Item lists */
|
|
101
|
+
table.table-h3 .list-unstyled {
|
|
102
|
+
list-style: none;
|
|
103
|
+
margin-left: 0;
|
|
104
|
+
padding-left: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
table.table-data th {
|
|
108
|
+
width: fit-content;
|
|
109
|
+
white-space: nowrap;
|
|
110
|
+
}
|
|
@@ -20,7 +20,9 @@ module SdrViewComponents
|
|
|
20
20
|
|
|
21
21
|
# Renders the component without the need for a .erb partial.
|
|
22
22
|
def call
|
|
23
|
-
|
|
23
|
+
return unless tag.respond_to?(@level)
|
|
24
|
+
|
|
25
|
+
tag.public_send(@level, class: classes) do
|
|
24
26
|
@text || content
|
|
25
27
|
end
|
|
26
28
|
end
|
|
@@ -12,6 +12,10 @@ module SdrViewComponents
|
|
|
12
12
|
super()
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
+
def before_render
|
|
16
|
+
raise SdrViewComponents::Error::UnknownComponentIcon, "Unknown icon type: #{@icon}" unless button_icon?
|
|
17
|
+
end
|
|
18
|
+
|
|
15
19
|
attr_reader :label, :options
|
|
16
20
|
|
|
17
21
|
def classes
|
|
@@ -21,6 +25,12 @@ module SdrViewComponents
|
|
|
21
25
|
def button_icon
|
|
22
26
|
helpers.public_send(:"#{@icon}_icon")
|
|
23
27
|
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def button_icon?
|
|
32
|
+
helpers.respond_to?(:"#{@icon}_icon")
|
|
33
|
+
end
|
|
24
34
|
end
|
|
25
35
|
end
|
|
26
36
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<%= tag.div class: classes do %>
|
|
2
2
|
<% if image_path %>
|
|
3
|
-
<%= tag.img src: image_path, alt: 'Spinner', class: spinner_classes, role: 'status', style: spinner_style, **
|
|
3
|
+
<%= tag.img src: image_path, alt: 'Spinner', class: spinner_classes, role: 'status', style: spinner_style, **spinner_options %>
|
|
4
4
|
<% else %>
|
|
5
|
-
<%= tag.div class: spinner_classes, role: 'status', style: spinner_style, **
|
|
5
|
+
<%= tag.div class: spinner_classes, role: 'status', style: spinner_style, **spinner_options %>
|
|
6
6
|
<% end %>
|
|
7
7
|
<%= tag.div class: message_classes do %><%= message %><% end %>
|
|
8
8
|
<% end %>
|
|
@@ -6,7 +6,7 @@ module SdrViewComponents
|
|
|
6
6
|
class SpinnerComponent < BaseComponent
|
|
7
7
|
def initialize(message: 'Loading...', message_classes: [], message_position: :right, hide_message: false, # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
|
8
8
|
image_path: nil, variant: nil, classes: [],
|
|
9
|
-
height: nil, width: nil, speed: 0.75, **
|
|
9
|
+
height: nil, width: nil, speed: 0.75, spinner_classes: ['mx-2'], **spinner_options)
|
|
10
10
|
@message = message
|
|
11
11
|
@variant = variant
|
|
12
12
|
@hide_message = hide_message
|
|
@@ -16,15 +16,16 @@ module SdrViewComponents
|
|
|
16
16
|
@width = width
|
|
17
17
|
@message_classes = message_classes
|
|
18
18
|
@speed = speed # In seconds, so a larger number is slower. The default (0.75) is the same as Bootstrap's default.
|
|
19
|
-
@
|
|
19
|
+
@spinner_classes = spinner_classes
|
|
20
|
+
@spinner_options = spinner_options
|
|
20
21
|
@message_position = message_position # :bottom or :right
|
|
21
22
|
super()
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
attr_reader :message, :image_path, :
|
|
25
|
+
attr_reader :message, :image_path, :spinner_options
|
|
25
26
|
|
|
26
27
|
def spinner_classes
|
|
27
|
-
merge_classes('spinner-border', variant_class, border_class,
|
|
28
|
+
merge_classes('spinner-border', variant_class, border_class, @spinner_classes)
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
def message_classes
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Elements
|
|
5
|
+
module Tabs
|
|
6
|
+
# Component for rendering a tab pane in a tabbed interface.
|
|
7
|
+
class PaneComponent < BaseComponent
|
|
8
|
+
def initialize(id:, tab_id:, active: false)
|
|
9
|
+
@id = id
|
|
10
|
+
@tab_id = tab_id
|
|
11
|
+
@active = active
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :id, :tab_id
|
|
16
|
+
|
|
17
|
+
def active?
|
|
18
|
+
@active
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def classes
|
|
22
|
+
merge_classes(%w[tab-pane fade], active? ? %w[show active] : nil)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Elements
|
|
5
|
+
module Tabs
|
|
6
|
+
# Component for rendering a tab in a tabbed interface.
|
|
7
|
+
class TabComponent < BaseComponent
|
|
8
|
+
def initialize(label:, id:, pane_id:, active: false, variant: :underline)
|
|
9
|
+
@label = label
|
|
10
|
+
@id = id
|
|
11
|
+
@pane_id = pane_id
|
|
12
|
+
@active = active
|
|
13
|
+
@variant = variant
|
|
14
|
+
|
|
15
|
+
raise ArgumentError, "Invalid variant: #{variant}" unless %i[underline default].include?(variant)
|
|
16
|
+
|
|
17
|
+
super()
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
attr_reader :label, :id, :pane_id, :variant
|
|
21
|
+
|
|
22
|
+
def active?
|
|
23
|
+
@active
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def classes
|
|
27
|
+
merge_classes('nav', variant_classes)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def button_classes
|
|
31
|
+
merge_classes('nav-link', active? ? 'active' : nil)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
private
|
|
35
|
+
|
|
36
|
+
def variant_classes
|
|
37
|
+
'nav-underline' if variant == :underline
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Elements
|
|
5
|
+
module Tabs
|
|
6
|
+
# Component for rendering a list of tabs in a tabbed interface.
|
|
7
|
+
class TabListComponent < BaseComponent
|
|
8
|
+
renders_one :header # optional
|
|
9
|
+
renders_many :tabs, Elements::Tabs::TabComponent
|
|
10
|
+
renders_many :panes, Elements::Tabs::PaneComponent
|
|
11
|
+
|
|
12
|
+
def initialize(classes: [], variant: :default)
|
|
13
|
+
@classes = classes
|
|
14
|
+
@variant = variant
|
|
15
|
+
|
|
16
|
+
raise ArgumentError, "Invalid variant: #{variant}" unless %i[underline default].include?(variant)
|
|
17
|
+
|
|
18
|
+
super()
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def classes
|
|
22
|
+
merge_classes('nav', @classes, variant_classes)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def variant_classes
|
|
28
|
+
'nav-underline' if @variant == :underline
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<% @table_content = capture do %>
|
|
2
|
+
<%= tag.table class: classes, 'aria-label': label, **@table_options do %>
|
|
3
|
+
<% if show_label? %>
|
|
4
|
+
<caption><%= label || caption %></caption>
|
|
5
|
+
<% end %>
|
|
6
|
+
<% if headers? %>
|
|
7
|
+
<%= tag.thead class: head_classes do %>
|
|
8
|
+
<tr>
|
|
9
|
+
<% headers.each do |header| %>
|
|
10
|
+
<%= header %>
|
|
11
|
+
<% end %>
|
|
12
|
+
</tr>
|
|
13
|
+
<% end %>
|
|
14
|
+
<% end %>
|
|
15
|
+
<%= tag.tbody class: body_classes do %>
|
|
16
|
+
<% rows.each do |row| %>
|
|
17
|
+
<%= row %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% if empty_message && !rows? %>
|
|
22
|
+
<p class="fst-italic"><%= empty_message %></p>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% end %>
|
|
25
|
+
|
|
26
|
+
<% if responsive? %>
|
|
27
|
+
<%= tag.div class: 'table-responsive' do %>
|
|
28
|
+
<%= @table_content %>
|
|
29
|
+
<% end %>
|
|
30
|
+
<% else %>
|
|
31
|
+
<%= @table_content %>
|
|
32
|
+
<% end %>
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Tables
|
|
5
|
+
# Base component for rendering a table.
|
|
6
|
+
class BaseTableComponent < BaseComponent
|
|
7
|
+
renders_many :headers, SdrViewComponents::Tables::HeaderComponent
|
|
8
|
+
renders_one :caption
|
|
9
|
+
# Subclasses should provide rows, e.g., renders_many :rows
|
|
10
|
+
|
|
11
|
+
def initialize(label: nil, classes: [], head_classes: [], body_classes: [], show_label: true, # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
|
12
|
+
empty_message: nil, responsive: false, variant: :h3, **table_options)
|
|
13
|
+
@classes = classes
|
|
14
|
+
@body_classes = body_classes
|
|
15
|
+
@label = label
|
|
16
|
+
@show_label = show_label
|
|
17
|
+
@empty_message = empty_message
|
|
18
|
+
@head_classes = head_classes
|
|
19
|
+
@responsive = responsive
|
|
20
|
+
@table_options = table_options
|
|
21
|
+
@variant = variant
|
|
22
|
+
raise ArgumentError, 'Unknown variant' unless %i[h3 data].include?(@variant)
|
|
23
|
+
|
|
24
|
+
raise ArgumentError, 'Subclasses must provide rows' unless respond_to?(:rows)
|
|
25
|
+
|
|
26
|
+
super()
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
attr_reader :label, :empty_message, :table_options, :variant
|
|
30
|
+
|
|
31
|
+
def before_render
|
|
32
|
+
raise ArgumentError, 'Must provide label or caption' unless label.present? || caption?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def classes
|
|
36
|
+
merge_classes(%w[table caption-top], variant_classes, @classes)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def head_classes
|
|
40
|
+
merge_classes(@head_classes)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def body_classes
|
|
44
|
+
merge_classes(@body_classes)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def show_label?
|
|
48
|
+
@show_label
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def render?
|
|
52
|
+
rows? || empty_message.present?
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def responsive?
|
|
56
|
+
@responsive
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def variant_classes
|
|
60
|
+
case variant
|
|
61
|
+
when :h3
|
|
62
|
+
'table-h3'
|
|
63
|
+
when :data
|
|
64
|
+
'table-data table-striped table-hover table-bordered'
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Tables
|
|
5
|
+
# Component for rendering a table cell.
|
|
6
|
+
class CellComponent < BaseComponent
|
|
7
|
+
def initialize(colspan: nil, classes: [], **cell_options)
|
|
8
|
+
@colspan = colspan
|
|
9
|
+
@classes = classes
|
|
10
|
+
@cell_options = cell_options
|
|
11
|
+
super()
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
attr_reader :colspan, :cell_options
|
|
15
|
+
|
|
16
|
+
def classes
|
|
17
|
+
merge_classes(@classes)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Tables
|
|
5
|
+
# Component for rendering a table header.
|
|
6
|
+
class HeaderComponent < BaseComponent
|
|
7
|
+
def initialize(label:, classes: [], tooltip: nil, **header_options)
|
|
8
|
+
@label = label
|
|
9
|
+
@classes = classes
|
|
10
|
+
@tooltip = tooltip
|
|
11
|
+
@header_options = header_options
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :label, :tooltip, :header_options
|
|
16
|
+
|
|
17
|
+
def classes
|
|
18
|
+
merge_classes(@classes)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Tables
|
|
5
|
+
# Component for rendering a list in a table cell.
|
|
6
|
+
class ListCellComponent < BaseComponent
|
|
7
|
+
renders_many :items
|
|
8
|
+
|
|
9
|
+
def initialize(item_values: [])
|
|
10
|
+
# Provide items or item_values
|
|
11
|
+
@item_values = item_values
|
|
12
|
+
super()
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_reader :item_values
|
|
16
|
+
|
|
17
|
+
def list_items
|
|
18
|
+
items? ? items : item_values
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<%= tag.tr **row_options do %>
|
|
2
|
+
<% if label.present? || label_content.present? %>
|
|
3
|
+
<th class="col-3" scope="row">
|
|
4
|
+
<%= label || label_content %>
|
|
5
|
+
<%= render SdrViewComponents::Elements::TooltipComponent.new(target_label: label, tooltip:) %>
|
|
6
|
+
</th>
|
|
7
|
+
<% end %>
|
|
8
|
+
|
|
9
|
+
<% if first_value.present? %>
|
|
10
|
+
<td class="col-3" scope="row"><%= first_value %></td>
|
|
11
|
+
<% end %>
|
|
12
|
+
|
|
13
|
+
<% values.each do |value| %>
|
|
14
|
+
<td><%= value %></td>
|
|
15
|
+
<% end %>
|
|
16
|
+
|
|
17
|
+
<% cells.each do |cell| %>
|
|
18
|
+
<%= cell %>
|
|
19
|
+
<% end %>
|
|
20
|
+
|
|
21
|
+
<% if empty_cell? %>
|
|
22
|
+
<td></td>
|
|
23
|
+
<% end %>
|
|
24
|
+
<% end %>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SdrViewComponents
|
|
4
|
+
module Tables
|
|
5
|
+
# Component for rendering a table row.
|
|
6
|
+
class RowComponent < BaseComponent
|
|
7
|
+
renders_many :cells, SdrViewComponents::Tables::CellComponent
|
|
8
|
+
renders_one :label_content
|
|
9
|
+
|
|
10
|
+
def initialize(label: nil, first_value: nil, values: [], value: nil, tooltip: nil, **row_options) # rubocop:disable Metrics/ParameterLists
|
|
11
|
+
# Provide either label or first_value but not both; these are rendered in the first column
|
|
12
|
+
# label renders with <th> (bold), first_value is a normal <td>
|
|
13
|
+
@label = label
|
|
14
|
+
@first_value = first_value
|
|
15
|
+
# Provide either value, values or cells (e.g. for content files).
|
|
16
|
+
@values = Array(value).presence || values
|
|
17
|
+
@tooltip = tooltip
|
|
18
|
+
@row_options = row_options
|
|
19
|
+
|
|
20
|
+
raise ArgumentError if label.present? && first_value.present?
|
|
21
|
+
|
|
22
|
+
super()
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
attr_reader :label, :values, :tooltip, :first_value, :row_options
|
|
26
|
+
|
|
27
|
+
def empty_cell?
|
|
28
|
+
label.present? && values.empty? && !cells?
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<title><%= content_for(:title) || 'Lookbook' %></title>
|
|
6
|
+
|
|
7
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
8
|
+
|
|
9
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
10
|
+
|
|
11
|
+
<meta name="application-name" content="Lookbook">
|
|
12
|
+
|
|
13
|
+
<meta name="mobile-web-app-capable" content="yes">
|
|
14
|
+
|
|
15
|
+
<%= csrf_meta_tags %>
|
|
16
|
+
<%= csp_meta_tag %>
|
|
17
|
+
|
|
18
|
+
<%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %>
|
|
19
|
+
<%# = tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %>
|
|
20
|
+
|
|
21
|
+
<link rel="icon" href="/icon.png" type="image/png">
|
|
22
|
+
|
|
23
|
+
<link rel="icon" href="/icon.svg" type="image/svg+xml">
|
|
24
|
+
|
|
25
|
+
<link rel="apple-touch-icon" href="/icon.png">
|
|
26
|
+
|
|
27
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
|
|
28
|
+
<link
|
|
29
|
+
rel="stylesheet"
|
|
30
|
+
href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css"
|
|
31
|
+
>
|
|
32
|
+
<%= tag.link rel: 'icon', href: "#{SdrViewComponents.configuration.component_library_url}/styles/icon.png", type: 'image/png' %>
|
|
33
|
+
<%= tag.link rel: 'icon', href: "#{SdrViewComponents.configuration.component_library_url}/styles/icon.svg", type: 'image/svg+xml' %>
|
|
34
|
+
<%= tag.link rel: 'apple-touch-icon', href: "#{SdrViewComponents.configuration.component_library_url}/styles/icon.png" %>
|
|
35
|
+
|
|
36
|
+
<%= stylesheet_link_tag 'sdr_view_components', 'data-turbo-track': 'reload' %>
|
|
37
|
+
<%= tag.link rel: 'stylesheet', href: "#{SdrViewComponents.configuration.component_library_url}/styles/sul.css" %>
|
|
38
|
+
</head>
|
|
39
|
+
|
|
40
|
+
<body>
|
|
41
|
+
<div class="container-fluid py-4">
|
|
42
|
+
<%= yield %>
|
|
43
|
+
</div>
|
|
44
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SDR View Components module
|
|
4
|
+
module SdrViewComponents
|
|
5
|
+
# Configuration class for the SDR View Components gem
|
|
6
|
+
class Configuration
|
|
7
|
+
attr_accessor :component_library_url
|
|
8
|
+
|
|
9
|
+
def initialize
|
|
10
|
+
# Default URL for the component library assets
|
|
11
|
+
@component_library_url = 'https://cdn.jsdelivr.net/gh/sul-dlss/component-library@v2026-01-27'
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.configuration
|
|
16
|
+
@configuration ||= Configuration.new
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.configure
|
|
20
|
+
yield configuration
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -7,19 +7,25 @@ module SdrViewComponents
|
|
|
7
7
|
class Engine < ::Rails::Engine
|
|
8
8
|
isolate_namespace SdrViewComponents
|
|
9
9
|
|
|
10
|
-
initializer 'sdr_view_components.
|
|
11
|
-
|
|
10
|
+
initializer 'sdr_view_components.preview_autoload', before: :set_autoload_paths do |app|
|
|
11
|
+
preview_path = root.join('spec/components/previews').to_s
|
|
12
|
+
app.config.autoload_paths |= [preview_path]
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
initializer 'sdr_view_components.preview_paths' do |app|
|
|
16
|
+
preview_path = root.join('spec/components/previews').to_s
|
|
12
17
|
|
|
13
|
-
|
|
14
|
-
config.view_component.previews.paths << root.join('spec/components/previews')
|
|
18
|
+
app.config.view_component.previews.paths |= [preview_path] if app.config.view_component.respond_to?(:previews)
|
|
15
19
|
|
|
16
|
-
#
|
|
17
|
-
config.
|
|
20
|
+
# Lookbook direct config
|
|
21
|
+
if app.config.respond_to?(:lookbook) && app.config.lookbook.respond_to?(:preview_paths)
|
|
22
|
+
app.config.lookbook.preview_paths |= [preview_path]
|
|
23
|
+
end
|
|
18
24
|
end
|
|
19
25
|
|
|
20
26
|
initializer 'sdr_view_components.assets' do |app|
|
|
27
|
+
app.config.assets.paths << Engine.root.join('app', 'assets').to_s
|
|
21
28
|
app.config.assets.paths << Engine.root.join('app', 'assets', 'stylesheets').to_s
|
|
22
|
-
app.config.assets.precompile += %w[sdr_view_components.css]
|
|
23
29
|
end
|
|
24
30
|
|
|
25
31
|
initializer 'sdr_view_components.helpers' do
|
|
@@ -27,5 +33,9 @@ module SdrViewComponents
|
|
|
27
33
|
include SdrViewComponents::Helpers
|
|
28
34
|
end
|
|
29
35
|
end
|
|
36
|
+
|
|
37
|
+
initializer 'sdr_view_components.configure_lookbook' do
|
|
38
|
+
config.view_component.previews.default_layout = 'lookbook'
|
|
39
|
+
end
|
|
30
40
|
end
|
|
31
41
|
end
|
data/lib/sdr_view_components.rb
CHANGED
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: sdr_view_components
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aaron Collier
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: rails
|
|
@@ -61,11 +61,10 @@ files:
|
|
|
61
61
|
- MIT-LICENSE
|
|
62
62
|
- README.md
|
|
63
63
|
- Rakefile
|
|
64
|
-
- app/assets/
|
|
64
|
+
- app/assets/sdr_view_components.css
|
|
65
65
|
- app/components/base_component.rb
|
|
66
66
|
- app/components/component_support/button_support.rb
|
|
67
67
|
- app/components/component_support/css_classes.rb
|
|
68
|
-
- app/components/component_support/file_hierarchy.rb
|
|
69
68
|
- app/components/sdr_view_components/elements/alert_component.html.erb
|
|
70
69
|
- app/components/sdr_view_components/elements/alert_component.rb
|
|
71
70
|
- app/components/sdr_view_components/elements/banner_component.html.erb
|
|
@@ -98,6 +97,12 @@ files:
|
|
|
98
97
|
- app/components/sdr_view_components/elements/skip_links_component.rb
|
|
99
98
|
- app/components/sdr_view_components/elements/spinner_component.html.erb
|
|
100
99
|
- app/components/sdr_view_components/elements/spinner_component.rb
|
|
100
|
+
- app/components/sdr_view_components/elements/tabs/pane_component.html.erb
|
|
101
|
+
- app/components/sdr_view_components/elements/tabs/pane_component.rb
|
|
102
|
+
- app/components/sdr_view_components/elements/tabs/tab_component.html.erb
|
|
103
|
+
- app/components/sdr_view_components/elements/tabs/tab_component.rb
|
|
104
|
+
- app/components/sdr_view_components/elements/tabs/tab_list_component.html.erb
|
|
105
|
+
- app/components/sdr_view_components/elements/tabs/tab_list_component.rb
|
|
101
106
|
- app/components/sdr_view_components/elements/toast_component.html.erb
|
|
102
107
|
- app/components/sdr_view_components/elements/toast_component.rb
|
|
103
108
|
- app/components/sdr_view_components/elements/tooltip_component.html.erb
|
|
@@ -108,7 +113,6 @@ files:
|
|
|
108
113
|
- app/components/sdr_view_components/forms/basic_radio_button_component.rb
|
|
109
114
|
- app/components/sdr_view_components/forms/basic_text_area_component.rb
|
|
110
115
|
- app/components/sdr_view_components/forms/basic_text_field_component.rb
|
|
111
|
-
- app/components/sdr_view_components/forms/button_component.rb
|
|
112
116
|
- app/components/sdr_view_components/forms/checkbox_component.rb
|
|
113
117
|
- app/components/sdr_view_components/forms/field_component.html.erb
|
|
114
118
|
- app/components/sdr_view_components/forms/field_component.rb
|
|
@@ -140,9 +144,24 @@ files:
|
|
|
140
144
|
- app/components/sdr_view_components/structure/style_override_dark_component.rb
|
|
141
145
|
- app/components/sdr_view_components/structure/style_override_light_component.html.erb
|
|
142
146
|
- app/components/sdr_view_components/structure/style_override_light_component.rb
|
|
147
|
+
- app/components/sdr_view_components/tables/base_table_component.html.erb
|
|
148
|
+
- app/components/sdr_view_components/tables/base_table_component.rb
|
|
149
|
+
- app/components/sdr_view_components/tables/cell_component.html.erb
|
|
150
|
+
- app/components/sdr_view_components/tables/cell_component.rb
|
|
151
|
+
- app/components/sdr_view_components/tables/header_component.html.erb
|
|
152
|
+
- app/components/sdr_view_components/tables/header_component.rb
|
|
153
|
+
- app/components/sdr_view_components/tables/list_cell_component.html.erb
|
|
154
|
+
- app/components/sdr_view_components/tables/list_cell_component.rb
|
|
155
|
+
- app/components/sdr_view_components/tables/raw_table_component.rb
|
|
156
|
+
- app/components/sdr_view_components/tables/row_component.html.erb
|
|
157
|
+
- app/components/sdr_view_components/tables/row_component.rb
|
|
158
|
+
- app/components/sdr_view_components/tables/table_component.rb
|
|
159
|
+
- app/views/layouts/lookbook.html.erb
|
|
143
160
|
- config/routes.rb
|
|
144
161
|
- lib/sdr_view_components.rb
|
|
162
|
+
- lib/sdr_view_components/configuration.rb
|
|
145
163
|
- lib/sdr_view_components/engine.rb
|
|
164
|
+
- lib/sdr_view_components/error.rb
|
|
146
165
|
- lib/sdr_view_components/helpers.rb
|
|
147
166
|
- lib/sdr_view_components/helpers/icon_helper.rb
|
|
148
167
|
- lib/sdr_view_components/version.rb
|
|
@@ -166,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
166
185
|
- !ruby/object:Gem::Version
|
|
167
186
|
version: '0'
|
|
168
187
|
requirements: []
|
|
169
|
-
rubygems_version:
|
|
188
|
+
rubygems_version: 4.0.6
|
|
170
189
|
specification_version: 4
|
|
171
190
|
summary: Rails gem for providing SDR-specific ViewComponents.
|
|
172
191
|
test_files: []
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
3
|
-
* listed below.
|
|
4
|
-
*
|
|
5
|
-
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
6
|
-
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
|
7
|
-
*
|
|
8
|
-
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
9
|
-
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
|
10
|
-
* files in this directory. Styles in this file should be added after the last require_* statement.
|
|
11
|
-
* It is generally better to create a new file per style scope.
|
|
12
|
-
*
|
|
13
|
-
*= require_tree .
|
|
14
|
-
*= require_self
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
// Header
|
|
18
|
-
.cardinal {
|
|
19
|
-
--bs-dark-rgb: var(--stanford-cardinal-rgb);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.container.without-progress-bar {
|
|
23
|
-
max-width: 960px;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
.masthead {
|
|
27
|
-
color: white;
|
|
28
|
-
|
|
29
|
-
h1 {
|
|
30
|
-
font-size: 2.25rem;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Submission form
|
|
35
|
-
.header-help {
|
|
36
|
-
padding-left: 42px;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
.header-help p:last-of-type {
|
|
40
|
-
margin-bottom: 0;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.character-circle {
|
|
44
|
-
@extend .d-inline-flex;
|
|
45
|
-
@extend .align-items-center;
|
|
46
|
-
@extend .justify-content-center;
|
|
47
|
-
@extend .rounded-circle;
|
|
48
|
-
@extend .text-white;
|
|
49
|
-
|
|
50
|
-
width: 28px;
|
|
51
|
-
height: 28px;
|
|
52
|
-
font-size: 1rem;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
.character-circle.character-circle-disabled {
|
|
56
|
-
background-color: var(--stanford-60-black);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
.character-circle.character-circle-success {
|
|
60
|
-
@extend .bg-success;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
.character-circle.character-circle-blank {
|
|
64
|
-
@extend .border;
|
|
65
|
-
@extend .border-1;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.character-circle.character-circle-check {
|
|
69
|
-
font-family: bootstrap-icons !important;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.badge.badge-in-progress {
|
|
73
|
-
background-color: var(--stanford-60-black);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.badge.badge-completed {
|
|
77
|
-
@extend .text-bg-success;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
.btn-group-toggle {
|
|
81
|
-
// Provides visible indication when selected.
|
|
82
|
-
label.btn {
|
|
83
|
-
--bs-btn-focus-box-shadow: 0 0 0 0.25rem rgb(var(--bs-btn-focus-shadow-rgb), .5);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
input:checked + label {
|
|
87
|
-
@extend .btn-primary;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
input:not(:checked) + label {
|
|
91
|
-
@extend .btn-outline-primary;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
.btn-check:checked + .btn {
|
|
95
|
-
background-color: var(--stanford-digital-blue);
|
|
96
|
-
border-color: var(--stanford-digital-blue);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
:not(.btn-check:checked) + .btn {
|
|
100
|
-
color: var(--stanford-digital-blue);
|
|
101
|
-
border-color: var(--stanford-digital-blue);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.card-step {
|
|
106
|
-
--bs-card-cap-padding-y: 1rem;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.banner.alert {
|
|
110
|
-
a.btn-primary {
|
|
111
|
-
color: white;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Increase contrast for input borders
|
|
116
|
-
.form-control, .form-select, .form-check-input {
|
|
117
|
-
border-color: var(--stanford-60-black);
|
|
118
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ComponentSupport
|
|
4
|
-
# Support methods for working with file hierarchies.
|
|
5
|
-
class FileHierarchy
|
|
6
|
-
# Determine the difference between the last path parts and the current path parts.
|
|
7
|
-
# @param [Array<String>] last_path_parts the last path parts (e.g., ['dir1', 'dir2'])
|
|
8
|
-
# @param [Array<String>] path_parts the current path parts
|
|
9
|
-
# @return [Array<String>] path parts from the current path parts that differ
|
|
10
|
-
def self.path_parts_diff(last_path_parts:, path_parts:)
|
|
11
|
-
return [] if last_path_parts == path_parts
|
|
12
|
-
|
|
13
|
-
matching_index = 0
|
|
14
|
-
loop do
|
|
15
|
-
break if path_parts[matching_index] != last_path_parts[matching_index]
|
|
16
|
-
|
|
17
|
-
matching_index += 1
|
|
18
|
-
end
|
|
19
|
-
path_parts.slice(matching_index..)
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module SdrViewComponents
|
|
4
|
-
module Forms
|
|
5
|
-
# Component for a button that is wrapped in a form
|
|
6
|
-
class ButtonComponent < BaseComponent
|
|
7
|
-
def initialize(link:, label: nil, variant: :primary, classes: [], method: :get, confirm: nil, # rubocop:disable Metrics/ParameterLists
|
|
8
|
-
top: true, data: {})
|
|
9
|
-
@link = link
|
|
10
|
-
@label = label
|
|
11
|
-
@variant = variant
|
|
12
|
-
@classes = classes
|
|
13
|
-
@method = method
|
|
14
|
-
@confirm = confirm
|
|
15
|
-
@top = top
|
|
16
|
-
@data = data
|
|
17
|
-
super()
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
attr_reader :link
|
|
21
|
-
|
|
22
|
-
def call
|
|
23
|
-
button_to(link, method: @method,
|
|
24
|
-
class: ComponentSupport::ButtonSupport.classes(variant: @variant, classes:),
|
|
25
|
-
form: { data: }) do
|
|
26
|
-
@label || content
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def classes
|
|
31
|
-
merge_classes(@classes)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def data
|
|
35
|
-
@data.tap do |data|
|
|
36
|
-
data[:turbo_frame] = '_top' if @top
|
|
37
|
-
data[:turbo_confirm] = @confirm if @confirm
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|