diff options
Diffstat (limited to 'static/scss')
-rw-r--r-- | static/scss/_global.scss | 17 | ||||
-rw-r--r-- | static/scss/_slider_input.scss | 10 | ||||
-rw-r--r-- | static/scss/_small-calendar.scss | 51 | ||||
-rw-r--r-- | static/scss/directory-listing.scss | 5 | ||||
-rw-r--r-- | static/scss/smallcal.scss | 2 | ||||
-rw-r--r-- | static/scss/style.scss | 1161 |
6 files changed, 1246 insertions, 0 deletions
diff --git a/static/scss/_global.scss b/static/scss/_global.scss new file mode 100644 index 00000000..58e05155 --- /dev/null +++ b/static/scss/_global.scss @@ -0,0 +1,17 @@ +$gray: #757575; +$blue: #3399ff; +/* TODO rename this */ +$btn-height: 0.5ex; + +$tablabel-height: 5ex; +$tablabel-margin: 0; + +// "left" or "top" +$popup-style: "left"; + +:root { + /* Each popup can have a different amoutn of tabs. + Override this as appropriate */ + --tabcount: 4; + --background-color: white; +} diff --git a/static/scss/_slider_input.scss b/static/scss/_slider_input.scss new file mode 100644 index 00000000..adae56ae --- /dev/null +++ b/static/scss/_slider_input.scss @@ -0,0 +1,10 @@ +/* See components/slider.ts */ + +slider-input { + display: flex; + + input { + min-width: 0; + } +} + diff --git a/static/scss/_small-calendar.scss b/static/scss/_small-calendar.scss new file mode 100644 index 00000000..c4814285 --- /dev/null +++ b/static/scss/_small-calendar.scss @@ -0,0 +1,51 @@ +.small-calendar { + display: grid; + grid-template-rows: auto; + grid-template-columns: auto; + + grid-auto-flow: dense; + + > * { + text-align: center; + > time { + width: 100%; + text-align: right; + /* padding place in <time> instead on parent block element + to allow a border radius without making the link area + smaller + */ + padding: 5px; + } + } + > *:not(.column-head) { + display: flex; + align-items: center; /* vertically center */ + text-align: right; + } + a { + color: initial; + text-decoration: none; + } + + .row-head { + grid-column: 1; + border-right: 1px solid black; + + /* Sort of hack to get week numbers looking ok */ + justify-content: right; + padding-right: 5px; + } + + .column-head { + grid-row: 1; + border-bottom: 1px solid black; + } + + .next, .prev { + color: $gray; + } + + .today { + border: 1px solid black; + } +} diff --git a/static/scss/directory-listing.scss b/static/scss/directory-listing.scss new file mode 100644 index 00000000..745b5bc3 --- /dev/null +++ b/static/scss/directory-listing.scss @@ -0,0 +1,5 @@ +@import 'global'; + +.directory-table td:nth-child(3) { + text-align: end; +} diff --git a/static/scss/smallcal.scss b/static/scss/smallcal.scss new file mode 100644 index 00000000..c9a356c4 --- /dev/null +++ b/static/scss/smallcal.scss @@ -0,0 +1,2 @@ +@import 'global'; +@import 'small-calendar'; diff --git a/static/scss/style.scss b/static/scss/style.scss new file mode 100644 index 00000000..d5920f79 --- /dev/null +++ b/static/scss/style.scss @@ -0,0 +1,1161 @@ +@import 'global'; + +html, body { + height: 100%; + margin: 0; +} + +body { + background-color: var(--background-color); + /* TODO --foreground-color or similar */ +} + +.root { + display: grid; + margin: 0; + max-width: 100%; + height: 100%; + + grid-template-columns: auto auto 20em; + grid-template-rows: auto; + + grid-template-areas: + "main main nav" + "main main cal" + "main main details" + "main main events" + "footer footer events"; + + /* main the graphical portion + of both the wide and the table + view */ + > main { + /* these allow the main area to shrink, so that all areas will fit the + screen. It will however not shrink the elements, leading to our + (desired) scrollbar */ + min-width: 0; /* for wide */ + min-height: 0; /* for tall */ + + /* apparently required if one wants to have multiple + items within main, without it overflowing + */ + display: flex; + flex-direction: column; + + .event:target { + box-shadow: + 1em 1em 0.5em gold, + -1em -1em 0.5em gold, + 1em -1em 0.5em gold, + -1em 1em 0.5em gold; + z-index: 1; + } + + /* For new event button */ + position: relative; + + /* add new event button */ + > button { + position: absolute; + right: 2mm; + bottom: 5mm; + + height: 1cm; + width: 1cm; + } + } + + + footer { + margin: 0.5em; + color: ray; + font-size: 8pt; + + display: flex; + justify-content: space-between; + + flex-direction: row; + + span { + margin: 0 1em; + white-space: nowrap; + } + } +} + +@media (max-aspect-ratio: 3/4) { + .root { + grid-template-areas: + "main main" + "nav events" + "cal events" + "details events" + ". events" + "footer events"; + grid-template-rows: 70% auto; + grid-template-columns: 50% auto; + + footer { + flex-direction: column; + } + } +} + +.hidelink { + color: inherit; + text-decoration: none; +} + +.hidden { + display: none; +} + + +/* Change View +---------------------------------------- +"Buttons" for changing between weekly and monthly layout +*/ + +.calnav { + display: flex; + flex-direction: column; + padding-left: 2em; + padding-right: 2em; +} + +.change-view { + display: flex; + flex-direction: row; + justify-content: space-between; + + padding-top: 1ex; + padding-bottom: 1ex; +} + +date-jump { + > form { + display: flex; + } + + input { + flex-grow: 2; + margin-right: 1em; + } + + button, a { + /* Same as height, figure out way to force this */ + width: 2.5em; + } +} + +/* button +-------------------------------------------------- +*/ + +.btn { + /* if a */ + text-decoration: none; + + /* if button */ + border: none; + background-color: inherit; + + /* --- */ + + box-sizing: border-box; + padding: 0.5em; + + background-color: $blue; + color: white; + + display: flex; + justify-content: center; + align-items: center; + + /* move button slightly, to give illusion of 3D */ + box-shadow: $btn-height $btn-height gray; + &:active { + transform: translate($btn-height, $btn-height); + box-shadow: none; + } +} + +.simplesearch { + display: flex; + + input[type=text] { + flex-grow: 1; + } +} + +li > button { + width: 100%; +} + +/* Eventlist +---------------------------------------- +The sidebar with all the events +*/ + +.eventlist { + min-height: 0; + overflow: auto; + border-top: 3px solid $gray; + /* mostly for long links */ + word-break: break-word; + + scroll-behavior: smooth; + + .eventtext { + border-bottom: 1px solid black; + margin-top: 1em; + border-left-style: solid; + border-left-width: 6px; + padding-left: 2px; + } + + .eventtext { + border-color: var(--color); + + &.tentative { + border-left-style: dashed; + } + } +} + +/* Text day +---------------------------------------- +Each event within the eventlist +*/ + +.text-day { + border-left: 2px solid black; + border-top: 2px solid black; + padding-left: 2px; + margin-top: 1em; + + header { + position: sticky; + top: 0; + background-color: var(--background-color); + + h2 { + width: 100%; + text-align: center; + font-size: 14pt; + } + } +} + +/* Small calendar +---------------------------------------- +*/ + +.smallcal { + display: flex; + justify-content: center; + + .nav { + display: flex; + flex-direction: column; + justify-content: center; + font-size: 150%; + } +} + +.smallcall-head { + text-align: center; + font-weight: bold; +} + +/* Sass greatly discourages @import in favour of @use. @use however doesn't work + for me. +*/ +@import 'small-calendar'; + + +/* Sliders +---------------------------------------- + */ + +.sliders { + label { + padding-left: 1em; + } + + input[type="range"] { + width: 100%; + margin: 0; + } + +} + +@import 'slider_input'; + +/* Calendar List +---------------------------------------- +The list of all the loaded calendars, +along with their colors. +*/ + +.calendarlist li { + font-size: 8pt; + list-style-type: none; + border-left-width: 1em; + border-left-style: solid; + border-color: var(--color); + padding-left: 1ex; + + /* force to single line */ + overflow: hidden; + white-space: nowrap; +} + +/* Caltable +---------------------------------------- +*/ + +.table-head { + font-size: 200%; + text-align: center; +} + +.caltable { + flex-grow: 10; + + display: grid; + grid-template-columns: repeat(7, 1fr); + /* grid template rows is generated + inline in the HTML */ + + max-height: 100%; + /* Apparently needed to ensure that parent + can contain all its children */ + min-height: 0; + + .thead { + font-weight: bold; + display: flex; + align-items: center; + justify-content: center; + } + + .thead, .cal-cell { + border: 1px solid $gray; + } + + .cal-cell { + overflow-y: auto; + + .event, vevent-block { + font-size: 8pt; + border-radius: 5px; + padding: 2px; + margin-top: 2px; + margin-bottom: 2px; + font-family: arial; + + box-sizing: border-box; + } + } + + .cal-cell-time { + border-bottom: none; + } + + .cal-cell-short { + border-top: none + } + + + .longevents { + border-bottom: none; + border-top: none; + position: relative; + + .event { + margin: 0; + /* TODO use other border rules */ + border: 1px solid black; + + position: absolute; + box-sizing: border-box; + padding: 0; + } + } +} + + +.date-info { + color: $gray; + .day-number { + padding: 2pt; + } + + &.current .day-number { + color: black; + } +} + + +/* Weekly calendar +---------------------------------------- +*/ + +.calendar { + width: 100%; + height: 100%; + display: flex; + flex-grow: 2; +} + +.clock { + color: $gray; + border-top: 1px dotted $gray; + width: 100%; + pointer-events: none; +} + +.sideclock { + padding: 0; + grid-row: 3; + position: relative; + .day { + border: 1px transparent; + min-width: 0; + } + .clock { + border-top: 1px dotted $gray; + grid-row: 3; + } +} + +.days { + display: grid; + grid-template-rows: 4em 4em auto; + grid-template-columns: 5ch auto; + width: 100%; + height: 100%; + padding: 0; + overflow-x: scroll; + + /* allow for popup placement */ + position: relative; + + .meta { + border-bottom: 2px solid $gray; + grid-row: 1; + } + + .events { + grid-row: 3; + } + + .event { + border: 1px solid black; + } + + .longevents { + grid-row: 2; + grid-column-start: 2; + position: relative; + } + + .week-indicator { + grid-row: 1 / span 2; + } + + .sideclock { + grid-row: 3; + } +} + +.week-indicator { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 200%; + color: $gray; +} + +.events { + position: relative; + border: 1px solid $gray; + + .event { + width: 100%; + + &.generated { + width: calc(100% * var(--editmode)); + } + + &.zero-length { + border-radius: 0 1cm 1cm 0; + height: calc(100% * 1/24) !important; + } + + &.continuing { + border-bottom: none; + background-image: linear-gradient(to top, #0007 0%,#FFF0 2em); + } + + &.continued { + border-top: none; + background-image: linear-gradient(to bottom, #FFF7 0%,#FFF0 3em); + } + + &.continued.continuing { + border-top: none; + border-bottom: none; + background-image: + linear-gradient(to bottom, + #FFF7 0%, #FFF0 10%, + #FFF0 90%, #0007 100%); + } + + } + +} + +/* + * This makes the borders of the object be part of the size. + * Making placing it on the correct line much simpler. + */ +.clock, .eventlike, +.days vevent-block { + position: absolute; + box-sizing: border-box; + margin: 0; + display: block; +} + +.clocktext { + z-index: 1; + text-align: right; +} + +.meta { + display: flex; + justify-content: center; + align-items: center; + position: relative; + + padding-left: 1em; + padding-right: 1em; + .dayname { + position: absolute; + left: 5px; + top: 2px; + color: $gray; + } + + .daydate { + white-space: nowrap; + font-size: 150%; + } +} + +/* graphical block in the calendar */ +vevent-block, .event { + transition: 0.3s; + font-size: var(--event-font-size); + overflow: hidden; + background-color: var(--color); + color: var(--complement); + + // position: absolute; + display: block; + + width: 100%; + min-height: 1em; + border: 1px solid black; + /* backgroudn: blue; */ + + /* Event is not confirmed to happen */ + &.tentative { + border: 3px dashed black; + } + + /* Event duration is not "busy" time */ + &.transparent { + background-image: linear-gradient(45deg, + #EE617DFF 25%, + #00000000 25%, + #00000000 50%, + #EE617DFF 50%, + #EE617DFF 75%, + #00000000 75%, + #00000000 100%); + background-size: 56px 56px; + } + + &.generated { + opacity: 40%; + /* TODO only disable transitions for top/botom, and only + * when dragging (not when updating through other means) */ + transition: none; + } + + &.repeating { + float: left; + font-size: 150%; + } + + .location { + display: block; + font-size: 80%; + font-style: italic; + white-space: pre; + } + +} + +.event-body { + padding: 0; + margin: 0; + width: 100%; + height: 100%; + overflow: hidden; + + /* TODO + This gets to large for really short events, placing the marker halfway + outside the event body. + */ + .description { + position: absolute; + right: 1ex; + bottom: 0; + font-size: 200%; + } +} + +/* +.zero-width-events .event { + width: initial; + padding: 0.5em; + margin: 0.2em; + border-radius: 1ex; + position: relative; + float: left; +} +*/ + + +.repeating { + color: red; +} + +.clear-input { + font-family: arial; + font-size: 200%; + color: grey; + + padding: 0; + background: none; + border: none; + + cursor: pointer; +} + +.eventtext { + white-space: pre-line; + font-size: 10pt; + + h3 { + font-size: 12pt; + border-bottom: 1px solid $gray; + margin-bottom: 0; + font-weight: 300; + margin-top: 0; + } + + .location { + display: inline-block; + vertical-align: text-top; + } + + .last-modified, .rrule { + display: flex; + justify-content: right; + text-align: right; + font-size: 80%; + color: $gray; + padding-right: 1em; + } + + .categories > a::after { + content: "," + } + + .categories > a:last-child::after { + content: "" + } + + .categories > a { + margin-right: 1ch; + } +} + +.attach { + max-width: 100%; + max-height: 3cm; +} + +/* */ + +.longevents { + .event { + border-radius: 1em; + padding-left: 1em; + + height: 90%; + + &.continuing { + border-right: none; + border-radius: 1em 0 0 1em; + } + + &.continued { + border-left: none; + border-radius: 0 1em 1em 0; + } + + &.continued.continuing { + border-radius: 0; + } + + } +} + +/* + * All other CAL_ classes are generated by the backend. + * NOTE Possibly move this there. + */ +.CAL_Generated { + background-color: #55FF55; +} + +.clock-0 { top: calc(100%/24 * 0); } +.clock-2 { top: calc(100%/24 * 2); } +.clock-4 { top: calc(100%/24 * 4); } +.clock-6 { top: calc(100%/24 * 6); } +.clock-8 { top: calc(100%/24 * 8); border-width: 2px; } +.clock-10 { top: calc(100%/24 * 10); } +.clock-12 { top: calc(100%/24 * 12); } +.clock-14 { top: calc(100%/24 * 14); } +.clock-16 { top: calc(100%/24 * 16); border-width: 2px; } +.clock-18 { top: calc(100%/24 * 18); } +.clock-20 { top: calc(100%/24 * 20); } +.clock-22 { top: calc(100%/24 * 22); } +.clock-24 { top: calc(100%/24 * 24); } + + +/* Search page +---------------------------------------- + */ + +.paginator > * { + padding-left: 1em; + display: inline-block; +} + +.summary-line { + display: inline-flex; + + > * { + display: inline-block; + padding-left: 1ch; + padding-right: 1ch; + } + + time { + font-family: monospace; + min-width: 18ch; + } +} + +.error { + border: 3px solid red; + background-color: pink; + + pre { + padding: 1em; + } +} + +/* Popups +---------------------------------------- +*/ + +popup-element { + display: none; + position: absolute; + z-index: 1000; + + &[active] { + z-index: 1001; + } + + /* ??? */ + left: 10px; + top: -50px; + + box-shadow: gray 10px 10px 10px; + + &[visible] { + display: block; + } + + > * { + resize: both; + /* This overflow: auto gives us the correct resize handle */ + overflow: auto; + + /* TODO this doesn't work, since tabcount is sepparate fronm + * popup... */ + min-height: calc(var(--tabcount) * #{$tablabel-margin + $tablabel-height}); + + /* some form of sensible minimi and default size for the popup (s main area). */ + min-width: 150px; + width: 350px; + height: 300px; + } +} + +.popup-control { + cursor: grab; + background-color: var(--color); + + display: flex; + + @if $popup-style == "left" { + flex-direction: column; + padding: 1.2ex; + } @else { + flex-direction: row-reverse; + padding: 1ex; + } + + + button { + display: block; + background: $blue; + color: white; + border: none; + box-shadow: $btn-height $btn-height gray; + + &:active { + transform: translate($btn-height, $btn-height); + box-shadow: none; + } + + @if $popup-style == "left" { + width: 9mm; + height: 9mm; + margin-bottom: 2mm; + } @else { + width: 7mm; + height: 7mm; + margin-left: 1mm; + } + } +} + +.popup-root { + display: flex; + + @if $popup-style == "left" { + flex-direction: row; + } @else { + flex-direction: column; + } +} + +tab-group { + background-color: #dedede; + color: black; + + width: 100%; + height: 100%; + /* This overflow: auto gives us the correct rendering of the content */ + overflow: auto; + + [role="tabpanel"] { + padding: 1em; + } + + [role="tablist"] { + display: flex; + flex-direction: column; + position: absolute; + left: 100%; + margin: 0; + padding: 0; + + [role="tab"] { + height: $tablabel-height; + margin-bottom: $tablabel-margin; + + width: 5ex; + &:hover { + width: 10ex; + } + + transition: width 0.1s ease-in-out; + border: 1px solid #ccc; + border-radius: 0 5px 5px 0; + background-color: #aeaeae; + } + + [aria-selected="true"] { + border-left: none; + background-color: #dedede; + } + } +} + +vevent-edit { + + select { + max-width: 100%; + } + + input { + white-space: initial; + border: 1px solid gray; + max-width: 100%; + } + + .eventtext { + word-break: break-word; + + table { + word-break: initial; + font-size: 65%; + } + } + + .edit-form { + label { + display: block; + } + + /* REG */ + input[type='text'], textarea { + width: 100%; + } + + .newfield { + width: 100%; + display: flex; + } + + .timeinput { + } + } +} + +.checkboxes { + display: grid; + grid-template-rows: 1fr 1fr; + justify-items: baseline; + + label {grid-row: 1;} + input {grid-row: 2;} +} + +vevent-dl { + font-size: 80%; + + dl { + display: grid; + grid-template-columns: 1fr 1fr; + } +} + + +#bar { + width: calc(100% + 2em); + height: 4px; + background: blue; + border-color: blue; + left: -1em; +} + + +.plusminuschecked label { + color: black; +} + +.plusminuscheck:checked ~ label .plus { + color: green; +} + +.plusminuscheck:not(:checked) ~ label .minus { + color: red; +} + +.inline-edit { + input { + /* important since regular spec is much stronger...*/ + /* [REG] */ + width: initial !important; + } +} + +/* Other +---------------------------------------- +*/ + +.template { + display: none; +} + + +.summary-line .square { + margin-right: 1em; +} + +.square { + width: 1em; + height: 1em; + background-color: var(--color); +} + +.side-by-side { + display: flex; +} + +/* Icalendar +---------------------------------------- +*/ + +/* Below is for styling embedded xcalendar components in the xhtml + document. I can't find anything about if this is allowed + according to any standard, but it seems to work. + Firefox doesn't want to admit it, and shows nothing in the + inspector, but the document renders fine. + Vivaldi works fine in the inspector. + */ + +icalendar { + display: inline-block; + padding-left: 1ch; + font-family: monospace; + font-size: xx-small; + padding-left: 1ch; + + properties > * { + display: block; + } + + properties * { + padding-right: 1ch; + } + + + /* All icalendar properties */ + calscale::before { content: "calscale: "; } + method::before { content: "method: "; } + prodid::before { content: "prodid: "; } + version::before { content: "version: "; } + attach::before { content: "attach: "; } + categories::before { content: "categories: "; } + class::before { content: "class: "; } + comment::before { content: "comment: "; } + description::before { content: "description: "; } + geo::before { content: "geo: "; } + location::before { content: "location: "; } + percent-complete::before { content: "percent-complete: "; } + priority::before { content: "priority: "; } + resources::before { content: "resources: "; } + status::before { content: "status: "; } + summary::before { content: "summary: "; } + completed::before { content: "completed: "; } + dtend::before { content: "dtend: "; } + due::before { content: "due: "; } + dtstart::before { content: "dtstart: "; } + duration::before { content: "duration: "; } + freebusy::before { content: "freebusy: "; } + transp::before { content: "transp: "; } + tzid::before { content: "tzid: "; } + tzname::before { content: "tzname: "; } + tzoffsetfrom::before { content: "tzoffsetfrom: "; } + tzoffsetto::before { content: "tzoffsetto: "; } + tzurl::before { content: "tzurl: "; } + attendee::before { content: "attendee: "; } + contact::before { content: "contact: "; } + organizer::before { content: "organizer: "; } + recurrence-id::before { content: "recurrence-id: "; } + related-to::before { content: "related-to: "; } + url::before { content: "url: "; } + uid::before { content: "uid: "; } + exdate::before { content: "exdate: "; } + rdate::before { content: "rdate: "; } + rrule::before { content: "rrule: "; } + action::before { content: "action: "; } + repeat::before { content: "repeat: "; } + trigger::before { content: "trigger: "; } + created::before { content: "created: "; } + dtstamp::before { content: "dtstamp: "; } + last-modified::before { content: "last-modified: "; } + sequence::before { content: "sequence: "; } + request-status::before { content: "request-status: "; } + + parameters { + color: gray; + + /* icalendar parameters */ + altrep::before { content: "altrep:"; } + cn::before { content: "cn:"; } + cutype::before { content: "cutype:"; } + delegated-from::before { content: "delegated-from:"; } + delegated-to::before { content: "delegated-to:"; } + dir::before { content: "dir:"; } + encoding::before { content: "encoding:"; } + fmttype::before { content: "fmttype:"; } + fbtype::before { content: "fbtype:"; } + language::before { content: "language:"; } + member::before { content: "member:"; } + partstat::before { content: "partstat:"; } + range::before { content: "range:"; } + related::before { content: "related:"; } + reltype::before { content: "reltype:"; } + role::before { content: "role:"; } + rsvp::before { content: "rsvp:"; } + sent-by::before { content: "sent-by:"; } + tzid::before { content: "tzid:"; } + } + + /* special fields inside some properties */ + period { + start { content: "start:"; } + end { content: "end:"; } + duration { content: "duration:" } + } + + recur { + freq { content: "freq:"; } + until { content: "until:"; } + count { content: "count:"; } + bymonth { content: "bymonth"; } + byweekno { content: "byweekno"; } + byyearday { content: "byyearday"; } + bymonthday { content: "bymonthday"; } + byday { content: "byday"; } + byhour { content: "byhour"; } + byminute { content: "byminute"; } + bysecond { content: "bysecond"; } + bysetpos { content: "bysetpos"; } + } + + /* types */ + date-time, date, until {color: purple;} + text { color: green; } + integer { color: blue; } + unknown { color: red; } +} + +/* vim:expandtab:softtabstop=4:shiftwidth=4: + */ |