Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

turbo_material

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

turbo_material

  • 0.2.18
  • Rubygems
  • Socket score

Version published
Maintainers
1
Created
Source

Material Components for Hotwire Turbo

This gem implements drop-in implementation for Material Design in Turbo. It is based on Material Components for the Web as it's being most feature rich implementation at the moment.

Requirements

  • Ruby 3.3+ (might work with older versions, but not tested)
  • Rails 7.1+ (Turbo is hard requirement for complex components like server based Chips)
  • Turbo
  • Stimulus
  • Importmaps
  • Tailwind

That list is based on the project from which this library is being extracted. If you like to make it less demanding, feel free to submit PRs. Only strict requirements are Turbo and Stimulus.

Usage

Run rails turbo_material:install to install the gem and add necessary files to your project. Alternatively, you can follow the steps below.

Add following to your app/javascript/controllers/index.js after eagerLoadControllersFrom("controllers", application) line:

eagerLoadControllersFrom("turbo_material", application)

Add following to your app/view/layouts/application.html.erb in <head> section:

<link href="//cdn.jsdelivr.net/npm/material-components-web@latest/dist/material-components-web.min.css" rel="stylesheet">
<script src="//cdn.jsdelivr.net/npm/material-components-web@latest/dist/material-components-web.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">

Material Components for Web customizations

For supporting custom styling for you components, consider including following in your application stylesheet:

@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,400;0,600;1,400;1,600&display=swap');

html, body, label {
    font-family: 'Roboto', sans-serif;
}

html, body {
    scroll-behavior: smooth;
}

html [id], body [id] {
    scroll-margin: 120px !important;
}

:root {
    --real-primary: #5d7dd4;
    --real-secondary: #607D8B;
    --real-warn: rgb(244, 67, 54);

    --mdc-theme-primary: var(--real-primary);
    --mdc-theme-secondary: var(--real-secondary);
    --mdc-dialog-z-index: 100;
    --mdc-ripple-color: white;
}

.turbo-progress-bar {
    background-color: #77a1d6;
    filter: brightness(90%);
}

.mdc-button.menu-item {
    --mdc-theme-primary: white;
}

.mdc-button--accent:not(.mdc-button--raised):not([disabled]) {
    color: #77a1d6;
    color: var(--mdc-theme-secondary, #77a1d6);
}

.mdc-button--accent.mdc-button--raised:not([disabled]) {
    background-color: #77a1d6;
    background-color: var(--mdc-theme-secondary, #77a1d6);
}

.mdc-button.mdc-button--accent .mdc-button__ripple::before, .mdc-button.mdc-button--accent .mdc-button__ripple::after {
    background-color: #77a1d6;
    background-color: var(--mdc-theme-secondary, #77a1d6);
}

.mdc-button--warn:not(.mdc-button--raised):not([disabled]) {
    color: rgb(244, 67, 54);
    color: var(--real-warn, rgb(244, 67, 54));
}

.mdc-button--warn.mdc-button--raised:not([disabled]) {
    background-color: rgb(244, 67, 54);
    background-color: var(--real-warn, rgb(244, 67, 54));
}

.mdc-button.mdc-button--warn .mdc-button__ripple::before, .mdc-button.mdc-button--warn .mdc-button__ripple::after {
    background-color: rgb(244, 67, 54);
    background-color: var(--real-warn, rgb(244, 67, 54));
}

.mdc-button--white:not(.mdc-button--raised):not([disabled]) {
    color: white;
}

.mdc-button--white.mdc-button--raised:not([disabled]) {
    background-color: white;
}

.mdc-button.mdc-button--white .mdc-button__ripple::before, .mdc-button.mdc-button--white .mdc-button__ripple::after {
    background-color: white;
}

.mdc-text-field:not(.mdc-text-field--label-floating) .iti__flag-container {
    display: none !important;
}

.mdc-drawer .mdc-deprecated-list-item {
    margin: 0;
    border-radius: 0;
}

aside.mdc-drawer:not(.mdc-drawer--right) {
    box-shadow: 0px 5px 5px -3px rgb(0 0 0 / 20%), 0px 8px 10px 1px rgb(0 0 0 / 14%), 0px 3px 14px 2px rgb(0 0 0 / 12%);
}

aside.mdc-drawer.main-drawer {
    background-color: #2d323e;
}

.mdc-drawer--right.mdc-drawer--dismissible {
    right: 0 !important;
    left: initial !important;
}

.mdc-drawer--right.mdc-drawer.mdc-drawer--open:not(.mdc-drawer--closing) + .mdc-drawer-app-content {
    margin-right: 16rem !important;
    margin-left: 0 !important;
}

.mdc-drawer--right.mdc-drawer.mdc-drawer--open.mdc-drawer--closing + .mdc-drawer-app-content {
    transition: margin-right 200ms 15ms linear;
}

.mdc-drawer--right.mdc-drawer.mdc-drawer--open.mdc-drawer--openening.mdc-drawer--closing + .mdc-drawer-app-content {
    transition: margin-right 200ms 15ms linear;
}

.mdc-drawer--right.mdc-drawer--animate {
    transform: translateX(100%) !important;
}

.mdc-drawer--right.mdc-drawer--closing {
    transform: translateX(100%) !important;
}

.mdc-drawer--right.mdc-drawer--opening {
    transform: translateX(0) !important;
}

.mdc-dialog__title::before {
    content: none !important;
}

.mdc-dialog__title {
    padding-top: 1rem;
}

.clip-path-bottom {
    clip-path: inset(-8px -8px 0px -8px);
}

.clip-path-top {
    clip-path: inset(0px -8px -8px -8px);
}

.mdc-drawer.mdc-drawer--open:not(.mdc-drawer--closing) + .mdc-drawer-app-content .mdc-top-app-bar {
    width: calc(100vw - 16rem);
}

.mdc-text-field .field_with_errors {
    width: 100%;
}

.bg-secondary .mdc-tab-indicator .mdc-tab-indicator__content--underline {
    border-color: white !important;
}

.bg-secondary .mdc-tab--active .mdc-tab__text-label {
    color: white !important;
}

.bg-secondary .mdc-tab .mdc-tab__icon {
    color: white !important;
}

.bg-secondary .mdc-tab--active .mdc-tab__icon {
    color: white !important;
}

.bg-secondary .mdc-tab:not(.mdc-tab--active) .mdc-tab__text-label {
    color: white !important;
}

.mdc-chip.red {
    background-color: #f44336 !important;
    color: white !important;
}

.mdc-chip.red .mdc-chip__icon {
    color: white !important;
}

Tailwind Forms customizations leakage

This gem uses Tailwind for additional customizations, I am noticed that @tailwindcss/forms leaking to Material inputs adding partial white backgrounds. For now I would recommend to disable forms plugin while using this gem.

Installation

Add this line to your application's Gemfile:

gem "turbo_material"

And then execute:

$ bundle

Or install it yourself as:

$ gem install turbo_material

Available components

Input

Implements Material Design Textfield component.

<%= material_input label: 'New password', name: 'password', required: true, parent: resource,
                   id: "user-password", form: form, type: 'password',
                   value: resource.password %>
Options
OptionTypeDescription
labelStringInput label text
nameStringName of the input
requiredBooleanWhether the input is required
disabledBooleanWhether the input is disabled
parentObjectParent object
idStringID of the input
formObjectForm object
typeStringType of the input conforming to HTML input type specification (e.g., text, password)
valueStringValue of the input
styleStringStyle of the input (filled, outlined)
custom_cssStringCustom CSS class
custom_controllerStringCustom Stimulus controller

Checkbox

Implements Material Design Checkbox component.

<%= material_checkbox name: 'remember_me', id: 'remember-me', form: form, label: 'Remember me' %>
Options
OptionTypeDescription
nameStringCheckbox name
idStringCheckbox ID
formObjectForm object
labelStringCheckbox label
disabledBooleanWhether the checkbox is disabled
checkedBooleanWhether the checkbox is checked
checked_valueStringValue when the checkbox is checked
unchecked_valueStringValue when the checkbox is unchecked
source_overrideStringUsed to populate checkbox value from another form field

Radio button

Implements Material Design Radio button component.

<%= material_radio name: 'option', id: 'option-1', form: form, label: 'Option 1' %>
Options
OptionTypeDescription
nameStringRadio button name
idStringRadio button ID
formObjectForm object
labelStringRadio button label
disabledBooleanWhether the radio button is disabled
valueStringRadio button value
parentObjectRadio button parent

Switch button

Implements Material Design Switch button component.

<%= material_switch label: 'Switch', true_label: 'On', false_label: 'Off' %>
Options
OptionTypeDescription
labelStringSwitch button label text
disabledBooleanWhether the switch is disabled
requiredBooleanWhether the switch is required
true_labelStringText that displays when switch is on
false_labelStringText that displays when switch is off

Select

Implements Material Design Select component.

<%= material_select name: 'country', id: 'country', form: form, options: Carmen::Country.all, selected_text: 'Select country' %>
Options
OptionTypeDescription
nameStringSelect name
idStringSelect ID
disabledBooleanWhether the select is disabled
requiredBooleanWhether the select is required
formObjectForm object
optionsArraySelect options
selected_textStringText that displays when nothing is selected
fixedBooleanWhether select uses mdc-menu-surface--fixed or mdc-menu-surface--fullwidth
outlinedBooleanWhether the select is outlined
additional_classesStringAdditional CSS classes for select
hintStringHint text to display

Chip Set

Implements Material Design Chip Set component.

<%= material_chip_set chips: [{label: 'Chip 1'}, {label: 'Chip 2'}] %>
Options
OptionTypeDescription
chipsArrayArray of chips to be included in the chip set

Chip

Implements Material Design Chip component.

<%= material_chip label: 'Chip' %>
Options
OptionTypeDescription
labelStringChip label text

Chips Input

Implements Material Design Chips Input component.

<%= material_chips_input form: form, name: 'tags', label: 'Tags', selected: [{label: 'Tag 1'}, {label: 'Tag 2'}], options: [{label: 'Option 1'}, {label: 'Option 2'}] %>
Options
OptionTypeDescription
formObjectForm object
disabledBooleanWhether the input is disabled
requiredBooleanWhether the input is required
nameStringName of the input
labelStringInput label text
idStringID of the input
frameStringFrame of the input
suffixStringSuffix of the input
typeStringType of the input
urlStringURL for fetching options
selectedArrayArray of selected chips
optionsArrayArray of available options
valueStringValue of the input
fixedBooleanWhether the input is fixed
prefetchBooleanWhether to prefetch options
additional_query_paramsHashAdditional query parameters

Chips Select

Implements Material Design Chips Select component.

<%= material_chips_select form: form, name: 'tags', label: 'Tags', options: [{label: 'Option 1', value: '1'}, {label: 'Option 2', value: '2'}] %>
Options
OptionTypeDescription
formObjectForm object
disabledBooleanWhether the select is disabled
requiredBooleanWhether the select is required
nameStringName of the select
labelStringSelect label text
idStringID of the select
valueStringValue of the select
urlStringURL for fetching options
frameStringFrame of the select
source_overrideStringSource override for the select
optionsArrayArray of available options
confirmableBooleanWhether the select is confirmable
query_stringStringQuery string for fetching options
modal_nameStringName of the modal
modal_urlStringURL of the modal
chip_cssStringCSS class for the chip
fixedBooleanWhether the select is fixed

Data Table

Implements Material Design Data Table component.

<%= material_data_table name: 'Users', table_body: 'users-table-body', url: users_path, table_params: params, records: @users, selected_records: @selected_users, pagy: @pagy, table_headers_partial: 'users/table_headers', table_contents_partial: 'users/table_contents' %>
Options
OptionTypeDescription
nameStringName of the data table
table_bodyStringID of the table body
urlStringURL for fetching table data
table_paramsHashParameters for the table
recordsArrayArray of records to be displayed
selected_recordsArrayArray of selected records
pagyObjectPagy object for pagination
table_headers_partialStringPartial name for table headers
table_contents_partialStringPartial name for table contents

Data Table Row Checkbox

Implements Material Design Data Table Row Checkbox component.

<%= material_data_table_row_checkbox id: record.id, checked: @selected_users.include?(record.id.to_s) %>
Options
OptionTypeDescription
idStringID of the row checkbox
checkedBooleanWhether the row checkbox is checked

Data Table Sortable Header

Implements Material Design Data Table Sortable Header component.

<%= material_data_table_sortable_header label: 'First Name', sort_value: aria_sort('first_name'), column_id: 'first_name' %>
Options
OptionTypeDescription
labelStringLabel of the sortable header
sort_valueStringValue of the sortable header
column_idStringID of the sortable header
aria_sort Helper

aria_sort helper is used to generate sort value for the header. It accepts one argument, which is the column name. It returns descending or ascending value depending on the current values of params[:order] and params[:reverse].

<%= aria_sort('first_name') %>

Data Table Header

Implements Material Design Data Table Header component.

<%= material_data_table_header %>
Options
OptionTypeDescription
labelStringLabel of the header
column_idStringID of the header

Menu Button

Implements Material Design Menu Button component.

<%= material_menu_button button_text: 'Menu', menu_contents_partial: 'common/menu_contents' %>

or with block

<%= material_menu_button button_text: 'Menu' do %>
  Contents
<% end %>
Options
OptionTypeDescription
button_textStringText of the menu button
menu_contents_partialStringPartial for menu contents
logout_pathStringPath for logout
custom_cssStringCustom CSS class
custom_surface_cssStringCustom CSS class for the menu surface

Modal

Implements Material Design Modal component.

<%= material_modal title: 'Modal Title', contents_partial: 'common/modal_contents' %>

or with block

<%= material_modal title: 'Modal Title' do %>
  Contents
<% end %>
Options
OptionTypeDescription
titleStringTitle of the modal
contents_partialStringPartial for modal contents
cancel_button_textStringText of the cancel button
ok_button_textStringText of the ok button
openedBooleanWhether the modal is opened
dialog_surface_custom_cssStringCustom CSS class for the dialog surface
close_action_urlStringURL for navigating to on modal close
formObjectForm object for form-centric modals, replaces ok button with form submit

Tooltip

Implements Material Design Tooltip component.

<%= material_tooltip id: dom_id(record) do %>
  Tooltip content
<% end %>
Options
OptionTypeDescription
idStringDOM ID of the element we displaying the tooltip for

Lookbook documentation for components

Gem implements Lookbook documentation for all components. To use it in the application, add gem 'lookbook' to your Gemfile and run bundle install. Then add following to your config/application.rb:

config.lookbook.preview_paths = [TurboMaterial::Engine.root.join('lib/lookbook')]
config.lookbook.preview_controller = 'TurboMaterial::LookbookController'

Or extend your existing config for lookbook.preview_paths with same value.

Contributing

This gem is open for new contributions. Use Material Components for Web documentation as a references for missing functionality.

License

The gem is available as open source under the terms of the MIT License.

FAQs

Package last updated on 12 Sep 2024

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc