## Graphics components The `@reuters-graphics/graphics-components` library includes pre-styled components for easily adding graphics or other elements to a page. ### Adding new components to a page Components from the `@reuters-graphics/graphics-components` library are often added to the `#each` loop in `src/lib/App.svelte` that loops over `content.blocks`. `content` represents text content pulled from our CMS as JSON that is passed into components via props. Each block in `content.blocks` (i.e., "content block") is usually an object with a `type` property and additional properties specific to the block type. For example: - **Text Block**: ```json { "type": "text", "text": "This is a text block." } ``` - **AI Graphic Block** ```json { "type": "ai-graphic", "chart": "AiMap", "width": "normal", "textWidth": "normal", "title": "Optional title of the graphic", "description": "Optional chatter describes more about the graphic.", "notes": "Note: Optional note clarifying something in the data.\r\n\r\nSource: Optional source of the data.", "altText": "Add a description of the graphic for screen readers. This is invisible on the page." } ``` To add a new component to the loop: 1. Import the component in the script portion of the Svelte component. 2. Add a new `else if` condition in the `{#each content.blocks as block}` loop to handle the new block type. 3. Pass the required props to the component, ensuring they match the structure of the content block object. For example, to add a new FeaturePhoto: ```svelte {#each content.blocks as block} {#if block.type === 'text'} {:else if block.type === 'feature-photo'} {:else} {/if} {/each} ``` ### Paths to multimedia files Notice in the example above, we append the `assets` variable from SvelteKit's `$app/paths` module to the `src` path we got from the content block. Always assume that paths to local multimedia files including images and videos specified in content blocks are relative and must be prefixed with the `assets` variable to make them absolute. For example: ```svelte ``` ### Adding AI Graphics AI (i.e., Adobe Illustrator) graphics are added to the page by importing a component from the `src/lib/ai2svelte/` directory and then adding that graphic to the `aiCharts` object in `src/lib/App.svelte`. Then the object key for that chart is included in the content block's `chart` property. For example, to use an AI graphic from `src/lib/ai2svelte/map.svelte`: - The AI graphic component is imported and added to the `aiCharts` object in `src/lib/App.svelte`: ```svelte ``` - Now the content block will specify the key to the chart in `aiCharts` in the `chart` property: ```json { "type": "ai-graphic", "chart": "Map", "width": "normal", "textWidth": "normal", "title": "My map", "description": "A map of the area", "notes": "Source: DataSource.org", "altText": "A map of a specific area showing something interesting" } ``` - Now the `{:else if block.type === 'ai-graphic'}` block in `src/lib/App.svelte` uses that key to get the component: ```svelte {#each content.blocks as block} {#if block.type === 'text'} {:else if block.type === 'ai-graphic'} {#if !aiCharts[block.chart]} {:else} {@const AiChart = aiCharts[block.chart]} {/if} {/if} {/each} ``` ### Refer to graphics components Storybook If you're unsure how to implement a particular graphics component, suggest the user check the Storybook documentation site, which is hosted on GitHub at https://reuters-graphics.github.io/graphics-components/. ### Writing content blocks in our CMS While the text content in the `content` object is formatted as JSON, that data is written into our CMS (which is called "RNGS.io") using ArchieML syntax. **When suggesting what content blocks to add for components, please also suggest how to write that content in our CMS (RNGS.io) using ArchieML.** #### ArchieML ArchieML is a lightweight and intuitive markup language that allows for easy structuring of data within text documents. It is designed to be human-readable, very flexible, and is particularly useful for creating structured data by users who may never have seen ArchieML or any other markup language before. ##### Basic Syntax - **Keys and Values** - Definition: Key-value pairs are defined by a line starting with a key followed by a colon. Keys can include any unicode character except whitespace and specific characters used within ArchieML ({ } [ ] : . +). - Example: ``` key: This is a value ☃: Unicode Snowman for you and you and you! ``` - Parsed JSON: ```json { "key": "This is a value", "☃": "Unicode Snowman for you and you and you!" } ``` - Whitespace around keys and values is ignored. Keys are case-sensitive. - **Multi-line Values**: Multi-line values are anchored with `:end`. All whitespace is preserved. - Example: ``` key: value More value Even more value :end ``` - Parsed JSON: ```json { "key": "value\n More value\n\nEven more value" } ``` - Escape Characters: Lines that would be interpreted as keys or commands can be escaped with a backslash `\`. - Example: ``` key: value \:end :end ``` - Parsed JSON: ```json { "key": "value\n:end" } ``` - **Nested Structures** - **Dot-Notation**: Use dot-notation for creating nested objects. - Example: ``` colors.red: #f00 colors.green: #0f0 colors.blue: #00f ``` - Parsed JSON: ```json { "colors": { "red": "#f00", "green": "#0f0", "blue": "#00f" } } ``` - **Object Blocks**: Group keys using object blocks defined by {}. Close an object with {} or by starting a new object. - Example: ``` {colors} red: #f00 green: #0f0 blue: #00f {} {numbers} one: 1 ten: 10 one-hundred: 100 {} ``` - Parsed JSON: ```json { "colors": { "red": "#f00", "green": "#0f0", "blue": "#00f" }, "numbers": { "one": "1", "ten": "10", "one-hundred": "100" } } ``` - **Arrays** - **Arrays of Objects**: Define arrays with brackets [arrayName]. New objects start when the first key is re-encountered. - Example: ``` [arrayName] name: Amanda age: 26 name: Tessa age: 30 [] ``` - Parsed JSON: ```json { "arrayName": [ { "name": "Amanda", "age": "26" }, { "name": "Tessa", "age": "30" } ] } ``` - **Arrays of Strings**: Simple arrays use _ for elements. If _ is first, the array ignores key-value pairs. - Example: ``` [days] * Sunday * Monday * Tuesday * Wednesday * Thursday * Friday * Saturday [] ``` - Parsed JSON: ```json { "days": [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ] } ``` - **Nested Arrays**: Nested arrays use dot notation and are closed with `[]`. - Example: ``` [days] name: Monday [.tasks] * Clean dishes * Pick up room [] name: Tuesday [.tasks] * Buy milk [] ``` - Parsed JSON: ```json { "days": [ { "name": "Monday", "tasks": ["Clean dishes", "Pick up room"] }, { "name": "Tuesday", "tasks": ["Buy milk"] } ] } ``` #### ArchieML conventions in our CMS Usually, content blocks are written in our CMS as objects inside an ArchieML array called `blocks` and always start with a `type:` key/value pair that defines the type of the content block object. For example, a user adding a content block for a FeaturePhoto component, might add the following to the existing `[blocks]` array in our CMS: ``` [blocks] type: feature-photo src: images/myPhoto.jpg alt: Alt text for my photo... ... which extends over multiple lines. :end caption: A photo of something interesting. credit: Jane Doe [] ``` ### Graphics components style tokens As well as Svelte components, the graphics components library includes a tailwind-like style system that can be used to style components and other page elements by adding a class or through SCSS mixins. These classes and mixins are defined as individual "tokens" representing the value for an individual style rule, like `font-size` or `color`. Each token sets just one style rule, and multiple tokens are combined together to style an element, like a `
`. Each set of tokens has several levels that represent the different values a style rule can take in our design system and are grouped in how they're named to make them easier to remember. For example, font weight tokens include `font-thin`, `font-light`, and `font-bold` which correspond to the style rules `font-weight: 100;`, `font-weight: 300;`, and `font-weight: 700;`, respectively. And those tokens can be applied via class name or SCSS mixin. For example: ```svelte

Here is some bold text with some thin text in it!

``` Not all our style tokens have both class names as well as SCSS mixins available to apply them. **Please use the tokens defined in the SCSS partials in the [@reuters-graphics/graphics-components/dist/scss/tokens/ directory](./../../../node_modules/@reuters-graphics/graphics-components/dist/scss/tokens/) liberally in instructions and code samples, BUT be sure the token exists before suggesting it. DO NOT MAKE UP TOKENS, CLASS NAMES OR SCSS MIXINS!** If you're not sure if there is a token to apply a particular style, you can refer the user to our Storybook documentation site for them at: https://reuters-graphics.github.io/graphics-components/?path=/docs/styles-intro--docs. #### Using style tokens To use a token to style an element, you can apply it directly to the element through a class name. For example, to apply the `text-primary` token (controlling font colour) you can apply it like this: ```svelte

Lorem ipsum...

``` OR you can apply some tokens via an SCSS mixin. For example: ```svelte

Lorem ipsum...

``` **Be sure to always include the `@use` line that imports the SCSS mixins from the library in your SCSS/styling suggestions.** Please consider the SCSS mixins and classes defined in the [@reuters-graphics/graphics-components/dist/scss/tokens/ directory](./../../../node_modules/@reuters-graphics/graphics-components/dist/scss/tokens/). #### Spacing tokens We have a special set of tokens to control spacing, i.e., paddings and margins. They operate like tailwind's padding and margin system. For example, `mt-1` represents `margin-top: 0.25rem;` and `px-2` represents `padding-right: 0.5rem; padding-left: 0.5rem;`, etc. These tokens can be applied only through a class. These tokens are all defined as a combination of a prefix and a level. The prefix is something like `mb` for bottom margin or `py` for padding top and bottom. The level is a number representing how large the padding are margin should be. The levels go like this: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, then increasing by 4 each time up to 96. For example, the full token set for top margin would be `mt-0`, `mt-0.5`, `mt-1`, `mt-1.5`, and so on. We also have a set of spacing tokens designed to work with _fluid_ typography. These are prefixed beginning with the letter `f`, for example, `fmb-1` represents a _fluid_ margin bottom, `margin-bottom: clamp(0.31rem, 0.31rem + 0vw, 0.31rem);`. These tokens can be applied through a class AND an SCSS mixin. For example: ```svelte

Some text with margin and padding

``` You should recommend fluid margin and padding tokens for spacing fluidly-sized typographical elements or elements that are spaced _next to_ fluidly-sized typographical elements. Typographical elements include page headings, paragraphs or elements containing text, generally.