Initial commit

This commit is contained in:
dongge 2024-01-15 20:23:51 +00:00
commit 3ddd06acc7
86 changed files with 16409 additions and 0 deletions

129
README.md Normal file
View File

@ -0,0 +1,129 @@
Roundcube Webmail Skin "Elastic"
================================
This skin package contains a theme for the Roundcube Webmail
software. It can be used, modified and redistributed according to
the terms described in the LICENSE section.
For information about building or modifying Roundcube skins please visit
https://github.com/roundcube/roundcubemail/wiki/Skins
LICENSE
-------
The contents of this folder are subject to the Creative Commons
Attribution-ShareAlike License. It is allowed to copy, distribute,
transmit and to adapt the work by keeping credits to the original
authors in the README.md file.
See http://creativecommons.org/licenses/by-sa/3.0/ for details.
This folder also contains code licensed separately:
- Bootstrap Framework 4 from https://github.com/twbs/bootstrap
- FontAwesome 5 fonts from https://fontawesome.com/
- Roboto font from https://google-webfonts-helper.herokuapp.com/fonts/roboto?subsets=cyrillic,latin-ext,cyrillic-ext,latin,greek,greek-ext
INSTALLATION
------------
All styles are written using LESS syntax. Thus it needs to be compiled
using the `lessc` (>= 2.5.2) command line tool. This comes with the `nodejs-less`
RPM package or using `npm install less` which depend on nodejs.
Here is how you can install those on Debian:
```
curl -sL https://deb.nodesource.com/setup_16.x | sudo bash -
apt-get install -y nodejs
npm install -g less
npm install -g less-plugin-clean-css
```
Then, go to the `styles` folder, and when you're done editing your files, do the following, as needed:
```
$ lessc --clean-css="--s1 --advanced" styles/styles.less > styles/styles.min.css
$ lessc --clean-css="--s1 --advanced" styles/print.less > styles/print.min.css
$ lessc --clean-css="--s1 --advanced" styles/embed.less > styles/embed.min.css
```
(`--clean-css="--s1 --advanced"` minifies the css, requires the clean-css Less plugin.
The plugin can be installed using `npm install less-plugin-clean-css`)
References to image files from the included CSS files can be appended
with cache-buster marks to avoid browser caching issues after updating.
Run `bin/updatecss.sh --dir skins/elastic` before packaging the skin
or after installing it on the destination system.
FOR DEVELOPERS
--------------
- Supported browsers: IE11+, Edge, Last 2 versions for Chrome/Firefox/Safari,
Android Browser 5+, iOS Safari 9+.
- Skin color palette changes and other css modifications can be done
via _styles.less and _variables.less files. Where you can overwrite all
variables and add custom styles.
- Minimum supported screen width is 240px (note that even if the device screen
resolution is e.g.320x372 changing the text size in device settings will reduce
the resolution)
- Every page (which is not a frame) has following required structure:
```
<body>
<div id="layout">
<div id="layout-menu"></div>
<div id="layout-sidebar"></div>
<div id="layout-list"></div>
<div id="layout-content"></div>
</div>
</body>
```
where `#layout-sidebar` and `#layout-list` are optional. Which element of the `#layout` will be displayed
as a main view on mobile devices can be defined by adding `selected` class to it.
- The `<html>` element will receive special classes that will be updated on resize
or orientation change:
- `touch`: A touch device, screen width <= 1024px,
- `layout-large`: Screen width > 1200px,
- `layout-normal`: Screen width <= 1200px and >= 768px,
- `layout-small`: Screen width < 768px and > 480px,
- `layout-phone`: Screen width <= 480px.
Frames will have the same classes applied as their parent windows.
- Every button, that is not <button> nor <input> should have inner <span class="inner"> element
for the button label.
- Every iframe need to be wrapped by an element with `iframe-wrapper` class. It is
required to have proper scrolling on mobile devices.
- Special attributes:
- `data-hidden`: Makes a menu entry/button hidden on specified screen sizes.
Can be used for example for functionality not implemented or that has no sense
on phones or touch devices. Contains a comma-separated list following values:
`large` (width > 1200px), `big` (width > 768px), `small` (width =< 768px),
`phone` (width =< 480px), `lbs` (width > 480px).
- `data-content-button`: Makes the action button with this attribute to be copied
to the content frame header on small/phone screens.
- Special URLs:
In phone mode we display Prev/Next navigation buttons below the content preview
frame. We do this e.g. for mail preview or contact preview. Plugins should use
_action=add* or _action=create* or _nav=hide in the frame URL if the navigation
should be hidden, which is the case when you create a content object.
- Dark mode:
In dark mode html element will have `dark-mode` class assigned.
It is possible to disable dark mode using less variable `@dark-mode-enabled`.
Option `dark_mode_support` in meta.json controls addition of the mode switch in the menu.
KNOWN ISSUES
------------
1. There are known issues with running less in Roundcube devel_mode:
- Dialogs executed on page load are displayed out of screen.
- CodeMirror editor (in managesieve raw script editing mode) is broken.

BIN
fonts/fa-regular-400.woff Normal file

Binary file not shown.

BIN
fonts/fa-regular-400.woff2 Normal file

Binary file not shown.

BIN
fonts/fa-solid-900.woff Normal file

Binary file not shown.

BIN
fonts/fa-solid-900.woff2 Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

3
images/contactgroup.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640">
<path d="M133.5 273.5c30.3 0 55-24.7 55-55s-24.7-55-55-55-55 24.7-55 55 24.7 55 55 55zm385 0c30.3 0 55-24.7 55-55s-24.7-55-55-55-55 24.7-55 55 24.7 55 55 55zM546 301h-55c-15.1 0-28.8 6.1-38.8 16 34.6 19 59.2 53.3 64.5 94h56.7c15.2 0 27.5-12.3 27.5-27.5V356c.1-30.3-24.6-55-54.9-55zm-220 0c53.2 0 96.2-43.1 96.2-96.2s-43.1-96.2-96.2-96.2-96.2 43.1-96.2 96.2 43 96.2 96.2 96.2zm66 27.5h-7.1c-17.9 8.6-37.7 13.8-58.9 13.8s-40.9-5.2-58.9-13.8H260c-54.7 0-99 44.3-99 99v24.8c0 22.8 18.5 41.2 41.2 41.2h247.5c22.8 0 41.2-18.5 41.2-41.2v-24.8c.1-54.7-44.2-99-98.9-99zM199.8 317c-10-9.9-23.6-16-38.8-16h-55c-30.3 0-55 24.7-55 55v27.5c0 15.2 12.3 27.5 27.5 27.5h56.6c5.4-40.7 30-75 64.7-94z" fill="#ccc"/>
</svg>

After

Width:  |  Height:  |  Size: 769 B

3
images/contactpic.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M256 246c50.5 0 91.4-40.9 91.4-91.4S306.5 63.1 256 63.1s-91.4 40.9-91.4 91.4S205.5 246 256 246zm64 22.9h-11.9c-15.9 7.3-33.5 11.4-52.1 11.4s-36.1-4.1-52.1-11.4H192c-53 0-96 43-96 96v29.7c0 18.9 15.4 34.3 34.3 34.3h251.4c18.9 0 34.3-15.4 34.3-34.3v-29.7c0-53-43-96-96-96z" fill="#ccc"/>
</svg>

After

Width:  |  Height:  |  Size: 367 B

3
images/corner-handle.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<path fill="#888" d="M6.7 16L16 6.7V5.3L5.3 16zM9.7 16L16 9.7V8.3L8.3 16zM12.7 16l3.3-3.3v-1.4L11.3 16zM15.7 16l.3-.3v-1.4L14.3 16z"/>
</svg>

After

Width:  |  Height:  |  Size: 205 B

BIN
images/disroot-root.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 153 KiB

3
images/download.svg Normal file
View File

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 960 560">
<path fill="#d4dbde" d="M690 245c0 9.2-3.5 17.9-10.1 24.9l-175 175c-6.6 6.6-15.3 10.1-24.9 10.1-9.2 0-18.4-3.5-24.9-10.1l-175-175c-6.6-7-10.1-15.8-10.1-24.9 0-4.4.9-9.2 2.6-13.6C277.9 218.3 291 210 305 210h87.5V35c0-19.2 15.8-35 35-35h105c19.2 0 35 15.8 35 35v175H655c14 0 27.1 8.3 32.4 21.4 1.7 4.4 2.6 9.2 2.6 13.6zm0 245H270V350h-70v140c0 38.5 31.5 70 70 70h420c38.5 0 70-31.5 70-70V350h-70v140z"/>
</svg>

After

Width:  |  Height:  |  Size: 472 B

BIN
images/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

1
images/google-icon.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path fill="#4285F4" d="M45.12 24.5c0-1.56-.14-3.06-.4-4.5H24v8.51h11.84c-.51 2.75-2.06 5.08-4.39 6.64v5.52h7.11c4.16-3.83 6.56-9.47 6.56-16.17z"></path><path fill="#34A853" d="M24 46c5.94 0 10.92-1.97 14.56-5.33l-7.11-5.52c-1.97 1.32-4.49 2.1-7.45 2.1-5.73 0-10.58-3.87-12.31-9.07H4.34v5.7C7.96 41.07 15.4 46 24 46z"></path><path fill="#FBBC05" d="M11.69 28.18C11.25 26.86 11 25.45 11 24s.25-2.86.69-4.18v-5.7H4.34C2.85 17.09 2 20.45 2 24c0 3.55.85 6.91 2.34 9.88l7.35-5.7z"></path><path fill="#EA4335" d="M24 10.75c3.23 0 6.13 1.11 8.41 3.29l6.31-6.31C34.91 4.18 29.93 2 24 2 15.4 2 7.96 6.93 4.34 14.12l7.35 5.7c1.73-5.2 6.58-9.07 12.31-9.07z"></path><path fill="none" d="M2 2h44v44H2z"></path></svg>

After

Width:  |  Height:  |  Size: 764 B

BIN
images/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

BIN
images/logo.svg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" viewBox="0 0 116 116" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
<g transform="matrix(1,0,0,1,-22.0613,-141.704)"><path d="M26.088,145.515L77.643,145.515L77.639,197.07L26.088,197.07L26.088,145.515Z" style="fill:rgb(246,83,20);"/></g>
<g transform="matrix(1,0,0,1,-22.0613,-141.704)"><path d="M82.907,145.515L134.462,145.515C134.462,162.7 134.465,179.885 134.459,197.07C117.277,197.067 100.092,197.07 82.91,197.07C82.904,179.885 82.907,162.7 82.907,145.515Z" style="fill:rgb(127,187,65);"/></g>
<g transform="matrix(1,0,0,1,-22.0613,-141.704)"><path d="M26.088,202.331C43.273,202.337 60.458,202.329 77.643,202.337C77.646,219.522 77.643,236.704 77.643,253.889L26.088,253.889L26.088,202.331Z" style="fill:rgb(0,161,241);"/></g>
<g transform="matrix(1,0,0,1,-22.0613,-141.704)"><path d="M82.91,202.337C100.092,202.331 117.277,202.334 134.462,202.334L134.462,253.889L82.907,253.889C82.91,236.704 82.904,219.519 82.91,202.337Z" style="fill:rgb(255,187,0);"/></g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

21
meta.json Normal file
View File

@ -0,0 +1,21 @@
{
"name": "Beetroot (elastic)",
"extends": "elastic",
"author": "muppeth & meaz of Disroot.org (based on Aleksander Machniak's - elastic)",
"license": "Creative Commons Attribution-ShareAlike",
"license-url": "http://creativecommons.org/licenses/by-sa/3.0/",
"config": {
"supported_layouts": ["widescreen"],
"jquery_ui_colors_theme": "bootstrap",
"embed_css_location": "/styles/embed.css",
"editor_css_location": "/styles/embed.css",
"dark_mode_support": true,
"media_browser_css_location": "none",
"additional_logo_types": ["dark", "small", "small-dark"]
},
"meta": {
"viewport": "width=device-width, initial-scale=1.0, shrink-to-fit=no, maximum-scale=1.0",
"theme-color": "#f4f4f4",
"msapplication-navbutton-color": "#f4f4f4"
}
}

46
styles/_colors.less Normal file
View File

@ -0,0 +1,46 @@
// Beetroot and Darkbeet colors
@color-main: #50162d;
@color-link: #bd139a;
@color-success: #50162d;
@color-warning: #F6609D;
@color-link-secondary: lighten(@color-font, 60%);
@color-layout-header-background: #50162d;
// Task menu
@color-taskmenu-background: #50162d;
@color-taskmenu-button-action: #E0548D;
@color-taskmenu-button-special: @color-taskmenu-button;
@color-taskmenu-button-special-background: @color-taskmenu-background;
@color-taskmenu-button-action-hover: #fff;
@color-taskmenu-button-special-hover: lighten(@color-taskmenu-button-special, 10%);
// @color-taskmenu-button-special-background-hover:lighten(@color-taskmenu-button-special-background, 10%);
// Toolbar
@color-toolbar-button-background-hover: lighten(@color-layout-header-background, 10%);
@color-searchbar-icon-active: green;
// Popovers (menus)
@color-popover-header: @color-black-shade-text;
@color-popover-header-background: transparent;
//Forms
@color-btn-secondary-background: lighten(@color-main, 10%);
// Dark mode colors
@color-dark-main: darken(@color-main, 10%);
@color-dark-background: #252121;
@color-dark-font: #DDDDDD;
@color-dark-border: #292525;
@color-dark-taskmenu-button-action: #4F8F93;
@color-dark-taskmenu-button-action-hover: @color-dark-font;
@color-dark-list-selected: #FFFFFF;
@color-dark-list-selected-background: #50162D;
@color-dark-list-droptarget-background: #353131;
@color-dark-list-border: #353131;
@color-dark-input-border: #471328;
@color-dark-input-addon-background: #292525;
@color-dark-popover-background: #201c1c;
@color-dark-popover-border: #50162d;

48
styles/_dark.less Normal file
View File

@ -0,0 +1,48 @@
// Darkbeet modifications based on elastic skin
@import "_darkc";
html.dark-mode {
// Have a black background when writing an email
// .tox {
// .tox-edit-area__iframe {
// background-color: @color-dark-popover-background;
// color: white;
// }
// }
#taskmenu {
a {
&.selected {
color: white;
background-color: @color-dark-list-selected-background;
}
}
.action-buttons a {
color: white;
}
}
.menu
a.compose::before {
color: white;
}
#layout > div > .header,
#layout-menu {
background-color: @color-dark-popover-background;
border: unset;
}
// The two following are to get lighter borders when composing message (to: and subject:), when focus
.custom-file-label:focus:not(.is-invalid), .form-control:focus:not(.is-invalid) {
border-color: #741d3f;
}
.recipient-input.focus {
border-color: #911648 !important;
}
// Get dotted line around attachment brighter
.file-upload {
border: .2rem dashed @color-main;
}
}

2
styles/_darkc.less Normal file
View File

@ -0,0 +1,2 @@
@color-font: blue;

44
styles/_styles.less Normal file
View File

@ -0,0 +1,44 @@
//Modification for Beetroot based on Elastic skin
//
@import "_colors";
#layout > div > .header {
color: #fff;
}
.menu.toolbar a {
color: #fff;
}
#layout > div > .header a.button {
color: #fff;
}
.popover .menu li a {
color: #2c363a;
}
/* login page */
& when (@dark-mode-enabled = true) {
@import "_dark";
}
/*** Fonts ***/
@font-face {
font-family: 'Icons';
font-style: normal;
font-weight: 900;
src: url("../fonts/la-solid-900.woff2") format('woff2'),
url("../fonts/la-solid-900.woff") format('woff');
}
@font-face {
font-family: 'Icons';
font-style: normal;
font-weight: 400;
src: url("../fonts/la-regular-400.woff2") format('woff2'),
url("../fonts/la-regular-400.woff") format('woff');
}

49
styles/_variables.less Normal file
View File

@ -0,0 +1,49 @@
// Variables for custom Darkbeet/Beetroot theme based on Elastic skin
@import "_colors";
@dark-mode-enabled: true; // on change also have to change dark_mode_support in meta.json
@screen-width-large: 1200px;
@screen-width-medium: 1024px;
@screen-width-small: 768px;
@screen-width-xs: 480px;
@screen-width-mini: 320px;
@screen-width-touch: @screen-width-medium;
@screen-width-bs-phone: 576px;
@page-font-size: 14px;
@page-min-width: 240px;
// Note: we'll set some values in pixels instead of rem to eliminate
// Firefox sub-pixel rendering bug(s)
@layout-menu-width: floor(5.6 * @page-font-size);
@layout-menu-width-sm: floor(3 * @page-font-size);
@layout-header-height: floor(4.2 * @page-font-size);
@layout-footer-height: @layout-header-height;
@layout-footer-small-height: floor(2.5 * @page-font-size);
@layout-header-font-size: 1rem;
@layout-searchbar-height: floor(2.6 * @page-font-size);
@layout-touch-header-height: @layout-header-height;
@layout-touch-header-font-size: floor(1.2 * @page-font-size);
@layout-touch-menu-record-height: floor(3.4 * @page-font-size);
@layout-touch-menu-record-font-size: floor(1.2 * @page-font-size);
@layout-touch-icon-width: 2.2em;
@layout-mobile-menu-width: (@screen-width-mini * .85);
@layout-contact-icon-width: 112px;
@layout-contact-icon-height: 135px;
@listing-line-height: floor(2.5 * @page-font-size);
@listing-touch-line-height: floor(3.4 * @page-font-size);
@listing-treetoggle-width: 1.5em;
@mail-header-photo-height: 4rem;
// Additional icons
@icon-resize-corner: data-uri("image/svg+xml;charset=utf-8", "../images/corner-handle.svg"); // size: 16x16
@icon-file-drop: data-uri("image/svg+xml;charset=utf-8", "../images/download.svg");

278
styles/colors.less Normal file
View File

@ -0,0 +1,278 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
@color-main: #37beff;
@color-main-dark: darken(@color-main, 35%);
@color-black: #161b1d;
@color-font: lighten(@color-black, 10%);
@color-link: #00acff;
@color-link-hover: darken(@color-link, 10%);
@color-border: #ddd;
@color-error: #ff5552;
@color-success: #41b849;
@color-warning: #ffd452;
@color-black-shade-text: tint(@color-black, 40%);
@color-black-shade-border: lighten(@color-black, 75%);
@color-black-shade-bg: lighten(@color-black, 85%);
// Layout elements
@color-layout-border: @color-black-shade-border;
@color-layout-header: @color-font;
@color-layout-sidebar-background: #fff;
@color-layout-list-background: #fff;
@color-layout-content-background: #fff;
@color-layout-header-background: #f4f4f4;
@color-layout-footer-background: #fff;
@color-layout-mobile-header-background: @color-layout-header-background;
@color-layout-mobile-footer-background: @color-layout-header-background;
// Task menu
@color-taskmenu-background: #2f3a3f;
@color-taskmenu-button: #fff;
@color-taskmenu-button-selected: @color-taskmenu-button;
@color-taskmenu-button-action: @color-main;
@color-taskmenu-button-selected-background: lighten(@color-taskmenu-background, 10%);
@color-taskmenu-button-action-background: transparent;
@color-taskmenu-button-hover: #fff;
@color-taskmenu-button-selected-hover: #fff;
@color-taskmenu-button-action-hover: @color-main;
@color-taskmenu-button-background-hover: lighten(@color-taskmenu-background, 10%);
@color-taskmenu-button-action-background-hover: @color-taskmenu-button-background-hover;
@color-taskmenu-button-logout: @color-error;
@color-taskmenu-button-logout-hover: @color-error;
// Toolbar
@color-toolbar-button: @color-font;
@color-toolbar-button-background-hover: darken(@color-layout-header-background, 3%);
@color-searchbar-background: #fbfbfb;
// Toolbar menu
@color-menu-hover: #fff;
@color-menu-hover-background: @color-main;
// Listings
@color-list: @color-font;
@color-list-selected: @color-font;
@color-list-selected-background: tint(@color-main, 90%);
@color-list-flagged: @color-error;
@color-list-deleted: fadeout(@color-font, 50%);
@color-list-secondary: @color-black-shade-text;
@color-list-droptarget-background: #ffffcc;
@color-list-focus-indicator: lighten(@color-main, 20%);
@color-list-border: @color-black-shade-bg;
@color-list-badge: #fff;
@color-list-badge-background: @color-main;
@color-list-recent: darken(@color-main, 20%);
@color-list-recent-badge: #fff;
@color-list-recent-badge-background: @color-main;
@color-list-pagenav: @color-black-shade-text;
@color-list-icon: fadeout(@color-list-secondary, 25%);
@color-list-unread-status: @color-warning;
@color-attachmentlist-border: #f4f4f4;
@color-attachmentlist-background: #fcfcfc;
// Drag-n-drop layer
@color-drag-layer: #fff;
@color-drag-layer-background: @color-taskmenu-background;
@color-drag-layer-shadow: @color-black-shade-bg;
// Messages
@color-message: @color-font;
@color-message-border: transparent;
@color-message-background: fadeout(@color-main, 95%);
@color-message-text: #fff;
@color-message-link: @color-main;
@color-message-link-font-weight: normal;
@color-message-information: @color-main;
@color-message-success: @color-success;
@color-message-warning: @color-warning;
@color-message-error: @color-error;
@color-message-loading: tint(@color-font, 30%);
@color-message-information-text: @color-message-text;
@color-message-success-text: @color-message-text;
@color-message-warning-text: @color-message;
@color-message-error-text: @color-message-text;
@color-message-loading-text: @color-message-text;
@color-message-error-box: @color-message;
@color-message-information-box: @color-message;
@color-message-success-box: @color-message;
@color-message-warning-box: @color-message;
@color-message-error-box-background: fadeout(@color-message-error, 80%);
@color-message-information-box-background: fadeout(@color-message-information, 80%);
@color-message-success-box-background: fadeout(@color-message-success, 80%);
@color-message-warning-box-background: fadeout(@color-message-warning, 80%);
// Popovers (menus)
@color-popover-shadow: @color-black-shade-bg;
@color-popover-separator: @color-black-shade-text;
@color-popover-separator-background: @color-black-shade-bg;
@color-popover-mobile-header: #fff;
@color-popover-mobile-header-background: @color-main-dark;
@color-popover-mobile-dropbutton-background: #f6f6f6;
// Dialogs
@color-dialog-overlay-background: fade(@color-font, 50%);
@color-dialog-header: @color-layout-header;
@color-dialog-header-border: @color-border;
@color-spinner-circle: @color-black-shade-bg;
@color-spinner-item: @color-black-shade-text;
// Forms
@color-input: @color-font;
@color-input-border: #ced4da; // from Bootstrap's .form-control
@color-input-border-focus: @color-main;
@color-input-border-focus-shadow: fadeout(@color-main, 75);
@color-input-border-invalid: @color-error;
@color-input-border-invalid-shadow: fadeout(@color-error, 75);
@color-input-addon-background: @color-black-shade-bg;
@color-recipient-input-border: @color-input-border;
@color-recipient-input-background: @color-black-shade-bg;
@color-input-placeholder: #bbb;
@color-checkbox: @color-main;
@color-checkbox-checked: @color-main;
@color-checkbox-checked-disabled: lighten(@color-main, 15%);
@color-checkbox-focus: @color-input-border-focus;
@color-checkbox-focus-shadow: @color-input-border-focus-shadow;
@color-form-hint: @color-black-shade-text;
@color-image-upload-background: #f4f4f4;
@color-btn-secondary: #fff;
@color-btn-secondary-background: lighten(@color-black, 50%);
@color-btn-primary: #fff;
@color-btn-primary-background: @color-main;
@color-btn-danger: #fff;
@color-btn-danger-background: @color-error;
@color-quota-background: #fff;
@color-quota-text: @color-black-shade-text;
@color-quota-value: @color-main;
@color-quota-value-warning: @color-error;
@color-blockquote-background: fadeout(@color-black-shade-bg, 50%);
@color-blockquote-0: darken(@color-main, 30%);
@color-blockquote-1: darken(@color-success, 25%);
@color-blockquote-2: darken(@color-error, 20%);
@color-blockquote-0-border: @color-blockquote-0;
@color-blockquote-1-border: @color-blockquote-1;
@color-blockquote-2-border: @color-blockquote-2;
@color-mail-signature: @color-black-shade-text;
@color-mail-headers: @color-black-shade-text;
@color-messagepart-border: #f4f4f4;
@color-messagepart-background: #fcfcfc;
@color-spellcheck-link: @color-error;
@color-table-border: @color-layout-border;
@color-table-selected: @color-list-selected;
@color-table-selected-background: @color-list-selected-background;
// Datepicker
@color-datepicker-border: @color-layout-border;
@color-datepicker-font: @color-font;
@color-datepicker-highlight: @color-main;
@color-datepicker-highlight-background: lighten(@color-main, 30%);
@color-datepicker-active: #fff;
@color-datepicker-active-background: @color-main;
// HTML editor
@color-editor-disabled-mask: fadeout(lighten(@color-black, 85), 10);
// Image tools
@color-image-tools: #fff;
@color-image-tools-background: fadeout(@color-main, 60%);
@color-image-tools-hover: fadeout(@color-main, 50%);
// Scrollbars
@color-scrollbar-thumb: #c1c1c1;
@color-scrollbar-track: #f1f1f1;
// Dark mode colors
@color-dark-main: darken(@color-main, 30%);
@color-dark-background: #21292c;
@color-dark-font: #c5d1d3;
@color-dark-border: #4d6066;
@color-dark-hint: darken(@color-dark-font, 20%);
@color-dark-information: shade(@color-main, 40%);
@color-dark-success: shade(@color-success, 40%);
@color-dark-warning: shade(@color-warning, 40%);
@color-dark-error: shade(@color-error, 40%);
@color-dark-list-selected: @color-main;
@color-dark-list-selected-background: #374549;
@color-dark-list-badge: lighten(@color-dark-font, 10%);
@color-dark-list-badge-background: @color-dark-border;
@color-dark-list-deleted: darken(@color-dark-hint, 15%);
@color-dark-list-droptarget-background: #4d4d00;
@color-dark-list-border: #2c373a;
@color-dark-input: @color-dark-font;
@color-dark-input-border: #7c949c;
@color-dark-input-background: @color-dark-background;
@color-dark-input-focus: #e2e7e9;
@color-dark-input-border-focus: @color-main;
@color-dark-input-background-focus: lighten(@color-dark-background, 5%);
@color-dark-input-addon-background: #374549;
@color-dark-input-addon-background-focus: lighten(@color-dark-list-selected-background, 15%);
@color-dark-checkbox: @color-dark-border;
@color-dark-checkbox-checked: @color-dark-main;
@color-dark-btn: lighten(@color-dark-font, 10%);
@color-dark-btn-primary-background: @color-dark-main;
@color-dark-btn-secondary-background: @color-dark-border;
@color-dark-btn-danger-background: @color-dark-error;
@color-dark-dialog-overlay-background: fade(black, 70%);
@color-dark-popover-background: #161b1d;
@color-dark-popover-border: lighten(#161b1d, 50%);
@color-dark-message-information: @color-dark-information;
@color-dark-message-success: @color-dark-success;
@color-dark-message-warning: @color-dark-warning;
@color-dark-message-error: @color-dark-error;
@color-dark-message-loading: lighten(@color-dark-background, 10%);
@color-dark-scrollbar-thumb: darken(@color-main, 25%);
@color-dark-scrollbar-track: @color-dark-border;
@color-dark-blockquote-0: lighten(@color-main, 10%);
@color-dark-blockquote-1: lighten(@color-success, 10%);
@color-dark-blockquote-2: lighten(@color-error, 10%);
@color-dark-blockquote-0-border: @color-dark-blockquote-0;
@color-dark-blockquote-1-border: @color-dark-blockquote-1;
@color-dark-blockquote-2-border: @color-dark-blockquote-2;

1123
styles/dark.less Normal file

File diff suppressed because it is too large Load Diff

95
styles/embed.less Normal file
View File

@ -0,0 +1,95 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/* Style for embedded pages and TinyMCE editor content page */
@import "global";
.mce-content-body {
margin: 4px;
color: @color-input;
div.pre {
font-family: monospace;
}
blockquote {
border-left: #1010ff 2px solid;
margin: 0;
padding: 0 0.4em;
}
}
.rcmail-inline-message {
.font-family();
font-size: @page-font-size;
padding: .5em;
margin: 0 0 .5em 0;
opacity: .95;
color: @color-message;
background-color: @color-message-warning-box-background;
display: flex;
align-items: center;
&:before {
.font-icon-class();
font-size: 1.5em;
line-height: 1;
width: 1em;
margin-right: .3em;
content: @fa-var-exclamation-triangle;
color: @color-message-warning;
}
span {
line-height: 1.5;
}
a {
color: @color-link;
}
a:hover {
color: @color-link-hover;
}
button {
vertical-align: middle;
white-space: nowrap;
padding: .375em .75em;
margin-left: .5em;
font-size: 1em;
line-height: 1.5;
border-radius: .25em;
border: 1px solid transparent;
color: @color-btn-primary;
background: @color-btn-primary-background;
&:focus {
box-shadow: 0 0 0 .2rem fade(@color-btn-primary-background, 50%);
}
&:hover {
background: darken(@color-btn-primary-background, 8%);
border-color: darken(@color-btn-primary-background, 10%);
}
&:not([disabled]):not(.disabled):active {
background: darken(@color-btn-primary-background, 11%);
border-color: darken(@color-btn-primary-background, 13%);
box-shadow: 0 0 0 .2rem fade(@color-btn-primary-background, 53%);
}
}
}
.rcmail-inline-buttons {
margin: 0;
}

1
styles/embed.min.css vendored Normal file
View File

@ -0,0 +1 @@
.popover,.rcmail-inline-message,body,button,input,optgroup,select,textarea{font-family:Roboto,sans-serif}@font-face{font-family:Icons;font-style:normal;font-weight:900;src:url(../fonts/fa-solid-900.woff2) format('woff2'),url(../fonts/fa-solid-900.woff) format('woff')}@font-face{font-family:Icons;font-style:normal;font-weight:400;src:url(../fonts/fa-regular-400.woff2) format('woff2'),url(../fonts/fa-regular-400.woff) format('woff')}@font-face{font-family:Roboto;font-style:normal;font-weight:400;src:local('Roboto'),local('Roboto-Regular'),url(../fonts/roboto-v29-regular.woff2) format('woff2'),url(../fonts/roboto-v29-regular.woff) format('woff')}@font-face{font-family:Roboto;font-style:italic;font-weight:400;src:local('Roboto Italic'),local('Roboto-Italic'),url(../fonts/roboto-v29-italic.woff2) format('woff2'),url(../fonts/roboto-v29-italic.woff) format('woff')}@font-face{font-family:Roboto;font-style:normal;font-weight:700;src:local('Roboto Bold'),local('Roboto-Bold'),url(../fonts/roboto-v29-regular-700.woff2) format('woff2'),url(../fonts/roboto-v29-regular-700.woff) format('woff')}@font-face{font-family:Roboto;font-style:italic;font-weight:700;src:local('Roboto Bold Italic'),local('Roboto-BoldItalic'),url(../fonts/roboto-v29-italic-700.woff2) format('woff2'),url(../fonts/roboto-v29-italic-700.woff) format('woff')}button,input,select,textarea{line-height:initial}input{vertical-align:middle}a{color:#bd139a}a:hover{color:#8f0e74}a.disabled{pointer-events:none}a.disabled:not(.btn){opacity:.5}html:not(.touch) ::-webkit-scrollbar{width:6px}html{scrollbar-color:#c1c1c1 #f1f1f1}html:not(.touch) ::-webkit-scrollbar-track{background-color:#f1f1f1}html:not(.touch) ::-webkit-scrollbar-thumb{background-color:#c1c1c1}.mce-content-body{margin:4px;color:#2c363a}.mce-content-body div.pre{font-family:monospace}.mce-content-body blockquote{border-left:#1010ff 2px solid;margin:0;padding:0 .4em}.rcmail-inline-message{font-size:14px;padding:.5em;margin:0 0 .5em;opacity:.95;color:#2c363a;background-color:rgba(246,96,157,.2);display:flex;align-items:center}.rcmail-inline-message:before{display:block;float:left;margin:0 .3em 0 0;height:1em;font-family:Icons;font-style:normal;font-weight:900;text-decoration:inherit;text-align:center;speak:none;font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-size:1.5em;line-height:1;width:1em;content:"\f071";color:#F6609D}.rcmail-inline-message span{line-height:1.5}.rcmail-inline-message a{color:#bd139a}.rcmail-inline-message a:hover{color:#8f0e74}.rcmail-inline-message button{vertical-align:middle;white-space:nowrap;padding:.375em .75em;margin-left:.5em;font-size:1em;line-height:1.5;border-radius:.25em;border:1px solid transparent;color:#fff;background:#50162d}.rcmail-inline-message button:focus{box-shadow:0 0 0 .2rem rgba(80,22,45,.5)}.rcmail-inline-message button:hover{background:#300d1b;border-color:#280b17}.rcmail-inline-message button:not([disabled]):not(.disabled):active{background:#240a14;border-color:#1c0810;box-shadow:0 0 0 .2rem rgba(80,22,45,.53)}.rcmail-inline-buttons{margin:0}

1397
styles/fontawesome.less vendored Normal file

File diff suppressed because it is too large Load Diff

149
styles/global.less Normal file
View File

@ -0,0 +1,149 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
@import (reference) "variables";
@import (reference) "mixins";
/*** Fonts ***/
@font-face {
font-family: 'Icons';
font-style: normal;
font-weight: 900;
src: url("../fonts/fa-solid-900.woff2") format('woff2'),
url("../fonts/fa-solid-900.woff") format('woff');
}
@font-face {
font-family: 'Icons';
font-style: normal;
font-weight: 400;
src: url("../fonts/fa-regular-400.woff2") format('woff2'),
url("../fonts/fa-regular-400.woff") format('woff');
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'),
url('../fonts/roboto-v29-regular.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+
url('../fonts/roboto-v29-regular.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 400;
src: local('Roboto Italic'), local('Roboto-Italic'),
url('../fonts/roboto-v29-italic.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+
url('../fonts/roboto-v29-italic.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+
}
@font-face {
font-family: 'Roboto';
font-style: normal;
font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'),
url('../fonts/roboto-v29-regular-700.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+
url('../fonts/roboto-v29-regular-700.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+
}
@font-face {
font-family: 'Roboto';
font-style: italic;
font-weight: 700;
src: local('Roboto Bold Italic'), local('Roboto-BoldItalic'),
url('../fonts/roboto-v29-italic-700.woff2') format('woff2'), // Chrome 26+, Opera 23+, Firefox 39+
url('../fonts/roboto-v29-italic-700.woff') format('woff'); // Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+
}
/* Reset some Bootstrap style */
body, button, input, optgroup, select, textarea, .popover {
.font-family();
}
button, input, select, textarea {
line-height: initial;
}
input {
vertical-align: middle;
}
a {
color: @color-link;
&:hover {
color: @color-link-hover;
}
&.disabled {
pointer-events: none;
}
&.disabled:not(.btn) {
opacity: .5;
}
}
/* Scrollbar styles */
html when not (@scrollbar-width = unset) {
// Ignore thin width setting for Firefox, it makes the scrollbar very very thin in Firefox >= 100
& when not (@scrollbar-width = thin) {
scrollbar-width: @scrollbar-width;
textarea,
select,
.popover-body,
.popupmenu,
.ui-menu,
.ui-dialog-content,
.frame-content,
.formcontent,
.table-responsive,
.table-responsive-sm,
.tox-menu,
.tox-dialog__body-nav,
.tox-collection__group,
.scroller {
// Firefox does not inherit scrollbar size from the html element
scrollbar-width: @scrollbar-width;
}
}
&:not(.touch) {
::-webkit-scrollbar when (@scrollbar-width = auto) {
// Note: If we do not set the width a default scrollbar is used in Chrome.
// And the custom colors set below do not work
width: 12px;
}
::-webkit-scrollbar when (@scrollbar-width = thin) {
width: 6px;
}
}
}
html {
scrollbar-color: @color-scrollbar-thumb @color-scrollbar-track;
&:not(.touch) {
::-webkit-scrollbar-track {
background-color: @color-scrollbar-track;
}
::-webkit-scrollbar-thumb {
background-color: @color-scrollbar-thumb;
}
}
}

414
styles/layout.less Normal file
View File

@ -0,0 +1,414 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Responsive design - Layout ***/
/*
- Large screen (width > 1200px)
-----------------------------------------------------------------------------------------------------
| menu | sidebar | list | content |
-----------------------------------------------------------------------------------------------------
- Normal screen (1200px => width => 768px) - typical: 768x1024 (iPad Mini/Air)
-------------------------------------------------------------------
|menu| sidebar/list | content |
-------------------------------------------------------------------
- Small (480px < width < 768px)
------------------------------------------
|menu| sidebar/list/content |
------------------------------------------
- Phone (width <= 480px) - typical: 320x480 (iPhone 5), 375x667 (iPhone 6-7), 360x564 (Galaxy S6)
------------------------
| sidebar/list/content |
------------------------
*/
html {
height: 100%;
font-size: @page-font-size;
}
body {
min-width: @page-min-width;
height: 100%;
color: @color-font;
overflow: hidden;
html.iframe & {
overflow: auto;
}
}
#layout {
overflow: hidden;
display: flex;
height: 100%;
width: 100%;
& > div {
& > .scroller {
flex: 1;
position: relative; // for .listing-info positioning
}
& > .header,
& > .footer {
font-size: @layout-header-font-size;
font-weight: bold;
line-height: @layout-header-height;
height: @layout-header-height;
min-height: @layout-header-height;
padding: 0 .25em;
margin: 0;
position: relative; // for absolute positioning of searchbar
overflow: hidden;
white-space: nowrap;
display: flex;
justify-content: center;
}
& > .header {
border-bottom: 1px solid @color-layout-border;
color: @color-layout-header;
background-color: @color-layout-header-background;
.header-title {
.overflow-ellipsis();
flex: 1;
text-align: center;
margin: 0 -20rem;
}
a.button {
color: @color-toolbar-button;
}
a.toolbar-list-button,
a.toolbar-menu-button {
order: 99; // always the last button
}
}
& > .footer {
border-top: 1px solid @color-layout-border;
background-color: @color-layout-footer-background;
& when not (@layout-footer-height = @layout-header-height) {
height: @layout-footer-height;
min-height: @layout-footer-height;
line-height: @layout-footer-height;
}
&.small {
height: @layout-footer-small-height;
min-height: @layout-footer-small-height;
line-height: @layout-footer-small-height;
}
&:empty {
display: none;
}
}
}
}
#layout-sidebar {
position: relative; // e.g. for .column-resizer
display: flex;
flex-direction: column;
flex: 2;
max-width: 30%;
min-width: 220px;
border-right: 1px solid @color-layout-border;
background-color: @color-layout-sidebar-background;
&.sidebar-right {
order: 2;
border-right: 0;
border-left: 1px solid @color-layout-border;
// sidebar on right is unusual situation, probably there's no list in layout,
// in such a case we can make it a little bit wider
flex: 3;
}
}
#layout-list {
position: relative; // e.g. for .column-resizer
display: flex;
flex-direction: column;
flex: 3;
max-width: 30%;
min-width: 300px;
border-right: 1px solid @color-layout-border;
background-color: @color-layout-list-background;
}
#layout-content {
display: flex;
flex: 6;
flex-direction: column;
background-color: @color-layout-content-background;
width: 100%;
html.iframe & {
height: 100%;
}
& > .formcontent, // e.g. Help plugin
& > .content {
height: 100%;
width: 100%;
overflow: auto;
flex: 1;
}
.iframe-wrapper {
width: 100%;
flex: 1;
iframe {
width: 100%;
height: 100%;
border: 0;
}
}
&.only > .scroller {
overflow: auto;
}
}
#layout-menu {
&.popover {
left: 0 !important;
}
.popover-header {
height: @layout-header-height;
line-height: @layout-header-height;
border: 0;
border-radius: 0;
text-align: center;
img {
max-height: @layout-header-height;
max-width: @layout-menu-width;
padding: .25rem;
@media screen and (min-width: (@screen-width-xs + 1px)) and (max-width: @screen-width-medium) {
max-width: @layout-menu-width * 0.45;
}
}
@media screen and (min-width: (@screen-width-xs + 1px)) {
padding: 0 !important;
background-color: @color-taskmenu-background !important;
a {
display: none !important;
}
}
html.layout-phone & {
display: flex !important;
align-items: center;
justify-content: center;
padding: 0 .5rem;
img {
max-width: @layout-mobile-menu-width - 50px;
}
a {
width: auto;
flex: 1;
&:before {
height: @layout-touch-header-height;
float: right;
}
.inner {
display: none;
}
}
}
}
}
.column-resizer {
cursor: col-resize;
z-index: 1;
position: absolute;
top: 0;
right: -3px;
width: 6px;
height: 100%;
&.inverted {
right: auto;
left: -3px;
}
&.active {
width: 10000px;
right: -5000px;
&.inverted {
right: auto;
left: -5000px;
}
}
}
@media screen and (max-width: @screen-width-large) {
#layout-sidebar,
#layout-list {
min-width: 260px;
flex: 3;
}
#layout-list > .header > a.button {
padding: 0 .25rem;
margin: 0 .25rem;
}
}
@media screen and (max-width: @screen-width-medium) {
// Disable column resizing by hiding splitters and resetting columns width
.column-resizer {
display: none;
}
#layout-sidebar,
#layout-list {
width: auto !important;
flex: 3 !important;
}
}
@media screen and (max-width: @screen-width-small) {
#layout-sidebar,
#layout-list {
max-width: none;
border: 0 !important;
}
#layout > div > .header {
background-color: @color-layout-mobile-header-background;
a.button {
// make the button active area smaller on touch devices
margin: 0 .3rem !important;
padding: 0 !important;
&:before {
font-size: 1.75rem;
height: @layout-touch-header-height;
margin: 0;
}
&.filter:before {
font-size: 1.6rem; // this icon is too big in FA5
}
.inner {
display: none;
}
}
}
#layout > div > .footer {
background-color: @color-layout-mobile-footer-background;
}
a.toolbar-list-button {
display: none;
}
}
@media screen and (max-width: @screen-width-xs) {
}
@media screen and (max-width: @screen-width-mini) {
#layout-sidebar,
#layout-list {
min-width: @page-min-width;
}
}
@media screen and (min-width: (@screen-width-xs + 1px)) {
a.task-menu-button {
display: none;
}
#layout-menu {
// FIXME: we set background color here not in taskmenu.less, because
// otherwise background is partially white on Android/iOS
background-color: @color-taskmenu-background;
width: @layout-menu-width-sm;
}
}
@media screen and (min-width: (@screen-width-small + 1px)) {
.floating-action-buttons,
#layout-content > .header > .header-title,
#layout > div > .header > .buttons,
a.toolbar-menu-button {
display: none;
}
}
@media screen and (min-width: (@screen-width-medium + 1px)) {
#layout-menu {
width: @layout-menu-width;
}
}
@media screen and (min-width: (@screen-width-large + 1px)) {
#layout-list > .header > .header-title:not(.all-sizes),
a.toolbar-list-button,
a.back-list-button,
a.back-sidebar-button {
display: none;
}
}
html.layout-phone {
.hidden-phone {
display: none !important;
}
}
html.layout-phone,
html.layout-small {
.hidden-small {
display: none !important;
}
}
html.layout-small {
.hidden-lbs {
display: none !important;
}
}
html.layout-large,
html.layout-normal {
.hidden-lbs,
.hidden-big {
display: none !important;
}
}
html.layout-large {
.hidden-large {
display: none !important;
}
}

62
styles/mixins.less Normal file
View File

@ -0,0 +1,62 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Font-icons ***/
.font-icon-class {
font-size: 1.25em;
// FIXME: with inline-block we have some problems with icon alignment
// display: inline-block;
display: block;
float: left;
margin: 0 .25rem 0 0;
width: 1.18em;
height: 1em;
font-family: 'Icons';
font-style: normal;
font-weight: 900;
text-decoration: inherit;
text-align: center;
speak: none;
font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
}
.animated-icon-class {
// spinner-border is defined in Bootstrap
-webkit-animation: spinner-border 1.5s infinite linear;
animation: spinner-border 1.5s infinite linear;
}
.font-icon-solid(@icon) {
content: @icon;
font-weight: 900;
}
.font-icon-regular(@icon) {
content: @icon;
font-weight: 400;
}
.overflow-ellipsis {
overflow: hidden;
text-overflow: ellipsis;
}
.font-family {
font-family: Roboto, sans-serif;
}
.style-input-focus {
border-color: @color-input-border-focus;
box-shadow: 0 0 0 .2rem @color-input-border-focus-shadow;
}

78
styles/print.less Normal file
View File

@ -0,0 +1,78 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Additional styles for printouts ***/
body {
overflow: auto;
height: auto;
}
#print-layout {
margin: 1rem;
#logo {
max-height: 80px;
}
// Overwrites for mail message printouts
.image-attachment {
.image-link {
margin-bottom: .5rem;
}
.attachment-links {
display: none;
}
}
#message-header {
margin-bottom: .5rem;
}
.attachment-size {
padding-left: .1rem;
}
blockquote {
page-break-inside: auto;
}
// Overwrites for contact printouts
.formcontent {
padding: 0;
legend {
margin-top: .5rem;
}
.row .form-control-plaintext {
padding: .1rem;
}
.contactfield {
padding: .2rem 0;
}
}
.propform.grouped .row.input-group .input-group-text {
padding: 0;
min-width: 12rem;
background: #fff;
border: 0;
}
.contact-header {
margin-bottom: 0;
}
}

1
styles/print.min.css vendored Normal file
View File

@ -0,0 +1 @@
#print-layout #message-header,#print-layout .image-attachment .image-link{margin-bottom:.5rem}body{overflow:auto;height:auto}#print-layout{margin:1rem}#print-layout #logo{max-height:80px}#print-layout .image-attachment .attachment-links{display:none}#print-layout .attachment-size{padding-left:.1rem}#print-layout blockquote{page-break-inside:auto}#print-layout .formcontent{padding:0}#print-layout .formcontent legend{margin-top:.5rem}#print-layout .formcontent .row .form-control-plaintext{padding:.1rem}#print-layout .formcontent .contactfield{padding:.2rem 0}#print-layout .propform.grouped .row.input-group .input-group-text{padding:0;min-width:12rem;background:#fff;border:0}#print-layout .contact-header{margin-bottom:0}

458
styles/styles.less Normal file
View File

@ -0,0 +1,458 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
@import "global";
@import "layout";
@import "widgets/common";
@import "widgets/buttons";
@import "widgets/jqueryui";
@import "widgets/dialogs";
@import "widgets/menu";
@import "widgets/messages";
@import "widgets/lists";
@import "widgets/forms";
@import "widgets/editor";
/*** Login form ***/
.task-login {
#layout-content {
text-align: center;
width: 100%;
display: block;
}
#logo {
display: inline-block;
position: relative;
top: 16vh;
max-height: 100px;
}
}
#login-form {
margin: 0 auto;
top: 20vh;
width: 95%;
max-width: 320px;
position: relative;
// Fixes table width in IE11
table, tbody {
display: block;
}
// Fixes input width in IE11
.row {
margin-right: 0;
margin-left: 0;
}
.oauthlogin {
margin-top: 1em;
padding-top: 1em;
}
.formbuttons + .oauthlogin {
border-top: 1px solid #ccc;
}
}
#rcmloginsubmit {
&:before {
display: none !important;
}
}
#login-footer {
flex: 1;
color: @color-black-shade-text;
& > div {
margin-top: 1rem;
padding: 1rem;
background: @color-black-shade-bg;
border-radius: .3rem;
}
}
#login-addon {
position: absolute;
bottom: 0;
max-height: 30%;
margin: 1rem !important;
width: auto !important;
overflow: auto;
@media screen and (min-width: (@screen-width-small + 1px)) {
max-width: @screen-width-small;
margin: auto !important;
bottom: 1rem;
left: 0;
right: 0;
}
}
body.task-error-login #layout {
#layout-menu,
#layout-content > .header {
display: none;
}
}
/*** Addressbook UI ***/
#contactpic {
width: @layout-contact-icon-width;
height: @layout-contact-icon-height;
border-radius: .5rem;
overflow: hidden;
display:table-cell;
vertical-align:middle;
text-align: center;
background-color: @color-image-upload-background;
img {
max-width: @layout-contact-icon-width;
max-height: @layout-contact-icon-height;
}
}
#contacthead {
.names {
margin-bottom: .5rem;
span.namefield {
font-size: 1.5rem;
font-weight: bold;
line-height: 1.2;
}
}
&.readonly {
.source.row {
color: @color-form-hint;
font-size: 90%;
margin-bottom: .25rem;
}
}
}
/*** Mail UI ***/
#message-header {
margin-bottom: 1rem;
& > .subject {
font-size: 1.5rem;
font-weight: bold;
body.status-flagged &:before {
&:extend(.font-icon-class);
display: inline;
float: none;
content: @fa-var-flag;
font-size: 1em;
color: @color-error;
}
a.extwin {
text-decoration: none;
&:before {
&:extend(.font-icon-class);
float: none;
display: inline-block;
font-size: 75%;
line-height: 1.5;
margin: 0;
content: @fa-var-external-link-square-alt;
}
}
span.inner {
display: none;
}
}
& > .header {
display: flex;
img.contactphoto {
margin: 0 1rem 0 0;
border-radius: 50%;
width: @mail-header-photo-height;
height: @mail-header-photo-height;
object-fit: cover;
background: @color-image-upload-background;
}
}
.header-content {
min-height: @mail-header-photo-height;
flex: 1;
&.details-view {
.header-summary {
display: none;
}
.header-headers {
display: initial;
}
}
}
.header-summary {
margin-top: .25rem;
& > span {
display: inline-block;
}
}
.header-headers {
display: none;
.header-title {
white-space: nowrap;
color: @color-black-shade-text;
font-weight: bold;
padding-right: 1rem;
vertical-align: top;
}
}
.header-links {
margin-top: .25rem;
a {
font-size: 90%;
margin-right: .5rem;
text-decoration: none;
white-space: nowrap;
display: inline-block;
&:before {
&:extend(.font-icon-class);
height: 1.5rem;
line-height: 1.3;
}
&.headers-details:before {
content: @fa-var-envelope;
}
&.headers-summary:before {
.font-icon-regular(@fa-var-envelope);
}
&.headers-all:before {
content: @fa-var-info-circle;
}
&.html:before {
content: @fa-var-image;
}
&.plain:before {
content: @fa-var-align-justify;
}
&.zipdownload:before {
content: @fa-var-download;
}
}
}
}
.message-partheaders {
padding: .25rem .5rem;
margin: .5rem 0 -.5rem 0;
border-top: 1px solid @color-messagepart-border;
background-color: @color-messagepart-background;
table.headers-table {
font-size: 90%;
color: @color-mail-headers;
.header-title {
.overflow-ellipsis();
white-space: nowrap;
max-width: 8em;
font-weight: bold;
padding-right: 1rem;
vertical-align: top;
}
.subject {
font-weight: bold;
}
& + .message-part,
& + .message-htmlpart {
border-top: 0;
margin: 0;
}
}
}
#message-content {
.attachmentslist:not(:empty) {
margin-bottom: 1rem;
}
}
#messagebody {
&.mailvelope {
iframe {
min-height: 75vh;
}
}
}
.message-part,
.message-htmlpart {
padding-top: .5rem;
// Fixes absolute positioned mail message content
position: relative;
&:not(:first-child) {
border-top: 1px solid @color-messagepart-border;
margin-top: .5rem;
}
&:last-child {
margin-bottom: .5rem;
}
div.rcmBody {
// Remove margins that can be set by the mail message styles
margin: 0 auto !important;
}
blockquote {
.overflow-ellipsis();
color: @color-blockquote-0;
border-left: 2px solid @color-blockquote-0-border;
border-right: 2px solid @color-blockquote-0-border;
background-color: @color-blockquote-background;
margin: 2px 0;
padding: 0 .4em;
blockquote {
color: @color-blockquote-1;
border-left: 2px solid @color-blockquote-1-border;
border-right: 2px solid @color-blockquote-1-border;
blockquote {
color: @color-blockquote-2;
border-left: 2px solid @color-blockquote-2-border;
border-right: 2px solid @color-blockquote-2-border;
}
}
span.blockquote-link {
top: 0;
cursor: pointer;
right: .5rem;
min-width: 4rem;
padding: .2rem .25rem .2rem .5rem;
font-size: 90%;
text-align: center;
color: @color-black-shade-text;
background: @color-black-shade-bg;
border: 1px solid @color-black-shade-border;
border-radius: .3rem;
line-height: 1;
.font-family(); // don't inherit monospace font
&:after {
&:extend(.font-icon-class);
content: @fa-var-angle-down;
display: inline-block;
float: none;
margin: 0;
font-size: 90%;
}
&.collapsed:after {
content: @fa-var-angle-up;
}
}
&.blockquote-header {
text-overflow: ellipsis !important;
padding-right: 5rem !important;
}
}
}
.message-part {
span.sig {
color: @color-mail-signature;
}
div.pre {
font-family: monospace;
font-size: 13px;
}
// This is needed for proper display of quoted plain text
blockquote {
display: inline-block;
min-width: 100%;
& + br {
// compensate the spacing "removed" by the inline-block style above
display: block;
margin-top: 1em;
}
}
}
#compose-attachments {
margin: 1rem 1rem 0 1rem;
}
#composestatusbar {
opacity: .3;
right: 2.5rem;
@media screen and (min-width: (@screen-width-small + 1px)) {
display: none;
}
a.button {
display: inline-block;
&:before {
line-height: @layout-touch-header-height;
font-size: 1.25rem !important;
}
}
}
/*** Settings UI ***/
// A default icon for settings menu entries added by plugins
.settings-default-icon {
tr > td.section::before,
li > a:before {
content: @fa-var-cog;
}
}
& when (@dark-mode-enabled = true) {
@import "dark";
}
@import (optional) "_styles";

1
styles/styles.min.css vendored Normal file

File diff suppressed because one or more lines are too long

63
styles/variables.less Normal file
View File

@ -0,0 +1,63 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
@import (reference) "fontawesome";
@import (reference) "colors";
@dark-mode-enabled: true; // on change also have to change dark_mode_support in meta.json
@screen-width-large: 1200px;
@screen-width-medium: 1024px;
@screen-width-small: 768px;
@screen-width-xs: 480px;
@screen-width-mini: 320px;
@screen-width-touch: @screen-width-medium;
@screen-width-bs-phone: 576px;
@page-font-size: 14px;
@page-min-width: 240px;
// Note: we'll set some values in pixels instead of rem to eliminate
// Firefox sub-pixel rendering bug(s)
@layout-menu-width: floor(5.6 * @page-font-size);
@layout-menu-width-sm: floor(3 * @page-font-size);
@layout-header-height: floor(4.2 * @page-font-size);
@layout-footer-height: @layout-header-height;
@layout-footer-small-height: floor(2.5 * @page-font-size);
@layout-header-font-size: 1rem;
@layout-searchbar-height: floor(2.6 * @page-font-size);
@layout-touch-header-height: @layout-header-height;
@layout-touch-header-font-size: floor(1.2 * @page-font-size);
@layout-touch-menu-record-height: floor(3.4 * @page-font-size);
@layout-touch-menu-record-font-size: floor(1.2 * @page-font-size);
@layout-touch-icon-width: 2.2em;
@layout-mobile-menu-width: (@screen-width-mini * .85);
@layout-contact-icon-width: 112px;
@layout-contact-icon-height: 135px;
@listing-line-height: floor(2.5 * @page-font-size);
@listing-touch-line-height: floor(3.4 * @page-font-size);
@listing-treetoggle-width: 1.5em;
@mail-header-photo-height: 4rem;
// Scrollbars
@scrollbar-width: thin; // 'auto' or 'thin' or 'unset'
// Additional icons
@icon-resize-corner: data-uri("image/svg+xml;charset=utf-8", "../images/corner-handle.svg"); // size: 16x16
@icon-file-drop: data-uri("image/svg+xml;charset=utf-8", "../images/download.svg");
@import (reference, optional) "_variables";

349
styles/widgets/buttons.less Normal file
View File

@ -0,0 +1,349 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Buttons ***/
.button.disabled {
opacity: .5;
}
a.button {
text-decoration: none !important;
}
/* font-icons */
a.button.icon,
button.btn {
&:before {
&:extend(.font-icon-class);
}
&.sidebar-menu:before,
&.toolbar-menu-button:before,
&.toolbar-list-button:before {
content: @fa-var-ellipsis-v;
width: 1em;
}
&.task-menu-button:before {
content: @fa-var-bars;
}
&.back-sidebar-button:before,
&.back-content-button:before,
&.back-list-button:before {
content: @fa-var-chevron-left;
}
&.refresh:before {
content: @fa-var-sync;
}
&.generate:before,
&.yes:before,
&.submit:before,
&.continue:before,
&.save:before {
content: @fa-var-check;
}
&.create:before {
content: @fa-var-plus-square;
}
&.edit:before {
content: @fa-var-pencil-alt;
}
&.qrcode:before {
content: @fa-var-qrcode;
}
&.search:before {
content: @fa-var-search;
}
&.filter:before {
content: @fa-var-filter;
font-size: 1.2em; // this icon is too-big in FA5
}
&.import:before {
content: @fa-var-upload;
}
&.export:before {
content: @fa-var-download;
}
&.discard:before,
&.delete:before {
.font-icon-regular(@fa-var-trash-alt);
}
&.next:before {
content: @fa-var-arrow-right;
}
&.restore:before {
content: @fa-var-undo;
}
&.send:before,
&.bounce:before {
content: @fa-var-paper-plane;
}
&.attach:before {
content: @fa-var-paperclip;
}
&.attach.vcard:before {
content: @fa-var-user;
}
&.no:before,
&.close:before,
&.cancel:before {
content: @fa-var-times;
}
&.back:before {
content: @fa-var-chevron-left;
}
&.remove:before {
content: @fa-var-times;
}
&.unlock:before {
content: @fa-var-unlock;
}
&.help:before {
.font-icon-regular(@fa-var-life-ring);
}
&.folders:before {
content: @fa-var-folder-open;
}
&.options:before {
content: @fa-var-sliders-h;
}
&.tools:before,
&.settings:before {
content: @fa-var-cog;
}
&.properties:before {
content: @fa-var-info-circle;
}
&.selection:before {
.font-icon-regular(@fa-var-check-square);
}
&.insert.recipient:before {
content: @fa-var-user-plus;
}
&.encrypt:before {
content: @fa-var-lock;
}
&.sign:before {
content: @fa-var-signature;
}
&.sso:before {
content: @fa-var-sign-in-alt;
}
&.extwin:before {
content: @fa-var-external-link-square-alt;
}
}
a.btn,
button.btn {
&:before {
display: inline !important;
float: none !important;
vertical-align: middle;
margin-right: .4rem !important; // !important needed for a.btn
}
&.oauth.google:before,
&.oauth.outlook:before {
content: " ";
display: inline-block !important;
height: 1.5rem;
width: 1.5rem;
margin-right: .8rem !important;
background-size: 100% auto;
}
&.oauth.google:before {
background: url('../images/google-icon.svg') top left no-repeat;
}
&.oauth.outlook:before {
background: url('../images/microsoft-icon.svg') top left no-repeat;
}
}
a.button.icon {
&.dropdown:before {
content: @fa-var-caret-down;
font-size: 1em;
}
& > span.inner {
display: none;
}
}
html.touch {
.btn:focus {
box-shadow: none !important;
}
}
@floating-action-button-size: 4rem;
.floating-action-buttons {
position: absolute;
right: 0;
bottom: 0;
.footer:not(:empty) + & {
bottom: @layout-footer-small-height;
}
a.button {
display: block;
float: left;
width: @floating-action-button-size;
height: @floating-action-button-size;
border-radius: 50%;
background: @color-main;
color: white;
opacity: .95;
box-shadow: 0 0 5px 5px lighten(@color-main, 35%);
margin: 0 1rem 1rem 0;
&:before {
&:extend(.font-icon-class);
content: @fa-var-plus;
width: @floating-action-button-size;
height: @floating-action-button-size;
line-height: @floating-action-button-size;
}
&.compose {
&:before {
content: @fa-var-pen;
}
}
.inner {
display: none;
}
}
}
/*** Bootstrap button style overrides ***/
.btn {
&:focus {
box-shadow: 0 0 0 .2rem fade(@color-btn-primary-background, 30%);
}
}
.btn-link {
color: @color-link;
}
.btn-secondary {
color: @color-btn-secondary;
background: @color-btn-secondary-background;
border-color: @color-btn-secondary-background;
&:focus {
background: darken(@color-btn-secondary-background, 5%);
border-color: darken(@color-btn-secondary-background, 7%);
box-shadow: 0 0 0 .2rem fade(@color-btn-secondary-background, 50%);
}
&:hover {
background: darken(@color-btn-secondary-background, 5%);
border-color: darken(@color-btn-secondary-background, 7%);
}
&.disabled,
&:disabled {
background: @color-btn-secondary-background;
border-color: @color-btn-secondary-background;
}
&:not(:disabled):not(.disabled) {
&:active,
&.active {
background: darken(@color-btn-secondary-background, 10%);
border-color: darken(@color-btn-secondary-background, 12%);
&:focus {
box-shadow: 0 0 0 .2rem fade(@color-btn-secondary-background, 53%);
}
}
}
}
.btn-primary {
color: @color-btn-primary;
background: @color-btn-primary-background;
border-color: @color-btn-primary-background;
&:focus {
background: darken(@color-btn-primary-background, 5%);
border-color: darken(@color-btn-primary-background, 7%);
box-shadow: 0 0 0 .2rem fade(@color-btn-primary-background, 50%);
}
&:hover {
background: darken(@color-btn-primary-background, 5%);
border-color: darken(@color-btn-primary-background, 7%);
}
&.disabled,
&:disabled {
background: @color-btn-primary-background;
border-color: @color-btn-primary-background;
}
&:not(:disabled):not(.disabled) {
&:active,
&.active {
background: darken(@color-btn-primary-background, 10%);
border-color: darken(@color-btn-primary-background, 12%);
&:focus {
box-shadow: 0 0 0 .2rem fade(@color-btn-primary-background, 53%);
}
}
}
}
.btn-danger {
color: @color-btn-danger;
background: @color-btn-danger-background;
border-color: @color-btn-danger-background;
&:focus {
background: darken(@color-btn-danger-background, 5%);
border-color: darken(@color-btn-danger-background, 7%);
box-shadow: 0 0 0 .2rem fade(@color-btn-danger-background, 50%);
}
&:hover {
background: darken(@color-btn-danger-background, 5%);
border-color: darken(@color-btn-danger-background, 7%);
}
&.disabled,
&:disabled {
background: @color-btn-danger-background;
border-color: @color-btn-danger-background;
}
&:not(:disabled):not(.disabled) {
&:active,
&.active {
background: darken(@color-btn-danger-background, 10%);
border-color: darken(@color-btn-danger-background, 12%);
&:focus {
box-shadow: 0 0 0 .2rem fade(@color-btn-danger-background, 53%);
}
}
}
}

585
styles/widgets/common.less Normal file
View File

@ -0,0 +1,585 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Common UI elements ***/
.rcmaddcontact,
.hidden,
.voice {
display: none !important;
}
font.bold {
font-weight: bold;
}
#rcmdraglayer {
min-width: 260px;
width: 260px;
background-color: @color-drag-layer-background;
color: @color-drag-layer;
box-shadow: 3px 3px 5px @color-drag-layer-shadow;
border-radius: .3rem;
z-index: 250;
opacity: .92;
padding: .5rem;
white-space: nowrap;
div {
line-height: 1.6em;
.overflow-ellipsis();
}
}
.frame-content {
padding: 1rem;
h2 {
font-weight: bold;
font-size: 1.5em;
}
h3 {
font-weight: bold;
font-size: 1.25em;
}
}
.listbox {
.scroller {
width: 100%;
overflow-x: hidden;
overflow-y: auto;
}
.navlist {
height: 0;
flex: initial !important;
.listing {
tr:last-child td,
li:last-child {
border-bottom: 0;
}
}
}
.popup & {
height: 100%;
display: flex;
flex-direction: column;
.scroller {
flex: 1;
}
.footer {
border-top: 1px solid @color-layout-border;
background-color: @color-searchbar-background;
}
}
}
.contact-header {
display: flex;
margin-bottom: 1rem;
.contact-photo {
min-width: @layout-contact-icon-width;
}
.contact-head {
margin-left: 1rem;
margin-top: 0 !important;
legend {
display: none;
}
}
}
@image-attachment-size: 250px;
// this is when image thumbnails are enabled
p.image-attachment {
position: relative;
border: 1px solid @color-border;
border-radius: .3rem;
background-color: @color-message-background;
float: left;
margin: .5rem;
min-width: 47%;
min-height: @image-attachment-size;
overflow: hidden;
// use flexbox to center the image
display: flex;
justify-content: center;
@media screen and (max-width: @screen-width-xs) {
float: none;
margin: .5rem 0 .5rem 0;
}
.image-link {
align-self: center;
text-align: center;
margin: 1.6rem .5rem;
}
span {
color: @color-form-hint;
padding: 0 .5rem;
font-size: 90%;
white-space: nowrap;
position: absolute;
line-height: 1.5rem;
}
.image-filename {
.overflow-ellipsis();
left: 0;
top: 0;
right: 0;
padding-right: 4rem;
}
.image-filesize {
right: 0;
top: 0;
}
.attachment-links {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
text-align: center;
a {
text-decoration: none;
display: inline-block;
padding: 0 .5rem;
line-height: 1.5rem;
}
a:before {
&:extend(.font-icon-class);
display: inline-block;
}
a.open:before {
content: @fa-var-external-link-square-alt;
}
a.download:before {
content: @fa-var-download;
}
}
}
// this is when image thumbnails are disabled
fieldset.image-attachment {
margin-top: .5rem;
legend {
color: @color-form-hint;
font-size: .9rem;
border-top: 1px solid lighten(@color-mail-headers, 50%);
margin: 0;
}
img {
max-width: 100%;
}
}
#folder-selector {
overflow-y: auto;
}
.noselect {
user-select: none;
-moz-user-select: none;
-khtml-user-select: none;
-ms-user-select: none;
-webkit-user-select: none;
}
.iframe-loader {
width: 100%;
position: absolute;
top: 0;
bottom: 0;
background-color: rgba(255, 255, 255, .95);
display: flex;
align-items: center;
justify-content: center;
z-index: 3;
.spinner-border {
width: 7rem;
height: 7rem;
color: @color-spinner-circle;
border: 1rem solid;
border-color: currentColor @color-spinner-item currentColor currentColor;
}
}
.footer.toolbar + .iframe-loader {
top: @layout-header-height;
bottom: @layout-header-height;
}
// iOS: Fix scrolling of iframe, display scrollbars on scrollable elements
.ios-scroll {
padding: 0;
-webkit-overflow-scrolling: touch !important;
overflow: scroll !important;
&.iframe-wrapper {
margin-top: 1px; // FIXME: without this scrolling hides the wrapper neighbours' border
}
}
.webkit-scroller {
&::-webkit-scrollbar {
-webkit-appearance: none;
}
&::-webkit-scrollbar:vertical {
width: .5rem;
}
&::-webkit-scrollbar:horizontal {
height: .5rem;
}
&::-webkit-scrollbar-thumb {
background-color: rgba(0, 0, 0, .3);
border-radius: .25rem;
border: 2px solid #fff;
}
}
.quota-widget {
width: 100%;
max-width: 15em;
padding: .5rem 1rem;
display: flex;
align-items: center;
color: @color-quota-text;
&:before {
&:extend(.font-icon-class);
content: @fa-var-hdd;
line-height: 1;
}
.count {
font-size: 80%;
order: 2;
}
.bar {
flex: 1;
height: .5rem;
margin: 0 1rem;
background-color: @color-quota-background;
border: 1px solid @color-layout-border;
border-radius: .25rem;
overflow: hidden;
}
.value {
display: block;
background-color: @color-quota-value;
height: 1rem;
opacity: .75;
&.warning {
background-color: @color-quota-value-warning;
}
}
}
.image-tools {
position: absolute;
top: 5rem;
left: 0;
height: @layout-header-height;
overflow: hidden;
transform: translateX(-87%);
transition: transform 0.3s ease-in-out;
background-color: @color-image-tools-background;
border-radius: 0 .3rem .3rem 0;
.menu {
float: left;
}
a.button.icon.tools {
padding: 0 .25rem;
display: inline-block;
height: @layout-header-height;
span.inner {
display: none;
}
&:before {
line-height: @layout-header-height;
margin: 0;
}
}
&.open {
transform: translateX(0);
a.button.icon.tools:before {
content: @fa-var-chevron-left;
}
}
a {
color: @color-image-tools !important;
&:focus,
&:hover {
background-color: @color-image-tools-hover !important;
outline: 0;
}
}
}
.quota-info {
width: 100%;
display: table !important;
td,th {
text-align: center;
white-space: nowrap;
}
th {
border-top: 0;
}
.root {
line-height: 1;
font-style: italic;
color: @color-popover-separator;
background-color: @color-popover-separator-background;
}
th:first-child,
.name {
text-align: left;
}
}
// Make Bootstrap tabs non-wrappable
.nav-tabs {
flex-wrap: nowrap;
.nav-item {
white-space: nowrap;
overflow: hidden;
}
.nav-link {
.overflow-ellipsis();
}
}
.props-table {
td.title {
width: 7em;
}
}
.table-widget {
display: flex;
flex-direction: column;
margin-bottom: .5rem;
border: 1px solid @color-table-border;
& > .content {
overflow-x: auto;
flex-grow: 1;
height: 18.5em;
table th {
border-top: 0;
}
}
& > .footer {
height: 3.5rem;
border-top: 1px solid @color-table-border;
text-align: left;
a {
padding: .2rem .45rem !important;
height: ~"calc(3.5rem - 1px)" !important;
}
}
table {
margin: 0;
max-height: 18.5em;
}
// Options table is a table with first column for identifier/description
// and other columns for a state flag. E.g. ACL table
table.options-table {
td,th {
text-align: center;
vertical-align: middle;
&:first-child {
.overflow-ellipsis();
text-align: left;
}
}
tr:last-child td {
border-bottom: 1px solid @color-table-border;
}
tr.selected td {
background-color: @color-table-selected-background;
color: @color-table-selected;
outline: 0;
}
td:not(:first-child) span {
display: inline-block;
line-height: 1.25;
&:before {
&:extend(.font-icon-class);
}
}
td.enabled span:before {
content: @fa-var-check;
}
td.partial span:before {
opacity: .3;
content: @fa-var-check;
}
}
}
table.compact-table {
margin: 0;
width: 100%;
*:not(.invalid-feedback) {
font-size: inherit;
}
td {
padding: .25rem;
border: 0;
}
td:first-child {
padding-left: 0;
}
td:last-child {
padding-right: 0;
}
}
table.table {
.checkbox-cell {
width: 3rem;
white-space: nowrap;
overflow: hidden;
text-align: center;
padding: .5rem;
html.touch & {
padding: .5rem .3rem;
}
}
th.checkbox-cell {
padding: .75rem 0;
max-width: 1rem;
&:before {
&:extend(.font-icon-class);
cursor: pointer;
margin: 0 1rem;
line-height: 1;
}
&.subscription:before {
content: @fa-var-rss-square;
}
&.alarm:before {
.font-icon-regular(@fa-var-bell);
}
&.read:before {
content: @fa-var-eye;
}
&.write:before {
content: @fa-var-pencil-alt;
}
}
.buttons-cell {
width: 1%;
white-space: nowrap;
text-align: center;
a.button:before {
line-height: 1;
float: none;
display: inline-block;
}
@media screen and (min-width: @screen-width-xs) {
a.button .inner {
display: inline;
}
}
}
label {
margin: 0;
display: inline;
}
fieldset.tab-pane & thead th {
border: 0;
}
tr.deleted td {
color: @color-list-deleted !important;
}
}
/* Bootstrap's .table style overwrites */
.table {
thead th {
border-width: 1px;
white-space: nowrap;
}
}

263
styles/widgets/dialogs.less Normal file
View File

@ -0,0 +1,263 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Dialogs and popovers ***/
.popupmenu {
display: none;
padding: 0;
min-width: 180px;
height: 100%;
li > a {
width: 100%;
}
&.propform {
overflow: hidden;
padding: .25rem; // so overflow do not truncate focus outline on inputs
}
&.simplelist {
min-width: 80px;
}
}
.popup.justified {
display: flex;
justify-content: space-around;
}
.popover-body {
padding: 0;
overflow-x: hidden;
& > .popupmenu {
display: block !important;
}
}
.popover {
box-shadow: 3px 3px 5px @color-popover-shadow;
border-color: @color-layout-border;
padding: 0;
z-index: 1300;
.popover-header {
// On mobile don't display popup arrows and titles
display: none;
}
@media screen and (min-width: (@screen-width-small + 1px)) {
.listing {
li:first-child {
border-radius: .25rem .25rem 0 0;
}
li:last-child {
border-bottom-right-radius: .25rem;
border-bottom-left-radius: .25rem;
}
ul.rounded-0 > li {
border-radius: 0;
}
}
}
}
html.layout-small,
html.layout-phone {
.popover:not(.select-menu) {
margin: 0 !important;
padding: 0;
right: 0;
left: initial !important;
bottom: 0;
top: 0;
width: @layout-mobile-menu-width;
transform: none !important;
border-radius: 0;
border: 0;
display: flex;
flex-direction: column;
box-shadow: none;
div.arrow {
display: none;
}
.listing li:last-child {
border-bottom: 1px solid @color-list-border;
}
}
.popover-overlay {
z-index: 1299;
background-color: @color-dialog-overlay-background;
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
.popover-header {
display: block;
border-radius: 0;
border: 0;
padding: 0 .5em;
height: @layout-touch-header-height;
min-height: @layout-touch-header-height; // for when it's a flex item
line-height: @layout-touch-header-height;
font-size: @layout-touch-header-font-size;
color: @color-popover-mobile-header;
background-color: @color-popover-mobile-header-background;
&:before {
display: none; // hide the Bootstrap's popover arrow element
}
a {
display: inline-block;
width: 100%;
color: @color-popover-mobile-header;
}
}
.popover-body > * {
max-height: 100% !important;
}
}
html.touch .popover {
.listing {
li a {
line-height: @layout-touch-menu-record-height;
font-size: @layout-touch-menu-record-font-size;
padding: 0 .5em;
&:before {
float: left; // overwrite icon float to have unified element height
}
}
}
}
.select-menu {
max-width: initial;
margin: 0;
height: auto;
z-index: 1301; // above TinyMCE dialogs
.popover-header {
border-radius: .25rem .25rem 0 0 !important;
}
.listing li {
a {
padding-left: .25rem;
outline: 0; // for Android browser
}
&:last-child {
border-bottom-right-radius: .25rem;
border-bottom-left-radius: .25rem;
}
}
// Use 'inline' class for menus that have a list elements with no <a> inside
// and no header
&.inline {
.listing li {
padding-right: .5rem;
&:first-child {
border-top-left-radius: .25rem;
border-top-right-radius: .25rem;
}
}
}
}
/** PGP Key search/import dialog **/
.pgpkeyimport {
div.key {
position: relative;
padding: .5rem 0;
&.revoked,
&.disabled {
color: @color-list-secondary;
}
label {
display: inline-block;
margin-right: 0.5em;
margin-bottom: 0;
&:after {
content: ":";
}
&.keyid {
display: none;
}
}
label + a,
label + span {
line-height: 2.6rem;
margin-right: 1em;
white-space: nowrap;
text-decoration: none;
}
label.keyid + a {
font-weight: bold;
&:before {
&:extend(.font-icon-class);
content: @fa-var-key;
}
}
}
ul.uids {
margin: 0;
padding: 0;
}
li.uid {
border: 0;
padding: .25rem 0 0 1.5em;
line-height: 1.5rem !important;
list-style-type: none;
&:before {
&:extend(.font-icon-class);
content: @fa-var-user;
opacity: 0.25;
font-size: 1em;
line-height: 1.25;
}
}
button.importkey {
position: absolute;
top: .5rem;
right: 0;
}
button:disabled {
display: none;
}
}

537
styles/widgets/editor.less Normal file
View File

@ -0,0 +1,537 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Text Editor widget (and TinyMCE editor) ***/
// use of div.tox instead of just .tox is to have prio over TinyMCE styles
div.tox {
font-size: 1rem;
&, :not(.svg) {
.font-family();
}
&.tox-tinymce {
border-radius: .25rem;
border: 1px solid @color-input-border;
}
&.focused {
border-color: @color-input-border-focus !important;
box-shadow: 0 0 0 .2rem @color-input-border-focus-shadow !important;
}
.tox-toolbar-overlord {
z-index: 1; // for sticky header feature
& > div {
// The svg is copied from TinyMCE with modified height params
background: url("data:image/svg+xml;charset=utf8,%3Csvg height='33px' viewBox='0 0 40 33px' width='40' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='0' y='32px' width='100' height='1' fill='%23cccccc'/%3E%3C/svg%3E");
background-color: @color-input-addon-background;
}
}
.tox-toolbar__primary {
border-top: 0;
}
// This one is for mobile
.tox-toolbar {
background-color: @color-input-addon-background;
}
.tox-edit-area {
border: 0;
}
.tox-dialog {
border-radius: 0;
border-color: @color-layout-border;
box-shadow: none;
align-self: unset !important;
.tox-form__group {
margin-top: 0;
margin-bottom: .75rem;
}
.tox-dialog__body-nav-item--active {
color: @color-link;
border-color: transparent;
&:hover {
color: @color-link-hover;
}
}
}
.tox-dialog__body-content {
overflow: unset;
}
.tox-dialog__content-js {
overflow: auto;
}
.tox-dialog-wrap__backdrop {
background-color: @color-dialog-overlay-background;
}
.tox-dialog__header {
height: (@layout-header-height - 1px);
border-bottom: 1px solid @color-dialog-header-border;
justify-content: flex-end; // fixes close button position when dialog has no title
padding: 0;
.tox-button {
color: @color-dialog-header;
right: 0;
height: (@layout-header-height - .7rem);
width: 2.25em;
margin-right: .4rem;
&:hover {
background: transparent;
border-color: transparent;
}
.tox-icon {
display: none;
}
&:before {
&:extend(.font-icon-class);
content: @fa-var-times;
line-height: 1.5rem;
margin: 0 !important;
}
}
}
.tox-dialog__footer {
height: (@layout-footer-height - 1px) !important;
border: 0;
margin: 0;
padding: 0 1rem;
@media screen and (max-width: @screen-width-xs) {
border-top: 1px solid @color-dialog-header-border;
}
& > div {
white-space: nowrap;
max-height: (@layout-footer-height - 1px);
button:first-child {
margin: 0;
}
}
.tox-button {
.btn-primary();
font-weight: normal;
padding: .5rem .75rem;
&:before {
&:extend(.font-icon-class);
width: 1em;
content: @fa-var-check;
line-height: 1;
}
// this is redundant, but required because of tinymce styles interference
&:focus:not(:disabled) {
background: @color-btn-primary-background;
border-color: @color-btn-primary-background;
}
&.tox-button--secondary {
.btn-secondary();
color: @color-btn-secondary;
&:before {
content: @fa-var-times;
}
// this is redundant, but required because of tinymce styles interference
&:focus:not(:disabled) {
background: @color-btn-secondary-background;
border-color: @color-btn-secondary-background;
}
}
}
}
.tox-search-dialog {
.tox-form__group:not(:first-child) {
flex: initial !important;
}
.tox-dialog__footer-start {
button {
padding: .25rem;
}
}
.tox-dialog__footer-end {
button {
&:before {
content: @fa-var-pencil-alt !important;
}
&:nth-of-type(1):before {
content: @fa-var-search !important;
}
}
}
}
.tox-dialog__title {
line-height: calc(@layout-header-height - 1px);
font-size: 1.25rem;
font-weight: bold;
padding: 0 0 0 1rem;
width: 100%;
color: @color-dialog-header;
}
// Make toolbar buttons smaller
.tox-tbtn {
height: 28px;
&:not(.tox-tbtn--select,.tox-split-button__chevron) {
width: 32px;
}
}
.tox-button {
line-height: 1.5;
}
.tox-label {
color: @color-font;
padding-bottom: .25rem;
}
// Adding .form-control does not work with TinyMCE skins,
// so we have to overwrite some props here
.tox-color-input > input,
.tox-listboxfield .tox-listbox--select,
.tox-textarea,
.tox-textfield {
.font-family() !important;
font-size: @page-font-size;
line-height: 1.5;
color: @color-font;
border-radius: .25rem;
min-height: 0;
padding: .375rem .75rem;
&:focus {
border-color: @color-input-border-focus;
box-shadow: 0 0 0 .2rem @color-input-border-focus-shadow;
}
}
.tox-listbox__select-label {
margin: 0;
}
.tox-color-input span {
top: 5px;
}
.custom-switch {
position: relative;
font-size: 1rem;
margin-top: .15rem;
.tox-checkbox__icons {
display: none;
}
.tox-checkbox__label {
margin: 0;
}
}
.image-selector {
font-size: 1rem;
button {
.btn-secondary();
padding: .5rem .75rem;
line-height: 1.5;
}
}
// small fix for image dialog
.tox-form__controls-h-stack div:not(:last-child) {
flex: 1;
}
.tox-collection__item-label {
white-space: nowrap; // fix TinyMCE bug
}
}
@media screen and (max-width: @screen-width-xs) {
div.tox {
.tox-dialog {
margin: 0 !important;
width: 100% !important;
height: 100%;
left: 0 !important;
top: 0 !important;
border-width: 0 !important;
}
.tox-dialog__header {
background-color: @color-layout-mobile-header-background;
.tox-button {
display: none;
}
}
.tox-dialog__title {
font-size: 1rem;
text-align: center;
padding: 0 1rem;
}
.tox-dialog__footer {
background-color: @color-layout-mobile-footer-background;
.tox-button {
color: @color-font !important;
background: transparent !important;
padding: .45rem;
margin: 0 !important;
border: 0;
font-size: 90%;
&:before {
display: block;
float: none;
width: 100%;
margin: 0;
line-height: 1.75;
height: 1.75rem;
}
&:active,
&:focus,
&:hover {
background: transparent;
border: 0;
box-shadow: none;
color: @color-font;
}
}
& > div {
justify-content: space-evenly;
display: flex;
width: 100%;
&:empty {
display: none;
}
}
}
}
}
/*** Media file selector for TinyMCE ***/
.image-selector {
padding: 1rem .5rem 10rem .5rem !important;
&.droptarget {
border: .2rem dashed @color-table-border;
&:after {
margin-top: 2rem;
}
}
form {
position: absolute;
top: 0;
}
.attachmentslist {
margin: 0;
overflow-x: hidden;
overflow-y: auto;
height: 19.1em;
padding: 0 !important;
li {
padding: .25rem;
cursor: pointer;
&:before {
display: none;
}
&:hover,
&:focus {
background: @color-list-selected-background;
}
span.name {
flex: 1;
margin: auto;
padding-left: 1rem;
.overflow-ellipsis();
}
span.img {
height: 80px;
width: 80px;
display: flex;
border: 1px solid @color-list-border;
background: white;
border-radius: .75rem;
overflow: hidden;
}
img {
margin: auto;
}
}
html.layout-phone & {
height: auto;
}
}
}
/*** HTML editor widget ***/
.html-editor {
position: relative;
margin-bottom: .2rem;
.editor-toolbar {
position: absolute;
left: 1px;
top: 1px;
right: 1px;
border-radius: .25rem .25rem 0 0;
border-bottom: 1px solid @color-input-border;
background-color: @color-input-addon-background;
.mce-i-html {
display: block;
margin: 2px 2px 2px 4px;
width: 34px;
height: 28px;
border-radius: .25rem;
color: #222f3e; // from TinyMCE
&:focus,
&:hover {
text-decoration: none;
border-color: #e2e4e7;
background-color: #dee0e2; // from TinyMCE
}
&:before {
&:extend(.font-icon-class);
content: @fa-var-image;
margin: 0;
width: 34px;
line-height: 28px;
}
&[disabled] {
opacity: .7;
cursor: not-allowed;
}
}
}
// hide toolbar in html mode and in mailvelope mode
&.mailvelope .editor-toolbar,
.tox-tinymce + .editor-toolbar {
display: none;
}
& > .googie_edit_layer,
& > textarea {
font-family: monospace;
font-size: 13px;
width: 100% !important;
padding-top: 40px;
resize: none;
}
& > iframe { // e.g. mailvelope frame
border-radius: .3rem;
border: 1px solid @color-input-border;
min-height: 30em;
}
}
/*** GoogieSpell widget ***/
.googie_window {
width: 16rem;
height: auto;
}
.googie_edit_layer {
font-family: monospace;
// from Bootstrap's textarea
padding: .5rem .75rem;
border: 1px solid @color-input-border;
border-radius: .3rem;
line-height: 1.5;
}
.googie_link {
color: @color-spellcheck-link;
text-decoration: underline;
cursor: pointer;
}
.googie_list {
li {
min-width: 8rem;
width: auto;
&.googie_list_onhover {
color: @color-menu-hover;
background-color: @color-menu-hover-background;
}
.googie_list_revert:before {
&:extend(.font-icon-class);
content: @fa-var-undo;
}
.googie_add_to_dict:before {
&:extend(.font-icon-class);
content: @fa-var-plus-square;
}
}
input {
display: inline-block;
margin: .25rem .5rem;
}
}

1429
styles/widgets/forms.less Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,440 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** jQuery-UI widgets' style overrides ***/
.ui-widget-overlay {
background-color: @color-dialog-overlay-background;
opacity: 1 !important; // override jQuery-UI opacity, the color above is semi-transparent
&.datepicker {
z-index: 119; // above Bootstrap's form controls, below datepicker
}
}
.ui-widget {
border: 1px solid @color-datepicker-border;
box-shadow: 3px 3px 5px @color-popover-shadow;
border-radius: .3rem;
}
.ui-menu {
overflow-y: auto;
overflow-x: hidden;
max-height: 400px;
border-radius: .3rem;
z-index: 240;
position: absolute;
.ui-state-active {
border: 0 !important;
background-color: @color-menu-hover-background !important;
}
.ui-menu-item {
white-space: nowrap;
cursor: default;
}
.ui-menu-item-wrapper {
margin: 0 !important;
}
}
.ui-dialog {
border-radius: 0;
box-shadow: none;
&.no-titlebar {
.ui-dialog-titlebar {
display: none;
}
}
.ui-dialog-titlebar {
height: @layout-header-height;
border-bottom: 1px solid @color-dialog-header-border;
button {
&:before {
margin: 0;
}
}
}
.ui-dialog-title {
line-height: @layout-header-height;
font-size: 1.25rem;
padding: 0 3rem 0 1rem;
color: @color-dialog-header;
}
.ui-dialog-titlebar-close {
border: 0;
color: @color-dialog-header;
background: transparent;
right: 0;
top: 0;
position: absolute;
padding: .25rem .5rem;
margin: ((@layout-header-height - 2 * @page-font-size) / 2) .5rem;
&:before {
&:extend(.font-icon-class);
content: @fa-var-times;
line-height: 1.5rem;
margin: 0 !important;
}
}
.ui-dialog-content {
& > .popupmenu {
display: block !important;
}
}
.ui-dialog-buttonpane {
.ui-dialog-buttonset {
display: flex;
justify-content: flex-end;
a.btn-link,
button {
.overflow-ellipsis();
min-width: 5rem;
margin: floor(.65 * @page-font-size) floor(.3 * @page-font-size);
&:last-child {
margin-right: 0;
}
}
a.btn-link {
padding-right: 0;
padding-left: 0;
text-decoration: none;
color: @color-font;
&:focus {
background-color: fade(@color-btn-primary-background, 50%);
}
&.options {
order: -1;
padding: .375rem .25rem;
margin-right: .3rem;
&:before {
// this icon is for mobile version
&:extend(.font-icon-class);
content: @fa-var-cog;
width: 100%;
height: 1.25em;
}
}
}
}
}
iframe,
.ui-dialog-content.iframe {
padding: 0;
width: 100% !important;
height: 100%;
border: 0;
overflow: hidden;
}
}
// Fix scrollbar/resize issue e.g. in qr-code dialog
.ui-dialog,
.ui-dialog-content {
box-sizing: initial;
}
// Overwriting this icon generally prevents from loading bigger images sprite from jQuery-UI
.ui-widget-content .ui-icon.ui-resizable-se {
background: @icon-resize-corner;
}
/* FIXME: why do I need !important here? */
@media screen and (max-width: @screen-width-xs) {
.ui-dialog {
width: 100% !important;
height: 100% !important;
display: flex;
flex-direction: column;
border: 0;
top: 0 !important; // for Chrome
.ui-resizable-handle,
.ui-dialog-titlebar-close {
display: none !important;
}
.ui-dialog-titlebar {
height: @layout-touch-header-height;
text-align: center;
background-color: @color-layout-mobile-header-background;
}
.ui-dialog-title {
line-height: @layout-touch-header-height;
font-size: @layout-header-font-size;
padding: 0 1rem;
}
.ui-dialog-content {
flex: 1;
&:not(.iframe) {
padding: 1rem;
}
}
.ui-dialog-buttonpane {
padding: 0 !important;
text-align: center !important;
border-top: 1px solid @color-dialog-header-border;
height: @layout-header-height !important;
background-color: @color-layout-mobile-footer-background;
.ui-dialog-buttonset {
justify-content: space-around;
button {
margin: 0 !important;
padding: .45rem;
border: 0 !important;
height: @layout-header-height;
box-shadow: none;
font-size: 90%;
line-height: 1.5;
&:before {
display: block !important;
float: none;
width: auto;
height: 1.75rem;
line-height: 1.75;
margin: 0 !important;
}
&:active {
box-shadow: none;
}
&.btn-primary,
&.btn-secondary {
color: @color-toolbar-button;
background: transparent;
}
&.btn-danger {
color: @color-btn-danger-background;
background: transparent;
}
&.disabled,
&:disabled {
opacity: .5;
}
&.cancel {
order: 100; // makes Cancel/close button the last one
}
}
a.btn-link {
color: @color-toolbar-button;
margin: 0;
padding: .45rem;
font-size: 90%;
&.options:before {
display: block !important;
height: 1.75rem;
line-height: 1.75;
margin: 0;
}
}
}
}
}
}
/* Slider widget */
.ui-slider {
box-shadow: none;
.ui-slider-range {
border-radius: .3rem;
background: lighten(@color-main, 30%);
}
.ui-slider-handle {
border-radius: .3rem;
&.ui-state-active {
background: @color-main;
border-color: @color-main-dark;
}
}
}
/* Datepicker widget */
.ui-datepicker {
// Always display datepicker centered, overwriting widgets position
margin: ~"calc(50vh - 10em) calc(50vw - 10em) !important";
top: 0 !important;
left: 0 !important;
box-shadow: none;
user-select: none;
&:not(.ui-datepicker-inline) {
z-index: 120 !important; // fixes datepicker over input-group and dialogs
}
.ui-datepicker-header,
.ui-datepicker-title {
line-height: 4rem;
height: 4rem;
padding: 0;
}
.ui-datepicker-header {
border-bottom: 1px solid @color-dialog-header-border;
a {
height: 4rem;
}
select {
display: inline-block;
}
}
.ui-icon {
background-image: none !important;
background-position: none !important;
}
.ui-datepicker-prev,
.ui-datepicker-next {
cursor: pointer;
width: auto;
color: @color-font;
text-decoration: none;
&:before {
&:extend(.font-icon-class);
content: "\f053";
margin: 0 .25em;
height: auto;
width: 1em;
}
}
.ui-datepicker-prev:before {
content: "\f053";
}
.ui-datepicker-next:before {
content: "\f054";
}
td a {
padding: 0;
line-height: 1.8em;
border-radius: .3rem;
}
.ui-state-default,
&.ui-widget-content .ui-state-default {
border: 0;
background: transparent;
color: @color-datepicker-font;
}
.ui-datepicker-days-cell-over a,
.ui-datepicker-days-cell-over a.ui-state-default,
.ui-state-highlight,
&.ui-widget-content .ui-state-highlight {
background: @color-datepicker-highlight-background;
color: @color-datepicker-highlight;
}
a.ui-state-active {
background: @color-datepicker-active-background !important;
color: @color-datepicker-active !important;
font-weight: bold;
}
html.touch {
& {
td a {
font-size: 1.2em;
line-height: 2.2em;
}
}
}
}
// Fixes datepicker z-index issue on input-group inputs in dialogs
// With non-relative position the input's z-index is ignored
.input-group > .form-control.hasDatepicker {
position: initial;
}
.minicolors-panel {
border: 1px solid @color-datepicker-border;
box-shadow: 3px 3px 5px @color-popover-shadow;
border-radius: .3rem;
height: 152px;
padding: 1px;
}
.input-group {
.minicolors-input {
width: 100%;
// needed so minicolors panel is not out of screen
// when the input is on the right side, e.g. Calendar plugin settings
// This is obviously minicolors script issue
min-width: 130px;
border-left: 0;
border-right: 0;
}
}
@media screen and (max-width: @screen-width-mini) {
.ui-widget-content {
border-radius: 0;
}
.ui-menu {
border-radius: .3rem;
left: 15px !important;
right: 15px;
width: auto;
}
.ui-dialog {
.ui-dialog-content:not(.iframe) {
padding: .65rem;
}
}
.ui-autocomplete {
// TODO: e.g. time input autocompletion on mobile
}
}

1085
styles/widgets/lists.less Normal file

File diff suppressed because it is too large Load Diff

952
styles/widgets/menu.less Normal file
View File

@ -0,0 +1,952 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** Toolbar widget ***/
.menu {
margin: 0;
text-align: center;
white-space: nowrap;
a {
.overflow-ellipsis();
text-decoration: none;
&:before {
&:extend(.font-icon-class);
content: "\00a0"; // blank placeholder
}
&:hover,
&:focus {
outline: 0;
}
&:not(.disabled):focus,
&:not(.disabled):hover {
background-color: @color-toolbar-button-background-hover;
}
}
&.toolbar {
li {
display: inline-block;
height: @layout-touch-header-height;
}
a {
color: @color-toolbar-button;
display: block;
float: left;
border: 0 !important;
height: @layout-header-height;
min-width: 3.2rem;
max-width: 6rem;
width: auto; // reset width defined for links in .listing
padding: .45rem;
line-height: 1.5;
cursor: pointer;
font-size: 1rem;
text-align: center;
&:before {
height: 1.75rem !important;
float: none !important;
width: auto !important;
margin: 0 !important;
}
&.selected {
color: @color-success;
}
}
& > .spacer {
width: 1em;
}
.dropbutton {
&:not(.disabled):hover {
background-color: @color-toolbar-button-background-hover;
}
a.dropdown {
padding: 0 .3rem;
&:before {
line-height: @layout-header-height;
}
&:hover {
background-color: darken(@color-toolbar-button-background-hover, 5%);
}
}
}
}
span.inner {
font-size: 90%;
font-weight: normal;
}
.dropbutton {
display: inline-block;
a.dropdown {
font-size: 75%;
min-width: 0;
html.ie11 &:before {
font-size: 80%;
}
span.inner {
display: none;
}
}
a:first-child {
padding-right: 0;
}
}
&.pagenav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 !important;
font-size: 100%; // in case this is .footer.small
a {
flex-grow: 1;
display: inline-block;
min-width: 2rem !important;
height: @layout-footer-small-height;
color: @color-toolbar-button;
&:before {
margin: 0;
display: inline;
float: none;
line-height: @layout-footer-small-height;
}
}
.pagenav-text {
.overflow-ellipsis();
color: @color-list-pagenav;
flex-grow: 4;
font-size: 80%;
}
input {
width: 3rem;
max-width: 5rem;
font-size: 90%;
text-align: center;
max-height: 1.6rem;
margin: 0 .2rem;
html.layout-phone & {
display: none;
}
}
span.inner {
display: none;
}
&.pagenav-list {
cursor: pointer;
background-color: @color-searchbar-background;
border-bottom: 1px solid @color-list-border;
a {
flex-grow: unset;
}
.pagenav-text {
text-align: left;
font-size: 100%;
}
& + .navlist {
background-color: #fbfbfb;
}
&.expanded + .navlist {
border-bottom: 1px solid @color-layout-border;
}
}
}
&.content-frame-navigation.hide-nav-buttons {
a.next,
a.prev {
display: none;
}
}
.listselectors {
max-width: 100%;
display: flex;
justify-content: space-around;
}
.buttons {
display: block;
button {
display: block;
float: left;
cursor: pointer;
color: @color-toolbar-button;
background-color: transparent;
border: 0;
padding: 0;
height: @layout-touch-header-height;
line-height: @layout-touch-header-height;
width: 2.5em;
&:before {
font-size: 1.75rem;
}
}
}
.popover & {
li {
display: block;
height: auto;
text-align: left;
&.spacer {
display: none;
}
&:last-child {
border: 0;
}
&.separator {
line-height: 1.5rem !important;
font-size: .75rem !important;
padding: 0 .5rem;
color: @color-popover-separator;
background-color: @color-popover-separator-background;
label {
margin: 0; // Unsets Bootstrap label margin, bug?
}
}
a {
height: unset;
max-width: 100%;
width: 100%;
line-height: @listing-line-height;
display: block;
padding: 0 .5rem;
text-align: left;
&:before {
line-height: inherit;
height: inherit !important;
margin-right: .5rem !important;
float: left !important;
width: 1.18em !important;
min-width: 1.18em;
}
&:not(.disabled):hover {
color: @color-menu-hover;
background-color: @color-menu-hover-background;
}
&[aria-haspopup] {
display: flex;
&:after {
&:extend(.font-icon-class);
color: @color-black-shade-text;
font-size: .9em;
margin: 0 0 0 .2em;
min-width: 1.18em;
content: @fa-var-chevron-right;
html.layout-small & {
margin: 0 .2em;
}
}
&.dropdown:after {
color: @color-list;
margin: 0 .6em !important;
}
&:hover:after {
color: @color-menu-hover;
}
& > span {
.overflow-ellipsis();
flex: 1;
}
}
}
span.inner {
font-size: 100%;
}
}
.dropbutton {
display: flex;
a:first-child {
.overflow-ellipsis();
flex: 1;
}
&:not(.disabled):hover {
background-color: @color-popover-mobile-dropbutton-background;
}
a.dropdown {
width: 3.5rem;
padding: 0 .5em;
background-color: @color-popover-mobile-dropbutton-background;
&:hover {
background-color: @color-menu-hover-background;
}
// Note: :before icon is replaced with :after icon by a[aria-haspopup] above
&:before,
span.inner {
display: none;
}
}
}
&.no-icon a:before {
display: none;
}
}
}
@media screen and (min-width: (@screen-width-small + 1px)) {
.content-frame-navigation {
display: none !important;
}
.header a.button.icon {
&:not(.disabled):focus,
&:not(.disabled):hover {
background-color: @color-toolbar-button-background-hover;
outline: 0;
}
&:before {
margin: 0;
}
}
}
@media screen and (max-width: @screen-width-small) {
.menu.footer {
justify-content: space-around !important;
& > * {
flex-grow: 1;
}
.buttons {
display: flex;
justify-content: space-evenly;
}
.listselectors > * {
flex-grow: 1;
}
}
.menu.listing a {
color: @color-font;
}
}
a.toolbar-button {
cursor: pointer;
@media screen and (min-width: (@screen-width-large + 1px)) {
line-height: 1.5;
padding: .45rem;
&:before {
float: none !important;
height: 1.75rem !important;
line-height: 1.5;
width: auto !important;
}
span.inner {
display: inline !important;
font-weight: normal;
font-size: 90%;
}
}
}
/*** Menu button icons ***/
.menu a {
&.mail:before {
content: @fa-var-envelope;
}
&.contacts:before {
content: @fa-var-users;
}
&.options:before {
content: @fa-var-sliders-h;
}
&.settings:before {
content: @fa-var-cog;
}
&.theme.light:before {
content: @fa-var-sun;
}
&.theme.dark:before {
content: @fa-var-moon;
}
&.help:before {
content: @fa-var-life-ring;
}
&.logout:before {
content: @fa-var-power-off;
}
&.about:before {
content: @fa-var-question;
}
&.refresh:before {
content: @fa-var-sync;
}
&.compose:before {
content: @fa-var-edit;
}
&.calendar:before {
content: @fa-var-calendar-alt;
}
&.tasklist:before {
content: @fa-var-tasks;
}
&.files:before {
content: @fa-var-folder;
}
&.notes:before {
content: @fa-var-sticky-note;
}
&.chat:before {
content: @fa-var-comments;
}
&.actions:before {
content: @fa-var-cog;
}
&.addressbook:before {
content: @fa-var-user;
}
&.archive:before {
content: @fa-var-archive;
}
&.assigngroup:before {
content: @fa-var-user-plus;
}
&.attach:before,
&.vcard:before {
content: @fa-var-paperclip;
}
&.next:before {
content: @fa-var-arrow-right;
}
&.prev:before,
&.back:before {
content: @fa-var-arrow-left;
}
&.check:before {
content: "\00a0"; // just a space
}
&.check.selected:before {
content: @fa-var-check;
}
&.closewin:before {
content: @fa-var-window-close;
}
&.collapse:before {
content: @fa-var-angle-down;
}
&.copy:before {
content: @fa-var-copy;
}
&.create:before {
content: @fa-var-plus-square;
}
&.delete:before {
content: @fa-var-trash-alt;
}
&.download:before,
&.download.eml:before,
&.download.maildir:before,
&.download.mbox:before {
content: @fa-var-download;
}
&.dropdown:before {
content: @fa-var-caret-down;
}
&.edit:before {
content: @fa-var-pencil-alt;
}
&.encrypt:before,
&.enigma:before {
content: @fa-var-lock;
}
&.encrypt.sign:before {
content: @fa-var-lock; // TODO
}
&.expand:before {
content: @fa-var-angle-right;
}
&.expand.all:before {
content: @fa-var-angle-double-down;
}
&.expand.none:before {
content: @fa-var-angle-double-up;
}
&.export:before,
&.export.all:before,
&.export.selection:before {
content: @fa-var-download;
}
&.expunge:before {
content: @fa-var-compress-arrows-alt;
}
&.extwin:before {
content: @fa-var-external-link-square-alt;
}
&.filterlink:before {
content: @fa-var-filter;
}
&.firstpage:before {
content: @fa-var-angle-double-left;
}
&.nextpage:before {
content: @fa-var-angle-right;
}
&.prevpage:before {
content: @fa-var-angle-left;
}
&.lastpage:before {
content: @fa-var-angle-double-right;
}
&.flag:before,
&.select.flagged:before {
.font-icon-solid(@fa-var-flag);
}
&.unflag:before {
.font-icon-regular(@fa-var-flag);
}
&.undo:before {
content: @fa-var-redo;
}
&.folders:before {
content: @fa-var-folder;
}
&.forward:before,
&.forward.attachment:before,
&.forward.bounce:before,
&.forward.inline:before {
content: @fa-var-share;
}
&.import:before,
&.upload:before {
content: @fa-var-upload;
}
&.insertresponse:before {
content: @fa-var-comment;
}
&.junk:before {
content: @fa-var-fire-alt;
}
&.notjunk:before {
content: @fa-var-inbox;
}
&.markmessage:before {
content: @fa-var-tag;
}
&.more:before {
content: @fa-var-ellipsis-h;
}
&.move:before {
content: @fa-var-folder-open;
}
&.print:before {
content: @fa-var-print;
}
&.properties:before {
content: @fa-var-file;
}
&.purge:before {
content: @fa-var-eraser;
}
&.qrcode:before {
content: @fa-var-qrcode;
}
&.read:before {
.font-icon-regular(@fa-var-envelope-open);
}
&.unread:before,
&.expand.unread:before,
&.select.unread:before {
.font-icon-solid(@fa-var-envelope);
}
&.recipient:before {
.font-icon-regular(@fa-var-envelope);
}
&.refresh:before {
content: @fa-var-sync;
}
&.remove:before {
content: @fa-var-eraser;
}
&.removegroup:before {
content: @fa-var-user-times;
}
&.rename:before {
content: @fa-var-pencil-alt;
}
&.reply:before {
content: @fa-var-reply;
}
&.reply-all:before,
&.reply.all:before,
&.reply.list:before {
content: @fa-var-reply-all;
}
&.responses:before {
content: @fa-var-comment;
}
&.rotate:before {
content: @fa-var-redo-alt;
}
&.save:before {
.font-icon-regular(@fa-var-save);
}
&.search:before {
content: @fa-var-search;
}
&.search.delete:before {
content: @fa-var-trash-alt;
}
&.select:before {
content: @fa-var-mouse-pointer;
}
&.select.all:before {
content: @fa-var-asterisk;
}
&.select.invert:before {
content: @fa-var-check-square;
}
&.select.none:before {
.font-icon-solid(@fa-var-times);
}
&.select.page:before {
.font-icon-solid(@fa-var-bars);
}
&.selection:before {
.font-icon-regular(@fa-var-check-square) !important;
}
&.send:before {
content: @fa-var-paper-plane;
}
&.showurl:before {
content: @fa-var-link;
}
&.signature:before {
content: @fa-var-signature;
}
&.source:before {
content: @fa-var-file-code;
}
&.spellcheck:before {
content: @fa-var-spell-check;
}
&.status:before {
.font-icon-regular(@fa-var-lightbulb);
}
&.submit:before {
content: @fa-var-check;
}
&.info:before {
content: @fa-var-info-circle;
}
&.threads:before {
content: @fa-var-comments;
}
&.zoomin:before {
content: @fa-var-search-plus;
}
&.zoomout:before {
content: @fa-var-search-minus;
}
}
/*** Searchbar and searchoptions widgets ***/
.searchbar {
height: @layout-searchbar-height;
min-height: @layout-searchbar-height; // because of Flexbox
line-height: @layout-searchbar-height;
background-color: @color-searchbar-background;
border-bottom: 1px solid @color-list-border;
display: flex;
align-items: center;
overflow: hidden;
position: relative;
form {
flex: 1;
display: flex;
&:before {
&:extend(.font-icon-class);
content: @fa-var-search;
height: @layout-searchbar-height;
color: @color-list-pagenav;
margin: 0 0 0 .75rem;
}
}
input {
width: 100%;
border: 0;
background: transparent;
padding: .5rem;
line-height: normal; // fixes placeholder misalignment in IE11
outline: 0; // removes focus outline in Chrome
&::-ms-clear {
display: none; // for IE
}
}
a {
color: @color-toolbar-button;
&:before {
&:extend(.font-icon-class);
width: 2rem;
height: @layout-searchbar-height;
margin: 0;
}
&.options:before {
content: @fa-var-angle-down;
}
&.reset:before {
content: @fa-var-times;
font-size: 1rem;
}
&.unread:before {
.font-icon-solid(@fa-var-envelope);
}
&.reset,
&.search {
display: none;
}
&.selected {
color: @color-success;
}
}
span.inner {
display: none;
}
&.active {
a.reset {
display: inline;
}
}
&.open a.options:before {
content: @fa-var-angle-up;
}
}
.searchoptions {
button.search {
width: 100%;
}
ul.proplist {
& + div {
margin-top: 1rem;
}
}
.input-group {
&:not(:last-child) {
margin-bottom: .5rem;
}
.input-group-prepend {
width: 30%;
}
label {
width: 100%;
}
}
.formbuttons {
// this is needed because we hide .formbuttons on small devices
// we don't want it for search options form
display: block !important;
}
}
/*** Taskmenu ***/
#taskmenu {
a {
display: block;
float: none;
}
@media screen and (max-width: @screen-width-xs) {
z-index: 30001; // because autocompletion popup uses z-index:30000
overflow-x: hidden;
a {
max-width: unset;
padding: 0 .5em;
margin-top: 1px;
text-align: left;
line-height: @layout-touch-menu-record-height;
height: @layout-touch-menu-record-height;
border-bottom: 1px solid @color-list-border !important;
color: @color-list;
font-size: 1.2rem;
&:before {
float: left !important;
width: 1.2em !important;
margin-right: .5rem !important;
}
}
span.inner {
font-size: 100%;
}
}
@media screen and (min-width: (@screen-width-xs + 1px)) {
a {
color: @color-taskmenu-button;
padding: .45rem 0;
min-width: unset;
&.selected {
color: @color-taskmenu-button-selected;
background: @color-taskmenu-button-selected-background;
&:hover {
color: @color-taskmenu-button-selected-hover;
background: @color-taskmenu-button-background-hover;
}
}
&:hover {
color: @color-taskmenu-button-hover;
background: @color-taskmenu-button-background-hover;
}
}
.special-buttons {
position: absolute;
bottom: 0;
left: 0;
background-color: @color-taskmenu-background;
}
.action-buttons {
a {
color: @color-taskmenu-button-action;
background: @color-taskmenu-button-action-background;
&:hover {
color: @color-taskmenu-button-action-hover;
background: @color-taskmenu-button-action-background-hover;
}
}
}
a.logout {
color: @color-taskmenu-button-logout !important;
&:hover {
color: @color-taskmenu-button-logout-hover !important;
}
}
}
@media screen and (min-width: (@screen-width-xs + 1px)) and (max-width: @screen-width-medium) {
a {
width: @layout-menu-width-sm;
height: @layout-menu-width-sm;
font-size: 1.2rem;
padding: 0;
&:before {
line-height: @layout-menu-width-sm;
}
}
span.inner {
display: none;
}
}
@media screen and (min-width: (@screen-width-medium + 1px)) {
a {
width: @layout-menu-width;
font-size: 1rem;
&:before {
float: none; // fixed overflowing text in Edge
}
&:focus {
background-color: @color-taskmenu-button-selected-background;
}
}
span.inner {
padding: 0 .1em;
}
}
}

View File

@ -0,0 +1,267 @@
/**
* Roundcube Webmail styles for the Elastic skin
*
* Copyright (c) The Roundcube Dev Team
*
* The contents are subject to the Creative Commons Attribution-ShareAlike
* License. It is allowed to copy, distribute, transmit and to adapt the work
* by keeping credits to the original authors in the README.md file.
* See http://creativecommons.org/licenses/by-sa/3.0/ for details.
*/
/*** UI Messages ***/
// .boxwarning/.boxerror/.boxinformation classes are converted to .ui.alert in bootstrap_init()
.ui.alert {
margin: 0;
margin-bottom: .2rem;
opacity: .95;
width: 100%;
padding: .75em;
color: @color-message;
border: 1px solid @color-message-border;
background-color: @color-message-background;
display: flex;
align-items: center;
@media screen and (max-width: @screen-width-xs) {
border: 0;
}
span {
margin: auto 0;
}
& > i.icon {
line-height: 1;
color: lighten(@color-black, 25%);
margin: auto 0;
}
& > i.icon:before {
&:extend(.font-icon-class);
content: @fa-var-info-circle;
margin-right: .6rem;
}
.btn {
margin-left: .5rem;
}
&.loading {
color: @color-message-loading;
& > i.icon:before {
content: @fa-var-circle-notch;
.animated-icon-class();
width: 1em;
}
}
&.alert-success > i.icon:before {
content: @fa-var-check-circle;
color: @color-message-success;
}
&.alert-warning > i.icon:before {
content: @fa-var-exclamation-triangle;
color: @color-message-warning;
}
&.alert-danger > i.icon:before {
content: @fa-var-exclamation-circle;
color: @color-message-error;
}
&.vcardattachment > i.icon:before {
content: @fa-var-address-card; // vcard_attachments plugin
}
&.enigmaattachment > i.icon:before {
content: @fa-var-key; // enigma plugin
}
&.signed > i.icon:before,
&.encrypted > i.icon:before {
content: @fa-var-lock; // enigma plugin
}
&.chat > i.icon:before {
content: @fa-var-comment;
}
// #6797: Fix for long buttons issue
.boxbuttons {
white-space: nowrap;
.btn {
.overflow-ellipsis();
max-width: 220px;
}
@media screen and (max-width: @screen-width-xs) {
display: flex;
flex-direction: column;
.btn {
max-width: 160px;
&:not(:first-child) {
margin-top: .25rem;
}
}
}
}
// This works with following structure: <i> <span> [button].
// <span> here is a one-line text, and button can be anything but <span>.
&.aligned-buttons {
display: flex;
span {
flex: 1;
}
}
a:not(.btn) {
color: @color-message-link;
font-weight: @color-message-link-font-weight;
}
h3 {
font-weight: bold;
font-size: 1.2rem;
}
p {
margin: 1rem 0;
}
&.boxerror,
&.boxconfirmation,
&.boxinformation,
&.boxwarning {
padding: .5em;
border-radius: 0;
i.icon {
font-size: 1.5em !important;
}
}
&.boxerror {
background-color: @color-message-error-box-background;
& when not(@color-message-error-box = @color-message) { color: @color-message-error-box; }
}
&.boxinformation {
background-color: @color-message-information-box-background;
& when not(@color-message-information-box = @color-message) { color: @color-message-information-box; }
}
&.boxconfirmation {
background-color: @color-message-success-box-background;
& when not(@color-message-error-box = @color-message) { color: @color-message-error-box; }
}
&.boxwarning {
background-color: @color-message-warning-box-background;
& when not(@color-message-warning-box = @color-message) { color: @color-message-warning-box; }
}
& + table {
margin-top: 1em;
}
}
#messagestack {
position: absolute;
bottom: .5em;
right: .7em;
z-index: 105; // needs to be above .ui-widget-overlay
width: 320px;
height: auto;
max-height: 85%;
@media screen and (max-width: @screen-width-xs) {
left: 0;
right: 0;
bottom: 0;
width: auto;
}
div {
background-color: @color-message;
color: @color-message-text;
@media screen and (max-width: @screen-width-xs) {
margin: 0;
border-radius: 0;
min-height: 4.2rem;
}
&.voice {
position: absolute;
top: -1000px;
}
i.icon {
font-size: 1.5em !important;
}
& > i.icon:before {
color: @color-message-text;
}
&:last-child {
margin-bottom: 0;
}
}
.loading {
background-color: @color-message-loading;
& when not(@color-message-loading-text = @color-message-text) { color: @color-message-loading-text; }
& > i.icon:before {
& when not(@color-message-loading-text = @color-message-text) { color: @color-message-loading-text; }
}
}
.alert-info.information {
background-color: @color-message-information;
& when not(@color-message-information-text = @color-message-text) { color: @color-message-information-text; }
& > i.icon:before {
& when not(@color-message-information-text = @color-message-text) { color: @color-message-information-text; }
}
}
.alert-success {
background-color: @color-message-success;
& when not(@color-message-success-text = @color-message-text) { color: @color-message-success-text; }
& > i.icon:before {
& when not(@color-message-success-text = @color-message-text) { color: @color-message-success-text; }
}
}
.alert-warning {
background-color: @color-message-warning;
& when not(@color-message-warning-text = @color-message-text) { color: @color-message-warning-text; }
& > i.icon:before {
& when not(@color-message-warning-text = @color-message-text) { color: @color-message-warning-text; }
}
}
.alert-danger {
background-color: @color-message-error;
& when not(@color-message-error-text = @color-message-text) { color: @color-message-error-text; }
& > i.icon:before {
& when not(@color-message-error-text = @color-message-text) { color: @color-message-error-text; }
}
}
a {
color: inherit !important;
text-decoration: underline;
cursor: pointer;
}
}

16
templates/about.html Normal file
View File

@ -0,0 +1,16 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="about" /></h1>
<div class="frame-content">
<roundcube:object name="aboutcontent" />
<h2 class="sysname">Roundcube Webmail <roundcube:object name="version" /></h2>
<p class="copyright"><roundcube:object name="copyright" /></p>
<p class="license"><roundcube:object name="license" /></p>
<div class="readtext">
<h3><roundcube:label name="installedplugins" /></h3>
<roundcube:object name="pluginlist" id="pluginlist" class="records-table" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

157
templates/addressbook.html Normal file
View File

@ -0,0 +1,157 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<h1 class="voice"><roundcube:label name="addressbook" /></h1>
<!-- sources/groups list -->
<div id="layout-sidebar" class="listbox" role="navigation" aria-labelledby="directorylist-header">
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span id="directorylist-header" class="header-title"><roundcube:label name="groups" /></span>
<roundcube:button name="groupoptions" type="link" title="arialabelabookgroupoptions" label="actions"
class="button icon sidebar-menu" innerClass="inner" data-popup="groupoptions-menu" />
</div>
<div class="scroller">
<roundcube:object name="directorylist" id="directorylist" class="treelist listing iconized" />
<h3 class="voice"><roundcube:label name="savedsearches" /></h3>
<roundcube:object name="savedsearchlist" id="savedsearchlist" class="treelist listing iconized" />
</div>
</div>
<!-- contacts list -->
<div id="layout-list" class="listbox selected" aria-labelledby="aria-label-contactslist">
<div class="header">
<a class="button icon task-menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button folders" href="#sidebar"><span class="inner"><roundcube:label name="groups" /></span></a>
<roundcube:object name="addresslisttitle" label="contacts" tag="span" class="header-title" />
<div class="toolbar menu" role="toolbar">
<a href="#select" class="button select disabled" data-popup="listselect-menu" data-toggle-button="list-toggle-button" title="<roundcube:label name="select" />"><span class="inner"><roundcube:label name="select" /></span></a>
<roundcube:container name="listcontrols" id="listcontrols" />
</div>
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:object name="searchform" id="searchform" wrapper="searchbar menu"
label="contactsearchform" buttontitle="findcontacts" options="searchmenu" ariatag="h2" />
<div id="searchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<ul class="proplist">
<li><label><input type="checkbox" name="s_mods[]" value="name" /><roundcube:label name="name" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="firstname" /><roundcube:label name="firstname" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="surname" /><roundcube:label name="surname" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="email" /><roundcube:label name="email" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="*" /><roundcube:label name="allfields" /></label></li>
</ul>
</div>
<div class="formbuttons">
<button type="button" class="btn btn-primary icon search" onclick="return rcmail.command('search')"><roundcube:label name="search" /></button>
</div>
</div>
<div class="scroller">
<h2 id="aria-label-contactslist" class="voice"><roundcube:label name="contacts" /></h2>
<roundcube:object name="addresslist" id="contacts-table" class="listing iconized contactlist"
noheader="true" role="listbox" data-list="contact_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="add" />
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
<!-- contact details frame -->
<div id="layout-content" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<!-- toolbar -->
<div id="addressbooktoolbar" class="toolbar menu">
<roundcube:button command="add" type="link" class="create disabled" classAct="create"
label="create" title="newcontact" innerclass="inner" data-fab="true" />
<roundcube:button command="print" type="link" data-hidden="small"
class="print disabled" classAct="print"
label="print" title="printcontact" innerclass="inner" />
<roundcube:button command="delete" type="link" class="delete disabled" classAct="delete"
label="delete" title="deletecontact" innerClass="inner" />
<span class="spacer"></span>
<roundcube:button command="advanced-search" type="link" class="search disabled" classAct="search"
label="search" title="advsearch" innerclass="inner" />
<roundcube:container name="toolbar" id="addressbooktoolbar" />
<roundcube:button command="import" type="link" class="import disabled" classAct="import"
label="import" title="importcontacts" innerclass="inner" />
<span class="dropbutton">
<roundcube:button command="export" type="link" class="export disabled" classAct="export"
label="export" title="exportvcards" innerclass="inner" />
<a href="#export" class="dropdown" data-popup="export-menu">
<span class="inner"><roundcube:label name="arialabelcontactexportoptions" /></span>
</a>
</span>
<roundcube:button name="contactmenulink" id="contactmenulink" type="link"
class="more" label="more" title="moreactions"
data-popup="contact-menu" innerclass="inner" />
</div>
</div>
<h2 id="aria-label-contact-frame" class="voice"><roundcube:label name="contactproperties" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="contentframe" id="contact-frame" src="env:blankpage" title="contactproperties"
aria-labelledby="aria-label-contact-frame" />
</div>
</div>
<!-- popup menus -->
<div id="export-menu" class="popupmenu">
<h3 id="aria-label-export-menu" class="voice"><roundcube:label name="arialabelcontactexportoptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-export-menu">
<roundcube:button type="link-menuitem" command="export" label="exportall" prop="sub" class="export all disabled" classAct="export all active" />
<roundcube:button type="link-menuitem" command="export-selected" label="exportsel" prop="sub" class="export select disabled" classAct="export select active" />
</ul>
</div>
<div id="groupoptions-menu" class="popupmenu">
<h3 id="aria-label-groupoptions-menu" class="voice"><roundcube:label name="arialabelabookgroupoptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-groupoptions-menu">
<roundcube:button type="link-menuitem" command="group-create" title="newgroup" label="addgroup" class="create disabled" classAct="create active" />
<roundcube:button type="link-menuitem" command="group-rename" label="grouprename" class="group rename disabled" classAct="group rename active" />
<roundcube:button type="link-menuitem" command="group-delete" label="groupdelete" class="group delete disabled" classAct="group delete active" />
<roundcube:button type="link-menuitem" command="search-create" label="searchsave" class="search disabled" classAct="search active" />
<roundcube:button type="link-menuitem" command="search-delete" label="searchdelete" class="search delete disabled" classAct="search delete active" />
<roundcube:container name="groupoptions" id="groupoptionsmenu" />
</ul>
</div>
<div id="listselect-menu" class="popupmenu">
<h3 id="aria-label-listselect-menu" class="voice"><roundcube:label name="arialabellistselectmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-listselect-menu">
<roundcube:button type="link-menuitem" label="selection" class="selection" classAct="selection active"
name="list-toggle-button" id="list-toggle-button" onclick="UI.toggle_list_selection(this, 'contacts-table')" />
<roundcube:button command="select-all" type="link-menuitem" prop="page" label="currpage" class="select page disabled" classAct="select page active" />
<roundcube:button command="select-all" type="link-menuitem" prop="invert" label="invert" class="select invert disabled" classAct="select invert active" />
<roundcube:button command="select-none" type="link-menuitem" label="none" class="select none disabled" classAct="select none active" />
</ul>
</div>
<div id="dragcontact-menu" class="popupmenu">
<h3 id="aria-label-dragcontact-menu" class="voice"><roundcube:label name="arialabeldropactionmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-dragcontact-menu">
<roundcube:button type="link-menuitem" command="move" onclick="return rcmail.drag_menu_action('move')" label="move" class="disabled" classAct="active" />
<roundcube:button type="link-menuitem" command="copy" onclick="return rcmail.drag_menu_action('copy')" label="copy" class="disabled" classAct="active" />
</ul>
</div>
<div id="contact-menu" class="popupmenu">
<h3 id="aria-label-contact-menu" class="voice"><roundcube:label name="arialabelmorecontactactions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-contact-menu">
<roundcube:if condition="env:qrcode" />
<roundcube:button type="link-menuitem" command="qrcode" label="qrcode" class="qrcode disabled" classAct="qrcode active" />
<roundcube:endif />
<roundcube:button type="link-menuitem" command="group-assign-selected" label="groupassign" class="assigngroup disabled" classAct="assigngroup active" innerclass="folder-selector-link" aria-haspopup="true" />
<roundcube:button type="link-menuitem" command="group-remove-selected" label="groupremove" class="removegroup disabled" classAct="removegroup active" />
<roundcube:if condition="env:contact_move_enabled" />
<roundcube:button type="link-menuitem" command="move" label="moveto" class="move disabled" classAct="move active" innerclass="folder-selector-link" aria-haspopup="true" />
<roundcube:endif />
<roundcube:if condition="env:contact_copy_enabled" />
<roundcube:button type="link-menuitem" command="copy" label="copyto" class="copy disabled" classAct="copy active" innerclass="folder-selector-link" aria-haspopup="true" />
<roundcube:endif />
<roundcube:container name="contactmenu" id="contact-menu" />
</ul>
</div>
<roundcube:include file="includes/footer.html" />

74
templates/bounce.html Normal file
View File

@ -0,0 +1,74 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="bouncemsg" /></h1>
<div class="formcontent">
<roundcube:object name="bounceObjects" id="bounce-objects" class="mb-3" />
<roundcube:object name="composeFormHead" role="main" />
<div id="bounceheaders" role="region" aria-labelledby="aria-label-composeheaders">
<h2 id="aria-label-composeheaders" class="voice"><roundcube:label name="arialabelmessageheaders" /></h2>
<div class="compose-headers">
<div id="compose_from" class="form-group row">
<label for="_from" class="col-2 col-form-label"><roundcube:label name="from" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="from" id="_from" form="form" tabindex="1" class="form-control" />
<span class="input-group-append">
<a href="#identities" onclick="return rcmail.command('switch-task', 'settings/identities')" class="input-group-text icon edit" title="<roundcube:label name="editidents" />" tabindex="1"><span class="inner"><roundcube:label name="editidents" /></span></a>
</div>
</div>
</div>
<div id="compose_to" class="form-group row">
<label for="_to" class="col-2 col-form-label"><roundcube:label name="to" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="to" id="_to" form="form" tabindex="1" aria-required="true" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-header" data-popup="headers-menu" class="input-group-text icon add" title="<roundcube:label name="addheader" />" tabindex="1"><span class="inner"><roundcube:label name="addheader" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_cc" class="hidden form-group row">
<label for="_cc" class="col-2 col-form-label"><roundcube:label name="cc" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="cc" id="_cc" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_cc')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_bcc" class="hidden form-group row">
<label for="_bcc" class="col-2 col-form-label"><roundcube:label name="bcc" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="bcc" id="_bcc" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_bcc')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
</div>
<roundcube:if condition="!config:no_save_sent_messages" />
<div class="form-group row">
<label for="compose-store-target" class="col-form-label col-6"><roundcube:label name="savesentmessagein" /></label>
<div class="col-6">
<roundcube:object name="storetarget" id="compose-store-target" noform="true" tabindex="2" class="form-control" />
</div>
</div>
<roundcube:endif />
</form>
</div>
<div id="headers-menu" class="popupmenu" data-popup-init="headersmenu">
<h3 id="aria-label-headersmenu" class="voice"><roundcube:label name="arialabelheadersmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-headersmenu">
<li role="menuitem"><a data-target="cc" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="cc" /></a></li>
<li role="menuitem"><a data-target="bcc" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="bcc" /></a></li>
</ul>
</div>
<roundcube:include file="includes/footer.html" />

286
templates/compose.html Normal file
View File

@ -0,0 +1,286 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" condition="!env:extwin && !env:framed" />
<roundcube:add_label name="recipientsadded" />
<roundcube:add_label name="nocontactselected" />
<roundcube:add_label name="recipient" />
<roundcube:add_label name="insert" />
<roundcube:add_label name="insertcontact" />
<roundcube:add_label name="recipientedit" />
<h1 class="voice"><roundcube:label name="compose" /></h1>
<!-- compose options and attachments list -->
<div id="layout-sidebar" class="listbox sidebar-right">
<div class="header">
<a class="button icon back-content-button" href="#content" data-hidden="big"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title all-sizes"><roundcube:label name="optionsandattachments" /></span>
</div>
<div class="scroller">
<!-- attachments -->
<div id="compose-attachments" class="file-upload" role="region" aria-labelledby="aria-label-compose-attachments">
<h2 id="aria-label-compose-attachments" class="voice"><roundcube:label name="attachments" /></h2>
<div class="upload-form">
<roundcube:object name="composeAttachmentForm" mode="hint" />
<button type="button" class="btn btn-secondary attach" tabindex="2" onclick="rcmail.upload_input('uploadform')"><roundcube:label name="addattachment" /></button>
</div>
<roundcube:object name="composeAttachmentList" id="attachment-list" class="attachmentslist" tabindex="2" />
<roundcube:object name="fileDropArea" id="compose-attachments" />
</div>
<!-- compose options -->
<div id="compose-options" class="formcontent" role="region" aria-labelledby="aria-label-composeoptions">
<h2 id="aria-label-composeoptions" class="voice"><roundcube:label name="arialabelcomposeoptions" /></h2>
<roundcube:container name="composeoptions" id="compose-options" />
<roundcube:if condition="!in_array('mdn_default', (array)config:dont_override)" />
<div class="form-group row form-check">
<label for="compose-mdn" class="col-form-label col-6"><roundcube:label name="returnreceipt" /></label>
<div class="col-6 form-check">
<roundcube:object name="mdnCheckBox" id="compose-mdn" noform="true" tabindex="2" class="form-check-input" />
</div>
</div>
<roundcube:endif />
<roundcube:if condition="!in_array('dsn_default', (array)config:dont_override)" />
<div class="form-group row form-check">
<label for="compose-dsn" class="col-form-label col-6"><roundcube:label name="dsn" /></label>
<div class="col-6 form-check">
<roundcube:object name="dsnCheckBox" id="compose-dsn" noform="true" tabindex="2" class="form-check-input" />
</div>
</div>
<roundcube:endif />
<div class="form-group row form-check">
<label for="compose-keep-formatting" class="col-form-label col-6"><roundcube:label name="keepformatting" /></label>
<div class="col-6 form-check">
<roundcube:object name="keepFormattingCheckBox" id="compose-keep-formatting" noform="true" tabindex="2" class="form-check-input" />
</div>
</div>
<div class="form-group row">
<label for="compose-priority" class="col-form-label col-6"><roundcube:label name="priority" /></label>
<div class="col-6">
<roundcube:object name="prioritySelector" id="compose-priority" noform="true" tabindex="2" class="custom-select" />
</div>
</div>
<roundcube:if condition="!config:no_save_sent_messages" />
<div class="form-group row">
<label for="compose-store-target" class="col-form-label col-6"><roundcube:label name="savesentmessagein" /></label>
<div class="col-6">
<roundcube:object name="storetarget" id="compose-store-target" noform="true" tabindex="2" class="custom-select" />
</div>
</div>
<roundcube:endif />
</div>
</div>
</div>
<div id="layout-content" class="listbox selected" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header">
<a class="button icon task-menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<span class="header-title"><roundcube:label name="compose" /></span>
<div id="composestatusbar" class="position-absolute"></div>
<!-- toolbar -->
<div id="messagetoolbar" class="toolbar menu" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="options" href="#options" onclick="UI.show_sidebar()" data-hidden="big">
<span class="inner"><roundcube:label name="optionsandattachments"></span>
</a>
<roundcube:button command="savedraft" type="link" class="save draft disabled" classAct="save draft"
label="save" title="savemessage" tabindex="2" innerclass="inner" data-content-button="true" />
<span class="spacer"></span>
<roundcube:button name="addattachment" type="link" class="attach"
label="attach" title="addattachment" data-hidden="small"
onclick="if (!$(this).is('.disabled')) rcmail.upload_input('uploadform')"
aria-haspopup="true" aria-expanded="false" tabindex="2" innerclass="inner" />
<roundcube:button command="insert-sig" type="link" class="signature disabled" classAct="signature"
label="signature" title="insertsignature" tabindex="2" innerclass="inner" />
<a href="#responses" class="responses" label="responses" title="<roundcube:label name='insertresponse' />" unselectable="on" tabindex="2" data-popup="responses-menu">
<span class="inner"><roundcube:label name="responses" /></span>
</a>
<roundcube:if condition="!empty(env:spell_langs)" />
<span class="dropbutton">
<roundcube:button command="spellcheck" type="link" class="spellcheck disabled"
classAct="spellcheck" classSel="button spellcheck pressed"
label="spellcheck" title="checkspelling" tabindex="2" innerclass="inner" />
<a href="#languages" class="dropdown" tabindex="2" data-popup="spell-menu">
<span class="inner"><roundcube:label name="language" /></span>
</a>
</span>
<roundcube:endif />
<span class="dropbutton" style="display:none">
<roundcube:button command="compose-encrypted" type="link" class="encrypt disabled"
classAct="encrypt" classSel="encrypt selected" innerclass="inner"
label="encrypt" title="encryptmessagemailvelope" tabindex="2" />
<a href="#encryption" id="encryption-menu-button" class="dropdown" tabindex="2" data-popup="encryption-menu">
<span class="inner"><roundcube:label name="encryptmessagemailvelope" /></span>
</a>
</span>
<roundcube:container name="toolbar" id="compose-toolbar" />
</div>
</div>
<div id="compose-content" class="formcontainer content">
<roundcube:object name="composeFormHead" role="main" class="formcontent scroller" />
<roundcube:object name="composeObjects" id="compose-objects" class="mb-3" />
<!-- message headers -->
<div id="compose-headers" role="region" aria-labelledby="aria-label-composeheaders">
<h2 id="aria-label-composeheaders" class="voice"><roundcube:label name="arialabelmessageheaders" /></h2>
<div class="compose-headers">
<div id="compose_from" class="form-group row">
<label for="_from" class="col-2 col-form-label"><roundcube:label name="from" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="from" id="_from" form="form" tabindex="1" class="form-control" />
<span class="input-group-append">
<a href="#identities" onclick="return rcmail.command('switch-task', 'settings/identities')" class="input-group-text icon edit" title="<roundcube:label name="editidents" />" tabindex="1"><span class="inner"><roundcube:label name="editidents" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_to" class="form-group row">
<label for="_to" class="col-2 col-form-label"><roundcube:label name="to" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="to" id="_to" form="form" tabindex="1" aria-required="true" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-contact" onclick="UI.recipient_selector('to')" class="input-group-text icon add recipient" title="<roundcube:label name="addcontact" />" tabindex="1"><span class="inner"><roundcube:label name="addcontact" /></span></a>
</span>
<span class="input-group-append">
<a href="#add-header" data-popup="headers-menu" class="input-group-text icon add" title="<roundcube:label name="addheader" />" tabindex="1"><span class="inner"><roundcube:label name="addheader" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_cc" class="hidden form-group row">
<label for="_cc" class="col-2 col-form-label"><roundcube:label name="cc" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="cc" id="_cc" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-contact" onclick="UI.recipient_selector('cc')" class="input-group-text icon add recipient" title="<roundcube:label name="addcontact" />" tabindex="1"><span class="inner"><roundcube:label name="addcontact" /></span></a>
</span>
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_cc')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_bcc" class="hidden form-group row">
<label for="_bcc" class="col-2 col-form-label"><roundcube:label name="bcc" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="bcc" id="_bcc" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-contact" onclick="UI.recipient_selector('bcc')" class="input-group-text icon add recipient" title="<roundcube:label name="addcontact" />" tabindex="1"><span class="inner"><roundcube:label name="addcontact" /></span></a>
</span>
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_bcc')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_replyto" class="hidden form-group row">
<label for="_replyto" class="col-2 col-form-label"><roundcube:label name="replyto" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="replyto" id="_replyto" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-contact" onclick="UI.recipient_selector('replyto')" class="input-group-text icon add recipient" title="<roundcube:label name="addcontact" />" tabindex="1"><span class="inner"><roundcube:label name="addcontact" /></span></a>
</span>
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_replyto')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_followupto" class="hidden form-group row">
<label for="_followupto" class="col-2 col-form-label"><roundcube:label name="followupto" /></label>
<div class="col-10">
<div class="input-group">
<roundcube:object name="composeHeaders" part="followupto" id="_followupto" form="form" tabindex="1" data-recipient-input="true" />
<span class="input-group-append">
<a href="#add-contact" onclick="UI.recipient_selector('followupto')" class="input-group-text icon add recipient" title="<roundcube:label name="addcontact" />" tabindex="1"><span class="inner"><roundcube:label name="addcontact" /></span></a>
</span>
<span class="input-group-append">
<a href="#delete" onclick="UI.header_reset('_followupto')" class="input-group-text icon delete" title="<roundcube:label name='delete' />" tabindex="1"><span class="inner"><roundcube:label name="delete" /></span></a>
</span>
</div>
</div>
</div>
<div id="compose_subject" class="form-group row">
<label for="compose-subject" class="col-2 col-form-label"><roundcube:label name="subject" /></label>
<div class="col-10">
<roundcube:object name="composeSubject" id="compose-subject" form="form" tabindex="1" class="form-control" />
</div>
</div>
</div>
</div>
<!-- message compose body -->
<div id="composebodycontainer">
<label for="composebody" class="voice"><roundcube:label name="arialabelmessagebody" /></label>
<roundcube:object name="composeBody" id="composebody" form="form" cols="70" rows="20" class="form-control" tabindex="1" />
<roundcube:if condition="!in_array('htmleditor', (array)config:dont_override)" />
<roundcube:object name="editorSelector" id="editor-selector" editorid="composebody" noform="true" class="hidden" />
<roundcube:endif />
</div>
</form>
<div class="formbuttons">
<roundcube:button command="send" class="btn btn-primary send" label="send" tabindex="1" data-content-button="true" />
<div class="float-right">
<roundcube:button command="extwin" type="link" label="openinextwin" data-hidden="small" class="button icon btn btn-link extwin" data-tabindex="1" condition="!env:extwin" />
</div>
</div>
</div>
</div>
<roundcube:object name="composeAttachmentForm" id="uploadform" mode="smart" />
<div id="spell-menu" class="popupmenu" data-popup-init="spellmenu"></div>
<div id="headers-menu" class="popupmenu" data-popup-init="headersmenu">
<h3 id="aria-label-headersmenu" class="voice"><roundcube:label name="arialabelheadersmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-headersmenu">
<li role="menuitem"><a data-target="cc" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="cc" /></a></li>
<li role="menuitem"><a data-target="bcc" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="bcc" /></a></li>
<li role="menuitem"><a data-target="replyto" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="replyto" /></a></li>
<li role="menuitem"><a data-target="followupto" href="#" role="button" tabindex="-1" class="recipient active"><roundcube:label name="followupto" /></a></li>
</ul>
</div>
<div id="responses-menu" class="popupmenu">
<h3 id="aria-label-responsesmenu" class="voice"><roundcube:label name="arialabelresponsesmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-responsesmenu">
<li role="separator" class="separator"><label><roundcube:label name="insertresponse" /></label></li>
<roundcube:object name="responseslist" id="responseslist" tagname="ul" class="rounded-0" itemclass="active" list-placeholder="noresponsesavailable" />
<li role="separator" class="separator"><label><roundcube:label name="manageresponses" /></label></li>
<roundcube:button name="responses" type="link-menuitem" label="editresponses" class="edit responses active" onclick="return rcmail.command('switch-task', 'settings/responses')" />
</ul>
</div>
<div id="attachmentmenu" class="popupmenu">
<h3 id="aria-label-attachmentmenu" class="voice"><roundcube:label name="arialabelattachmentmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-attachmentmenu">
<roundcube:button command="open-attachment" id="attachmenuopen" type="link-menuitem" label="open" class="extwin disabled" classAct="extwin active" />
<roundcube:button command="download-attachment" id="attachmenudownload" type="link-menuitem" label="download" class="download disabled" classAct="download active" />
<roundcube:button command="rename-attachment" id="attachmenurename" type="link-menuitem" label="rename" class="rename disabled" classAct="rename active" />
<roundcube:container name="attachmentmenu" id="attachmentoptionsmenu" />
</ul>
</div>
<div id="encryption-menu" class="popupmenu">
<ul class="menu listing" role="menu">
<roundcube:button command="compose-encrypted" type="link-menuitem" label="encryptmessage" class="encrypt disabled" classAct="encrypt active" />
<roundcube:button command="compose-encrypted-signed" type="link-menuitem" label="encryptandsign" class="encrypt sign disabled" classAct="encrypt sign active" />
</ul>
</div>
<div id="recipient-dialog" class="popupmenu" role="region" aria-labelledby="aria-label-composecontacts">
<div class="listbox">
<roundcube:object name="searchform" id="searchform" wrapper="searchbar menu"
label="contactsearchform" buttontitle="findcontacts" ariatag="h2" class="no-bs" />
<div class="scroller" tabindex="-1">
<roundcube:object name="addressbooks" id="directorylist" class="treelist listing iconized"
summary="ariasummarycomposecontacts" />
<roundcube:object name="addresslist" id="contacts-table" class="listing iconized contactlist"
noheader="true" role="listbox" data-list="contact_list" data-list-select-replace="#recipient-dialog .pagenav-text" />
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

23
templates/contact.html Normal file
View File

@ -0,0 +1,23 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="contactproperties" /></h1>
<div class="formcontent">
<div class="contact-header">
<div id="contactphoto" class="contact-photo">
<roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.svg"
placeholderGroup="/images/contactgroup.svg" bg-color="transparent" />
</div>
<roundcube:object name="contacthead" id="contacthead" class="contact-head readonly" with-source="true" />
</div>
<div id="contacttabs" class="tabbed">
<roundcube:object name="contactdetails" fieldset-class="propform grouped readonly"
short-legend-labels="true" />
</div>
</div>
<div class="formbuttons">
<roundcube:button command="edit" class="btn btn-primary edit" label="edit" condition="!ENV:readonly" />
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,29 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:object name="steptitle" /></h1>
<roundcube:form name="editform" method="post" id="contact-details" class="formcontent">
<div class="contact-header">
<fieldset id="contactphoto" class="contact-photo">
<legend class="voice"><roundcube:label name="contactphoto" /></legend>
<roundcube:object name="contactphoto" id="contactpic" class="image-upload" placeholder="/images/contactpic.svg" />
<roundcube:if condition="env:photocol" />
<roundcube:object name="fileDropArea" id="contactpic" />
<roundcube:endif />
</fieldset>
<roundcube:object name="contactedithead" id="contacthead" form="editform"
class="propform contact-head" use-labels="true" with-source="true" />
</div>
<div id="contacttabs" class="tabbed">
<roundcube:object name="contacteditform" textareacols="60" form="editform"
fieldset-class="propform grouped" compact-form="true" short-legend-labels="true" />
</div>
</form>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" />
</div>
<roundcube:object name="photoUploadForm" id="upload-form" mode="smart" />
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,9 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="addressbook" /> : <roundcube:label name="importcontacts" /></h1>
<div class="formcontent">
<roundcube:object name="importstep" class="propform" table-header-class="form-group row d-none d-sm-flex" table-col-source-class="col-sm-4" table-col-destination-class="col-sm-8" />
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,19 @@
<roundcube:include file="includes/layout.html" />
<roundcube:object name="logo" id="logo" alt="Logo" logo-type="print" logo-match="template" class="float-sm-right" />
<div class="print-content formcontent" role="main">
<div class="contact-header">
<div id="contactphoto" class="contact-photo">
<roundcube:object name="contactphoto" id="contactpic" placeholder="/images/contactpic.svg"
placeholderGroup="/images/contactgroup.svg" />
</div>
<roundcube:object name="contacthead" id="contacthead" class="contact-head readonly" with-source="true" />
</div>
<div id="contacttabs">
<roundcube:object name="contactdetails" fieldset-class="propform grouped readonly"
short-legend-labels="true" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,9 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="addressbook" /> : <roundcube:label name="advsearch" /></h1>
<div class="formcontent">
<roundcube:object name="searchform" id="advsearchform" class="tabbed propform" short-legend-labels="true" />
</div>
<roundcube:include file="includes/footer.html" />

7
templates/dialog.html Normal file
View File

@ -0,0 +1,7 @@
<roundcube:include file="includes/layout.html" />
<div class="frame-content <roundcube:var name="env:dialog_class" />">
<roundcube:object name="dialogcontent" />
</div>
<roundcube:include file="includes/footer.html" />

21
templates/error.html Normal file
View File

@ -0,0 +1,21 @@
<roundcube:include file="includes/layout.html" />
<roundcube:if condition="!env:framed && !env:extwin" />
<roundcube:include file="includes/menu.html" />
<div id="layout-content" class="selected" role="main">
<div class="header">
<a class="button icon task-menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<span class="header-title"></span>
</div>
<div class="frame-content scroller">
<roundcube:else />
<div id="layout-content" class="selected" role="main">
<div class="frame-content scroller">
<roundcube:endif />
$__page_content
</div>
</div>
<roundcube:include file="includes/footer.html" />

13
templates/folderedit.html Normal file
View File

@ -0,0 +1,13 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:label name="folderproperties" /></h1>
<div class="formcontent">
<roundcube:object name="folderdetails" class="propform" />
</div>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" />
</div>
<roundcube:include file="includes/footer.html" />

61
templates/folders.html Normal file
View File

@ -0,0 +1,61 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<roundcube:include file="includes/settings-menu.html" />
<h1 class="voice"><roundcube:label name="folders" /></h1>
<!-- folders list -->
<div id="layout-list" class="listbox selected" aria-labelledby="aria-label-folderslist">
<div class="header">
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-folderslist" class="header-title"><roundcube:label name="folders" /></span>
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:object name="searchform" id="foldersearch" wrapper="searchbar menu" ariatag="h2"
label="foldersearchform" buttontitle="findfolders" options="foldersearchmenu" />
<div id="foldersearchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu" aria-controls="subscription-table">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<roundcube:object name="folderfilter" id="folderlist-filter" noheader="true" noevent="true" />
</div>
<div class="formbuttons">
<button type="button" class="btn btn-primary icon search" onclick="rcmail.folder_filter($('#folderlist-filter').val())"><roundcube:label name="search" /></button>
</div>
</div>
<div class="scroller" tabindex="-1">
<roundcube:object name="foldersubscription" id="subscription-table"
class="treelist listing folderlist iconized" role="listbox" data-list="subscription_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="folder-create" />
</div>
<div class="footer small">
<roundcube:if condition="env:quota" />
<div id="quotadisplay" class="quota-widget">
<span class="voice"><roundcube:label name="quota"></span>
<roundcube:object name="quotaDisplay" class="count" display="text" />
</div>
<roundcube:endif />
</div>
</div>
<!-- folder info frame -->
<div id="layout-content" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<!-- toolbar -->
<div id="folderstoolbar" class="toolbar menu">
<roundcube:button command="create-folder" type="link" class="create disabled" classAct="create"
label="create" title="createfolder" innerClass="inner" data-fab="true" />
<roundcube:button command="delete-folder" type="link" class="delete disabled" classAct="delete"
label="delete" title="delete" innerclass="inner" />
<roundcube:button command="purge" type="link" class="purge disabled" classAct="purge"
label="empty" title="empty" innerclass="inner" />
</div>
</div>
<div class="iframe-wrapper">
<roundcube:object name="contentframe" id="preferences-frame" src="env:blankpage" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

43
templates/identities.html Normal file
View File

@ -0,0 +1,43 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<roundcube:include file="includes/settings-menu.html" />
<h1 class="voice"><roundcube:label name="settings" /> : <roundcube:label name="identities" /></h1>
<!-- responses list -->
<div id="layout-list" class="listbox selected" aria-labelledby="aria-label-identitieslist">
<div class="header">
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-identitieslist" class="header-title"><roundcube:label name="identities" /></span>
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<div class="scroller">
<roundcube:object name="identitieslist" id="identities-table" class="listing"
noheader="true" role="listbox" data-list="identity_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="add" />
</div>
<div class="footer"></div>
</div>
<!-- response details frame -->
<div id="layout-content" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<!-- toolbar -->
<div id="identitiestoolbar" class="toolbar menu">
<roundcube:button command="add" type="link" class="create disabled" classAct="create"
label="create" title="newidentity" innerClass="inner"
condition="config:identities_level:0<2" data-fab="true" />
<roundcube:button command="delete" type="link" class="delete disabled" classAct="delete"
label="delete" title="delete" innerClass="inner"
condition="config:identities_level:0<2" />
</div>
</div>
<div class="iframe-wrapper">
<roundcube:object name="contentframe" id="preferences-frame" src="env:blankpage" title="arialabelidentityeditfrom" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,13 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:object name="steptitle" /></h1>
<div class="formcontent">
<roundcube:object name="identityform" class="propform" size="40" textareacols="40" textarearows="6" />
</div>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" condition="!env:readonly" />
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,14 @@
<roundcube:if condition="!env:framed || env:extwin" />
</div>
<roundcube:if condition="config:support_url" />
<a href="<roundcube:var name='config:support_url' />" target="_blank" id="supportlink" class="hidden"><roundcube:label name="support" /></a>
<roundcube:endif />
<roundcube:endif />
<roundcube:object name="message" id="messagestack" />
<script src="/deps/bootstrap.bundle.min.js"></script>
<script src="/ui.js"></script>
</body>
</html>

View File

@ -0,0 +1,46 @@
<roundcube:add_label name="back" />
<roundcube:add_label name="errortitle" />
<roundcube:add_label name="options" />
<roundcube:add_label name="plaintoggle" />
<roundcube:add_label name="htmltoggle" />
<roundcube:add_label name="previous" />
<roundcube:add_label name="next" />
<roundcube:add_label name="select" />
<roundcube:add_label name="close" />
<roundcube:add_label name="browse" />
<roundcube:add_label name="choosefile" />
<roundcube:add_label name="choosefiles" />
<roundcube:object name="doctype" value="html5" />
<roundcube:if condition="!env:framed || env:extwin" />
<html>
<roundcube:else />
<html class="iframe">
<roundcube:endif />
<head>
<roundcube:object name="meta" />
<roundcube:object name="links" />
<link rel="stylesheet" href="/deps/bootstrap.min.css">
<roundcube:if condition="config:devel_mode" />
<link rel="stylesheet/less" href="/styles/styles.less">
<roundcube:link rel="stylesheet/less" href="/styles/print.less" condition="env:action == 'print'" />
<script src="/deps/less.min.js" data-env="development"></script>
<roundcube:else />
<link rel="stylesheet" href="/styles/styles.css">
<roundcube:link rel="stylesheet" href="/styles/print.css" condition="env:action == 'print'" />
<roundcube:endif />
<roundcube:if condition="env:action != 'print' && !config:devel_mode && config:dark_mode_support" />
<script>
try {
if (document.cookie.indexOf('colorMode=dark') > -1
|| (document.cookie.indexOf('colorMode=light') === -1 && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.className += ' dark-mode';
}
} catch (e) { }
</script>
<roundcube:endif />
</head>
<body class="task-<roundcube:exp expression="env:error_task ?: env:task ?: 'error'"> action-<roundcube:exp expression="asciiwords(env:action, true, '-') ?: 'none'">">
<roundcube:if condition="!env:framed || env:extwin" />
<div id="<roundcube:exp expression="env:action == 'print' ? 'print-' : ''">layout">
<roundcube:endif />

View File

@ -0,0 +1,95 @@
<roundcube:add_label name="viewsource" />
<div id="mailtoolbar" class="toolbar menu" role="toolbar">
<roundcube:button command="compose" type="link" class="compose hidden"
label="compose" title="writenewmessage" innerclass="inner" />
<roundcube:button command="reply" type="link" class="reply disabled" classAct="reply"
label="reply" title="replytomessage" innerclass="inner" data-content-button="true" />
<span class="dropbutton">
<roundcube:button command="reply-all" type="link" class="reply-all disabled" classAct="reply-all"
label="replyall" title="replytoallmessage" innerclass="inner" />
<a href="#reply-all" id="replyallmenulink" class="dropdown" data-popup="replyall-menu" tabindex="0">
<span class="inner"><roundcube:label name="arialabelreplyalloptions" /></span>
</a>
</span>
<span class="dropbutton">
<roundcube:button command="forward" type="link" class="forward disabled" classAct="forward"
label="forward" title="forwardmessage" innerclass="inner" />
<a href="#forward" id="forwardmenulink" class="dropdown" data-popup="forward-menu" tabindex="0">
<span class="inner"><roundcube:label name="arialabelforwardingoptions" /></span>
</a>
</span>
<span class="spacer"></span>
<roundcube:button command="delete" type="link" class="delete disabled" classAct="delete"
label="delete" title="deletemessage" innerclass="inner" />
<roundcube:if condition="template:name == 'message'" />
<roundcube:button command="print" type="link" class="print disabled" classAct="print"
label="print" title="printmessage" innerclass="inner" data-hidden="small" />
<roundcube:endif />
<roundcube:container name="toolbar" id="mailtoolbar" />
<roundcube:button name="markmenulink" id="markmessagemenulink" type="link" class="markmessage"
label="mark" title="markmessages" data-popup="markmessage-menu" innerclass="inner" />
<roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="more"
label="more" title="moreactions" data-popup="message-menu" innerclass="inner" />
<roundcube:if condition="template:name == 'message'" />
<span class="spacer"></span>
<roundcube:button command="previousmessage" type="link" class="prev disabled" classAct="prev"
innerclass="inner" label="previous" title="previousmessage" data-hidden="small" />
<roundcube:button command="nextmessage" type="link" class="next disabled" classAct="next"
innerclass="inner" label="next" title="nextmessage" data-hidden="small" />
<roundcube:endif />
</div>
<div id="forward-menu" class="popupmenu">
<h3 id="aria-label-forward-menu" class="voice"><roundcube:label name="arialabelforwardingoptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-forward-menu">
<roundcube:button type="link-menuitem" command="forward-inline" label="forwardinline" prop="sub" class="forward inline disabled" classAct="forward inline active" />
<roundcube:button type="link-menuitem" command="forward-attachment" label="forwardattachment" prop="sub" class="forward attachment disabled" classAct="forward attachment active" />
<roundcube:button type="link-menuitem" command="bounce" label="bouncemsg" class="forward bounce disabled" classAct="forward bounce active" />
<roundcube:container name="forwardmenu" id="forward-menu" />
</ul>
</div>
<div id="replyall-menu" class="popupmenu">
<h3 id="aria-label-replyall-menu" class="voice"><roundcube:label name="arialabelreplyalloptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-replyall-menu">
<roundcube:button type="link-menuitem" command="reply-all" label="replyall" prop="sub" class="reply all disabled" classAct="reply all active" />
<roundcube:button type="link-menuitem" command="reply-list" label="replylist" prop="sub" class="reply list disabled" classAct="reply list active" />
<roundcube:container name="replyallmenu" id="replyall-menu" />
</ul>
</div>
<div id="message-menu" class="popupmenu">
<h3 id="aria-label-message-menu" class="voice"><roundcube:label name="arialabelmoremessageactions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-message-menu">
<roundcube:button type="link-menuitem" command="print" label="printmessage" class="print disabled" classAct="print active" data-hidden="small"/>
<roundcube:if condition="template:name != 'message'" />
<roundcube:button type="link-menuitem" command="import-messages" label="import" class="import disabled" classAct="import active"
name="messageimport" onclick="UI.import_dialog()" />
<roundcube:endif />
<roundcube:button type="link-menuitem" command="download" label="export" class="download disabled" classAct="download active" />
<roundcube:button type="link-menuitem" command="edit" prop="new" label="editasnew" class="edit asnew disabled" classAct="edit asnew active" />
<roundcube:button type="link-menuitem" command="viewsource" label="viewsource" class="source disabled" classAct="source active" />
<roundcube:button type="link-menuitem" command="move" label="moveto" class="move disabled" classAct="move active" innerclass="folder-selector-link" aria-haspopup="true" />
<roundcube:button type="link-menuitem" command="copy" label="copyto" class="copy disabled" classAct="copy active" innerclass="folder-selector-link" aria-haspopup="true" />
<roundcube:button type="link-menuitem" command="open" label="openinextwin" target="_blank" class="extwin disabled" classAct="extwin active" data-hidden="small" />
<roundcube:container name="messagemenu" id="message-menu" />
</ul>
</div>
<div id="markmessage-menu" class="popupmenu">
<h3 id="aria-label-markmessage-menu" class="voice"><roundcube:label name="arialabelmarkmessagesas" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-markmessage-menu">
<roundcube:button type="link-menuitem" command="mark" prop="read" label="markread" classAct="read active" class="read disabled" />
<roundcube:button type="link-menuitem" command="mark" prop="unread" label="markunread" classAct="unread active" class="unread disabled" />
<roundcube:button type="link-menuitem" command="mark" prop="flagged" label="markflagged" classAct="flag active" class="flag disabled" />
<roundcube:button type="link-menuitem" command="mark" prop="unflagged" label="markunflagged" classAct="unflag active" class="unflag disabled" />
<roundcube:if condition="config:flag_for_deletion && !config:skip_deleted" />
<roundcube:button type="link-menuitem" command="mark" prop="undelete" label="markundeleted" classAct="undo active" class="undo disabled" />
<roundcube:endif />
<roundcube:container name="markmenu" id="markmessage-menu" />
</ul>
</div>
<roundcube:if condition="template:name != 'message'" />
<roundcube:object name="messageimportform" id="uploadform" class="popupmenu formcontent" buttons="no" />
<roundcube:endif />

View File

@ -0,0 +1,42 @@
<div id="layout-menu">
<h2 id="aria-label-tasknav" class="voice"><roundcube:label name="arialabeltasknav" /></h2>
<div class="popover-header">
<roundcube:object name="logo" src="/images/logo.png" id="logo" alt="Logo" />
<a class="button icon cancel"><span class="inner"><roundcube:label name="close" /></span></a>
</div>
<div id="taskmenu" class="menu toolbar" role="navigation" aria-labelledby="aria-label-tasknav">
<span class="action-buttons">
<roundcube:if condition="env:action == 'compose' and env:task == 'mail'" />
<roundcube:button command="compose" type="link" class="compose selected"
label="compose" title="writenewmessage" innerclass="inner" />
<roundcube:else />
<roundcube:button command="compose" type="link" class="compose"
label="compose" title="writenewmessage" innerclass="inner"
data-fab="true" data-fab-task="mail" data-fab-action="none" />
<roundcube:endif />
</span>
<roundcube:if condition="env:action == 'compose' and env:task == 'mail'" />
<roundcube:button command="mail" label="mail" type="link" innerClass="inner"
class="mail" />
<roundcube:else />
<roundcube:button command="mail" label="mail" type="link" innerClass="inner"
class="mail" classSel="mail selected" />
<roundcube:endif />
<roundcube:button command="addressbook" label="contacts" type="link" innerClass="inner"
class="contacts" classSel="contacts selected" />
<roundcube:container name="taskbar" id="taskmenu" />
<roundcube:button command="settings" label="settings" type="link" innerClass="inner"
class="settings" classSel="settings selected" />
<span class="special-buttons">
<roundcube:if condition="config:dark_mode_support" />
<roundcube:add_label name="darkmode" />
<roundcube:add_label name="lightmode" />
<roundcube:button name="theme" label="darkmode" type="link" innerClass="inner" class="theme dark" />
<roundcube:endif />
<roundcube:button name="about" label="about" type="link"
class="about" innerClass="inner" onclick="UI.about_dialog(this)" />
<roundcube:button command="logout" label="logout" type="link"
class="logout" innerClass="inner" />
</span>
</div>
</div>

View File

@ -0,0 +1,20 @@
<div class="pagenav menu footer small" role="toolbar" aria-label="<roundcube:label name="arialabellistnav" />">
<roundcube:button command="firstpage" type="link" class="firstpage disabled" classAct="firstpage"
title="firstpage" label="first" innerclass="inner" />
<roundcube:button command="previouspage" type="link" class="prevpage disabled" classAct="prevpage"
title="previouspage" label="previous" innerclass="inner" />
<roundcube:if condition="template:name == 'mail'" />
<roundcube:object name="messageCountDisplay" class="pagenav-text" aria-live="polite" aria-relevant="text" />
<input class="form-control" type="text" size="3" disabled title="<roundcube:label name="currpage" />" />
<roundcube:elseif condition="template:name == 'addressbook'" />
<span class="pagenav-text" aria-live="polite" aria-relevant="text">
<roundcube:object name="recordsCountDisplay" label="fromtoshort" />
</span>
<roundcube:else />
<span class="pagenav-text" aria-live="polite" aria-relevant="text">&nbsp;</span>
<roundcube:endif />
<roundcube:button command="nextpage" type="link" class="nextpage disabled" classAct="nextpage"
title="nextpage" label="next" innerclass="inner" />
<roundcube:button command="lastpage" type="link" class="lastpage disabled" classAct="lastpage"
title="lastpage" label="last" innerclass="inner" />
</div>

View File

@ -0,0 +1,12 @@
<div id="layout-sidebar" class="listbox<roundcube:exp expression="!request:_action ? ' selected' : ''"/>" role="navigation" aria-labelledby="aria-label-settingstabs">
<div class="header">
<a class="button icon task-menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<span id="aria-label-settingstabs" class="header-title"><roundcube:label name="settings" /></span>
</div>
<div class="scroller">
<ul id="settings-menu" class="listing iconized settings-default-icon<roundcube:exp expression="!request:_action ? ' selection-large-only' : ''"/>">
<roundcube:object name="settingstabs" class="listitem" tagname="li" />
<roundcube:container name="tabs" id="settings-menu" />
</ul>
</div>
</div>

24
templates/login.html Normal file
View File

@ -0,0 +1,24 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:object name="productname" /> <roundcube:label name="login" /></h1>
<div id="layout-content" class="selected no-navbar" role="main">
<roundcube:object name="logo" src="/images/logo.png" id="logo" alt="Logo" />
<roundcube:form id="login-form" name="login-form" method="post" class="propform">
<roundcube:object name="loginform" form="login-form" size="40" submit=true class="form-control" />
<div id="login-footer" role="contentinfo">
<roundcube:object name="productname" condition="config:display_product_info &gt; 0" />
<roundcube:object name="version" condition="config:display_product_info == 2" />
<roundcube:if condition="config:support_url" />
&nbsp;&bull;&nbsp; <a href="<roundcube:var name='config:support_url' />" target="_blank" class="support-link"><roundcube:label name="support" /></a>
<roundcube:endif />
<roundcube:container name="loginfooter" id="login-footer" />
</div>
</form>
</div>
<noscript>
<p class="noscriptwarning"><roundcube:label name="noscriptwarning" /></p>
</noscript>
<roundcube:include file="includes/footer.html" />

220
templates/mail.html Normal file
View File

@ -0,0 +1,220 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<h1 class="voice"><roundcube:label name="mail" /></h1>
<!-- folders list -->
<div id="layout-sidebar" class="listbox" role="navigation" aria-labelledby="aria-label-folderlist">
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title username"><roundcube:object name="username" /></span>
<roundcube:button name="folderactions" type="link" title="folderactions" label="actions"
class="button icon sidebar-menu" innerclass="inner" data-popup="mailboxoptions-menu" />
</div>
<h2 id="aria-label-folderlist" class="voice"><roundcube:label name="arialabelfolderlist" /></h2>
<div id="folderlist-content" class="scroller">
<roundcube:object name="mailboxlist" id="mailboxlist" class="treelist listing folderlist" folder_filter="mail" unreadwrap="%s" />
</div>
<div class="footer small">
<roundcube:if condition="env:quota" />
<div id="quotadisplay" class="quota-widget">
<span class="voice"><roundcube:label name="quota"></span>
<roundcube:object name="quotaDisplay" class="count" display="text" />
</div>
<roundcube:endif />
</div>
</div>
<!-- messages list -->
<div id="layout-list" class="listbox selected">
<div id="messagelist-header" class="header">
<a class="button icon task-menu-button" href="#menu"><span class="inner"><roundcube:label name="menu" /></span></a>
<a class="button icon back-sidebar-button folders" href="#sidebar"><span class="inner"><roundcube:label name="mailboxlist" /></span></a>
<span class="header-title"></span>
<div class="toolbar menu" role="toolbar">
<a href="#select" class="select disabled" data-popup="listselect-menu" data-toggle-button="list-toggle-button" title="<roundcube:label name="select" />"><span class="inner"><roundcube:label name="select" /></span></a>
<roundcube:if condition="env:threads" />
<a href="#threads" class="threads disabled" data-popup="threadselect-menu" title="<roundcube:label name="threads" />"><span class="inner"><roundcube:label name="threads" /></span></a>
<roundcube:endif />
<roundcube:object name="listmenulink" class="options active" label="options" innerclass="inner" />
<roundcube:container name="listcontrols" id="listcontrols" />
</div>
<roundcube:button command="checkmail" type="link" class="button icon toolbar-button refresh"
label="refresh" title="checkmail" innerclass="inner" />
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<roundcube:add_label name="showunread" />
<roundcube:object name="searchform" id="mailsearchform" wrapper="searchbar menu"
label="mailquicksearchbox" buttontitle="findmail" options="searchmenu" ariatag="h2" />
<div id="searchmenu" class="hidden searchoptions scroller propform formcontainer" aria-labelledby="aria-label-search-menu" aria-controls="messagelist">
<h3 id="aria-label-search-menu" class="voice"><roundcube:label name="searchmod" /></h3>
<div class="formcontent">
<ul class="proplist">
<li><label><input type="checkbox" name="s_mods[]" value="subject" /><roundcube:label name="subject" /></label></li>
<li class="with-sublist">
<label><input type="checkbox" name="s_mods[]" value="sender" /><roundcube:label name="sender" /></label>
<a class="button icon dropdown" role="button" href="#" title="<roundcube:label name="details" />"></a>
<ul class="proplist d-none">
<li><label><input type="checkbox" name="s_mods[]" value="from" /><roundcube:label name="from" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="replyto" /><roundcube:label name="replyto" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="followupto" /><roundcube:label name="followupto" /></label></li>
</ul>
</li>
<li class="with-sublist">
<label><input type="checkbox" name="s_mods[]" value="recipient" /><roundcube:label name="recipient" /></label>
<a class="button icon dropdown" role="button" href="#" title="<roundcube:label name="details" />"></a>
<ul class="proplist d-none">
<li><label><input type="checkbox" name="s_mods[]" value="to" /><roundcube:label name="to" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="cc" /><roundcube:label name="cc" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="bcc" /><roundcube:label name="bcc" /></label></li>
</ul>
</li>
<li><label><input type="checkbox" name="s_mods[]" value="body" /><roundcube:label name="body" /></label></li>
<li><label><input type="checkbox" name="s_mods[]" value="text" /><roundcube:label name="msgtext" /></label></li>
</ul>
<div class="input-group">
<div class="input-group-prepend">
<label for="searchfilter" class="input-group-text"><roundcube:label name="type" /></label>
</div>
<roundcube:object name="searchfilter" id="searchfilter" noevent="true" class="custom-select" />
</div>
<div class="input-group">
<div class="input-group-prepend">
<label for="s_interval" class="input-group-text"><roundcube:label name="date" /></label>
</div>
<roundcube:object name="searchinterval" id="s_interval" class="custom-select" />
</div>
<div class="input-group">
<div class="input-group-prepend">
<label for="s_scope" class="input-group-text"><roundcube:label name="searchscope" /></label>
</div>
<select name="s_scope" id="s_scope" class="custom-select">
<option value="base"><roundcube:label name="currentfolder" /></option>
<option value="sub"><roundcube:label name="subfolders" /></option>
<option value="all"><roundcube:label name="allfolders" /></option>
</select>
</div>
</div>
<div class="formbuttons">
<button type="button" class="btn btn-primary icon search" onclick="return rcmail.command('search')"><roundcube:label name="search" /></button>
</div>
</div>
<div id="messagelist-content" class="scroller" tabindex="-1">
<h2 id="aria-label-messagelist" class="voice"><roundcube:label name="arialabelmessagelist" /></h2>
<roundcube:object name="messages" id="messagelist" class="listing messagelist sortheader fixedheader"
aria-labelledby="aria-label-messagelist" data-list="message_list" data-label-msg="listempty"
/>
</div>
<roundcube:include file="includes/pagenav.html" />
</div>
<!-- message preview -->
<div id="layout-content">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<roundcube:include file="includes/mail-menu.html" />
</div>
<h2 id="aria-label-mailpreviewframe" class="voice"><roundcube:label name="arialabelmailpreviewframe" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="contentframe"
id="messagecontframe"
aria-labelledby="aria-label-mailpreviewframe"
src="env:blankpage"
title="arialabelmailpreviewframe"
/>
</div>
</div>
<!-- popup menus -->
<div id="dragmessage-menu" class="popupmenu">
<h3 id="aria-label-dragmessage-menu" class="voice"><roundcube:label name="arialabeldropactionmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-dragmessage-menu">
<roundcube:button command="move" type="link-menuitem" onclick="return rcmail.drag_menu_action('move')" label="move" class="disabled" classAct="active" />
<roundcube:button command="copy" type="link-menuitem" onclick="return rcmail.drag_menu_action('copy')" label="copy" class="disabled" classAct="active" />
</ul>
</div>
<div id="mailboxoptions-menu" class="popupmenu">
<h3 id="aria-label-mailboxoptions-menu" class="voice"><roundcube:label name="arialabelmailboxmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-mailboxoptions-menu">
<roundcube:button command="expunge" type="link-menuitem" label="compact" class="expunge disabled" classAct="expunge active" />
<roundcube:button command="purge" type="link-menuitem" label="empty" class="purge disabled" classAct="purge active" />
<roundcube:button command="mark-all-read" type="link-menuitem" label="markallread" class="read disabled" classAct="read active" />
<roundcube:button command="folders" task="settings" type="link-menuitem" label="managefolders" class="folders disabled" classAct="folders active" />
<roundcube:container name="mailboxoptions" id="mailboxoptionsmenu" />
</ul>
</div>
<div id="listselect-menu" class="popupmenu">
<h3 id="aria-label-listselect-menu" class="voice"><roundcube:label name="arialabellistselectmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-listselect-menu">
<roundcube:button type="link-menuitem" label="selection" class="selection disabled" classAct="selection active"
name="list-toggle-button" id="list-toggle-button" onclick="UI.toggle_list_selection(this, 'messagelist')" />
<roundcube:button command="select-all" type="link-menuitem" label="all" class="select all disabled" classAct="select all active" />
<roundcube:button command="select-all" type="link-menuitem" prop="page" label="currpage" class="select page disabled" classAct="select page active" />
<roundcube:button command="select-all" type="link-menuitem" prop="unread" label="unread" class="select unread disabled" classAct="select unread active" />
<roundcube:button command="select-all" type="link-menuitem" prop="flagged" label="flagged" class="select flagged disabled" classAct="select flagged active" />
<roundcube:button command="select-all" type="link-menuitem" prop="invert" label="invert" class="select invert disabled" classAct="select invert active" />
<roundcube:button command="select-none" type="link-menuitem" label="none" class="select none disabled" classAct="select none active" />
</ul>
</div>
<div id="threadselect-menu" class="popupmenu">
<h3 id="aria-label-threadselectmenu" class="voice"><roundcube:label name="arialabelthreadselectmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-threadselectmenu">
<roundcube:button command="expand-unread" type="link-menuitem" label="expand-unread" class="expand unread disabled" classAct="expand unread active" />
<roundcube:button command="expand-all" type="link-menuitem" label="expand-all" class="expand all disabled" classAct="expand all active" />
<roundcube:button command="collapse-all" type="link-menuitem" label="collapse-all" class="expand none disabled" classAct="expand none active" />
</ul>
</div>
<div id="listoptions-menu" class="popupmenu propform" role="dialog" aria-labelledby="aria-label-listoptions">
<h3 id="aria-label-listoptions" class="voice"><roundcube:label name="arialabelmessagelistoptions" /></h3>
<roundcube:if condition="!in_array('message_sort_col', (array)config:dont_override)" />
<div class="form-group row">
<label for="listoptions-sortcol" class="col-form-label col-sm-4"><roundcube:label name="listsorting" /></label>
<div class="col-sm-8">
<select id="listoptions-sortcol" name="sort_col">
<option value=""><roundcube:label name="nonesort" /></option>
<option value="arrival"><roundcube:label name="arrival" /></option>
<option value="date"><roundcube:label name="sentdate" /></option>
<option value="subject"><roundcube:label name="subject" /></option>
<option value="fromto"><roundcube:label name="fromto" /></option>
<option value="from"><roundcube:label name="from" /></option>
<option value="to"><roundcube:label name="to" /></option>
<option value="cc"><roundcube:label name="cc" /></option>
<option value="size"><roundcube:label name="size" /></option>
</select>
</div>
</div>
<roundcube:endif />
<roundcube:if condition="!in_array('message_sort_order', (array)config:dont_override)" />
<div class="form-group row">
<label for="listoptions-sortord" class="col-form-label col-sm-4"><roundcube:label name="listorder" /></label>
<div class="col-sm-8">
<select id="listoptions-sortord" name="sort_ord">
<option value="ASC"><roundcube:label name="asc" /></option>
<option value="DESC"><roundcube:label name="desc" /></option>
</select>
</div>
</div>
<roundcube:endif />
<roundcube:if condition="env:threads" />
<div class="form-group row">
<label for="listoptions-threads" class="col-form-label col-sm-4"><roundcube:label name="lmode" /></label>
<div class="col-sm-8">
<select id="listoptions-threads" name="mode">
<option value="list"><roundcube:label name="list" /></option>
<option value="threads"><roundcube:label name="threads" /></option>
</select>
</div>
</div>
<roundcube:endif />
<roundcube:container name="listoptions" id="listoptionsmenu" />
<roundcube:add_label name="listoptionstitle" />
</div>
<roundcube:include file="includes/footer.html" />

83
templates/message.html Normal file
View File

@ -0,0 +1,83 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" condition="!env:framed && !env:extwin" />
<roundcube:object name="mailboxlist" folder_filter="mail" type="js" />
<h1 class="voice"><roundcube:label name="arialabelmailpreviewframe" /></h1>
<div id="layout-content" class="selected">
<roundcube:if condition="!env:framed" />
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<roundcube:include file="includes/mail-menu.html" />
</div>
<roundcube:endif />
<div class="content frame-content" role="main">
<div id="message-header">
<h2 class="subject">
<span class="voice"><roundcube:label name="subject" />: </span>
<roundcube:object name="messageHeaders" valueOf="subject" />
<roundcube:if condition="!env:message_context && !env:extwin">
<roundcube:button command="extwin" type="link" class="extwin" innerClass="inner"
label="openinextwin" title="openinextwin" data-hidden="small" />
<roundcube:endif />
</h2>
<div class="header">
<roundcube:object name="contactphoto" class="contactphoto" placeholder="/images/contactpic.svg" bg-color="transparent" />
<div class="header-content">
<roundcube:object name="messageSummary" class="header-summary" addicon="virtual" />
<roundcube:object name="messageHeaders" class="header-headers" addicon="virtual" exclude="subject" max="10" />
<div class="header-links">
<roundcube:add_label name="details" />
<roundcube:add_label name="summary" />
<a href="#headers" class="headers-summary" onclick="return UI.headers_show(true)"></a>
<a href="#all-headers" class="headers-all" onclick="return UI.headers_dialog()"><roundcube:label name="headers" /></a>
<roundcube:add_label name="arialabelmessageheaders" />
<roundcube:if condition="env:optional_format=='text'" />
<roundcube:button command="change-format" prop="text" type="link" class="plain" innerClass="inner"
title="changeformattext" label="plaintoggle" />
<roundcube:elseif condition="env:optional_format=='html'" />
<roundcube:button command="change-format" prop="html" type="link" class="html" innerClass="inner"
title="changeformathtml" label="htmltoggle" />
<roundcube:endif />
<roundcube:container name="headerlinks" id="header-links" />
</div>
</div>
</div>
</div>
<div id="message-content">
<div class="leftcol" role="region" aria-labelledby="aria-label-messageattachments">
<h2 id="aria-label-messageattachments" class="voice"><roundcube:label name="attachments" /></h2>
<roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
</div>
<div class="rightcol" role="region" aria-labelledby="aria-label-messagebody">
<h2 id="aria-label-messagebody" class="voice"><roundcube:label name="arialabelmessagebody" /></h2>
<roundcube:object name="messageObjects" id="message-objects" />
<roundcube:object name="messageBody" id="messagebody" headertableclass="headers-table" />
</div>
</div>
</div>
</div>
<!-- popup menus -->
<div id="attachmentmenu" class="popupmenu">
<h3 id="aria-label-attachmentmenu" class="voice"><roundcube:label name="arialabelattachmentmenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-attachmentmenu">
<roundcube:button command="open-attachment" type="link-menuitem" id="attachmenuopen" label="open" class="extwin disabled" classAct="extwin active" />
<roundcube:button command="download-attachment" type="link-menuitem" id="attachmenudownload" label="download" class="download disabled" classAct="download active" />
<roundcube:container name="attachmentmenu" id="attachmentmenu" />
</ul>
</div>
<div id="mailto-menu" class="popupmenu">
<h3 id="aria-label-mailtomenu" class="voice"><roundcube:label name="arialabelmailtomenu" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-mailtomenu">
<roundcube:button name="addtoaddressbook" type="link-menuitem" label="addtoaddressbook" class="addressbook" classAct="addressbook active" />
<roundcube:button name="composeto" type="link-menuitem" label="composeto" class="compose" classAct="compose active" />
<roundcube:container name="mailtomenu" id="mailto-menu" />
</ul>
</div>
<roundcube:include file="includes/footer.html" />

119
templates/messagepart.html Normal file
View File

@ -0,0 +1,119 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:var name="env:filename" /></h1>
<div id="layout-content" class="selected">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<span class="header-title constant"><roundcube:var name="env:filename" /></span>
<div id="messagetoolbar" class="toolbar menu">
<roundcube:button type="link" name="info" label="properties" title="properties"
class="info" innerclass="inner" onclick="UI.props_dialog()" />
<roundcube:button command="download" type="link" label="download" title="download"
class="download disabled" classAct="download" innerclass="inner" />
<roundcube:button command="print" type="link" label="print" title="print"
class="print disabled" classAct="print" innerclass="inner" data-hidden="small" />
<roundcube:container name="toolbar" id="messagetoolbar" />
<roundcube:if condition="env:is_message" />
<span class="spacer"></span>
<roundcube:button command="reply" type="link" class="reply disabled" classAct="reply"
label="reply" title="replytomessage" innerclass="inner" />
<span class="dropbutton">
<roundcube:button command="reply-all" type="link" class="reply-all disabled" classAct="reply-all"
label="replyall" title="replytoallmessage" innerclass="inner" />
<a href="#reply-all" id="replyallmenulink" class="dropdown" data-popup="replyall-menu" tabindex="0">
<span class="inner"><roundcube:label name="arialabelreplyalloptions" /></span>
</a>
</span>
<span class="dropbutton">
<roundcube:button command="forward" type="link" class="forward disabled" classAct="forward"
label="forward" title="forwardmessage" innerclass="inner" />
<a href="#forward" id="forwardmenulink" class="dropdown" data-popup="forward-menu" tabindex="0">
<span class="inner"><roundcube:label name="arialabelforwardingoptions" /></span>
</a>
</span>
<span class="spacer"></span>
<roundcube:button name="messagemenulink" id="messagemenulink" type="link"
class="more" label="more" title="moreactions" data-popup="message-menu"
innerclass="inner" data-hidden="small" />
<roundcube:endif />
<roundcube:if condition="stripos(env:mimetype, 'image/') === 0" />
<span class="spacer"></span>
<roundcube:button command="image-scale" type="link" prop="+" data-hidden="small"
class="zoomin disabled" classAct="zoomin"
label="zoomin" title="increaseimage" innerclass="inner" />
<roundcube:button command="image-scale" type="link" prop="-" data-hidden="small"
class="zoomout disabled" classAct="zoomout"
label="zoomout" title="decreaseimage" innerclass="inner" />
<roundcube:button command="image-rotate" type="link" data-hidden="small"
class="rotate disabled" classAct="rotate"
label="rotate" title="rotateimage" innerclass="inner" />
<roundcube:endif />
</div>
</div>
<h2 id="aria-label-messagepart" class="voice"><roundcube:label name="arialabelattachmentpreview" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="messagePartFrame" id="messagepartframe" title="arialabelattachmentpreview"
role="main" aria-labelledby="aria-label-messagepart" />
</div>
<roundcube:if condition="stripos(env:mimetype, 'image/') === 0" />
<div id="image-tools" class="image-tools" data-hidden="big">
<h3 id="aria-label-imagetools" class="voice"><roundcube:label name="arialabelimagetools" /></h3>
<div class="toolbar menu" role="menu" aria-labelledby="aria-label-imagetools">
<roundcube:button command="image-scale" type="link" prop="+"
class="zoomin disabled" classAct="zoomin"
label="zoomin" title="increaseimage" innerclass="inner" />
<roundcube:button command="image-scale" type="link" prop="-"
class="zoomout disabled" classAct="zoomout"
label="zoomout" title="decreaseimage" innerclass="inner" />
<roundcube:button command="image-rotate" type="link"
class="rotate disabled" classAct="rotate"
label="rotate" title="rotateimage" innerclass="inner" />
</div>
<a href="#" class="button icon tools" onclick="$(this).attr('title', $(this).data('label-' + ($('#image-tools').toggleClass('open').is('.open') ? 'hide' : 'show')))"
data-label-show="<roundcube:label name="showtools" />" data-label-hide="<roundcube:label name="hidetools" />" title="<roundcube:label name="showtools" />">
<span class="inner"><roundcube:label name="showtools" /></span>
</a>
</div>
<roundcube:endif />
</div>
<roundcube:if condition="env:is_message" />
<div id="forward-menu" class="popupmenu">
<h3 id="aria-label-forwardmenu" class="voice"><roundcube:label name="arialabelforwardingoptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-forwardmenu">
<roundcube:button type="link-menuitem" command="forward-inline" label="forwardinline" prop="sub" classAct="forward inline active" class="forward disabled" />
<roundcube:button type="link-menuitem" command="forward-attachment" label="forwardattachment" prop="sub" classAct="forward attachment active" class="forward attachment disabled" />
<roundcube:container name="forwardmenu" id="forward-menu" />
</ul>
</div>
<div id="replyall-menu" class="popupmenu">
<h3 id="aria-label-replyallmenu" class="voice"><roundcube:label name="arialabelreplyalloptions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-replyallmenu">
<roundcube:button type="link-menuitem" command="reply-all" label="replyall" prop="sub" class="reply all disabled" classAct="reply all active" />
<roundcube:button type="link-menuitem" command="reply-list" label="replylist" prop="sub" class="reply list disabled" classAct="reply list active" />
<roundcube:container name="replyallmenu" id="replyall-menu" />
</ul>
</div>
<div id="message-menu" class="popupmenu">
<h3 id="aria-label-messagemenu" class="voice"><roundcube:label name="arialabelmoremessageactions" /></h3>
<ul class="menu listing" role="menu" aria-labelledby="aria-label-messagemenu">
<roundcube:button type="link-menuitem" command="edit" prop="new" label="editasnew" class="edit asnew disabled" classAct="edit asnew active" />
<roundcube:button type="link-menuitem" command="viewsource" label="viewsource" class="source disabled" classAct="source active" />
<roundcube:container name="messagemenu" id="message-menu" />
</ul>
</div>
<roundcube:endif />
<roundcube:add_label name="properties" />
<div id="properties-menu" class="popupmenu" role="dialog" aria-labelledby="aria-label-contentinfo">
<h3 id="aria-label-contentinfo" class="voice"><roundcube:label name="properties" /></h3>
<div class="scroller">
<roundcube:object name="messagePartControls" class="listing props-table" role="contentinfo"
aria-labelledby="aria-label-contentinfo" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,27 @@
<roundcube:include file="includes/layout.html" />
<roundcube:object name="logo" id="logo" alt="Logo" logo-type="print" logo-match="template" class="float-sm-right" />
<div class="print-content" role="main">
<div id="message-header">
<h2 class="subject">
<roundcube:object name="messageHeaders" valueOf="subject" />
</h2>
<div class="header">
<roundcube:object name="contactphoto" class="contactphoto" placeholder="/images/contactpic.svg" />
<div class="header-content details-view">
<roundcube:object name="messageHeaders" class="header-headers" addicon="virtual" exclude="subject" max="10" />
</div>
</div>
</div>
<div id="message-content">
<div role="region">
<roundcube:object name="messageAttachments" id="attachment-list" class="attachmentslist" />
</div>
<div role="region">
<roundcube:object name="messageBody" id="messagebody" headertableclass="headers-table" />
</div>
</div>
</div>
<roundcube:include file="includes/footer.html" />

15
templates/plugin.html Normal file
View File

@ -0,0 +1,15 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<roundcube:include file="includes/settings-menu.html" condition="env:task == 'settings'" />
<div id="layout-content" class="selected" role="main">
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
</div>
<roundcube:object name="plugin.body" />
</div>
<roundcube:object name="plugin.footer" />
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,13 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:object name="steptitle" /></h1>
<div class="formcontent">
<roundcube:object name="responseform" class="propform" size="60" textareacols="60" textarearows="18" />
</div>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" condition="!env:readonly" />
</div>
<roundcube:include file="includes/footer.html" />

41
templates/responses.html Normal file
View File

@ -0,0 +1,41 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<roundcube:include file="includes/settings-menu.html" />
<h1 class="voice"><roundcube:label name="responses" /></h1>
<!-- responses list -->
<div id="layout-list" class="listbox selected" aria-labelledby="aria-label-responseslist">
<div class="header">
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-responseslist" class="header-title"><roundcube:label name="responses" /></span>
<a class="button icon toolbar-menu-button" href="#list-menu"><span class="inner"><roundcube:label name="menu" /></span></a>
</div>
<div class="scroller">
<roundcube:object name="responseslist" id="responses-table" class="listing"
noheader="true" role="listbox" data-list="responses_list"
data-label-msg="listempty" data-label-ext="listusebutton" data-create-command="add" />
</div>
<div class="footer"></div>
</div>
<!-- response details frame -->
<div id="layout-content" role="main">
<h2 id="aria-label-toolbar" class="voice"><roundcube:label name="arialabeltoolbar" /></h2>
<div class="header" role="toolbar" aria-labelledby="aria-label-toolbar">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
<!-- toolbar -->
<div id="responsestoolbar" class="toolbar menu">
<roundcube:button command="add" type="link" class="create disabled" classAct="create"
label="create" title="newresponse" innerClass="inner" data-fab="true" />
<roundcube:button command="delete" type="link" class="delete disabled" classAct="delete"
label="delete" title="delete" innerClass="inner" />
</div>
</div>
<div class="iframe-wrapper">
<roundcube:object name="contentframe" id="preferences-frame" src="env:blankpage" title="arialabelresponseeditfrom" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

28
templates/settings.html Normal file
View File

@ -0,0 +1,28 @@
<roundcube:include file="includes/layout.html" />
<roundcube:include file="includes/menu.html" />
<roundcube:include file="includes/settings-menu.html" />
<h1 class="voice"><roundcube:label name="preferences" /></h1>
<div id="layout-list" class="listbox<roundcube:exp expression="!request:_action ? '' : ' selected'"/>" aria-labelledby="aria-label-prefsection">
<div class="header">
<a class="button icon back-sidebar-button" href="#sidebar"><span class="inner"><roundcube:label name="settings" /></span></a>
<span id="aria-label-prefsection" class="header-title"><roundcube:label name="preferences" /></span>
</div>
<div class="scroller">
<roundcube:object name="sectionslist" id="sections-table" class="listing iconized settings-default-icon"
noheader="true" role="listbox" data-list="sections_list" />
</div>
</div>
<div id="layout-content" role="main">
<div class="header">
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span>
</div>
<div class="iframe-wrapper">
<roundcube:object name="contentframe" id="preferences-frame" src="env:blankpage" title="arialabelpreferencesform" />
</div>
</div>
<roundcube:include file="includes/footer.html" />

View File

@ -0,0 +1,13 @@
<roundcube:include file="includes/layout.html" />
<h1 class="voice"><roundcube:object name="sectionname" /></h1>
<div class="formcontent">
<roundcube:object name="userprefs" form="form" class="propform cols-sm-6-6" />
</div>
<div class="formbuttons">
<roundcube:button command="save" class="btn btn-primary submit" label="save" />
</div>
<roundcube:include file="includes/footer.html" />

BIN
thumbnail.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

4378
ui.js Normal file

File diff suppressed because it is too large Load Diff

13
ui.min.js vendored Normal file

File diff suppressed because one or more lines are too long

39
watermark.html Normal file
View File

@ -0,0 +1,39 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
html, body { height: 100%; overflow: hidden; }
body {
background: url(https://disroot.org/user/themes/disroot/images/disroot-root.png) center no-repeat;
background-size: 30%;
background-blend-mode: luminosity;
opacity: 0.8;
}
html:not(.dark-mode) body:before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, .85);
}
html.dark-mode > body {
background-color: #21292c;
background-blend-mode: soft-light;
}
</style>
<script>
try {
if (document.cookie.indexOf('colorMode=dark') > -1
|| (document.cookie.indexOf('colorMode=light') === -1 && window.matchMedia('(prefers-color-scheme: dark)').matches)
) {
document.documentElement.className += ' dark-mode';
}
} catch (e) { }
</script>
</head>
<body></body>
</html>