New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sage dynamic select input - select2 #709
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good here, @jamell-kajabi !
Regarding nesting depth, if its necessary (which in vendor situations like this would be understandable!) you can add /* stylelint-disable selector-max-compound-selectors */
before the set of styles that violate the rule and then /* stylelint-enable selector-max-compound-selectors */
afterwards.
One thing that would be great to add is some documentation around this and how it can be used. This is typically adding a folder and the set of files you can see for others inside docs/app/views/examples/components
and then an entry for this component in docs/app/helpers/components_helper.rb
. Then it will appear in the Components sidebar.
However, I understand following the other examples may not be 100% possible due to the asynchronous nature. It would be great to add the required files, document the props
from your sage_dynamic_select.rb
file similar to other components. But then if you can't easily show actual uses in the preview
file, consider at least providing a code sample like what is shown on the Toast
component.
I know this is going to be work well invested since this component is used so much in the app now. Thanks SO MUCh for doing this!! 🙇♂️
// empty state // | ||
.sage-dynamic-select { | ||
position: relative; | ||
&__data { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we please move this out onto its own? We tend to avoid this type of use of &
in Sage.
.sage-dynamic-select {
// ...
}
.sage-dynamic-select__data {
// ...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity, the goal is to avoid using &
for segments of a particular element selector, but OK to use it for a whole element. So:
❌
.block {
&__element {
// stuff
}
&--variant {
&__element {
// stuff
}
}
}
✅
.block__element {
// stuff
.block--variant & {
// stuff
}
&::after {
// stuff
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And with the BEM naming we'd typically not nest an element selector inside a block selector so that the styles contained in a selector are ideally applied to that actual thing. If specificity or context is needed you bascially flip it so instead of:
.block {
&--variant {
&__element {
// stuff
}
}
}
You do:
.block__element {
// stuff
.block--variant & {
// stuff
}
}
It is more typing (increased chance for typos 😬 ) but helps ensure each selector block is explicitly applying to that thing, thus preventing style leaks. Everything is also in one place for that particular thing too. Hope this makes sense. 👍 but if not please let me know and we can sync up. 🙌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done :)
bottom: sage-spacing(xs); | ||
left: 50%; | ||
} | ||
.select2-container--sage { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this need to be nested for sufficient specificity, or could this be pulled out to avoid the extra nesting depth?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done 👍
height: $-dynamic-select-selected-height; | ||
padding: $-dynamic-select-selected-padding; | ||
border-color: $-dynamic-select-border-color; | ||
.select2-selection__rendered { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here... if not needed, can this be pulled out a layer or more to avoid the deep nesting?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1
Thank you for your review @philschanely! I was able to refactor some nesting which definitely helps with readability. I did have some questions regarding adding the input to our docs site, would love to sync with you around this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 This is looking great, Jamell! Will be a substantial improvement to our select2 implementation in the app.
In addition to the nesting items that Phil suggested, my comments below are primarily on some cleanup and hopefully clearing up my understanding on derived values.
<%= component.generated_html_attributes.html_safe %> | ||
name="<%= component.name %>" | ||
id="<%= component.id %>" | ||
tabindex="-1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for the group (no actionable items as of yet): we'll have to be mindful of this and the aria-hidden="true"
below for accessibility. Select2 has been actively working on improving their compliance, but it's not quite there, so we'll have to keep a close watch on it.
packages/sage-assets/lib/stylesheets/components/_dynamic_select.scss
Outdated
Show resolved
Hide resolved
docs/lib/sage_rails/app/views/sage_components/_sage_dynamic_select.html.erb
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼 LGTM, a few minor edit tweaks to the preview copy but no major blockers that I can see. After testing with the bridge, I think we may need some additional design input re: the height change for selected values as a follow-up. Great work, this will be a useful addition!
clear: "Allow user to clear input value" | ||
|
||
// Example Implementation | ||
sage_component SageDynamicSelect, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @philschanely had mentioned earlier, ideally we'd have a rendered preview of the component in action, but this works as a substitute.
As a follow-up, I wonder if we could reference the external JS dependencies (jquery and select2) from a CDN just for this preview page. That'd give us a working preview but prevent the dependencies from being packaged up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may be able to add them as peer dependencies in the repo. @voodooGQ would this make sense?
</p> | ||
|
||
<h4>Error Handling</h4> | ||
<p>Much like other sage inputs, the dynamic select includes options to render error messages from the server. By using the <code>has_error</code> attribute, one can trigger the erros states and print an error message that gets placed below the input.</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tiny typo here "error states"
@@ -0,0 +1,42 @@ | |||
<h3>Working with the<code>Sage Dynamic Select Input (Select2)</code></h3> | |||
<p> | |||
The dynamic select input is a sagified version of the select2 input that resides in <code>Kajabi Products.</code> The input fuctionality leverages the Javascript library select2 and includes several options for tailoring the input to the UI. The input can retrieve options from any arbitrary API that will return validly structured JSON.<br/> <br/> Basic usage and complete documentation ca be found |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍 Beautifully written!
One suggestion, we can replace the <br>
tags with a new <p>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note as well that the md()
helper may be useful to simplify as well.
$-dynamic-select-placeholder-color: sage-color(gray, 400); | ||
$-dynamic-select-color-success: map-get($sage-field-colors, success); | ||
$-dynamic-select-border-box-shadow-size: map-get($sage-field-configs, box-shadow-size); | ||
$-dynamic-select-selected-height: rem(54); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't have an existing spec in Figma for this, so I won't consider it a blocker but do want to note that the height for the component is much taller (3.375rem) than the standard SageFormSelect
field (2.25rem) with an option selected. This shouldn't be an issue for standalone fields, but in cases where inputs are horizontally aligned, the difference will be noticeable:
SageFormSelect | SageDynamicSelect |
---|---|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking really nice Jamell! Thanks so much for putting the time in to convert this to Sage. Will make an awesome addition to our collection. I left one comment, not a blocker. 👍🏼
c9382c6
to
3731a69
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking in great shape, @jamell-kajabi ! Thanks for your hard work on this!
Description
Adds a select2 input type for sage forms
API Options:
Screenshots
Component States
Empty state
Selected state
Input open w/ search
Input open w/o search
input w/ error
Testing in
sage-lib
IMPORTANT
This input has dependencies that are only available in Kajabi Products. There's no way to test this from
sage-lib
.Testing in
kajabi-products
Testing is straightforward. You will need a URL generated from rails to deliver the select options via
AJAX
request. See component sample code here.Examples of possible URLs can be found in the
select_options
controller found here in Kajabi Productsapp/controllers/admin/select_options_controller.rb
.Once you've found a URL to fetch data, you can then play with the different API attributes to reviews the input in different states. Screenshots are provided above as well.
This PR is additive, meaning it will not affect ant current implementation of the select2 inputs. It may be wise to double-check some existing select2 inputs just to make sure there's no overlap in styles or js.