@use "../../themes/ionic/ionic.globals.scss" as globals; // Ionic Checkbox // -------------------------------------------------- :host { // Border --border-width: #{globals.$ion-border-size-025}; --border-style: #{globals.$ion-border-style-solid}; --border-color: #{globals.$ion-primitives-neutral-800}; --checkmark-width: #{globals.$ion-scale-400}; --checkmark-height: var(--checkmark-width); // Focus --focus-ring-color: #{globals.$ion-border-focus-default}; --focus-ring-width: #{globals.$ion-border-size-050}; --focus-ring-offset: #{globals.$ion-space-050}; // Size --size: #{globals.$ion-scale-600}; --checkbox-background-checked: #{globals.$ion-semantics-primary-base}; --border-color-checked: #{globals.$ion-semantics-primary-base}; --checkmark-color: #{globals.$ion-primitives-base-white}; --transition: none; display: inline-block; position: relative; cursor: pointer; user-select: none; z-index: 2; // Checkbox Target area // -------------------------------------------------- &::after { @include globals.position(50%, 0, null, 0); position: absolute; height: 100%; min-height: globals.$ion-scale-1200; transform: translateY(-50%); content: ""; cursor: pointer; z-index: 1; } .native-wrapper { position: relative; } } :host(.in-item) { flex: 1 1 0; width: 100%; height: 100%; } /** * Checkbox can be slotted * in components such as item and * toolbar which is why we do not * limit the below behavior to just ion-item. */ :host([slot="start"]), :host([slot="end"]) { // Reset the flex property when the checkbox // is slotted to avoid growing the element larger // than its content. flex: initial; width: auto; } .checkbox-wrapper { display: flex; flex-grow: 1; align-items: center; height: inherit; cursor: inherit; } .label-text-wrapper { color: globals.$ion-primitives-neutral-1200; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; } :host(.in-item) .label-text-wrapper { @include globals.margin(globals.$ion-space-250, null, globals.$ion-space-250, null); } :host(.in-item.checkbox-label-placement-stacked) .label-text-wrapper { @include globals.margin(globals.$ion-space-250, null, globals.$ion-space-400, null); } :host(.in-item.checkbox-label-placement-stacked) .native-wrapper { @include globals.margin(null, null, globals.$ion-space-250, null); } /** * If no label text is placed into the slot * then the element should be hidden otherwise * there will be additional margins added. */ .label-text-wrapper-hidden { display: none; } input { @include globals.visually-hidden(); } .native-wrapper { @include globals.border-radius(var(--border-radius)); display: flex; flex-shrink: 0; align-items: center; justify-content: center; width: var(--size); height: var(--size); transition: var(--transition); border-width: var(--border-width); border-style: var(--border-style); border-color: var(--border-color); background: var(--checkbox-background); box-sizing: border-box; } .checkbox-icon { position: relative; width: var(--checkmark-width); height: var(--checkmark-height); } .checkbox-icon path { fill: var(--checkmark-color); opacity: 0; } // TODO move all justify and alignment styles to the common file // when it is created // Justify Content // --------------------------------------------- :host(.checkbox-justify-space-between) .checkbox-wrapper { justify-content: space-between; } :host(.checkbox-justify-start) .checkbox-wrapper { justify-content: start; } :host(.checkbox-justify-end) .checkbox-wrapper { justify-content: end; } // Align Items // --------------------------------------------- :host(.checkbox-alignment-start) .checkbox-wrapper { align-items: start; } :host(.checkbox-alignment-center) .checkbox-wrapper { align-items: center; } // Justify Content & Align Items // --------------------------------------------- // The checkbox should be displayed as block when either justify // or alignment is set; otherwise, these properties will have no // visible effect. :host(.checkbox-justify-space-between), :host(.checkbox-justify-start), :host(.checkbox-justify-end), :host(.checkbox-alignment-start), :host(.checkbox-alignment-center) { display: block; } // Label Placement - Start // ---------------------------------------------------------------- /** * Label is on the left of the checkbox in LTR and * on the right in RTL. */ :host(.checkbox-label-placement-start) .checkbox-wrapper { flex-direction: row; } :host(.checkbox-label-placement-start) .label-text-wrapper { /** * The margin between the label and * the checkbox should be on the end * when the label sits at the start. */ @include globals.margin(null, globals.$ion-space-400, null, 0); } // Label Placement - End // ---------------------------------------------------------------- /** * Label is on the right of the checkbox in LTR and * on the left in RTL. */ :host(.checkbox-label-placement-end) .checkbox-wrapper { flex-direction: row-reverse; } /** * The margin between the label and * the checkbox should be on the start * when the label sits at the end. */ :host(.checkbox-label-placement-end) .label-text-wrapper { @include globals.margin(null, 0, null, globals.$ion-space-400); } // Label Placement - Fixed // ---------------------------------------------------------------- :host(.checkbox-label-placement-fixed) .label-text-wrapper { /** * The margin between the label and * the checkbox should be on the end * when the label sits at the start. */ @include globals.margin(null, globals.$ion-space-400, null, 0); } /** * Label is on the left of the checkbox in LTR and * on the right in RTL. Label also has a fixed width. */ :host(.checkbox-label-placement-fixed) .label-text-wrapper { flex: 0 0 100px; width: 100px; min-width: 100px; max-width: 200px; } // Label Placement - Stacked // ---------------------------------------------------------------- /** * Label is on top of the checkbox. */ :host(.checkbox-label-placement-stacked) .checkbox-wrapper { flex-direction: column; } :host(.checkbox-label-placement-stacked) .label-text-wrapper { @include globals.transform(scale(0.75)); /** * The margin between the label and * the checkbox should be on the bottom * when the label sits at the top. */ @include globals.margin(null, 0, globals.$ion-space-400, 0); /** * Label text should not extend * beyond the bounds of the checkbox. */ max-width: calc(100% / 0.75); } // TODO(ROU-10796): uncomment this when the scss compilation issue is fixed // :host(.checkbox-label-placement-stacked.checkbox-alignment-start) .label-text-wrapper { // @include globals.transform-origin(start, top); // } // :host(.checkbox-label-placement-stacked.checkbox-alignment-center) .label-text-wrapper { // @include globals.transform-origin(center, top); // } // Ionic Design Checkbox Sizes // -------------------------------------------------- :host(.checkbox-size-small) { --size: #{globals.$ion-scale-400}; } // Checked / Indeterminate Checkbox // --------------------------------------------- :host(.checkbox-checked) .native-wrapper, :host(.checkbox-indeterminate) .native-wrapper { border-color: var(--border-color-checked); background: var(--checkbox-background-checked); } :host(.checkbox-checked) .checkbox-icon path, :host(.checkbox-indeterminate) .checkbox-icon path { opacity: 1; } // Ionic Design Checkbox Invalid // -------------------------------------------------- :host(.ion-invalid) { --focus-ring-color: #{globals.$ion-border-focus-error}; .native-wrapper { border-color: globals.$ion-semantics-danger-800; } } // Checkbox Disabled // -------------------------------------------------- :host(.checkbox-disabled) { pointer-events: none; } // Checkbox overrides the disabled state mixin properties // to fix positioning issues, as the top and left properties // cause the overlay to start inside the border. We unset // these position properties and inherit width and height to // ensure the border is covered. :host(.checkbox-disabled) .native-wrapper:after { @include globals.disabled-state(); @include globals.position(unset, unset, unset, unset); width: inherit; height: inherit; } // disabled, checked checkbox :host(.checkbox-disabled.checkbox-checked) .native-wrapper { border-width: globals.$ion-border-size-0; background-color: globals.$ion-semantics-primary-base; } // Checkbox Hover // -------------------------------------------------------- @media (any-hover: hover) { :host(:hover) .native-wrapper { background-color: globals.$ion-primitives-neutral-100; } :host(:hover.checkbox-checked) .native-wrapper, :host(:hover.checkbox-indeterminate) .native-wrapper { background-color: globals.$ion-semantics-primary-800; } } // Checkbox Focus // -------------------------------------------------- // Only show the focus ring when the checkbox is focused and not disabled :host(.ion-focused:not(.checkbox-disabled)) .native-wrapper { outline: var(--focus-ring-width) globals.$ion-border-style-solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); } // Checkbox: Active // -------------------------------------------------------- :host(.ion-activated) .native-wrapper { background-color: globals.$ion-primitives-neutral-200; } :host(.ion-activated.checkbox-checked) .native-wrapper, :host(.ion-activated.checkbox-indeterminate) .native-wrapper { background-color: globals.$ion-semantics-primary-900; } // Ionic Design Checkbox Shapes // -------------------------------------------------- :host(.checkbox-shape-soft) { --border-radius: #{globals.$ion-border-radius-100}; } :host(.checkbox-size-small.checkbox-shape-soft) { --border-radius: #{globals.$ion-border-radius-025}; } :host(.checkbox-shape-rectangular) { --border-radius: #{globals.$ion-border-radius-0}; } .checkbox-wrapper { min-height: #{globals.$ion-scale-1200}; }