Skip to content

Graphical design guide

Yannick Warnier edited this page Dec 26, 2023 · 96 revisions

Technical guide

Chamilo 2.0 (and superior) change drastically in the way it handles web design. From a relatively static and sequential (and difficult to optimize) CSS loading process in Chamilo 1.* (mostly managed by the main/inc/lib/display.lib.php::display_header() method) to relying on Vue.js, Vuetify and Tailwind for styles in Chamilo 2.0+.

Vue.js

Vue is a javascript framework meant to simplify the building of reactive interfaces. It integrates progressively (by opposition with React and other similar libraries), meaning we don't have to rely on it entirely for every bit of our interface, which suits us best as Chamilo 2.0 is not a complete rewrite of Chamilo 1, but rather a big sequential improvement.

Vue is great to have the page work as semi-independent blocks of information. With Vue, we expect load times for many elements in Chamilo to be considerably reduced, as the whole page will not be reloaded after each action when the action only affect a piece of the page.

Primevue, Vuetify and Quasar

Primevue, Vuetify and Quasar are "components libraries" on top of Vue, that provide advanced interface components that can be re-used and extended through our interface. After some hesitation (so there might remain some traces of the others in the code) we are focusing on using Primevue.

Tailwind

Where Primevue offers mechanisms to improve the management of styles through default CSS packages, Tailwind is really an advanced CSS management library that allows us to mix and match pieces of CSS into a logical (although initially very confusing) structure.

Tailwind reduces the amount of CSS you have to write and, as such, makes it more maintainable. With Tailwind, you will practically never see pure CSS in your HTML. Each CSS style piece is named in a structured (and kind of magical) way and you only call these pieces from your HTML (or in our case, from our Vuetify components, most of the time).

The loading mechanism

To understand how the styles in Chamilo are generated, we'll take a user-facing approach first and dive into how these are generated.

When loading a Chamilo 2+ page, your will essentially find 2 CSS files:

  • /build/vue.css
  • /build/css/app.css
  • /build/css/[legacy].css

The first one is just the default Vue CSS. The second one, however, is generated through a complex process which we will analyse below. The third one(s) are legacy CSS files that have not yet been properly converted or that are very specific to one Chamilo tool

app.css

app.css is generated by Encore, using a configuration file located at /webpack.config.js (around line 15). It defines (around line 30) the list of CSS files that will have to be included in any Chamilo page. That's where we find the main one:

  .addStyleEntry('css/app', './assets/css/app.scss')

This /assets/css/app.scss is a working file that includes Tailwind packages (usually base, components and utilities), then goes on top of those Tailwind elements and define additional styles (like .btn-primary which will define the style of primary buttons).

These additional styles can include pure CSS, as this is where we will customize the Chamilo stylesheet to look as we intend Chamilo to look.

If you want to modify styles in a development context (and until we provide a better mechanism), edit /assets/css/app.scss, then run yarn run encore dev to regenerate app.css, reload your browser page and... voilà!

Primevue/Vuetify

Vuetify is not "compiled" by any process on the server. Vue will detect and manage the elements declared by Vuetify, and Vuetify is simply made available through a few lines in webpack.config.js. To use Vuetify (or Quasar), simply use the Vuetify (or Quasar) components inside your .vue files.

.vue files will be defined, mainly, in /assets/vue/views/ (although some are defined in parallel folders). They define pages layouts and blocks of information that will have a style and a behaviour defined by a combination of Vuetify and Vue.

Vue

Vue "simply" offers JS features. You would have to watch the video tutorials (see https://www.vuemastery.com/courses/intro-to-vue-3/intro-to-vue3) for Vue to make sure you understand it, because it is quite the opposite of sequential backend PHP code.

Vue is included into the loader stack through /assets/vue/main.js, loaded in webpack.config.js.

Design guide

Chamilo 2.0 is the first version of Chamilo of which the design has really been worked on as a framework, as opposed to common libraries used here and there. We expect the first stable version of Chamilo 2 to still have a lot of legacy parts that will still not integrate fully due to lack of resources (aren't we all hoping for a project that finances itself lavishly?), but we have a roadmap and expect to convert every layout to this new design as soon as possible.

8 point grid layout

We decided to use an 8 point grid layout, meaning we use multiples of 8px for pretty much anything. So as you design new interfaces, you should follow these rules:

  1. Use multiples of 8px when defining measurements, spacing, and positioning elements.
  2. When necessary use 4/6/12px to make more fine tuned adjustments.
  3. Whenever possible, make sure that objects line up, both vertically and horizontally.
  4. Align your bounding box to the grid, not the baseline of your text.

Because Tailwind mostly uses "rem" as distance units, it is important to note that, in many browsers, the default for 1rem = 16px, so our base unit for an 8 point grid is actually 0.5rem.

Fonts

We use DejaVu Sans for its permissive license (see https://commons.wikimedia.org/wiki/File:DejaVu_Sans_font.svg) and for its rounded shape that blends well into the general rounded design of Chamilo 2.

Icons

All "non-legacy" icons are coming from the excellent Material Design Icons library. They are usually loaded either through a Vuetify component called <v-icon>(more), or through a legacy-hack method (so only for legacy code) called Display::getMdiIcon() (more).

We have already established a few standard uses for icons, and we believe establishing this standard list of icons here will simplify the process for designers and developers to implement new interfaces with a common look.

Classes

We have defined a few handy classes to give style to your icons, depending on context:

Class Purpose
ch-tool-icon Whenever using an icon to represent a type of object, an action or a state. This style uses the "primary" color defined in tailwind.config.js as the main icon color.
ch-tool-icon-disabled This is the same as ch-tool-icon, but when the icon represents an action or a state, and the action or state is considered disabled (for some reason), this style will ensure they appear grayed out.
ch-tool-icon-gradient Use only for bigger icons, for example on the course homepage to represent tools. This icon type uses a gradient from the primary to the primary-light color.
ch-tool-icon-button Use this style when the icon appears on top of an unstyled button. This renders an icon in the same color as the basic text (ch-text style from tailwind.config.js).

Default icons terminology

Because there are so many icons in the MDI library, and because we want to keep a certain cohesion between all parts of Chamilo (unlike in previous versions), some icons have been established to represent specific types of contents or actions. Here is a list of such icons.

The names given in the "icon name" column below are the names that will be given to Display::getMdiIcon() or, with an mdi- prefix, the names given to the <v-icon> component, in the icon attribute (e.g. <v-icon icon="mdi-pencil"/>).

First: common actions

A class exists to provide shortcuts to those icons: https://github.com/chamilo/chamilo-lms/blob/master/src/CoreBundle/Component/Utils/ActionIcon.php

You can call it through:

use Chamilo\CoreBundle\Component\Utils\ActionIcon;

The second column in the table below shows how to call the icon from your PHP code (Display::getMdiIcon(ActionIcon::[shortcut])).

Icon name Shortcut Action
plus-box ADD Add/Create a resource
pencil EDIT Edit
delete DELETE Delete
hammer-wrench CONFIGURE Configure
download DOWNLOAD Download
download-box DOWNLOAD_MULTIPLE Download multiple items
upload UPLOAD Upload
arrow-left-bold-box BACK Go back one page
account-multiple-plus SUBSCRIBE_GROUP_USERS_TO_RESOURCE Assign groups of users to some resource
cursor-move MOVE_DRAG_DROP Handle to move an element by drag & drop
chevron-left MOVE_LP_BACKWARD Move backward one page (learning paths)
chevron-right MOVE_LP_FORWARD Move forward one page (learning paths)
arrow-up-bold UP Move something up
arrow-down-bold DOWN Move something down or show some unfolded interface component
arrow-right-bold MOVE Move something (from one folder to another) or unfold some interface component
magnify-plus-outline PREVIEW_CONTENT Preview some content
archive-arrow-up IMPORT_ARCHIVE Import some kind of archive/packaged
folder-multiple-plus CREATE_CATEGORY Create a category
folder-plus CREATE_FOLDER Create a folder
alert ALERT Alert the user of something important/unexpected/undesired
checkbox-marked INFORM Inform of something completed
pencil-off EDIT_OFF Crossed pencil to show the inability to edit for the current user
eye VISIBLE Make invisible (by showing the current visible state)
eye-off INVISIBLE Make visible (by showing the current invisible state)
checkbox-multiple-blank UNPUBLISH_COURSE_TOOL Hide from course homepage (unpublish)
checkbox-multiple-blank-outline PUBLISH_COURSE_TOOL Show on course homepage
sync DISABLE_MULTIPLE_ATTEMPTS Disable multiple attempts (or show multiple attempts are currently enabled)
sync-circle ENABLE_MULTIPLE_ATTEMPTS Enable multiple attempts (or show multiple attempts are currently disabled)
fullscreen SET_DISPLAY_MODE_1 Display mode 1
fullscreen-exit SET_DISPLAY_MODE_2 Display mode 2
overscan SET_DISPLAY_MODE_3 Display mode 3
play-box-outline SET_DISPLAY_MODE_4 Display mode 4
fit-to-screen EXIT_FULLSCREEN Equivalent to fullscreen-exit?
bug-check ENABLE_DEBUG Enable debug
bug-outline DISABLE_DEBUG Disable debug
archive-arrow-down EXPORT_ARCHIVE Export in some type of archive/package
text-box-plus COPY_CONTENT Copy content
rocket-launch AUTOLAUNCH Enable/Disable auto-launch of some content
file-pdf-box EXPORT_PDF Export to PDF
file-delimited-outline EXPORT_CSV CSV export
microsoft-excel EXPORT_SPREADSHEET Spreadsheet export
microsoft-word EXPORT_DOC Document export
content-save SAVE_FORM Save the current form
send SEND_MESSAGE Send a message
paperclip-plus ADD_ATTACHMENT Add an attachment
dots-vertical VERTICAL_DOTS Three vertical dots to indicate the possibility to extend a menu/set of options
information INFORMATION Information icon - Get more info
account-key LOGIN_AS Login as
cloud-download TAKE_BACKUP Take backup
cloud-upload RESTORE_BACKUP Restore backup
printer PRINT Print
fast-forward-outline VIEW_DETAILS See details/View details
broom RESET Clean/Reset
music-note-plus ADD_AUDIO Add audio
arrow-collapse-all COLLAPSE Collapse/Contract
arrow-expand-all EXPAND Expand
checkbox-marked-circle-plus-outline GRADE Give grades to work/learner
lock LOCK Lock
lock-open-variant UNLOCK Unlock
file-document-refresh REFRESH Refresh/Reload some resource
account-plus ADD_USER Add a user
format-color-fill FILL Fill (group with members, etc)

Second: Tools

These are the tools usually found on the course homepage. These are managed mostly through classes here: https://github.com/chamilo/chamilo-lms/tree/master/src/CoreBundle/Tool, so this list is relatively useless for development purposes (just instanciate the class and call $this->getIcon()).

A class exists to provide shortcuts to those icons: https://github.com/chamilo/chamilo-lms/blob/master/src/CoreBundle/Component/Utils/ToolIcon.php

You can call it through:

use Chamilo\CoreBundle\Component\Utils\ToolIcon;

The second column in the table below shows how to call the icon from your PHP code (Display::getMdiIcon(ToolIcon::[shortcut])).

Icon name Shortcut Tool
calendar-text AGENDA Agenda
bullhorn ANNOUNCEMENT Announcement
inbox-full ASSIGNMENT Assignment/Work/Student publication
av-timer ATTENDANCE Attendance
chat-processing CHAT Chat
apple-safari COURSE_DESCRIPTION Course description
home COURSE_HOME Course homepage
progress-star COURSE_PROGRESS Course progress/Thematic advance
progress-check COURSE_PROGRESS_PLAN Course progress' lesson plan
progress-clock COURSE_PROGRESS_SCHEDULE Course progress' lesson plan schedule
book-open-page-variant COURSE Course tool
bookshelf DOCUMENT Documents
order-bool-ascending-variant QUIZ Exercise/Test
comment-quote FORUM Forum
alphabetical GLOSSARY Glossary
certificate GRADEBOOK Gradebook
account-group GROUP Group
map-marker-path LP Learning path
file-link LINK Link
wrench-cog MAINTENANCE Maintenance
account MEMBER Member (was: Users)
book-alphabet Mobidico (extension)
note NOTEBOOK Notebook
cog SETTINGS Settings
flash-outline SHORTCUT Shortcut
form-dropdown SURVEY Survey
image-text INTRO Tool intro
chart-box TRACKING Tracking/Reporting
video VIDEOCONFERENCE Videoconference
view-dashboard-edit WIKI Wiki
security SECURITY Security-related settings, security section

Third: Objects

These can be used anywhere in the interface (menu, course homepage to represent tools, table of contents of learning paths, action bars, etc). Although many of the "objects" replicate "tools", a forum tool has many threads and posts within, so the same icon that represents the forum tool (which inherently might contain many forums/fora) will not necessarily be the same as one forum object.

A class exists to provide shortcuts to those icons: https://github.com/chamilo/chamilo-lms/blob/master/src/CoreBundle/Component/Utils/ObjectIcon.php

You can call it through:

use Chamilo\CoreBundle\Component\Utils\ObjectIcon;

The second column in the table below shows how to call the icon from your PHP code (Display::getMdiIcon(ObjectIcon::[shortcut])).

Icon name Shortcut Object type/Resource
bookshelf DOCUMENT Documents
order-bool-ascending-variant TEST Tests
file-link LINK Links
inbox-full ASSIGNMENT Assignments
comment-quote FORUM Forums
format-quote-open-outline FORUM_THREAD Forum thread
format-quote-open FORUM_POST Forum post
bookmark-multiple CHAPTER Chapter (e.g. in learning paths) / folder type (as opposed to document type)
certificate CERTIFICATE Gradebooks/Certificates
chart-box REPORT Tracking/Reporting/Statistics alternative
graph PREREQUISITE Prerequisites (e.g. in learning paths)
map-marker-path LP Learning paths
file-powerpoint PPT PowerPoint/Impress type document
pdf PDF PDF format
star STAR Indicator that the resource belongs to a specific session, or is an admin user
home HOME Homepage
book-open-page-variant COURSE Courses
google-classroom SESSION Sessions (not yet final choice of icon)
calendar-text AGENDA Calendar/Agenda
calendar-month AGENDA_EVENT Calendar event
account-multiple USER_LIST List of users
cogs ADMIN_SETTINGS Admin settings
cog SETTINGS Normal settings
bullhorn ANNOUNCEMENT Announcements
av-timer ATTENDANCE Attendances
apple-safari DESCRIPTION Course description
progress-upload COURSE_PROGRESS Course progress
alphabetical GLOSSARY Glossary
account-group GROUP Groups
account USER User account/Users tool
human-male-board TEACHER Teacher
form-dropdown SURVEY Survey
calendar-multiselect SURVEY_DOODLE Doodle-type survey
incognito ANONYMOUS Anonymous user/Make anonymous
video VIDEOCONFERENCE Videoconference
book-alphabet DICTIONARY Dictionary
shield-star BADGE Badges
file-tree-outline CATEGORY Categories (of anything)
package-variant-closed RESOURCE Resource (in the large sense, usually an object or set of objects that do not qualify as an existing object)
music-note AUDIO Audio file
paperclip ATTACHMENT Attachment
note-outline SINGLE_ELEMENT Single element (single squared white sheet as opposed to multiple)
note-multiple-outline MULTI_ELEMENT Multiple element (two squared white sheets as opposed to single one)

Fourth: States/Events/Alerts

States represent states of objects, visibilities, etc. This should not be used for buttons (actions) but for display (expressing the current state).

A class exists to provide shortcuts to those icons: https://github.com/chamilo/chamilo-lms/blob/master/src/CoreBundle/Component/Utils/StateIcon.php

You can call it through:

use Chamilo\CoreBundle\Component\Utils\StateIcon;

The second column in the table below shows how to call the icon from your PHP code (Display::getMdiIcon(StateIcon::[shortcut])).

Icon name Shortcut Object state
eye PUBLIC_VISIBILITY Public (used for courses visibility)
eye-outline OPEN_VISIBILITY Open (used for courses visibility)
eye-off PRIVATE_VISIBILITY Private (used for courses visibility) / Invisible resource
eye-off-outline CLOSED_VISIBILITY Closed (used for courses visibility)
eye-closed HIDDEN_VISIBILITY Hidden (used for courses visibility)
toggle-switch ACTIVE Active
toggle-switch-off INACTIVE Inactive
timer-alert-outline EXPIRED Expired (used for user accounts automatically expired)
alert-circle ERROR Error
alert WARNING Warning
check-circle COMPLETE Complete/Success
close-circle INCOMPLETE Incomplete/Failure
email-alert MAIL_NOTIFICATION Notification/Alert by mail

Fifth: Presentation styles

View types for list of items.

Icon name View type
percent-box Percentage
format-list-text List of items

Converting legacy icons to material design icons

While converting Chamilo to use the new icons, there are 3 cases to take into account:

As a standard img tag in a Twig template

Convert

<img src="{{ 'edit.png'|icon(22) }}"/>

to

{{ 'pencil'|mdi_icon(22) }}

In an editor, you can use the following replace formula (with regexp enabled) to alliviate a little of the pain converting one syntax to the other:

Search: \<img src="\{\{\s*'(.*?)\.png'|icon\(22\)\s*\}\}"\/\>
Replace: {{ '$1'|mdi_icon(22) }}

You will still have to adapt to icon size and the real icon name in MDI, but at least it saves you from editing the lines one by one.

Template + Font Awesome to MDI

Convert

<a href="{{ something }}" class="btn ...">
  <i class="fa fa-plus" aria-hidden="true"></i>
</a>

to

<a href="{{ something }}" class="btn ...">
  {{ 'plus'|mdi_icon(64) }}
</a>

Search and replace syntax:

Search: \<i class="fa fa-(.*?)"(\s*aria-hidden="true")?\s*\>\<\/i\>
Replace: {{ '$1'|mdi_icon(22) }}
Inside PHP code, part of a link
Display::url(Display::return_icon('teacher_na.png', get_lang('Trainer view'), [], ICON_SIZE_MEDIUM), '#');

to

Display::url(Display::return_icon('human-male-board', 'ch-tool-icon-disabled', null, ICON_SIZE_MEDIUM, get_lang('Trainer view')),'#');

For action icons, a "translator" class is available to use a similar taxonomy to the one used in Chamilo 1.11 for the icon names: https://github.com/chamilo/chamilo-lms/blob/master/src/CoreBundle/Component/Utils/ActionIcon.php

Search and replace syntax:

Search: Display::return_icon\(\s*'(.*?)\.png',\s*(get_lang\(.*?\)?)(,\s*(.*?),\s*(.*?)\s*)?\)
Replace: Display::getMdiIcon('$1', 'ch-tool-icon', null, ICON_SIZE_MEDIUM, $2)

Notes: 1- make sure you vary the size depending on whether it's originally ICON_SIZE_SMALL(22) or ICON_SIZE_MEDIUM(32) 2- if the icon includes "_na", this usually means the icon must be in "disabled" mode, which translates in Chamilo to 'ch-tool-icon-disabled' (see the "Classes" section above)

Clone this wiki locally