# LO-TEK > Framework-agnostic design system: tokens, CSS components and web components. Version 0.40.0. The components are CSS classes and web components, things the browser already understands, so the same components work in plain HTML, in a Go template, with bundles, in React, in Astro and with Datastar. Four mistakes account for almost everything that goes wrong. They apply in every environment: 1. The stylesheet must be loaded. If it is missing, the components look unstyled, and the answer is to load it, never to write your own CSS to make them look right. 2. Only the classes and elements that exist, exist. `lt-modal`, `lt-datepicker` and `data-variant="outlined"` belong to other design systems. The full list is in every rulebook. 3. No hard-coded colours or pixels. `var(--lt-color-…)` and `var(--lt-spacing-…)`. 4. Web components are registered once with `defineLt*()`, and a boolean attribute is true as long as it is there: `hidden="false"` still hides the error text. The attribute has to be removed, not set to `false`. Check the markup when you are done, and fix what it reports: npx @lo-tek/interfaces check npx @lo-tek/interfaces check http://localhost:8080/page It knows every class, every element, every attribute and every valid value, writes `file:line:column: error: message`, or `warning:`, and exits with an error code when it finds something. With an address it checks the page as the server sends it, and also requires that every `for` and `aria-describedby` points at an id that exists, and that every field has a label. You are done when both answer "The markup matches LO-TEK". Everything about the commands: https://lo-tek.sobernetics.no/command-line/ ## Rulebooks for coding agents - [LO-TEK in Astro](https://lo-tek.sobernetics.no/agent/astro.md): LO-TEK in an Astro project. - [LO-TEK with a bundler](https://lo-tek.sobernetics.no/agent/bundles.md): LO-TEK in a project with a build step, where the markup is ordinary HTML: Vue, Svelte, Solid, Lit, and plain TypeScript with Vite, Rollup, esbuild or webpack. - [LO-TEK with Datastar](https://lo-tek.sobernetics.no/agent/datastar.md): LO-TEK together with [Datastar](https://data-star.dev), which adds reactivity to ordinary HTML with `data-*` attributes. - [LO-TEK in plain HTML](https://lo-tek.sobernetics.no/agent/html.md): LO-TEK in a project without a build step: hand-written HTML, where the browser loads the files directly. - [LO-TEK in React](https://lo-tek.sobernetics.no/agent/react.md): LO-TEK in a React app. - [LO-TEK in templates and server-written HTML](https://lo-tek.sobernetics.no/agent/templates.md): LO-TEK where the server produces the markup: Go templates, Razor, PHP, Blade, Twig, Jinja, Django, ERB, Liquid, Handlebars, Nunjucks and Edge, and HTML built as strings in Kotlin, Java, C# or Python. Each rulebook is complete for its environment. If the package is installed, the same files are in `node_modules/@lo-tek/interfaces/agent/`, and `npx @lo-tek/interfaces agent` prints the one that fits this project. ## Guides - [Accessibility](https://lo-tek.sobernetics.no/accessibility.md): What LO-TEK handles centrally, what is checked by tests, and what you have to do yourself. - [Coding agents](https://lo-tek.sobernetics.no/coding-agents.md): LO-TEK for Claude Code, GitHub Copilot and other coding agents. The rulebook comes with the package, and nothing is written to your files. - [Command line](https://lo-tek.sobernetics.no/command-line.md): The commands in @lo-tek/interfaces, with flags, output and exit codes. Check markup and whole pages, get the rulebook for coding agents, take over a component and make a theme. - [Components](https://lo-tek.sobernetics.no/components.md): Every component in LO-TEK, grouped by who creates the markup and whether a web component adds behaviour to it. - [Customising](https://lo-tek.sobernetics.no/customising.md): Change colours, shape and size in LO-TEK without losing the changes on the next upgrade. - [Design tokens](https://lo-tek.sobernetics.no/design-tokens.md): Colours, sizes and typography as CSS variables, TypeScript constants and a Tailwind theme. - [Frameworks](https://lo-tek.sobernetics.no/frameworks.md): Setting up LO-TEK in plain HTML, React, Astro and Datastar, with the same components and the same API. - [Getting started](https://lo-tek.sobernetics.no/getting-started.md): Install LO-TEK, import what you need, and get the first component on screen. - [Introduction](https://lo-tek.sobernetics.no/introduction.md): What LO-TEK is, how the components are divided, and why they are divided that way. - [Kotlin and Java](https://lo-tek.sobernetics.no/kotlin.md): The builder functions with enums, and LO-TEK's check in ordinary tests, on the JVM without Node and without JavaScript. - [Licence and price](https://lo-tek.sobernetics.no/licence.md): What LO-TEK costs, what you are allowed to do, what is not promised, and how to contribute or fork. - [Markup and behaviour](https://lo-tek.sobernetics.no/markup-and-behaviour.md): Who writes the HTML, who attaches the behaviour, and which of the two forms to use. - [Roadmap](https://lo-tek.sobernetics.no/roadmap.md): What is left to build in LO-TEK, and what has already been delivered from the original plan. - [Tailwind](https://lo-tek.sobernetics.no/tailwind.md): Use Tailwind freely together with LO-TEK, with the same values and nothing fighting over the order. - [The editor](https://lo-tek.sobernetics.no/the-editor.md): Completion, hover help and error messages for LO-TEK in VS Code, JetBrains, Neovim, Helix and other editors with LSP, also where no compiler looks at the markup. - [Translation](https://lo-tek.sobernetics.no/translation.md): LO-TEK has almost no text. You write it with the translation tool your app already uses, and the few texts the package has can be replaced. - [Type-safe use](https://lo-tek.sobernetics.no/type-safe-use.md): One namespace, one shape. Autocompletion for the whole system, without tying you to a framework. - [Your own theme](https://lo-tek.sobernetics.no/your-own-theme.md): Build a colour theme from your brand colours, with contrast checked in both themes. ## Patterns - [Confirming an action](https://lo-tek.sobernetics.no/patterns/confirmation.md): Dialog, wording and what happens afterwards, when the action cannot be undone. - [Dates in a form](https://lo-tek.sobernetics.no/patterns/date.md): Why LO-TEK has no date picker, and how to ask for a date that works everywhere. - [Form with validation](https://lo-tek.sobernetics.no/patterns/form.md): From field to error message to summary, with focus where the user needs it. - [List with filters](https://lo-tek.sobernetics.no/patterns/list.md): Search, filters and the four states a list has: loading, results, empty and failed. - [Page skeleton](https://lo-tek.sobernetics.no/patterns/page-skeleton.md): Skip link, landmarks and heading levels, the things the components cannot take responsibility for. - [Letting the user choose a theme](https://lo-tek.sobernetics.no/patterns/theme.md): A theme picker in plain CSS, and the two ways to make the choice last. ## Components - [Accordion](https://lo-tek.sobernetics.no/components/accordion.md): A panel that can be expanded, built on details and summary. CSS component with two classes and no JavaScript. - [Alert](https://lo-tek.sobernetics.no/components/alert.md): A message about the whole page or the whole form. CSS component with two classes and no JavaScript. - [Avatar](https://lo-tek.sobernetics.no/components/avatar.md): Profile picture or initials. A CSS component with two classes and no JavaScript. - [Badge](https://lo-tek.sobernetics.no/components/badge.md): Compact status badge. A CSS component with one class and no JavaScript. - [Breadcrumbs](https://lo-tek.sobernetics.no/components/breadcrumbs.md): A breadcrumb trail that shows where on the site the user is. A CSS component with one class and no JavaScript. - [Button](https://lo-tek.sobernetics.no/components/button.md): A button for actions. CSS component with one class and no JavaScript. - [Card](https://lo-tek.sobernetics.no/components/card.md): A box that groups content that belongs together. A CSS component with two classes and no JavaScript. - [Checkbox](https://lo-tek.sobernetics.no/components/checkbox.md): A checkbox for a choice that stands on its own. CSS component with two classes and no JavaScript. - [Connection Status](https://lo-tek.sobernetics.no/components/connection-status.md): Tells the user when the connection to the server is gone. Standalone component. - [Dialog](https://lo-tek.sobernetics.no/components/dialog.md): Modal dialog built on the native dialog element. Six classes and no JavaScript, with an optional component for when the server decides that the dialog is open. - [Divider](https://lo-tek.sobernetics.no/components/divider.md): A line between parts of the content. A CSS component with one class and no JavaScript. - [Error Summary](https://lo-tek.sobernetics.no/components/error-summary.md): Collects the errors in a form and takes the user to the field that failed. Frame component. - [Error Text](https://lo-tek.sobernetics.no/components/error-text.md): Error message below a form field. A CSS component with one class and no JavaScript. - [Field](https://lo-tek.sobernetics.no/components/field.md): Frame component that wires the label, field, help text and error text together for you. - [Fieldset](https://lo-tek.sobernetics.no/components/fieldset.md): A group of controls with a shared label. CSS component with two classes and no JavaScript. - [File Upload](https://lo-tek.sobernetics.no/components/file-upload.md): A field for uploading files. A CSS component with two classes and no JavaScript. - [Heading](https://lo-tek.sobernetics.no/components/heading.md): Headings in six sizes, independent of level. A CSS component with one class and no JavaScript. - [Help Text](https://lo-tek.sobernetics.no/components/help-text.md): Explanatory text below a form field. A CSS component with one class and no JavaScript. - [Icon](https://lo-tek.sobernetics.no/components/icon.md): An icon from the app's own set, as large as the text around it. A CSS component with one class and no JavaScript. - [Input](https://lo-tek.sobernetics.no/components/input.md): A text field for forms, with states for valid and invalid. CSS component. - [Label](https://lo-tek.sobernetics.no/components/label.md): A label for form fields, with marking of required and optional. A CSS component. - [Link](https://lo-tek.sobernetics.no/components/link.md): Link style for navigation in running text. A CSS component with one class and no JavaScript. - [List](https://lo-tek.sobernetics.no/components/list.md): Bulleted lists, numbered lists and lists without bullets. A CSS component with one class and no JavaScript. - [Pagination](https://lo-tek.sobernetics.no/components/pagination.md): Page navigation for long lists. A CSS component with two classes and no JavaScript. - [Paragraph](https://lo-tek.sobernetics.no/components/paragraph.md): Body text and lead paragraphs with a limited line length. A CSS component with one class and no JavaScript. - [Popover](https://lo-tek.sobernetics.no/components/popover.md): Panel that hangs below a button and closes itself. Frame component. - [Progress](https://lo-tek.sobernetics.no/components/progress.md): A progress bar for something that has an end. CSS component with one class and no JavaScript. - [Radio](https://lo-tek.sobernetics.no/components/radio.md): Radio buttons for one choice among several. A CSS component with two classes and no JavaScript. - [Search](https://lo-tek.sobernetics.no/components/search.md): A search field with a magnifying glass. A CSS component with two classes and no JavaScript. - [Select](https://lo-tek.sobernetics.no/components/select.md): A dropdown list. CSS component with one class and no JavaScript. - [Session Timeout](https://lo-tek.sobernetics.no/components/session-timeout.md): Warns before a logged-in session expires, and counts down. You write the dialog, the component keeps the time. - [Skeleton](https://lo-tek.sobernetics.no/components/skeleton.md): A placeholder that shows the shape of content being loaded. A CSS component with one class and no JavaScript. - [Skip Link](https://lo-tek.sobernetics.no/components/skip-link.md): A link that skips past the menu to the main content. A CSS component with one class and no JavaScript. - [Spinner](https://lo-tek.sobernetics.no/components/spinner.md): A wait indicator for something in progress. CSS component with one class and no JavaScript. - [Sr Only](https://lo-tek.sobernetics.no/components/sr-only.md): Text only screen readers get. A CSS component with one class and no JavaScript. - [Suggestion](https://lo-tek.sobernetics.no/components/suggestion.md): Field with a suggestion list that narrows as the user types. Frame component. - [Switch](https://lo-tek.sobernetics.no/components/switch.md): A switch for a setting that takes effect immediately. CSS component with two classes and no JavaScript. - [Table](https://lo-tek.sobernetics.no/components/table.md): A table for data in rows and columns. CSS component with two classes and no JavaScript. - [Tabs](https://lo-tek.sobernetics.no/components/tabs.md): Tab list of links to their panels. Frame component. - [Tag](https://lo-tek.sobernetics.no/components/tag.md): A tag for topics and filters. A CSS component with one class and no JavaScript. - [Textarea](https://lo-tek.sobernetics.no/components/textarea.md): A multi-line text field. A CSS component with one class and no JavaScript. - [Toast](https://lo-tek.sobernetics.no/components/toast.md): A queue of short messages in the corner of the screen. Standalone component. - [Toggle Group](https://lo-tek.sobernetics.no/components/toggle-group.md): A group where one option is selected at a time. A CSS component with two classes and no JavaScript. - [Tooltip](https://lo-tek.sobernetics.no/components/tooltip.md): A small help text shown on hover and focus. CSS component with two classes and no JavaScript.