<div class="flex flex-col gap-2"> <button class="lui-button lui-button--size-default lui-button--neutral--secondary w-fit w-fit relative" data-controller="lui--button"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Open in Validation </div> </div> <div class="flex items-center justify-center opacity-100" data-lui--button-target="leadingIcon" style="width: 16px; height: 16px;"> <svg height="24" width="24" viewBox="0 0 12 10"> <path d="M4.708 9.24858C3.95829 9.24858 3.20859 8.96398 2.63778 8.39317L0.912326 6.66772C0.876549 6.63194 0.00162625 5.75051 0 4.54058C0 3.81202 0.305735 3.13388 0.912326 2.52728C1.97915 1.46046 3.06223 1.52226 3.78266 1.76295C4.53073 2.01176 5.02999 2.50614 5.05113 2.52728L5.56828 3.04443L6.94897 1.66375C6.98475 1.62797 7.8678 0.753045 9.0761 0.751419H9.08098C9.80792 0.751419 10.4844 1.05878 11.0894 1.66375C12.1562 2.73057 12.0944 3.81365 11.8537 4.53408C11.6049 5.28215 11.1105 5.78141 11.0894 5.80255C10.3982 6.49371 9.44526 6.76692 8.54595 6.62056L6.77659 8.38992C6.20577 8.96073 5.45607 9.24533 4.70637 9.24533L4.708 9.24858ZM2.94026 2.59559C2.53207 2.59559 2.07022 2.75171 1.60348 3.21844C1.18716 3.63476 0.97575 4.07873 0.977377 4.53896C0.977377 5.33419 1.59698 5.97006 1.60186 5.97656L3.32731 7.70201C4.08839 8.4631 5.32597 8.4631 6.08706 7.70201L7.46612 6.32295L4.3616 3.21844C4.27053 3.129 3.69484 2.59559 2.93863 2.59559H2.94026ZM6.26107 3.73559L7.64175 5.11627C8.40284 5.87736 9.64041 5.87736 10.4015 5.11627C10.5397 4.97479 11.7301 3.68517 10.4015 2.35653C9.98518 1.94021 9.53633 1.73205 9.08098 1.73042C8.28575 1.73042 7.64988 2.35002 7.64338 2.3549L6.26269 3.73559H6.26107Z" fill="url(#paint0_linear_238_3029)"/> <defs> <linearGradient id="paint0_linear_238_3029" x1="6.00086" y1="9.24858" x2="6.00086" y2="0.754671" gradientUnits="userSpaceOnUse"> <stop stop-color="#059898"/> <stop offset="1" stop-color="#00D8B5"/> </linearGradient> </defs> </svg> </div> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Follow up item </span> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 16px;"> progress_activity </i> </div> </button> <button class="lui-button lui-button--size-default lui-button--neutral--secondary w-fit w-fit relative" data-controller="lui--button"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Open in Handling </div> </div> <div class="flex items-center justify-center opacity-100" data-lui--button-target="leadingIcon" style="width: 16px; height: 16px;"> <svg height="24" width="24" viewBox="0 0 12 12"> <path d="M8.75904 11.9991C7.80809 11.9991 7.0374 11.7103 6.46904 11.1401C5.5236 10.191 5.51625 8.81515 5.51809 8.75629V6.481H3.24096C1.4531 6.481 0 5.02606 0 3.24004C0 3.18302 0.00551777 1.80718 0.95095 0.858066C1.51931 0.287864 2.29001 -0.000915527 3.24096 -0.000915527C4.91294 -0.000915527 5.71122 0.894854 6.08645 1.64531C6.28878 2.05181 6.38811 2.45647 6.43593 2.75813H8.7572C10.5451 2.75813 12 4.21306 12 6.00092V8.75997C12 9.88198 11.3231 12.0009 8.75904 12.0009V11.9991ZM6.48191 3.72195V8.75813C6.48191 8.99173 6.55549 11.0353 8.75904 11.0353C9.70448 11.0353 10.3722 10.66 10.7419 9.92244C11.027 9.3504 11.0362 8.76549 11.0362 8.75813V5.99908C11.0362 4.74464 10.0153 3.72195 8.75904 3.72195H6.48375H6.48191ZM3.24096 0.96291C1.03924 0.96291 0.965665 3.00644 0.963826 3.24004C0.963826 4.49449 1.98467 5.51533 3.24096 5.51533H5.51625V3.2382C5.51625 3.00644 5.43532 0.961071 3.24096 0.961071V0.96291Z" fill="url(#paint0_linear_238_2402)"/> <defs> <linearGradient id="paint0_linear_238_2402" x1="6" y1="11.9991" x2="6" y2="-0.00275473" gradientUnits="userSpaceOnUse"> <stop stop-color="#443092"/> <stop offset="1" stop-color="#8044FF"/> </linearGradient> </defs> </svg> </div> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Follow up item </span> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 16px;"> progress_activity </i> </div> </button> <button class="lui-button lui-button--size-default lui-button--neutral--secondary w-fit w-fit relative" data-controller="lui--button"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Open in Hubs </div> </div> <div class="flex items-center justify-center opacity-100" data-lui--button-target="leadingIcon" style="width: 16px; height: 16px;"> <svg height="24" width="24" viewBox="0 0 12 12"> <path d="M8.53012 11.9971C7.37157 11.9971 6.3441 11.4265 5.71373 10.5513H3.46988C2.3653 10.5513 0.722892 9.82073 0.722892 7.80434C0.722892 7.00241 0.969639 6.34892 1.45735 5.86314C1.47663 5.84386 1.49783 5.82265 1.51904 5.8053C1.28 5.68 1.04289 5.51615 0.828915 5.30217C0.279518 4.7547 0 4.01639 0 3.10651C0 0.648677 2.03373 -0.000961304 3.10747 -0.000961304C4.49349 -0.000961304 5.67132 0.910846 6.07036 2.16771H7.08241C7.8959 2.16771 9.10651 2.70747 9.10651 4.19181C9.10651 4.52145 9.04482 4.8241 8.92723 5.09012C9.44771 5.15759 10.3711 5.37542 11.0766 6.07904C11.6896 6.69012 12 7.51326 12 8.53109C12 11.2761 9.73108 12.001 8.53012 12.001V11.9971ZM6.21687 8.52723C6.21687 9.80338 7.25398 10.8405 8.53012 10.8405C8.7653 10.8386 10.8434 10.7557 10.8434 8.52723C10.8434 6.2988 8.76723 6.21591 8.53012 6.21398H6.21687V8.52723ZM3.46988 6.21398C3.46988 6.21398 3.02843 6.21976 2.61398 6.43566C2.11855 6.69398 1.87952 7.14121 1.87952 7.80434C1.87952 8.46747 2.12048 8.91084 2.6159 9.16916C3.03036 9.38506 3.46988 9.3947 3.47373 9.3947H5.06024V6.21398H3.46988ZM3.1094 1.15374C2.91277 1.15566 1.15855 1.22892 1.15855 3.10458C1.15855 3.69446 1.32241 4.15904 1.64627 4.48097C2.20916 5.04193 3.09783 5.05542 3.10747 5.05542H5.06024V3.10458C5.06024 2.02892 4.18506 1.15374 3.10747 1.15374H3.1094ZM6.21687 5.05735H7.08434C7.34265 5.0535 7.95181 4.96097 7.95181 4.18988C7.95181 3.4188 7.34072 3.32819 7.07855 3.32241H6.21687V5.05735Z" fill="url(#paint0_linear_238_3090)"/> <defs> <linearGradient id="paint0_linear_238_3090" x1="6.00096" y1="11.9971" x2="6.00096" y2="-0.00288892" gradientUnits="userSpaceOnUse"> <stop stop-color="#0072FF"/> <stop offset="1" stop-color="#00C5FF"/> </linearGradient> </defs> </svg> </div> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Follow up item </span> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 16px;"> progress_activity </i> </div> </button> <button class="lui-button lui-button--size-default lui-button--neutral--secondary w-fit w-fit relative" data-controller="lui--button"> <div class="lui-tooltip hidden" data-controller="tooltips" data-tooltips-tippy-target-id-value="" data-tooltips-position-value="top" data-tooltips-interactive-value="false" > <div class="lui-tooltip__title"> Open in Core </div> </div> <div class="flex items-center justify-center opacity-100" data-lui--button-target="leadingIcon" style="width: 16px; height: 16px;"> <svg height="24" width="24" viewBox="0 0 12 12"> <path d="M5.94853 12.0007C5.35232 12.0007 4.69999 11.7762 4.07192 11.1481C3.76092 10.8371 3.53185 10.5018 3.39076 10.1484C3.04487 10.0118 2.72629 9.80398 2.46232 9.54002L0.852712 7.93041C0.185204 7.2629 -0.674971 5.59565 0.852712 4.06797C1.16371 3.75697 1.49898 3.52789 1.85246 3.3868C1.98899 3.04091 2.19683 2.72233 2.4608 2.45836L4.0704 0.848758C4.09013 0.829036 4.55738 0.367849 5.25371 0.135738C5.92577 -0.0887876 6.93614 -0.146436 7.93133 0.848758C8.24233 1.15976 8.47141 1.49503 8.61249 1.8485C8.95838 1.98504 9.27697 2.19288 9.54094 2.45685L11.1505 4.06645C11.1703 4.08617 11.6315 4.55343 11.8636 5.24976C12.0881 5.92182 12.1457 6.93218 11.1505 7.92738C10.8395 8.23837 10.5043 8.46745 10.1508 8.60854C10.0143 8.95443 9.80642 9.27149 9.54245 9.53698L7.93285 11.1466C7.53993 11.5395 6.80112 11.9992 5.94701 11.9992L5.94853 12.0007ZM4.17812 9.63407L4.18722 9.66593C4.27066 9.95417 4.44815 10.2363 4.71667 10.5049C5.95611 11.7443 7.15915 10.6338 7.29265 10.5049L8.90074 8.89678C8.9417 8.85582 8.98114 8.81182 9.01907 8.76783C8.03298 8.6586 7.33057 7.96985 7.29265 7.93193L6.00466 6.64394L4.71667 7.93193C4.71667 7.93193 4.13412 8.53268 4.13412 9.2806C4.13412 9.39589 4.14777 9.51423 4.17963 9.63407H4.17812ZM2.37129 4.17264L2.3364 4.18175C2.04816 4.26518 1.76598 4.44268 1.49746 4.7112C0.258023 5.95064 1.36851 7.15367 1.49746 7.28718L3.10555 8.89526C3.14651 8.93622 3.19051 8.97567 3.2345 9.01359C3.34373 8.02599 4.03399 7.32359 4.0704 7.28718L5.35839 5.99919L4.0704 4.7112C4.0704 4.7112 3.27546 3.93902 2.36978 4.17264H2.37129ZM7.93285 7.28566C7.9465 7.29931 8.60491 7.93344 9.41047 7.86366C9.48481 7.85759 9.55914 7.84394 9.63651 7.82422L9.66989 7.81511C9.95813 7.73168 10.2403 7.55418 10.5088 7.28566C11.7483 6.04622 10.6378 4.84319 10.5088 4.70968L8.90074 3.1016C8.85977 3.06064 8.81578 3.02119 8.77178 2.98478C8.66256 3.97239 7.97229 4.67479 7.93437 4.7112L6.64789 5.99767L7.93437 7.28414L7.93285 7.28566ZM2.98874 3.23206C3.97635 3.34129 4.67875 4.03004 4.71516 4.06797L6.00314 5.35595L7.29113 4.06797C7.29113 4.06797 7.87368 3.46721 7.87368 2.7193C7.87368 2.604 7.86003 2.48567 7.82817 2.36582L7.81907 2.33396C7.73563 2.04572 7.55813 1.76355 7.28961 1.49503C6.05017 0.255586 4.84714 1.36608 4.71364 1.49503L3.10555 3.10311C3.06459 3.14407 3.02515 3.18807 2.98722 3.23206H2.98874Z" fill="url(#paint0_linear_238_1315)"/> <defs> <linearGradient id="paint0_linear_238_1315" x1="6.00163" y1="12.0007" x2="6.00163" y2="0.00071859" gradientUnits="userSpaceOnUse"> <stop stop-color="#F27335"/> <stop offset="1" stop-color="#FCAA30"/> </linearGradient> </defs> </svg> </div> <span class="lui-button__text opacity-100 inline-flex" data-lui--button-target="text"> Follow up item </span> <div class="absolute w-full flex items-center justify-center opacity-0" data-lui--button-target="loadingIcon"> <i class="lui-m_icon animate-spin material-symbols-outlined" style="--lui-micon-size: 16px;"> progress_activity </i> </div> </button></div>No Usage documentation to display.
<div class="flex flex-col gap-2"> <% [:validation, :handling, :hubs, :core].each do |app| %> <%= render LooposUi::Button.new(**preview_params, app: app, leading_icon: app, tooltip_text: "Open in #{app.to_s.titleize}") %> <% end %></div>No notes provided.
| Param | Description | Input |
|---|---|---|
|
— |
|
|
|
— |
|
|
|
Button text |
|
Description
The Button component is a simple button that can be used to trigger actions or navigate to different parts of the application.
Arguments
| Property | Description | Default Value |
|---|---|---|
kind |
(Deprecated, all button kinds are now neutral, will be removed) The kind of the button. Can be :app, :neutral, :success, or :danger. |
:app |
app |
(Deprecated, will be removed) The application type. If kind is :app and app is not provided, it defaults to LooposUi.config.app_type. |
nil |
text |
The text displayed on the button. | nil |
size |
The size of the button. Can be :default, :small, or :tiny. |
:default |
type |
The type of the button. Can be :primary, :secondary, or :tertiary. |
:primary |
href |
Decides the type of the button. If present, the button will be rendered as an anchor tag, otherwise as a button. | nil |
tag |
The wrapper HTML tag that should be used to create the button. Eg: button, a, label, etc. Default is button, unless you specify href |
button |
tag_options |
Hash with additional options to be passed to the tag builder. | {} |
leading_icon |
The icon displayed before the text. If the string is an app name, the respective app icon will be rendered | nil |
icon |
The icon displayed before the text, alternative way to set leading_icon. |
nil |
trailing_icon |
The icon displayed after the text. If the string is an app name, the respective app icon will be rendered | nil |
disabled |
Boolean value, controls whether the button/link is clickable. | false |
active |
Boolean value, controls whether the button/link is in an active state. | true |
When the kind is set to :app and the app property is not provided, it will default to LooposUi.config.app_type.
Color Customization
To customize button colors (primary color, hover color, border color, text color), use the ThemeContext component to wrap your buttons. This only works if button is of type primary:
<%= render LooposUi::ThemeContext.new(theme: { button: { primary_color: "apps-default-800-primary", hover_color: "apps-default-900-hover", border_color: "apps-default-800-primary", text_color: "general-global-white" }}) do %> <%= render LooposUi::Button.new(text: "Custom Button") %><% end %>icon, leading_icon, and trailing_icon should be a string with the FontAwesome icon class (for example, fa-regular fa-plus).
You can also pass in just the icon name - if the passed in value does not contain fa-, it will be prepended with fa-regular fa-{VALUE}. This way you can just pass in plus for the same effect.
The button component also supports Material Design Icons (MIcon). You can pass icon names like "home", "settings", "arrow_forward" etc. and they will be rendered as Material Design Icons with appropriate sizing based on the button size.
Presets
As most buttons will have the same kind, size, and type, there are some presets available to make it easier to create buttons.
The presets are defined in the LooposUi::Button::Presets module.
Currently, the available presets are:
new:delete:back:enable:copy:export:validation:
All presets accept the same arguments as the Button component, but most only require the href property.
Slots
There are three slots available for the Button component: counter, leading_icon and trailing_icon. The counter slot renders a LooposUi::Counter component next to the button content, while the other two add the respective icons.
The last two can also be passed in as properties, which is the heavily recommended way of doing it.
JavaScript/Stimulus Controller
The Button component includes a Stimulus controller (lui--button) that provides dynamic functionality for updating button content and handling icon interactions.
Whenever the button is rendered as:
- an anchor tag (
hrefpresent and not disabled), or - a
buttontag withtype: :submit, or - a
buttontag with aformattribute
the component will automatically add data-controller="lui--button" and data-action="lui--button#startLoading" to enable the loading state behavior (showing the spinner, disabling the button, and setting aria-busy/aria-disabled).
Controller Targets
| Target | Description |
|---|---|
text |
The text content span element within the button |
leadingIcon |
The leading icon element (when using FontAwesome icons) |
Controller Methods
| Method | Description |
|---|---|
rotateLeadingIcon() |
Toggles a 180-degree rotation on the leading icon. Useful for expand/collapse buttons. |
Dynamic Updates
The controller automatically watches for changes to specific data attributes and updates the button content accordingly:
data-text: Updates the button text contentdata-leading-icon: Updates the leading icon classdata-tooltip-title: Updates the tooltip if it exists
Usage Examples
Dynamic Text Updates
<%= render LooposUi::Button.new(text: "Initial Text", icon: :chevron-down) %><script> // Update button text dynamically const button = document.querySelector('[data-controller="lui--button"]') button.dataset.text = "Updated Text"</script>Integration with Other Components
The button controller is often used in conjunction with other components. For example, in the Log component:
<%= render LooposUi::Button.new( text: "Show More", leading_icon: "fa-regular fa-chevron-down", data: { action: "click->log#showMore log:toggleExpand->lui--button#rotateLeadingIcon" }) %>