diff --git a/resources/css/components.css b/resources/css/components.css index bedf3183..d6309bee 100644 --- a/resources/css/components.css +++ b/resources/css/components.css @@ -52,6 +52,7 @@ @import './components/table.css'; @import './components/sort-header.css'; @import './components/pagination.css'; +@import './components/datepicker.css'; /* Containment */ diff --git a/resources/css/components/datepicker.css b/resources/css/components/datepicker.css index 1d10d92e..1a077731 100644 --- a/resources/css/components/datepicker.css +++ b/resources/css/components/datepicker.css @@ -13,35 +13,49 @@ * DateInput.kt; the docked picker's from material-web's md-comp-date-picker-docked tokens (v0_192). * Apache-2.0. * - * [data-datepicker] the root: the field, its support line, the dialog - * [data-datepicker-support] the hint, a server error, or what is wrong with the typed date - * [data-datepicker-picker] the ; data-presentation="docked" | "modal" | "full" - * [data-datepicker-surface] - * [data-datepicker-header] modal only: title, headline, switch - * [data-datepicker-full] full only: [data-datepicker-app-bar] (close, switch, Save) - * and [data-datepicker-full-headline] (title, headline) - * [data-datepicker-calendar] the scroller, full screen - * [data-datepicker-nav] month and year: one menu button and arrows (modal), - * or a month and a year stepper (docked, data-docked) - * [data-datepicker-grid] the weekdays and six weeks of [data-datepicker-day] cells: - * data-today, data-selected, data-start, data-end, - * data-between, data-outside, data-blank, aria-disabled — - * full screen, every month of the window under a - * [data-datepicker-month-label] row - * [data-datepicker-years] the modal year grid - * [data-datepicker-menu] a docked month or year list of [data-datepicker-option]s - * [data-datepicker-entry] the text field(s) of the modal input - * [data-datepicker-actions] Cancel and OK + * [data-md-datepicker] the root: the field, its support line, the dialog + * [data-md-datepicker-support] the hint, a server error, or what is wrong with the typed date + * [data-md-datepicker-picker] the ; data-md-presentation="docked" | "modal" | "full" + * [data-md-datepicker-surface] + * [data-md-datepicker-header] modal only: title, headline, switch + * [data-md-datepicker-full] full only: [data-md-datepicker-app-bar] (close, switch, Save) + * and [data-md-datepicker-full-headline] (title, headline) + * [data-md-datepicker-calendar] the scroller, full screen + * [data-md-datepicker-nav] month and year: one menu button and arrows (modal), + * or a month and a year stepper (docked, data-md-docked) + * [data-md-datepicker-grid] the weekdays and six weeks of [data-md-datepicker-day] + * cells: data-md-today, data-md-selected, data-md-start, + * data-md-end, data-md-between, data-md-outside, + * data-md-blank, aria-disabled — full screen, every month + * of the window under a [data-md-datepicker-month-label] row + * [data-md-datepicker-years] the modal year grid + * [data-md-datepicker-menu] a docked month or year list of [data-md-datepicker-option]s + * [data-md-datepicker-entry] the text field(s) of the modal input + * [data-md-datepicker-actions] Cancel and OK * - * Every state layer is the content colour at 8% on hover (only where a pointer can hover) and 10% on - * focus and press; keyboard focus adds the package's 3px secondary ring. + * Cancel, OK and the icon buttons in the app bar and the nav are , which draws its own + * state layer and focus ring from the foundation classes. The day, the year, the menu button and + * the list option keep their own hand-rolled state layer and focus ring, as `data-md-field-button` + * does (field.css): each interactive box is bigger than the round indicator drawn inside it (a + * day's cell is 48px, its indicator 40px; a menu button and an option are full rows), which the + * foundation's classes, fixed to the element they are on, cannot draw — and `:focus-visible` only + * ever matches the element actually focused, never a smaller child inside it. + * + * Every state layer here is the content colour at 8% on hover (only where a pointer can hover) and + * 10% on focus and press; keyboard focus adds the package's 3px secondary ring. */ -@layer components { +@layer material.reset, material.tokens, material.base, material.layout, material.components, material.text, material.visibility; + +@import './field.css'; +@import './icon.css'; +@import './button.css'; + +@layer material.components { /* ---- The support line under the field ------------------------------------------------------ */ /* The padding is on the lines, not the box, so a box with nothing to say takes no room. */ - [data-datepicker-support] { + [data-md-datepicker-support] { --datepicker-pad: 1rem; color: var(--md-sys-color-on-surface-variant); @@ -49,25 +63,25 @@ letter-spacing: var(--md-sys-typescale-body-sm-tracking); } - [data-datepicker-support] > * { + [data-md-datepicker-support] > * { padding: 0.25rem var(--datepicker-pad) 0; } - [data-datepicker-support][data-size="sm"] { + [data-md-datepicker-support][data-md-size='sm'] { --datepicker-pad: 0.75rem; } - [data-datepicker-support][data-size="xs"] { + [data-md-datepicker-support][data-md-size='xs'] { --datepicker-pad: 0.625rem; } - [data-datepicker-error] { + [data-md-datepicker-error] { color: var(--md-sys-color-error); } /* ---- The dialog ---------------------------------------------------------------------------- */ - [data-datepicker-picker] { + [data-md-datepicker-picker] { inset: auto; width: 22.5rem; max-width: calc(100vw - 1rem); @@ -80,7 +94,7 @@ color: var(--md-sys-color-on-surface); } - [data-datepicker-picker]:popover-open { + [data-md-datepicker-picker]:popover-open { top: anchor(bottom); left: anchor(left); margin-block: 0.25rem; @@ -92,12 +106,12 @@ } @starting-style { - [data-datepicker-picker]:popover-open { + [data-md-datepicker-picker]:popover-open { opacity: 0; } } - [data-datepicker-picker]:modal { + [data-md-datepicker-picker]:modal { inset: 0; margin: auto; opacity: 1; @@ -108,17 +122,17 @@ } @starting-style { - [data-datepicker-picker]:modal { + [data-md-datepicker-picker]:modal { opacity: 0; scale: 0.95; } } - [data-datepicker-picker]:modal::backdrop { + [data-md-datepicker-picker]:modal::backdrop { background-color: color-mix(in srgb, var(--md-sys-color-scrim) 32%, transparent); } - [data-datepicker-surface] { + [data-md-datepicker-surface] { display: flex; flex-direction: column; max-height: inherit; @@ -130,7 +144,7 @@ outline: none; } - [data-datepicker-picker][data-presentation="modal"] [data-datepicker-surface] { + [data-md-datepicker-picker][data-md-presentation='modal'] [data-md-datepicker-surface] { border-radius: var(--md-sys-shape-corner-xl); } @@ -142,7 +156,7 @@ * different order: an app bar, the supporting text and the range as the headline, a divider, the * day-of-week labels, and a vertically scrolling list of months under them, each with its label. * Only the months scroll; everything above them stays where it is. */ - [data-datepicker-picker][data-presentation="full"] { + [data-md-datepicker-picker][data-md-presentation='full'] { inset: 0; width: 100vw; max-width: none; @@ -151,7 +165,7 @@ margin: 0; } - [data-datepicker-picker][data-presentation="full"] [data-datepicker-surface] { + [data-md-datepicker-picker][data-md-presentation='full'] [data-md-datepicker-surface] { height: 100%; max-height: none; padding-block: var(--material-safe-top, env(safe-area-inset-top)) var(--material-safe-bottom, env(safe-area-inset-bottom)); @@ -160,13 +174,13 @@ box-shadow: none; } - [data-datepicker-full] { + [data-md-datepicker-full] { flex: none; border-bottom: 1px solid var(--md-sys-color-outline-variant); color: var(--md-sys-color-on-surface-variant); } - [data-datepicker-app-bar] { + [data-md-datepicker-app-bar] { display: flex; align-items: center; justify-content: space-between; @@ -175,13 +189,13 @@ padding-inline: 0.25rem 0.75rem; } - [data-datepicker-app-bar-actions] { + [data-md-datepicker-app-bar-actions] { display: flex; align-items: center; gap: 0.25rem; } - [data-datepicker-full-headline] { + [data-md-datepicker-full-headline] { display: flex; flex-direction: column; gap: 0.25rem; @@ -189,25 +203,25 @@ } /* The calendar is the only part that scrolls, with the weekday header held at its top. */ - [data-datepicker-picker][data-presentation="full"] [data-datepicker-calendar] { + [data-md-datepicker-picker][data-md-presentation='full'] [data-md-datepicker-calendar] { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; } - [data-datepicker-picker][data-presentation="full"] [data-datepicker-grid] thead th { + [data-md-datepicker-picker][data-md-presentation='full'] [data-md-datepicker-grid] thead th { position: sticky; top: 0; z-index: 1; background-color: var(--md-sys-color-surface-container-high); } - [data-datepicker-picker][data-presentation="full"] [data-datepicker-day] { + [data-md-datepicker-picker][data-md-presentation='full'] [data-md-datepicker-day] { scroll-margin-block: 3rem; } - [data-datepicker-month-label] { + [data-md-datepicker-month-label] { padding: 1.25rem 0 0.5rem; color: var(--md-sys-color-on-surface-variant); font: var(--md-sys-typescale-title-sm); @@ -217,7 +231,7 @@ /* ---- The modal header ---------------------------------------------------------------------- */ - [data-datepicker-header] { + [data-md-datepicker-header] { display: flex; flex-direction: column; justify-content: space-between; @@ -227,17 +241,17 @@ color: var(--md-sys-color-on-surface-variant); } - [data-datepicker-header][data-range] { + [data-md-datepicker-header][data-md-range] { min-height: 8rem; } - [data-datepicker-title] { + [data-md-datepicker-title] { padding: 1rem 0.75rem 0 1.5rem; font: var(--md-sys-typescale-label-lg); letter-spacing: var(--md-sys-typescale-label-lg-tracking); } - [data-datepicker-headline-row] { + [data-md-datepicker-headline-row] { display: flex; align-items: center; justify-content: space-between; @@ -245,7 +259,7 @@ padding: 0 0.75rem 0.75rem 1.5rem; } - [data-datepicker-headline] { + [data-md-datepicker-headline] { min-width: 0; overflow: hidden; text-overflow: ellipsis; @@ -254,14 +268,14 @@ letter-spacing: var(--md-sys-typescale-headline-lg-tracking); } - [data-datepicker-header][data-range] [data-datepicker-headline] { + [data-md-datepicker-header][data-md-range] [data-md-datepicker-headline] { font: var(--md-sys-typescale-title-lg); letter-spacing: var(--md-sys-typescale-title-lg-tracking); } /* ---- Month and year navigation -------------------------------------------------------------- */ - [data-datepicker-nav] { + [data-md-datepicker-nav] { display: flex; flex: none; align-items: center; @@ -271,23 +285,23 @@ color: var(--md-sys-color-on-surface-variant); } - [data-datepicker-nav][data-docked] { + [data-md-datepicker-nav][data-md-docked] { height: 4rem; padding-inline: 0.25rem; } - [data-datepicker-stepper], - [data-datepicker-arrows] { + [data-md-datepicker-stepper], + [data-md-datepicker-arrows] { display: flex; align-items: center; } /* While a year or month list is open the arrows keep their place but are gone, as androidx hides them. */ - [data-datepicker-arrows][data-concealed] { + [data-md-datepicker-arrows][data-md-concealed] { visibility: hidden; } - [data-datepicker-menu-button] { + [data-md-datepicker-menu-button] { position: relative; display: inline-flex; align-items: center; @@ -304,26 +318,26 @@ isolation: isolate; } - [data-datepicker-nav][data-docked] [data-datepicker-menu-button] { + [data-md-datepicker-nav][data-md-docked] [data-md-datepicker-menu-button] { padding-inline: 0.5rem 0.25rem; gap: 0.25rem; } - [data-datepicker-menu-arrow] { + [data-md-datepicker-menu-arrow] { transition: rotate var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } - [data-datepicker-menu-button][aria-expanded="true"] [data-datepicker-menu-arrow] { + [data-md-datepicker-menu-button][aria-expanded='true'] [data-md-datepicker-menu-arrow] { rotate: 180deg; } /* ---- State layers shared by days, years, menu buttons and list rows ------------------------ */ - [data-datepicker-menu-button]::before, - [data-datepicker-day] > span::before, - [data-datepicker-year]::before, - [data-datepicker-option]::before { - content: ""; + [data-md-datepicker-menu-button]::before, + [data-md-datepicker-day] > span::before, + [data-md-datepicker-year]::before, + [data-md-datepicker-option]::before { + content: ''; position: absolute; inset: 0; z-index: -1; @@ -335,47 +349,47 @@ } @media (hover: hover) { - [data-datepicker-menu-button]:hover::before, - [data-datepicker-day]:not([aria-disabled="true"], [data-blank]):hover > span::before, - [data-datepicker-year]:hover::before, - [data-datepicker-option]:not([aria-disabled="true"]):hover::before { + [data-md-datepicker-menu-button]:hover::before, + [data-md-datepicker-day]:not([aria-disabled='true'], [data-md-blank]):hover > span::before, + [data-md-datepicker-year]:hover::before, + [data-md-datepicker-option]:not([aria-disabled='true']):hover::before { opacity: 0.08; } } - [data-datepicker-menu-button]:focus-visible::before, - [data-datepicker-menu-button]:active::before, - [data-datepicker-day]:focus-visible > span::before, - [data-datepicker-day]:not([aria-disabled="true"], [data-blank]):active > span::before, - [data-datepicker-year]:focus-visible::before, - [data-datepicker-year]:active::before, - [data-datepicker-option]:focus-visible::before, - [data-datepicker-option]:not([aria-disabled="true"]):active::before { + [data-md-datepicker-menu-button]:focus-visible::before, + [data-md-datepicker-menu-button]:active::before, + [data-md-datepicker-day]:focus-visible > span::before, + [data-md-datepicker-day]:not([aria-disabled='true'], [data-md-blank]):active > span::before, + [data-md-datepicker-year]:focus-visible::before, + [data-md-datepicker-year]:active::before, + [data-md-datepicker-option]:focus-visible::before, + [data-md-datepicker-option]:not([aria-disabled='true']):active::before { opacity: 0.1; } - [data-datepicker-menu-button]:focus-visible, - [data-datepicker-day]:focus-visible > span, - [data-datepicker-year]:focus-visible { + [data-md-datepicker-menu-button]:focus-visible, + [data-md-datepicker-day]:focus-visible > span, + [data-md-datepicker-year]:focus-visible { outline: 3px solid var(--md-sys-color-secondary); outline-offset: 2px; } - [data-datepicker-option]:focus-visible { + [data-md-datepicker-option]:focus-visible { outline: 3px solid var(--md-sys-color-secondary); outline-offset: -3px; } /* ---- The days ----------------------------------------------------------------------------- */ - [data-datepicker-grid] { + [data-md-datepicker-grid] { width: calc(100% - 1.5rem); margin-inline: 0.75rem; border-collapse: collapse; table-layout: fixed; } - [data-datepicker-grid] th { + [data-md-datepicker-grid] th { height: 3rem; padding: 0; color: var(--md-sys-color-on-surface); @@ -384,7 +398,7 @@ text-align: center; } - [data-datepicker-day] { + [data-md-datepicker-day] { --datepicker-layer: var(--md-sys-color-on-surface-variant); position: relative; @@ -400,7 +414,7 @@ -webkit-tap-highlight-color: transparent; } - [data-datepicker-day] > span { + [data-md-datepicker-day] > span { position: relative; display: grid; place-items: center; @@ -411,30 +425,30 @@ transition: background-color var(--md-sys-motion-effects-fast-duration) var(--md-sys-motion-effects-fast); } - [data-datepicker-day][data-blank] { + [data-md-datepicker-day][data-md-blank] { cursor: default; } /* A docked picker shows the neighbouring months' days, quieter. */ - [data-datepicker-day][data-outside] { + [data-md-datepicker-day][data-md-outside] { color: var(--md-sys-color-on-surface-variant); } - [data-datepicker-day][data-today] { + [data-md-datepicker-day][data-md-today] { --datepicker-layer: var(--md-sys-color-primary); color: var(--md-sys-color-primary); } - [data-datepicker-day][data-today] > span { + [data-md-datepicker-day][data-md-today] > span { box-shadow: inset 0 0 0 1px var(--md-sys-color-primary); } /* A range's band: secondary-container behind the days between its ends, from the middle of each end. */ - [data-datepicker-day][data-between]::before, - [data-datepicker-day][data-start]::before, - [data-datepicker-day][data-end]::before { - content: ""; + [data-md-datepicker-day][data-md-between]::before, + [data-md-datepicker-day][data-md-start]::before, + [data-md-datepicker-day][data-md-end]::before { + content: ''; position: absolute; inset-block: 0.25rem; inset-inline: 0; @@ -442,43 +456,43 @@ background-color: var(--md-sys-color-secondary-container); } - [data-datepicker-day][data-start]::before { + [data-md-datepicker-day][data-md-start]::before { inset-inline-start: 50%; } - [data-datepicker-day][data-end]::before { + [data-md-datepicker-day][data-md-end]::before { inset-inline-end: 50%; } - [data-datepicker-day][data-between] { + [data-md-datepicker-day][data-md-between] { --datepicker-layer: var(--md-sys-color-on-secondary-container); color: var(--md-sys-color-on-secondary-container); } - [data-datepicker-day][data-selected] { + [data-md-datepicker-day][data-md-selected] { --datepicker-layer: var(--md-sys-color-on-primary); color: var(--md-sys-color-on-primary); } - [data-datepicker-day][data-selected] > span { + [data-md-datepicker-day][data-md-selected] > span { background-color: var(--md-sys-color-primary); box-shadow: none; } - [data-datepicker-day][aria-disabled="true"] { + [data-md-datepicker-day][aria-disabled='true'] { color: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); cursor: default; } - [data-datepicker-day][aria-disabled="true"][data-today] > span { + [data-md-datepicker-day][aria-disabled='true'][data-md-today] > span { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); } /* ---- The modal year grid ----------------------------------------------------------------- */ - [data-datepicker-years] { + [data-md-datepicker-years] { display: grid; grid-template-columns: repeat(3, 1fr); align-content: start; @@ -491,7 +505,7 @@ border-bottom: 1px solid var(--md-sys-color-outline-variant); } - [data-datepicker-year] { + [data-md-datepicker-year] { --datepicker-layer: var(--md-sys-color-on-surface-variant); position: relative; @@ -507,14 +521,14 @@ scroll-margin-block: 0.5rem; } - [data-datepicker-year][data-current] { + [data-md-datepicker-year][data-md-current] { --datepicker-layer: var(--md-sys-color-primary); color: var(--md-sys-color-primary); box-shadow: inset 0 0 0 1px var(--md-sys-color-primary); } - [data-datepicker-year][aria-selected="true"] { + [data-md-datepicker-year][aria-selected='true'] { --datepicker-layer: var(--md-sys-color-on-primary); background-color: var(--md-sys-color-primary); @@ -524,7 +538,7 @@ /* ---- The docked month and year lists ------------------------------------------------------ */ - [data-datepicker-menu] { + [data-md-datepicker-menu] { height: 21.5rem; padding-block: 0.5rem; overflow-y: auto; @@ -532,7 +546,7 @@ border-top: 1px solid var(--md-sys-color-outline-variant); } - [data-datepicker-option] { + [data-md-datepicker-option] { --datepicker-layer: var(--md-sys-color-on-surface); position: relative; @@ -551,39 +565,54 @@ isolation: isolate; } - [data-datepicker-option][aria-selected="true"] { + [data-md-datepicker-option][aria-selected='true'] { background-color: var(--md-sys-color-surface-container-highest); } - [data-datepicker-option][aria-disabled="true"] { + [data-md-datepicker-option][aria-disabled='true'] { color: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent); cursor: default; } - [data-datepicker-check] { + [data-md-datepicker-check] { color: var(--md-sys-color-on-surface); } - [data-datepicker-option]:not([aria-selected="true"]) [data-datepicker-check] { + [data-md-datepicker-option]:not([aria-selected='true']) [data-md-datepicker-check] { visibility: hidden; } /* ---- The modal input ------------------------------------------------------------------------ */ - [data-datepicker-entry] { + [data-md-datepicker-entry] { padding: 0.625rem 1.5rem 1rem; } - [data-datepicker-entry-fields][data-range] { + [data-md-datepicker-entry-fields][data-md-range] { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; } + /* ---- The month announcement, spoken but not drawn -------------------------------------------- */ + + /* Same clip as the text classes' `md-visually-hidden`, kept as a hook because a package view + writes no class but the interaction classes (plan step 36). */ + [data-md-datepicker-month-live] { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; + border-width: 0; + } /* ---- Cancel and OK ---------------------------------------------------------------------------- */ - [data-datepicker-actions] { + [data-md-datepicker-actions] { display: flex; flex: none; flex-wrap: wrap; diff --git a/resources/css/tailwind.css b/resources/css/tailwind.css index 298f5408..a8755fa0 100644 --- a/resources/css/tailwind.css +++ b/resources/css/tailwind.css @@ -18,7 +18,6 @@ @import './tokens/utilities.css'; /* Inputs, selection and data — leaving in step 36 */ -@import './components/datepicker.css'; @import './components/timepicker.css'; /* Containment — leaving in step 36 */ diff --git a/resources/js/datepicker.js b/resources/js/datepicker.js index 1ed26d78..59b03efa 100644 --- a/resources/js/datepicker.js +++ b/resources/js/datepicker.js @@ -586,7 +586,7 @@ document.addEventListener('alpine:init', () => { }, focusDay() { - this.settled(() => this.$refs.dialog.querySelector('[data-datepicker-day][tabindex="0"]')?.focus()) + this.settled(() => this.$refs.dialog.querySelector('[data-md-datepicker-day][tabindex="0"]')?.focus()) }, /** Focuses a day (inside min and max) and shows its month. */ @@ -660,9 +660,9 @@ document.addEventListener('alpine:init', () => { * picker has one of each, the modal picker a single button that opens the years. */ menuButton(view) { - const buttons = [...this.$refs.dialog.querySelectorAll('[data-datepicker-menu-button]')].filter((button) => button.getClientRects().length > 0) + const buttons = [...this.$refs.dialog.querySelectorAll('[data-md-datepicker-menu-button]')].filter((button) => button.getClientRects().length > 0) - return buttons.find((button) => button.dataset.datepickerMenuButton === view) ?? buttons[0] ?? null + return buttons.find((button) => button.dataset.mdDatepickerMenuButton === view) ?? buttons[0] ?? null }, gridKey(event) { @@ -745,7 +745,7 @@ document.addEventListener('alpine:init', () => { } this.settled(() => { - const list = [...this.$refs.dialog.querySelectorAll('[data-datepicker-list]')].find((each) => each.getClientRects().length > 0) + const list = [...this.$refs.dialog.querySelectorAll('[data-md-datepicker-list]')].find((each) => each.getClientRects().length > 0) const option = list?.querySelector('[aria-selected="true"]') ?? list?.querySelector('[role="option"]') option?.scrollIntoView({ block: 'center' }) diff --git a/resources/views/components/datepicker.blade.php b/resources/views/components/datepicker.blade.php index 20520b58..b7dfb116 100644 --- a/resources/views/components/datepicker.blade.php +++ b/resources/views/components/datepicker.blade.php @@ -155,7 +155,7 @@ @if ($model === null) x-modelable="value" @endif x-on:focusout="leave($event)" x-on:pointerdown.outside="open && presentation === 'docked' && cancel(false)" - data-datepicker + data-md-datepicker >
get('disabled') || $attributes->get('readonly')) - data-datepicker-toggle + data-md-datepicker-toggle > @@ -237,11 +237,11 @@
-
-

+
+

@if ($invalid) -
+
@foreach ($messages as $message)

{{ $message }}

@endforeach @@ -267,114 +267,114 @@ popover="manual" aria-label="{{ $title }}" style="position-anchor: {{ $anchor }}" - x-bind:data-presentation="presentation" + x-bind:data-md-presentation="presentation" x-on:cancel.prevent="cancel()" x-on:click.self="presentation === 'modal' && cancel()" x-on:keydown.escape.prevent.stop="cancel()" - data-datepicker-picker + data-md-datepicker-picker > -
+
{{-- M3's full-screen range picker (compact): an app bar with a close button and Save, then the supporting text and the range as the headline, over a divider. --}} -
-
- +
+
+ - + - + - + - +
-
-

{{ $title }}

-

+
+

{{ $title }}

+

-
-

{{ $title }}

+
+

{{ $title }}

-
-

+
+

- + - +
-
- +
+ -
+
- - - + + +
-
- - +
+ + - + - - + + - +
- +