Skip to content

Commit

Permalink
Add new dashboard customization page (#137)
Browse files Browse the repository at this point in the history
* Add new dashboard customization page

* Fix typos
  • Loading branch information
yanthomasdev authored Apr 24, 2024
1 parent 12c6c80 commit 64630d8
Show file tree
Hide file tree
Showing 3 changed files with 369 additions and 8 deletions.
11 changes: 8 additions & 3 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,15 @@ export default defineConfig({
},
],
},
/*{
{
label: 'Guides',
autogenerate: { directory: 'guides' },
},*/
items: [
{
label: "Dashboard Customization",
link: "guides/dashboard-customization"
}
],
},
{
label: 'Tools',
autogenerate: { directory: 'tools' },
Expand Down
358 changes: 357 additions & 1 deletion docs/src/content/docs/guides/dashboard-customization.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,360 @@ title: Dashboard Customization
description: Learn how to make your dashboard unique, with your own styles, structure, and more.
---

TODO.
import { Steps, FileTree } from '@astrojs/starlight/components';

Lunaria provides several ways to customize your localization dashboard to better fit your project's look and feel. Follow this guide to understand all the available customization options.

## Title and description

By default, Lunaria will add a default title and description for your dashboard. You can change it to make it easy to identify and find your project's dashboard through search engines.

<Steps>
1. Add the [`dashboard.title`](/reference/configuration/#dashboardtitle) option to your Lunaria config. The defined title will also be shown in the dashboard's heading:

```json title="lunaria.config.json" add={2-4}
{
"dashboard": {
"title": "Lunaria Localization Status"
}
}
```

2. Add the [`dashboard.description`](/reference/configuration/#dashboarddescription) option to your Lunaria config:

```json title="lunaria.config.json" add={4}
{
"dashboard": {
"title": "Lunaria Localization Status",
"description": "Localization status dashboard for the Lunaria project."
}
}
```
</Steps>

## Canonical URL

If you desire to publicize different versions of your dashboard (e.g. localized versions of the dashboard itself), it might be helpful to set a [canonical URL](https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls#rel-canonical-link-method) to optimize your dashboard's ranking on search engines.

To add a canonical URL, you can set [`dashboard.site`](/reference/configuration/#dashboardsite) in your Lunaria configuration file:

```json title="lunaria.config.json" add={3}
{
"dashboard": {
"site": "https://localization.lunaria.dev/"
}
}
```

## Favicons

Setting a favicon can help match your project's feel and make it easier to identify your dashboard in the user's web browser. Lunaria allows you to define both multiple external and one inline favicon.

To add a favicon, you have to set [`dashboard.favicon`](/reference/configuration/#dashboardfavicon) in your Lunaria configuration, with one of, or both the `external` or `inline` properties.

:::note[Why should I have multiple favicons?]
Currently, [not all browsers support SVG favicons](https://caniuse.com/link-icon-svg), therefore having a fallback favicon (generally a `.ico` icon) is a good way to ensure most users will be able to see an icon when they open the website.
:::

### External favicons

External favicons are favicons you load through another URL as a resource. You can add them in the `external` property of [`dashboard.favicon`](/reference/configuration/#dashboardfavicon). The example below adds both `.svg` and `.ico` favicons.

```json title="lunaria.config.json" add={4-13}
{
"dashboard": {
"favicon": {
"external": [
{
"link": "https://lunaria.dev/favicon.svg",
"type": "image/svg+xml"
},
{
"link": "https://lunaria.dev/favicon.ico",
"type": "image/x-icon"
},
]
}
}
}
```

### Inline favicon

An inline favicon is a local [`.svg` favicon appended to your dashboard through a Data URI](https://css-tricks.com/lodge/svg/09-svg-data-uris/). You can add one through the `inline` property of [`dashboard.favicon`](/reference/configuration/#dashboardfavicon).

<Steps>
1. Add your favicon SVG file to a directory in your project (e.g. `src/assets/`):

<FileTree>
- src/
- assets/
- **favicon.svg**
- lunaria.config.json
</FileTree>

2. Add the path to your favicon as the `inline` property of [`dashboard.favicon`](/reference/configuration/#dashboardfavicon) in your Lunaria config:

```json title="lunaria.config.json" add={4}
{
"dashboard": {
"favicon": {
"inline": "./src/assets/favicon.svg"
}
}
}
```
</Steps>

## Hidden path bases

The dashboard contains several paths as links to your source and localized content. These can be quite lengthy depending on how far they are from your project's root directory. For example, if the unique part of your content files' paths starts only after `src/content/docs/`, you might want to hide this portion of the path and only show what's relevant, e.g. `guides/my-content.mdx`.

To do so, you can set the [`dashboard.basesToHide`](/reference/configuration/#dashboardbasestohide) option in your Lunaria config with all the desired path bases to hide. This example assumes you're tracking content files that start at `src/content/docs/` or `src/i18n/`:

```json title="lunaria.config.json" add={3}
{
"dashboard": {
"basesToHide": ["src/content/docs/", "src/i18n/"]
}
}
```

With this, references to paths like `src/content/docs/guide.mdx` and `src/i18n/dictionary.ts` will be shortened to their unique parts, namely `guide.mdx` and `dictionary.ts`.


## Custom CSS

The dashboard can be further customized by adding your own custom CSS, allowing you to modify or extend the default styles provided by Lunaria out of the box.

<Steps>
1. Add a CSS file to a directory in your project (e.g. `src/styles/`). For example, you can change the default body font family used:

```css title="src/styles/lunaria.css"
:root {
--ln-font-body: Tahoma, sans-serif;
}
```

2. Add the path to your CSS file to your Lunaria config's [`dashboard.customCss`](/reference/configuration/#dashboardcustomcss) array property:

```json title="lunaria.config.json" add={3}
{
"dashboard": {
"customCss": ["./src/styles/lunaria.css"]
}
}
```
</Steps>

:::tip
Check out the Lunaria repository to see [all the available CSS custom properties set by Lunaria and its implementation](https://github.com/yanthomasdev/lunaria/blob/main/packages/core/src/dashboard/styles.ts).
:::

## Custom labels and language

By default, Lunaria's dashboard comes with UI labels written in English. These UI labels can be completely changed, be it simple text labels, language values, or dynamic sentences (e.g. "X done, X outdated, X missing").

### Text labels

For example, you can change the default message shown when a locale's localization is 100% complete by changing the `statusByLocale.completeLocalization` property of [`dashboard.ui`](/reference/configuration/#dashboardui):

```json title="lunaria.config.json" add={4}
{
"dashboard": {
"ui": {
"statusByLocale.completeLocalization": "No missing or outdated changes found, congratulations!"
}
}
}
```

:::tip
Check the reference section about [`dashboard.ui`](/reference/configuration/#dashboardui) for a complete list of the available properties and their default values.
:::

### Format labels

Some labels, suffixed with `Format` in their name, come with named `{}` blocks that are going to be dynamically replaced with values from other UI labels or from the internal context, for example:

```json
"statusByLocale.detailsTitleFormat": "{locale_name} ({locale_tag})",
```

These can also be changed, though it is highly recommended to not remove any of the `{}` blocks present by default, as that would mean possibly not inserting a dynamic value that was expected.

For example, you could modify your dashboard to show the language details' summary from the format `Deutsch (de)` to `Deutsch - de` by making a small change in the default `statusByLocale.detailsTitleFormat` value:

```json title="lunaria.config.json" add={4}
{
"dashboard": {
"ui": {
"statusByLocale.detailsTitleFormat": "{locale_name} - {locale_tag}",
}
}
}
```

### `lang` and `dir`

Since all labels can be changed, there is no imposition from completely translating the dashboard to another language. To make this even easier, [`dashboard.ui`](/reference/configuration/#dashboardui) exposes the `lang` and `dir` properties, which directly translates to the HTML [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/lang) and [`dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir) attributes used in your dashboard.

For example, that's how you could go about changing your dashboard's language to Brazilian Portuguese (most properties have been omitted from this example for simplicity's sake):

```json title="lunaria.config.json" add={4-6}
{
"dashboard": {
"ui": {
"lang": "pt-BR",
"statusByFile.heading": "Estado da localização por arquivo",
"statusByFile.tableRowFile": "Arquivo",
}
}
}
```

## Custom UI elements

Lunaria's dashboard was designed to be flexible and easily customizable through [custom CSS](#custom-css) and the available [configuration options](/reference/configuration/#dashboard-options). When that's not enough, Lunaria allows you to extend and override your dashboard's UI using its [Renderer API](/reference/renderer/).

<Steps>
1. Add a new `renderer.config.ts` or `renderer.config.js` file to your project with the following content:

```ts title="renderer.config.ts"
import { defineRendererConfig } from '@lunariajs/core';

export default defineRendererConfig({
// options will go here...
});
```

2. Add the path to your renderer file to your Lunaria config's [`renderer`](/reference/configuration/#renderer) configuration property:

```json title="lunaria.config.json" add={2}
{
"renderer": "./renderer.config.ts"
}
```
</Steps>

### Custom components

All UI elements in Lunaria are built without the use of frameworks, using only the good ol' HTML. To improve the authoring experience, Lunaria comes with a built-in `html` tagged template to help you build your own components.

:::tip[Syntax highlighting]
You can get syntax highlighting and language support inside `html` using the [`lit-html` VSCode extension](https://marketplace.visualstudio.com/items?itemName=bierner.lit-html) or the [`vim-jsx-pretty` plugin for Vim](https://github.com/MaxMEllon/vim-jsx-pretty).
:::

A component in Lunaria is a function that receives a few parameters and returns a string of HTML:

```ts title="example-component.ts"
import { html } from '@lunariajs/core';

const CustomParagraph = () => html`<p>This is my custom paragraph component!</p>`;
```
Since these components are [template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals), you can interpolate values using the `${}` notation as you normally would in JavaScript:
```ts title="interpolating-value.ts"
import { html } from '@lunariajs/core';

const favoriteColor = "red";

const ColorComponent = () => html`<p>My favorite color is ${favoriteColor}!</p>`.
```
<details>
<summary>See the resulting HTML</summary>
```html
<p>My favorite color is red!</p>
```
</details>
You can also interpolate over lists of values (e.g. arrays) using the `.map()` method:
```ts title="interpolating-list.ts"
import { html } from '@lunariajs/core';

const catColors = ["grey", "white", "black", "orange", "buff"];

const CatColorsList = () => html`<ul>${catColors.map((catColor) => html`<li>${catColor}</li>`)}</ul>`
```
<details>
<summary>See the resulting HTML</summary>
```html
<ul>
<li>grey</li>
<li>white</li>
<li>black</li>
<li>orange</li>
<li>buff</li>
</ul>
```
</details>
:::caution
Lunaria's `html` tagged template does not sanitize HTML input. Be sure to only interpolate trusted values in your components or use a package like [`sanitize-html`](https://www.npmjs.com/package/sanitize-html) to do it safely.
:::
### Slotting elements
Elements can be slotted into the dashboard with the [renderer's `slots` property](/reference/renderer/#slots). All components will be passed a copy of your Lunaria configuration you can use to get values from:
<Steps>
1. Create a new component using the `html` tagged template. In this case, a `"robots"` [meta tag](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta) with the `"noindex"` content to avoid indexing the dashboard in search engines:
```ts title="renderer.config.ts" add={3}
import { defineRendererConfig, html } from '@lunariajs/core';

const NoIndex = () => html`<meta name="robots" content="noindex" />`;

export default defineRendererConfig({});
```
2. Add the created component to one of the available slots in the [`slots` property](/reference/renderer/#slots). Here, the `head` slot will be used to insert the component into the dashboard's [`<head>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/head):
```ts title="renderer.config.ts" add={6-8}
import { defineRendererConfig, html } from '@lunariajs/core';

const NoIndex = () => html`<meta name="robots" content="noindex" />`;

export default defineRendererConfig({
slots: {
head: NoIndex,
}
});
```
</Steps>
### Overriding elements
Elements can also be overridden in the dashboard with the [renderer's `overrides` property](/reference/renderer/#overrides). All components added to `overrides` will be passed a copy of your Lunaria configuration, as well as the generated Lunaria status (except for the `meta` property) you can use to get values from:
<Steps>
1. Create a new component using the `html` tagged template. In this case, the component will override the dashboard's body and show the `sharedPath` for each localized content:
```ts title="renderer.config.ts" add={3}
import { defineRendererConfig, html } from '@lunariajs/core';

const NewBody = (config, status) => html`<ul>${status.map((s) => html`<li>${s.sharedPath}</li>`)}</ul>`;

export default defineRendererConfig({});
```
2. Add the created component to one of the available overrides in the [`overrides` property](/reference/renderer/#overrides). Here, the `body` slot will be used to insert the component and override everything inside the dashboard's [`<body>` element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/body):
```ts title="renderer.config.ts" add={6-8}
import { defineRendererConfig, html } from '@lunariajs/core';

const NewBody = (config, status) => html`<ul>${status.map((s) => html`<li>${s.sharedPath}</li>`)}</ul>`;

export default defineRendererConfig({
overrides: {
body: NewBody,
}
});
```
</Steps>
8 changes: 4 additions & 4 deletions docs/src/content/docs/manual-installation.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ Then, add the following `lunaria` commands as part of your `package.json`'s `scr

```json title="package.json" ins={5}
"scripts": {
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"lunaria:build": "lunaria build",
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"lunaria:build": "lunaria build",
"lunaria:preview": "lunaria preview",
}
```
Expand Down

0 comments on commit 64630d8

Please sign in to comment.