mirror of
https://github.com/penpot/penpot.git
synced 2025-05-22 10:06:11 +02:00
Merge pull request #4851 from penpot/eva-add-heading-component-to-storybook
✨ Add heading component to storybook
This commit is contained in:
commit
6e55260160
14 changed files with 634 additions and 36 deletions
|
@ -14,9 +14,11 @@
|
||||||
url($filepath + ".ttf") format("truetype");
|
url($filepath + ".ttf") format("truetype");
|
||||||
font-weight: unquote($weight);
|
font-weight: unquote($weight);
|
||||||
font-style: unquote($style);
|
font-style: unquote($style);
|
||||||
|
@if $unicode-range {
|
||||||
unicode-range: $unicode-range;
|
unicode-range: $unicode-range;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@mixin font-face-variable($style-name, $file, $unicode-range) {
|
@mixin font-face-variable($style-name, $file, $unicode-range) {
|
||||||
$filepath: "/fonts/" + $file;
|
$filepath: "/fonts/" + $file;
|
||||||
|
@ -35,18 +37,18 @@ $_latin-unicode-list: "U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+
|
||||||
@include font-face-variable("vazirmatn", "Vazirmatn-VariableFont", $_arabic-unicode-list);
|
@include font-face-variable("vazirmatn", "Vazirmatn-VariableFont", $_arabic-unicode-list);
|
||||||
|
|
||||||
// Source Sans Pro
|
// Source Sans Pro
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-extralight", $_latin-unicode-list, "200");
|
@include font-face("sourcesanspro", "sourcesanspro-extralight", "200");
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-extralightitalic", $_latin-unicode-list, "200", italic);
|
@include font-face("sourcesanspro", "sourcesanspro-extralightitalic", "200", italic);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-light", $_latin-unicode-list, "300");
|
@include font-face("sourcesanspro", "sourcesanspro-light", "300");
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-lightitalic", $_latin-unicode-list, "300", italic);
|
@include font-face("sourcesanspro", "sourcesanspro-lightitalic", "300", italic);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-regular", $_latin-unicode-list, normal);
|
@include font-face("sourcesanspro", "sourcesanspro-regular", normal);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-italic", $_latin-unicode-list, normal, italic);
|
@include font-face("sourcesanspro", "sourcesanspro-italic", normal, italic);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-semibold", $_latin-unicode-list, "600");
|
@include font-face("sourcesanspro", "sourcesanspro-semibold", "600");
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-semibolditalic", $_latin-unicode-list, "600", italic);
|
@include font-face("sourcesanspro", "sourcesanspro-semibolditalic", "600", italic);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-bold", $_latin-unicode-list, bold);
|
@include font-face("sourcesanspro", "sourcesanspro-bold", bold);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-bolditalic", $_latin-unicode-list, bold, italic);
|
@include font-face("sourcesanspro", "sourcesanspro-bolditalic", bold, italic);
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-black", $_latin-unicode-list, "900");
|
@include font-face("sourcesanspro", "sourcesanspro-black", "900");
|
||||||
@include font-face("sourcesanspro", "sourcesanspro-blackitalic", $_latin-unicode-list, "900", italic);
|
@include font-face("sourcesanspro", "sourcesanspro-blackitalic", "900", italic);
|
||||||
|
|
||||||
// Roboto mono
|
// Roboto mono
|
||||||
@include font-face("robotomono", "RobotoMono-Regular", $_latin-unicode-list, normal);
|
@include font-face("robotomono", "RobotoMono-Regular", $_latin-unicode-list, normal);
|
||||||
|
|
|
@ -6,17 +6,25 @@
|
||||||
|
|
||||||
(ns app.main.ui.ds
|
(ns app.main.ui.ds
|
||||||
(:require
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.heading :refer [heading*]]
|
||||||
[app.main.ui.ds.foundations.icon :refer [icon* icon-list]]
|
[app.main.ui.ds.foundations.icon :refer [icon* icon-list]]
|
||||||
[app.main.ui.ds.foundations.raw-svg :refer [raw-svg* raw-svg-list]]
|
[app.main.ui.ds.foundations.raw-svg :refer [raw-svg* raw-svg-list]]
|
||||||
|
[app.main.ui.ds.foundations.text :refer [text*]]
|
||||||
|
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
||||||
[app.main.ui.ds.storybook :as sb]))
|
[app.main.ui.ds.storybook :as sb]))
|
||||||
|
|
||||||
(def default
|
(def default
|
||||||
"A export used for storybook"
|
"A export used for storybook"
|
||||||
#js {:Icon icon*
|
#js {:Heading heading*
|
||||||
|
:Icon icon*
|
||||||
:RawSvg raw-svg*
|
:RawSvg raw-svg*
|
||||||
|
:Text text*
|
||||||
;; meta / misc
|
;; meta / misc
|
||||||
:meta #js {:icons icon-list :svgs raw-svg-list}
|
:meta #js {:icons icon-list
|
||||||
|
:svgs raw-svg-list
|
||||||
|
:typography (clj->js typography-list)}
|
||||||
:storybook #js {:StoryGrid sb/story-grid*
|
:storybook #js {:StoryGrid sb/story-grid*
|
||||||
:StoryGridCell sb/story-grid-cell*
|
:StoryGridCell sb/story-grid-cell*
|
||||||
|
:StoryGridRow sb/story-grid-row*
|
||||||
:StoryHeader sb/story-header*
|
:StoryHeader sb/story-header*
|
||||||
:StoryWrapper sb/story-wrapper*}})
|
:StoryWrapper sb/story-wrapper*}})
|
||||||
|
|
47
frontend/src/app/main/ui/ds/foundations/heading.cljs
Normal file
47
frontend/src/app/main/ui/ds/foundations/heading.cljs
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.ds.foundations.heading
|
||||||
|
(:require-macros
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(defn- valid-level? [value]
|
||||||
|
(let [number-set #{"1" "2" "3" "4" "5" "6"}]
|
||||||
|
(contains? number-set (dm/str value))))
|
||||||
|
|
||||||
|
(defn- valid-typography? [value]
|
||||||
|
(contains? typography-list value))
|
||||||
|
|
||||||
|
(mf/defc heading*
|
||||||
|
{::mf/props :obj}
|
||||||
|
[{:keys [level typography class children] :rest props}]
|
||||||
|
(assert (or (valid-level? level)
|
||||||
|
(nil? level))
|
||||||
|
(dm/str "Invalid level: " level ". Valid numbers are 1 to 6."))
|
||||||
|
|
||||||
|
(assert (valid-typography? (dm/str typography))
|
||||||
|
(dm/str typography " is an unknown typography"))
|
||||||
|
|
||||||
|
(let [level (or level "1")
|
||||||
|
tag (dm/str "h" level)
|
||||||
|
class (dm/str (or class "") " " (stl/css-case :display-typography (= typography "display")
|
||||||
|
:title-large-typography (= typography "title-large")
|
||||||
|
:title-medium-typography (= typography "title-medium")
|
||||||
|
:title-small-typography (= typography "title-small")
|
||||||
|
:headline-large-typography (= typography "headline-large")
|
||||||
|
:headline-medium-typography (= typography "headline-medium")
|
||||||
|
:headline-small-typography (= typography "headline-small")
|
||||||
|
:body-large-typography (= typography "body-large")
|
||||||
|
:body-medium-typography (= typography "body-medium")
|
||||||
|
:body-small-typography (= typography "body-small")
|
||||||
|
:code-font-typography (= typography "code-font")))
|
||||||
|
props (mf/spread-props props {:class class})]
|
||||||
|
[:> tag props
|
||||||
|
children]))
|
49
frontend/src/app/main/ui/ds/foundations/heading.mdx
Normal file
49
frontend/src/app/main/ui/ds/foundations/heading.mdx
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import { Canvas, Meta } from "@storybook/blocks";
|
||||||
|
import * as HeadingStories from "./heading.stories";
|
||||||
|
|
||||||
|
<Meta of={HeadingStories} />
|
||||||
|
|
||||||
|
# Headings
|
||||||
|
|
||||||
|
This component will add a heading tag element to our code.
|
||||||
|
|
||||||
|
## Technical notes
|
||||||
|
|
||||||
|
This components accepts to props:
|
||||||
|
|
||||||
|
- `level` (default value: `1`) : A number from `1` to `6`, to set the heading level (i.e. `<h1>`, `<h2>`, etc.).
|
||||||
|
- `typography` (mandatory): Any of the [supported typography IDs](?path=/docs/foundations-typography--docs).
|
||||||
|
|
||||||
|
You can check passed props to renderized components on hover `level / typography`;
|
||||||
|
|
||||||
|
|
||||||
|
### Using typography IDs
|
||||||
|
|
||||||
|
There are typography ID definitions you can use in your code rather than typing the
|
||||||
|
typography ID by hand.
|
||||||
|
|
||||||
|
**Using these IDs is recommended**.
|
||||||
|
|
||||||
|
Assuming the namespace of the typography is required as `t`:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(ns app.main.ui.foo
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.heading :refer [heading*]]
|
||||||
|
[app.main.ui.ds.foundations.typography :as t]))
|
||||||
|
```
|
||||||
|
|
||||||
|
You can now use the typography IDs defined in the namespace:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
[:> heading* {:typography t/title-large} "Welcome to Penpot"]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Accesibility
|
||||||
|
|
||||||
|
There should only be one level 1 heading `<h1>` per page.
|
||||||
|
|
||||||
|
Headings are used to navigate the page and must follow the `<h1>` → `<h2>` → `<h3>` → `<h4>` → `<h5>` → `<h6>` hierarchy.
|
||||||
|
For example, do not skip levels in the `<h1>` → `<h3>` hierarchy if there is no `<h2>` in between.
|
||||||
|
|
||||||
|
We should not choose the heading level by its visual aspect.
|
50
frontend/src/app/main/ui/ds/foundations/heading.scss
Normal file
50
frontend/src/app/main/ui/ds/foundations/heading.scss
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
@use "../typography.scss" as t;
|
||||||
|
|
||||||
|
.display-typography {
|
||||||
|
@include t.use-typography("display");
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-large-typography {
|
||||||
|
@include t.use-typography("title-large");
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-medium-typography {
|
||||||
|
@include t.use-typography("title-medium");
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-small-typography {
|
||||||
|
@include t.use-typography("title-small");
|
||||||
|
}
|
||||||
|
|
||||||
|
.headline-large-typography {
|
||||||
|
@include t.use-typography("headline-large");
|
||||||
|
}
|
||||||
|
|
||||||
|
.headline-medium-typography {
|
||||||
|
@include t.use-typography("headline-medium");
|
||||||
|
}
|
||||||
|
|
||||||
|
.headline-small-typography {
|
||||||
|
@include t.use-typography("headline-small");
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-large-typography {
|
||||||
|
@include t.use-typography("body-large");
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-medium-typography {
|
||||||
|
@include t.use-typography("body-medium");
|
||||||
|
}
|
||||||
|
|
||||||
|
.body-small-typography {
|
||||||
|
@include t.use-typography("body-small");
|
||||||
|
}
|
||||||
|
|
||||||
|
.code-font-typography {
|
||||||
|
@include t.use-typography("code-font");
|
||||||
|
}
|
54
frontend/src/app/main/ui/ds/foundations/heading.stories.jsx
Normal file
54
frontend/src/app/main/ui/ds/foundations/heading.stories.jsx
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
const { Heading } = Components;
|
||||||
|
const { StoryWrapper, StoryGridRow } = Components.storybook;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Foundations/Heading",
|
||||||
|
component: Components.Heading,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Levels = {
|
||||||
|
render: () => (
|
||||||
|
<StoryWrapper theme="default">
|
||||||
|
<StoryGridRow title={"1 / display"}>
|
||||||
|
<Heading level="1" typography="display">
|
||||||
|
h1 / display
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
<StoryGridRow title={"2 / display"}>
|
||||||
|
<Heading level="2" typography="display">
|
||||||
|
h2 / display
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
<StoryGridRow title={"3 / display"}>
|
||||||
|
<Heading level="3" typography="display">
|
||||||
|
h3 / display
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
</StoryWrapper>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HeadingTypography = {
|
||||||
|
render: () => (
|
||||||
|
<StoryWrapper theme="default">
|
||||||
|
<StoryGridRow title={"1 / title-large"}>
|
||||||
|
<Heading level="1" typography="title-large">
|
||||||
|
h1 / title-large
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
<StoryGridRow title={"1 / title-medium"}>
|
||||||
|
<Heading level="1" typography="title-medium">
|
||||||
|
h1 / title-medium
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
<StoryGridRow title={"1 / code-font"}>
|
||||||
|
<Heading level="1" typography="code-font">
|
||||||
|
h1 / code-font
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
</StoryWrapper>
|
||||||
|
),
|
||||||
|
};
|
|
@ -1,3 +1,9 @@
|
||||||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
//
|
||||||
|
// Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
fill: none;
|
fill: none;
|
||||||
stroke: currentColor;
|
stroke: currentColor;
|
||||||
|
|
37
frontend/src/app/main/ui/ds/foundations/text.cljs
Normal file
37
frontend/src/app/main/ui/ds/foundations/text.cljs
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.ds.foundations.text
|
||||||
|
(:require-macros
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
|
[app.main.style :as stl])
|
||||||
|
(:require
|
||||||
|
[app.main.ui.ds.foundations.typography :refer [typography-list]]
|
||||||
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(defn- valid-typography? [value]
|
||||||
|
(contains? typography-list value))
|
||||||
|
|
||||||
|
(mf/defc text*
|
||||||
|
{::mf/props :obj}
|
||||||
|
[{:keys [tag typography children] :rest props}]
|
||||||
|
|
||||||
|
(assert (valid-typography? (dm/str typography))
|
||||||
|
(dm/str typography " is an unknown typography"))
|
||||||
|
|
||||||
|
(let [props (mf/spread-props props {:class (stl/css-case :display-typography (= typography "display")
|
||||||
|
:title-large-typography (= typography "title-large")
|
||||||
|
:title-medium-typography (= typography "title-medium")
|
||||||
|
:title-small-typography (= typography "title-small")
|
||||||
|
:headline-large-typography (= typography "headline-large")
|
||||||
|
:headline-medium-typography (= typography "headline-medium")
|
||||||
|
:headline-small-typography (= typography "headline-small")
|
||||||
|
:body-large-typography (= typography "body-large")
|
||||||
|
:body-medium-typography (= typography "body-medium")
|
||||||
|
:body-small-typography (= typography "body-small")
|
||||||
|
:code-font-typography (= typography "code-font"))})]
|
||||||
|
[:> tag props
|
||||||
|
children]))
|
32
frontend/src/app/main/ui/ds/foundations/typography.cljs
Normal file
32
frontend/src/app/main/ui/ds/foundations/typography.cljs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
;; This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) KALEIDOS INC
|
||||||
|
|
||||||
|
(ns app.main.ui.ds.foundations.typography)
|
||||||
|
|
||||||
|
(def ^:typography-id display "display")
|
||||||
|
(def ^:typography-id title-large "title-large")
|
||||||
|
(def ^:typography-id title-medium "title-medium")
|
||||||
|
(def ^:typography-id title-small "title-small")
|
||||||
|
(def ^:typography-id headline-large "headline-large")
|
||||||
|
(def ^:typography-id headline-medium "headline-medium")
|
||||||
|
(def ^:typography-id headline-small "headline-small")
|
||||||
|
(def ^:typography-id body-large "body-large")
|
||||||
|
(def ^:typography-id body-medium "body-medium")
|
||||||
|
(def ^:typography-id body-small "body-small")
|
||||||
|
(def ^:typography-id code-font "code-font")
|
||||||
|
|
||||||
|
|
||||||
|
(def typography-list #{display
|
||||||
|
title-large
|
||||||
|
title-medium
|
||||||
|
title-small
|
||||||
|
headline-large
|
||||||
|
headline-medium
|
||||||
|
headline-small
|
||||||
|
body-large
|
||||||
|
body-medium
|
||||||
|
body-small
|
||||||
|
code-font})
|
153
frontend/src/app/main/ui/ds/foundations/typography.mdx
Normal file
153
frontend/src/app/main/ui/ds/foundations/typography.mdx
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
import { Canvas, Meta, Story } from "@storybook/blocks";
|
||||||
|
import * as TypographyStories from "./typography.stories";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
<Meta of={TypographyStories} />
|
||||||
|
|
||||||
|
# Typography
|
||||||
|
|
||||||
|
We currently work with 3 scales depending on whether the typography
|
||||||
|
is applied in the workspace, in the dashboard and access areas
|
||||||
|
and in the communication modalities.
|
||||||
|
|
||||||
|
This situation is something to be corrected in future improvements.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Standard text colours
|
||||||
|
|
||||||
|
Typographic colours are used in text elements such as headers
|
||||||
|
and body and in the various components that make up the tool...
|
||||||
|
|
||||||
|
The colours used in typography are the Foreground colours such
|
||||||
|
`--color-foreground-primary` or `--color-foreground-secondary`
|
||||||
|
but different colours can be applied in specific component
|
||||||
|
applications with their own styles, such as buttons.
|
||||||
|
|
||||||
|
As far as possible and as long as accessibility is not affected,
|
||||||
|
we will use colour in typography as a way of hierarchising
|
||||||
|
the content displayed using tone, built in luminance changes and
|
||||||
|
size as differentiating elements between main and secondary text.
|
||||||
|
|
||||||
|
### Status text colous
|
||||||
|
|
||||||
|
Another possible application of colour is semantic, when we use text to convey some system state.
|
||||||
|
|
||||||
|
Use the tokens:
|
||||||
|
|
||||||
|
`--color-accent-success` - Use as text colour to indicate success.
|
||||||
|
|
||||||
|
`--color-accent-warning` - Use as text colour to indicate a warning or caution.
|
||||||
|
|
||||||
|
`--color-accent-error` - Use as text colour to indicate an error.
|
||||||
|
|
||||||
|
|
||||||
|
## Accesibility
|
||||||
|
|
||||||
|
Typefaces should be sized for legibility and accessibility.
|
||||||
|
The minimum size for texts in Penpot will be 14px except
|
||||||
|
for exceptions based on the size of the components.
|
||||||
|
|
||||||
|
## Title
|
||||||
|
|
||||||
|
### Display `display`
|
||||||
|
|
||||||
|
Hero style text for transitional pages (Login). If too large use large title in narrow windows.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="display" >Display - 400 - 36px/1.4 "Work Sans" </Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Title large `title-large`
|
||||||
|
|
||||||
|
Page headers for main pages (dashboard, Profiles...). If too big use title
|
||||||
|
(medium) in narrow windows.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="title-large" >Title large - 400 - 24px/1.4 "Work Sans" </Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Title medium `title-medium`
|
||||||
|
|
||||||
|
Default page title. Equivalent line height of 32px matches the height
|
||||||
|
of buttons and other medium controls. Ideal for page header layout.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="title-medium" >Title medium - 400 - 20px/1.4 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Title small `title-small`
|
||||||
|
|
||||||
|
Uses the same size as body (large).
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="title-small" >Title small - 400 - 14px/1.2 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Headline
|
||||||
|
|
||||||
|
Page sections/subtitles, or names of less important objects in
|
||||||
|
page titles (automated action titles, for example). Same line height as title (medium).
|
||||||
|
|
||||||
|
### Headline large `headline-large`
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="headline-large" >Headline large - 400 - 18px/1.4 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Headline medium `headline-medium`
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="headline-medium" >Headline medium - 400 - 16px/1.4 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
|
||||||
|
### Headline small `headline-small`
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="headline-small" >Headline small - 500 - 12px/1.2 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Body
|
||||||
|
|
||||||
|
### Body large `body-large`
|
||||||
|
|
||||||
|
Generic content.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="body-large" >Body large - 400 - 16px/1.4 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
### Body medium `body-medium`
|
||||||
|
|
||||||
|
Default UI font. Most commonly used for body text.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="body-medium" >Body medium - 400 - 14px/1.3 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
|
||||||
|
### Body small `body-small`
|
||||||
|
|
||||||
|
Small compact font with a line height of less than 16px.
|
||||||
|
Use for single line scenarios, as the small size does not meet accessibility requirements.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="body-small" >Body small - 400 - 12px/1.3 "Work Sans"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Code font `code-font`
|
||||||
|
|
||||||
|
Default style for rendering code blocks.
|
||||||
|
|
||||||
|
<Canvas style={{background: "var(--color-background-primary)", color: "var(--color-foreground-primary)"}}>
|
||||||
|
<Components.Heading level="1" typography="code-font" >Code font - 400 - 12px/1.2 "Roboto Mono"</Components.Heading>
|
||||||
|
</Canvas>
|
||||||
|
|
||||||
|
## Fonts
|
||||||
|
|
||||||
|
We are using 3 fonts
|
||||||
|
|
||||||
|
- The default font family is `Work Sans`. It was chosen for its efficiency and legibility.
|
||||||
|
- In case of having the interface in Farsi or Arabic this font will be replaced by `Vazirmatn`.
|
||||||
|
- For code blocks we are useng `Roboto Mono`.
|
135
frontend/src/app/main/ui/ds/foundations/typography.stories.jsx
Normal file
135
frontend/src/app/main/ui/ds/foundations/typography.stories.jsx
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
import * as React from "react";
|
||||||
|
import Components from "@target/components";
|
||||||
|
|
||||||
|
const { Heading } = Components;
|
||||||
|
const { StoryWrapper, StoryHeader, StoryGridRow } = Components.storybook;
|
||||||
|
|
||||||
|
const typographyList = {
|
||||||
|
display: {
|
||||||
|
name: "Display",
|
||||||
|
id: "display",
|
||||||
|
size: "36px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
titleLarge: {
|
||||||
|
name: "Title large",
|
||||||
|
id: "title-large",
|
||||||
|
size: "24px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
titleMedium: {
|
||||||
|
name: "Title medium",
|
||||||
|
id: "title-medium",
|
||||||
|
size: "20px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
titleSmall: {
|
||||||
|
name: "Title small",
|
||||||
|
id: "title-small",
|
||||||
|
size: "14px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.2",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
headlineLarge: {
|
||||||
|
name: "Headline large",
|
||||||
|
id: "headline-large",
|
||||||
|
size: "18px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: true,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
headlineMedium: {
|
||||||
|
name: "Headline medium",
|
||||||
|
id: "headline-medium",
|
||||||
|
size: "16px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: true,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
headlineSmall: {
|
||||||
|
name: "Headline small",
|
||||||
|
id: "headline-small",
|
||||||
|
size: "12px",
|
||||||
|
weight: "500",
|
||||||
|
line: "1.2",
|
||||||
|
uppercase: true,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
bodyLarge: {
|
||||||
|
name: "Body large",
|
||||||
|
id: "body-large",
|
||||||
|
size: "16px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.4",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
bodyMedium: {
|
||||||
|
name: "Body medium",
|
||||||
|
id: "body-medium",
|
||||||
|
size: "14px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.3",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
bodySmall: {
|
||||||
|
name: "Body small",
|
||||||
|
id: "body-small",
|
||||||
|
size: "12px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.3",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Work Sans",
|
||||||
|
},
|
||||||
|
codeFont: {
|
||||||
|
name: "Code font",
|
||||||
|
id: "code-font",
|
||||||
|
size: "12px",
|
||||||
|
weight: "400",
|
||||||
|
line: "1.2",
|
||||||
|
uppercase: false,
|
||||||
|
font: "Roboto Mono",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Foundations/Typography",
|
||||||
|
component: Components.StoryHeader,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AllTypography = {
|
||||||
|
render: () => (
|
||||||
|
<StoryWrapper theme="default">
|
||||||
|
<StoryHeader>
|
||||||
|
<h1>All Typography</h1>
|
||||||
|
<p>Hover on a heading to see its ID</p>
|
||||||
|
</StoryHeader>
|
||||||
|
{Object.values(typographyList).map(
|
||||||
|
({ id, name, size, weight, line, font }) => (
|
||||||
|
<StoryGridRow title={id} key={id}>
|
||||||
|
<Heading level="1" typography={id}>
|
||||||
|
{name} - {weight} - {size}/{line} {font}
|
||||||
|
</Heading>
|
||||||
|
</StoryGridRow>
|
||||||
|
),
|
||||||
|
)}
|
||||||
|
</StoryWrapper>
|
||||||
|
),
|
||||||
|
parameters: {
|
||||||
|
backgrounds: { disable: true },
|
||||||
|
},
|
||||||
|
};
|
|
@ -45,3 +45,10 @@
|
||||||
(let [class (stl/css :story-header)
|
(let [class (stl/css :story-header)
|
||||||
props (mf/spread-props other {:class class})]
|
props (mf/spread-props other {:class class})]
|
||||||
[:> "header" props children]))
|
[:> "header" props children]))
|
||||||
|
|
||||||
|
(mf/defc story-grid-row*
|
||||||
|
{::mf/props :obj}
|
||||||
|
[{:keys [children] :rest other}]
|
||||||
|
(let [class (stl/css :story-grid-row)
|
||||||
|
props (mf/spread-props other {:class class})]
|
||||||
|
[:> "article" props children]))
|
|
@ -19,3 +19,11 @@
|
||||||
.story-header {
|
.story-header {
|
||||||
color: var(--color-foreground-primary);
|
color: var(--color-foreground-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.story-grid-row {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: 60px;
|
||||||
|
gap: 1rem;
|
||||||
|
color: var(--color-foreground-primary);
|
||||||
|
}
|
||||||
|
|
|
@ -13,24 +13,24 @@ $_font-lineheight-dense: 1.2;
|
||||||
$_font-lineheight-compact: 1.3;
|
$_font-lineheight-compact: 1.3;
|
||||||
$_font-lineheight-normal: 1.4;
|
$_font-lineheight-normal: 1.4;
|
||||||
|
|
||||||
@function px2Rem($value) {
|
@function px2rem($value) {
|
||||||
$remValue: math.div($value, 16) * 1rem;
|
$remValue: math.div($value, 16) * 1rem;
|
||||||
@return $remValue;
|
@return $remValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_fs-12: px2Rem(12);
|
$_fs-12: px2rem(12);
|
||||||
$_fs-14: px2Rem(14);
|
$_fs-14: px2rem(14);
|
||||||
$_fs-16: px2Rem(16);
|
$_fs-16: px2rem(16);
|
||||||
$_fs-18: px2Rem(18);
|
$_fs-18: px2rem(18);
|
||||||
$_fs-20: px2Rem(20);
|
$_fs-20: px2rem(20);
|
||||||
$_fs-24: px2Rem(24);
|
$_fs-24: px2rem(24);
|
||||||
$_fs-36: px2Rem(36);
|
$_fs-36: px2rem(36);
|
||||||
|
|
||||||
@mixin _font-style-display {
|
@mixin _font-style-display {
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-regular;
|
font-weight: $_font-weight-regular;
|
||||||
line-height: $_font-lineheight-dense;
|
line-height: $_font-lineheight-normal;
|
||||||
font-size: $_fs-36;
|
font-size: $_fs-36;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ $_fs-36: px2Rem(36);
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-regular;
|
font-weight: $_font-weight-regular;
|
||||||
line-height: $_font-lineheight-dense;
|
line-height: $_font-lineheight-normal;
|
||||||
font-size: $_fs-24;
|
font-size: $_fs-24;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,11 +46,19 @@ $_fs-36: px2Rem(36);
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-regular;
|
font-weight: $_font-weight-regular;
|
||||||
line-height: $_font-lineheight-dense;
|
line-height: $_font-lineheight-normal;
|
||||||
font-size: $_fs-20;
|
font-size: $_fs-20;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin _font-style-heading-large {
|
@mixin _font-style-title-small {
|
||||||
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
|
font-optical-sizing: auto;
|
||||||
|
font-weight: $_font-weight-regular;
|
||||||
|
line-height: $_font-lineheight-dense;
|
||||||
|
font-size: $_fs-14;
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin _font-style-headline-large {
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-regular;
|
font-weight: $_font-weight-regular;
|
||||||
|
@ -59,16 +67,16 @@ $_fs-36: px2Rem(36);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin _font-style-heading-medium {
|
@mixin _font-style-headline-medium {
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-regular;
|
font-weight: $_font-weight-regular;
|
||||||
line-height: $_font-lineheight-dense;
|
line-height: $_font-lineheight-normal;
|
||||||
font-size: $_fs-16;
|
font-size: $_fs-16;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin _font-style-heading-small {
|
@mixin _font-style-headline-small {
|
||||||
font-family: "worksans", "vazirmatn", sans-serif;
|
font-family: "worksans", "vazirmatn", sans-serif;
|
||||||
font-optical-sizing: auto;
|
font-optical-sizing: auto;
|
||||||
font-weight: $_font-weight-medium;
|
font-weight: $_font-weight-medium;
|
||||||
|
@ -116,12 +124,14 @@ $_fs-36: px2Rem(36);
|
||||||
@include _font-style-title-large;
|
@include _font-style-title-large;
|
||||||
} @else if $typography-name == "title-medium" {
|
} @else if $typography-name == "title-medium" {
|
||||||
@include _font-style-title-medium;
|
@include _font-style-title-medium;
|
||||||
} @else if $typography-name == "heading-large" {
|
} @else if $typography-name == "title-small" {
|
||||||
@include _font-style-heading-large;
|
@include _font-style-title-small;
|
||||||
} @else if $typography-name == "heading-medium" {
|
} @else if $typography-name == "headline-large" {
|
||||||
@include _font-style-heading-medium;
|
@include _font-style-headline-large;
|
||||||
} @else if $typography-name == "heading-small" {
|
} @else if $typography-name == "headline-medium" {
|
||||||
@include _font-style-heading-small;
|
@include _font-style-headline-medium;
|
||||||
|
} @else if $typography-name == "headline-small" {
|
||||||
|
@include _font-style-headline-small;
|
||||||
} @else if $typography-name == "body-large" {
|
} @else if $typography-name == "body-large" {
|
||||||
@include _font-style-body-large;
|
@include _font-style-body-large;
|
||||||
} @else if $typography-name == "body-medium" {
|
} @else if $typography-name == "body-medium" {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue