docbrown/app/assets/stylesheets/components/forms.scss
2023-10-11 12:17:05 -04:00

493 lines
10 KiB
SCSS

@import '../config/import';
@import './buttons';
@import 'react-dates/lib/css/_datepicker.css';
%form-styling {
--border-width: 1.5px;
background-color: var(--form-bg);
border: var(--border-width) solid var(--form-border);
color: var(--body-color);
appearance: none;
-webkit-appearance: none;
border-radius: var(--radius);
transition: all var(--transition-props);
&-hover {
border-color: var(--form-border-hover);
}
&-focus {
background-color: var(--form-bg-focus);
border-color: var(--focus);
box-shadow: 0 0 0 1px var(--focus);
}
&-disabled {
opacity: 0.6;
}
&-checked {
background-color: var(--form-border-focus);
border-color: var(--form-border-focus);
color: var(--form-bg-focus);
background-position: center center;
background-repeat: no-repeat;
}
}
// Text inputs and textareas.
.crayons-textfield {
line-height: var(--lh-base);
padding: calc(0.5em - var(--border-width)) 0.5em;
font-family: inherit;
font-size: var(--fs-base);
width: 100%;
resize: vertical;
@extend %form-styling;
&::placeholder {
color: var(--form-placeholder-color);
}
&:hover {
@extend %form-styling-hover;
}
&:focus {
@extend %form-styling-focus;
}
&--disabled,
&[disabled] {
@extend %form-styling-disabled;
}
&::-ms-clear {
display: none;
}
&::-webkit-date-and-time-value {
min-height: 1.5em;
}
&--icon {
padding-left: var(--su-7);
}
}
// Checkboxes, Radios
.crayons-checkbox,
.crayons-radio {
@extend %form-styling;
width: 1.125em;
height: 1.125em;
cursor: pointer;
background-position: center center;
vertical-align: middle;
flex-shrink: 0;
&:hover {
@extend %form-styling-hover;
}
&--disabled,
&[disabled] {
@extend %form-styling-disabled;
cursor: not-allowed;
}
&--checked,
&:checked {
@extend %form-styling-checked;
background-image: url("data:image/svg+xml,%3Csvg width='12' height='10' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11.157.933a.75.75 0 01.077 1.058L4.817 9.407a.75.75 0 01-1.134 0L.766 6.037a.75.75 0 011.135-.982L4.25 7.77l5.85-6.76a.75.75 0 011.057-.077z' fill='%23fff'/%3E%3C/svg%3E");
&--disabled,
&[disabled] {
@extend %form-styling-disabled;
}
}
}
// Radios
.crayons-radio {
border-radius: 50%;
&--checked,
&:checked {
@extend %form-styling-checked;
background-image: url("data:image/svg+xml,%3Csvg width='6' height='6' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='6' height='6' rx='3' fill='%23fff'/%3E%3C/svg%3E");
}
}
// Selects
.crayons-select {
line-height: var(--lh-base);
padding: calc(0.5em - var(--border-width)) 0.5em;
padding-right: var(--su-7);
font-family: inherit;
font-size: var(--fs-base);
width: 100%;
position: relative;
outline: none;
@extend %form-styling;
background-image: var(--select-icon);
background-position: calc(100% - var(--su-2)) calc(50% - 1px);
background-repeat: no-repeat;
&:hover {
@extend %form-styling-hover;
}
&:focus {
@extend %form-styling-focus;
}
&--disabled,
&[disabled] {
@extend %form-styling-disabled;
}
&::-ms-clear {
display: none;
}
}
///////////////////////////////////////////////////
// Full Fields markup
.crayons-field {
display: flex;
flex-flow: column;
font-size: var(--fs-base); // todo: do we need it?
$this: &;
&__label {
color: var(--label-primary);
font-weight: var(--fw-medium);
+ .crayons-field__description {
margin-top: 0;
}
&.required:after {
content: '*';
}
}
&__required {
color: var(--accent-danger);
padding: 0 var(--su-1);
display: inline-block;
}
&__description {
color: var(--label-secondary);
font-size: var(--fs-s);
font-weight: var(--fw-normal); // for when it's inside --label
margin: 0; //todo remove
}
> * + * {
margin-top: var(--su-2);
}
&--checkbox,
&--radio {
display: grid;
grid-template-columns: 1.5em 1fr;
grid-gap: var(--su-2);
border-radius: var(--radius);
transition: all var(--transition-props);
&:hover {
background: var(--body-bg);
box-shadow: 0 0 0 var(--su-1) var(--body-bg);
}
#{$this}__label {
margin-top: 0;
padding-right: var(
--su-2
); // adding this to make hovers look slightly better.
}
}
.crayons-checkbox,
.crayons-radio {
margin: 0.1875em; // centering checkbox within 1.5em grid cell.
justify-self: center;
}
}
input[type='file']::file-selector-button {
@extend .crayons-btn;
@extend .crayons-btn--secondary;
}
.crayons-fields {
display: flex;
flex-flow: column;
$this: &;
&:not(#{$this}--horizontal) {
> .crayons-field + .crayons-field {
margin-top: var(--su-4);
}
}
&--horizontal {
flex-flow: row;
flex-wrap: wrap;
> .crayons-field:not(:last-child) {
margin-right: var(--su-4);
}
}
}
///////////////////////////////////////////////////
.crayons-textfield {
&--ghost,
&--ghost:hover,
&--ghost:focus,
&--ghost[disabled] {
background: transparent;
border: none;
padding: 0;
margin: 0;
outline: none;
width: 100%;
box-shadow: none;
resize: none;
transition: none;
}
}
textarea.crayons-textfield.crayons-textfield--ghost {
white-space: pre-wrap;
}
.c-color-picker {
--swatch-width: var(--su-7);
--swatch-height: var(--su-7);
--input-padding-left: calc(var(--swatch-width) + var(--su-3));
&__input {
padding-left: var(--input-padding-left);
}
&__swatch {
width: var(--swatch-width);
height: var(--swatch-height);
border: 1px solid var(--swatch-border-color);
top: var(--su-1);
left: var(--su-1);
z-index: var(--z-elevate);
}
&__popover {
min-width: min-content;
& .react-colorful {
padding: var(--su-2);
border-radius: var(--radius);
background: var(--card-bg);
box-shadow: var(--shadow-1);
width: 220px;
height: 160px;
&__pointer {
cursor: pointer;
}
&__saturation {
margin: 0 0 var(--su-2) 0;
border-radius: var(--radius);
}
&__saturation-pointer {
width: var(--fs-s);
height: var(--fs-s);
border: 2px solid var(--card-bg);
border-radius: 50%;
}
&__hue {
height: var(--fs-xs);
border-radius: var(--radius);
}
&__hue-pointer {
border: 2px solid var(--card-bg);
border-radius: 1px;
width: var(--fs-s);
height: calc(100% + 8px);
}
}
}
}
.c-date-picker {
// The following class names come from the react-dates library we use for date pickers.
// We group them in the c-date-picker class so we can override styles via specificity.
.DateRangePickerInput {
@extend .crayons-textfield;
padding: var(--su-1) var(--su-2);
&_calendarIcon {
@extend .c-btn;
padding: 0;
}
.DateInput_input {
background-color: var(--form-bg);
color: var(--body-color);
font-size: var(--fs-base);
&__focused {
border-bottom-color: var(--focus);
}
}
&_arrow_svg {
fill: var(--body-color);
}
&_clearDates {
@extend .c-btn;
position: absolute;
padding: var(--su-2);
&:hover,
&:focus-visible {
border-radius: var(--radius);
}
}
}
&--error {
.DateRangePickerInput {
border-color: var(--accent-danger);
}
}
.DateRangePicker:focus-within {
.DateRangePickerInput {
border-color: var(--focus);
}
}
.CalendarDay {
border-color: var(--date-border-color);
&__default:hover {
background-color: transparent;
position: relative;
// We set this in ::after selector to avoid neighbouring date borders overlapping our styles
&::after {
border: 1px solid var(--hover-date-border-color);
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
content: '';
}
}
&__today {
color: var(--current-date-color);
}
// Everything selected including everything between a range of dates
&__selected_span {
background: var(--selected-range-bg);
color: var(--selected-range-color);
border-color: var(--selected-date-border);
&:active,
&:hover {
background: var(--selected-range-bg);
color: var(--fs-base);
border-color: var(--selected-date-border);
}
}
// The selected start and end dates
&__selected {
background: var(--selected-date-bg);
color: var(--selected-date-color);
&:hover {
background: var(--selected-date-bg);
color: var(--selected-date-color);
border-color: var(--selected-date-border);
}
}
// Used when end date is not yet selected. Targets dates between mouse and said end date
&__hovered_span,
&__hovered_span:hover {
background: var(--selected-range-bg);
color: var(--selected-range-color);
border-color: var(--selected-date-border);
}
}
.CalendarMonthGrid__vertical {
margin-top: var(--su-2);
.c-date-picker__month {
margin-top: var(--su-2);
}
.CalendarMonth {
&_caption {
padding-bottom: var(--su-2);
padding-top: var(--su-3);
}
}
}
// The triangular ? button which shows keyboard shortcut information
.DayPickerKeyboardShortcuts_buttonReset {
&::before {
border-right-color: var(--accent-brand);
}
&:hover::before {
border-right-color: var(--accent-brand-lighter);
}
}
.DayPickerNavigation {
display: flex;
justify-content: space-between;
&_button {
@extend .c-btn;
margin: var(--su-6) var(--su-3) 0 var(--su-3);
height: min-content;
padding: var(--su-1);
&:hover,
&:focus {
background-color: var(--bg-hover);
}
&__disabled {
opacity: 0.2;
cursor: not-allowed;
}
}
}
&__errors {
color: var(--accent-danger);
}
}