@codenhub/styles 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/NOTICE +18 -16
  2. package/README.es.md +61 -0
  3. package/README.md +27 -22
  4. package/README.pt-BR.md +61 -0
  5. package/dist/aesthetics/chunky-tile.css +1 -1
  6. package/dist/aesthetics/cyber.css +1 -1
  7. package/dist/aesthetics/glass.css +1 -1
  8. package/dist/aesthetics/index.css +2 -2
  9. package/dist/aesthetics/neobrutalism.css +1 -1
  10. package/dist/aesthetics/pixel.css +1 -1
  11. package/dist/aesthetics/sketch.css +1 -1
  12. package/dist/components.css +2 -2
  13. package/dist/index.css +2 -2
  14. package/dist/native.css +2 -2
  15. package/dist/palette.css +1 -1
  16. package/dist/theme.css +2 -2
  17. package/dist/tw/aesthetics/chunky-tile.css +120 -62
  18. package/dist/tw/aesthetics/cyber.css +102 -40
  19. package/dist/tw/aesthetics/glass.css +371 -19
  20. package/dist/tw/aesthetics/index.css +2 -1
  21. package/dist/tw/aesthetics/neobrutalism.css +121 -33
  22. package/dist/tw/aesthetics/pixel.css +111 -16
  23. package/dist/tw/aesthetics/sketch.css +100 -28
  24. package/dist/tw/box.css +69 -28
  25. package/dist/tw/components/button.css +35 -14
  26. package/dist/tw/components/feedback.css +61 -58
  27. package/dist/tw/components/form.css +255 -142
  28. package/dist/tw/components/index.css +4 -9
  29. package/dist/tw/components/surface.css +80 -68
  30. package/dist/tw/components/tooltip.css +75 -41
  31. package/dist/tw/elevation.css +14 -22
  32. package/dist/tw/index.css +15 -19
  33. package/dist/tw/intent.css +35 -27
  34. package/dist/tw/native.css +22 -12
  35. package/dist/tw/palette.css +14 -11
  36. package/dist/tw/presentation.css +16 -30
  37. package/dist/tw/reset.css +36 -43
  38. package/dist/tw/surface.css +11 -12
  39. package/dist/tw/theme.css +87 -103
  40. package/dist/tw/utilities/content.css +311 -200
  41. package/dist/tw/utilities/layout.css +41 -37
  42. package/docs/accessibility.md +104 -58
  43. package/docs/changelog/0.1.1.md +1 -0
  44. package/docs/changelog/0.2.0.md +1 -0
  45. package/docs/changelog/0.3.0.md +1 -0
  46. package/docs/changelog/0.4.0.md +1 -0
  47. package/docs/changelog/0.5.0.md +8 -3
  48. package/docs/changelog/0.6.0.md +53 -0
  49. package/docs/changelog/0.7.0.md +50 -0
  50. package/docs/changelog/index.md +2 -0
  51. package/docs/concepts.md +188 -46
  52. package/docs/es/accessibility.md +150 -0
  53. package/docs/es/concepts.md +212 -0
  54. package/docs/es/index.md +104 -0
  55. package/docs/es/integrating/astro.md +35 -0
  56. package/docs/es/integrating/index.md +47 -0
  57. package/docs/es/integrating/nextjs.md +67 -0
  58. package/docs/es/integrating/svelte.md +45 -0
  59. package/docs/es/integrating/tailwind.md +78 -0
  60. package/docs/es/integrating/vue.md +31 -0
  61. package/docs/es/integrating/without-a-bundler.md +115 -0
  62. package/docs/es/setup.md +180 -0
  63. package/docs/es/usage/aesthetics.md +276 -0
  64. package/docs/es/usage/buttons.md +131 -0
  65. package/docs/es/usage/composing.md +164 -0
  66. package/docs/es/usage/content-and-layout.md +215 -0
  67. package/docs/es/usage/customizing.md +298 -0
  68. package/docs/es/usage/feedback.md +153 -0
  69. package/docs/es/usage/forms.md +231 -0
  70. package/docs/es/usage/index.md +29 -0
  71. package/docs/es/usage/solo.md +84 -0
  72. package/docs/es/usage/theming.md +296 -0
  73. package/docs/es/usage/tooltips.md +127 -0
  74. package/docs/index.md +89 -21
  75. package/docs/integrating/astro.md +3 -4
  76. package/docs/integrating/index.md +18 -13
  77. package/docs/integrating/nextjs.md +4 -5
  78. package/docs/integrating/svelte.md +5 -4
  79. package/docs/integrating/tailwind.md +29 -8
  80. package/docs/integrating/vue.md +3 -4
  81. package/docs/integrating/without-a-bundler.md +114 -0
  82. package/docs/pt-BR/accessibility.md +150 -0
  83. package/docs/pt-BR/concepts.md +212 -0
  84. package/docs/pt-BR/index.md +104 -0
  85. package/docs/pt-BR/integrating/astro.md +35 -0
  86. package/docs/pt-BR/integrating/index.md +47 -0
  87. package/docs/pt-BR/integrating/nextjs.md +67 -0
  88. package/docs/pt-BR/integrating/svelte.md +45 -0
  89. package/docs/pt-BR/integrating/tailwind.md +78 -0
  90. package/docs/pt-BR/integrating/vue.md +31 -0
  91. package/docs/pt-BR/integrating/without-a-bundler.md +115 -0
  92. package/docs/pt-BR/setup.md +180 -0
  93. package/docs/pt-BR/usage/aesthetics.md +276 -0
  94. package/docs/pt-BR/usage/buttons.md +131 -0
  95. package/docs/pt-BR/usage/composing.md +164 -0
  96. package/docs/pt-BR/usage/content-and-layout.md +215 -0
  97. package/docs/pt-BR/usage/customizing.md +298 -0
  98. package/docs/pt-BR/usage/feedback.md +153 -0
  99. package/docs/pt-BR/usage/forms.md +231 -0
  100. package/docs/pt-BR/usage/index.md +29 -0
  101. package/docs/pt-BR/usage/solo.md +84 -0
  102. package/docs/pt-BR/usage/theming.md +296 -0
  103. package/docs/pt-BR/usage/tooltips.md +127 -0
  104. package/docs/setup.md +134 -91
  105. package/docs/usage/aesthetics.md +102 -65
  106. package/docs/usage/buttons.md +108 -40
  107. package/docs/usage/composing.md +105 -92
  108. package/docs/usage/content-and-layout.md +159 -127
  109. package/docs/usage/customizing.md +112 -43
  110. package/docs/usage/feedback.md +135 -70
  111. package/docs/usage/forms.md +184 -99
  112. package/docs/usage/index.md +18 -14
  113. package/docs/usage/solo.md +83 -0
  114. package/docs/usage/theming.md +260 -119
  115. package/docs/usage/tooltips.md +103 -42
  116. package/llms-full.txt +2465 -1272
  117. package/llms.txt +25 -17
  118. package/package.json +28 -35
  119. package/dist/tw/components/loader.css +0 -117
@@ -1,182 +1,214 @@
1
1
  ---
2
2
  title: Content and layout
3
- description: Layout helpers, content chips and tables, surfaces, and typography utilities.
4
- order: 9
3
+ description: Lookup for every layout helper with its spacing, the type scale with its sizes, cards and panels with their padding, tables, quotes, code, and keyboard keys.
4
+ order: 10
5
5
  ---
6
6
 
7
7
  # Content and layout
8
8
 
9
+ This is a lookup page for the classes that arrange a page and set its content: layout helpers, the type scale, cards and panels, tables, and the small content chips. [Building a screen](../concepts.md#lay-out-the-page) shows them in use.
10
+
9
11
  ## Layout
10
12
 
11
- Layout helpers use the shared `--layout-gap` token. `.tight` sets it to `0.5rem` and `.loose` sets it to `1.5rem` within a view, stack, cluster, or auto-grid.
12
-
13
- - `.view` is a flex container; `.vertical` and `.horizontal` set its direction, and horizontal views wrap with centered cross-axis alignment.
14
- - `.stack` is a vertical flex stack.
15
- - `.cluster` is a wrapping horizontal flex row; `.between` adds `space-between` alignment.
16
- - `.auto-grid` is a responsive auto-fit grid using `--layout-grid-min`.
17
- - `.tight` and `.loose` set the shared gap to `0.5rem` or `1.5rem` on views, stacks, clusters, and auto-grids.
18
- - `.section` adds responsive block padding and an inline gutter.
19
- - `.section-content` centers content at `--container-max`; `.narrow` and `.wide` select the corresponding container tokens.
20
- - `.divider` is horizontal; `.vertical` makes it self-stretch vertically. It takes intent, but presentation classes do not affect it.
21
- - `.visually-hidden` hides content visually while keeping it in the accessibility tree, using the standard clip-based recipe. Not named `.sr-only`: on a `/tw` entry the consumer's own Tailwind build already ships a real `.sr-only`, and a same-named utility of this package's own would silently collide with it in the cascade — the same reason `.data-table` is not named `.table`.
22
-
23
- The removed `--layout-stack-gap` and `--layout-cluster-gap` tokens have no compatibility aliases.
24
-
25
- ## Content
26
-
27
- | Class | Purpose | Intent affects |
28
- | --------------- | ---------------------------------------------------------------------------------------- | ---------------------- |
29
- | `.table-wrap` | Full-width horizontal overflow wrapper for wide tables. | Nothing. |
30
- | `.data-table` | Rounded nested table styling for captions, heads, footers, cells, and rows. | Head, border, hover. |
31
- | `.ruled` | On `.data-table`. Draws a rule between body rows. | Rule color. |
32
- | `.ruleless` | On `.data-table`. Draws no lines inside the table at all. | Nothing. |
33
- | `.kbd` | Inline keyboard-input styling. | Surface, border, text. |
34
- | `.quote` | Block quote styling; a nested `cite` is set upright and takes the quotation's own color. | Bar, surface, text. |
35
- | `.quote-inline` | Inline quotation styling. | Nothing. |
36
- | `.code` | Inline code formatting. | Surface. |
37
- | `.pre` | Scrollable block code formatting with larger padding. | Surface. |
13
+ Every layout helper's gap is `--layout-gap`, `1rem` by default. Setting `--layout-gap` on an element changes the gap of every layout inside it. `.tight` and `.loose` change only the layout they are on; a layout nested inside keeps its own gap.
38
14
 
39
- ### Table rules
15
+ | Class | Layout | Gap |
16
+ | ------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
17
+ | `.stack` | A vertical column. | `--layout-gap`, `.tight` 0.5rem, `.loose` 1.5rem |
18
+ | `.cluster` | A row that wraps, with items centered vertically. `.between` spreads the items to both ends. | Same |
19
+ | `.view` | A flex container. `.vertical` makes it a column; `.horizontal` a wrapping row with items centered. | Same |
20
+ | `.auto-grid` | A grid of equal columns, each at least `--layout-grid-min` (16rem) wide, as many as fit. | Same |
21
+ | `.section` | Padding around a page section: `--layout-gutter` at the sides, `--layout-section-block` at the top and bottom. | None |
22
+ | `.section-content` | Centers its content at a width of `--container-max` (80rem). `.narrow` uses 48rem, `.wide` 90rem. | None |
23
+ | `.divider` | A horizontal line, as wide as its container. `.vertical` makes it a vertical line as tall as the row. | None |
24
+ | `.visually-hidden` | Hides content on screen and keeps it for screen readers. | None |
40
25
 
41
- A table draws three kinds of line, and `.ruled` and `.ruleless` move all of them together:
26
+ `.auto-grid` fits two 16rem columns once its container is 32rem plus the gap wide, three at 48rem plus two gaps, and so on. Below one column's width, the column shrinks to fit. Set `--layout-grid-min` on the grid to change the column width.
42
27
 
43
- | Class | Head and foot boundaries | Rules between body rows |
44
- | ----------- | ------------------------ | ----------------------- |
45
- | `.ruleless` | No | No |
46
- | _no class_ | Yes | No |
47
- | `.ruled` | Yes | Yes |
28
+ `--layout-gutter` is `clamp(1rem, 4vw, 2rem)` and `--layout-section-block` is `clamp(4rem, 9vw, 7rem)`: both grow with the window between those bounds. The full list of foundation tokens is in [Theming → Foundation tokens](./theming.md#foundation-tokens).
48
29
 
49
- ```html
50
- <table class="data-table">
51
- Head and foot boundaries only
52
- </table>
53
- <table class="data-table ruled">
54
- Every row separated
55
- </table>
56
- <table class="data-table ruleless">
57
- No lines inside the table at all
58
- </table>
59
- ```
30
+ A `.divider` takes an intent, which colors it, and ignores presentation classes, so a `.ghost.edgeless` container does not hide the dividers inside it. Its width is the aesthetic's border width.
60
31
 
61
- The boundaries under a head and above a foot separate the parts of a table from each other, so they are drawn by default where the row rules are not. Rules between body rows used to arrive on their own, because the component's published edge default is `edged` and the edge axis wrote the rules along with the boundary — so whether you got them depended on a registry default rather than on anything in your markup.
32
+ `.visually-hidden` is not named `.sr-only` because Tailwind ships a `.sr-only` of its own, and two classes with one name would conflict.
62
33
 
63
- `--ui-rule` is the token behind both classes, so a container can set the answer for a whole region without classing each table:
34
+ ## Typography
64
35
 
65
- ```html
66
- <section style="--ui-rule: 100%">
67
- <table class="data-table">
68
- Ruled by the region
69
- </table>
70
- </section>
71
- ```
36
+ | Class | Size | Weight | Letter spacing |
37
+ | ---------------- | ----------------------------- | -------- | -------------- |
38
+ | `.text-display` | 3.75rem, 6rem from 48rem wide | Bold | Tight |
39
+ | `.text-title-lg` | 3rem, 3.75rem from 48rem wide | Bold | Tight |
40
+ | `.text-title` | 1.875rem | Bold | Tight |
41
+ | `.text-title-sm` | 1.25rem | Semibold | Tight |
42
+ | `.text-label-lg` | 1.125rem | Medium | Wide |
43
+ | `.text-label` | 1rem | Medium | Wide |
44
+ | `.text-body` | 0.875rem | Normal | Wider |
72
45
 
73
- The frame around the table is the edge axis and is asked for the same way: `.data-table` publishes `edgeless`, so `.edged` draws one. None of the three switches reaches the others — `.data-table.ruleless.edged` is a framed table with no lines inside it, and `.data-table.ruled` is a frameless one with every row separated.
46
+ The two largest sizes grow at Tailwind's `md` breakpoint, 48rem by default. With the Tailwind source entrypoints, your own `md` breakpoint applies. The package sets no size on unclassed text: body text and unclassed headings take the browser's size, or the surrounding text size under the reset; see [Setup → Classless HTML](../setup.md#classless-html) for the classless mapping.
74
47
 
75
- A table's rows deliberately inherit its intent instead of resetting it, so `.data-table.success` tints throughout. A row carrying its own intent still wins:
48
+ `.text-body` is 0.875rem, smaller than the 1rem page text; use it for secondary or dense copy, not for the page's main text.
76
49
 
77
- ```html
78
- <table class="data-table success">
79
- <tbody>
80
- <tr>
81
- <td>Inherits the table intent</td>
82
- </tr>
83
- <tr class="destructive">
84
- <td>Overrides it for this row</td>
85
- </tr>
86
- </tbody>
87
- </table>
88
- ```
50
+ `.selection-contrast` on an element swaps the colors of selected text inside it to `--color-primary` on `--color-primary-contrast`. Use it on a `.solid.primary` area, where the default selection color would match the background.
89
51
 
90
- This is the one place intent cascades, because a table's rows are parts of the table rather than independent components.
52
+ ## Surfaces
91
53
 
92
- `.data-table`, `.kbd`, `.code`, and `.pre` also read [presentation](./composing.md#presentation). A table applies it to its header, its rules and its border; a chip to its whole plate:
54
+ `.card` and `.panel` are the two containers. Both take intent, [presentation](./composing.md#presentation), and [material tokens](./customizing.md#material-tokens).
93
55
 
94
- ```html
95
- <table class="data-table success soft edged">
96
- ...
97
- </table>
98
- <table class="data-table">
99
- A ghost table: rules and type, no header plate
100
- </table>
101
- <kbd class="kbd primary solid">Ctrl</kbd>
102
- <kbd class="kbd primary soft edged">Shift</kbd>
103
- ```
56
+ | Class | Default look | Padding by default |
57
+ | -------- | --------------------------------------------------------------------------- | ------------------ |
58
+ | `.card` | No fill, a border, the surface corner, and a resting elevation of 1. | 1.25rem |
59
+ | `.panel` | The quiet background tone, no border, the surface corner, and no elevation. | 1rem |
60
+
61
+ A resting elevation of 1 shows no shadow by itself. A card has a shadow only under an [aesthetic](./aesthetics.md) that draws depth, or with `.raised` or `.floating`; see [Composing → Elevation](./composing.md#elevation).
62
+
63
+ Padding classes:
64
+
65
+ | Class | On `.card` | On `.panel` |
66
+ | -------- | ---------- | ----------- |
67
+ | `.p-xs` | 0.5rem | 0.25rem |
68
+ | `.p-sm` | 0.75rem | 0.5rem |
69
+ | _none_ | 1.25rem | 1rem |
70
+ | `.p-lg` | 2rem | 1.5rem |
71
+ | `.flush` | 0 | 0 |
72
+
73
+ `.flush` is for content that runs edge to edge, such as an image or a table inside a card.
74
+
75
+ A padding class applies only to the card or panel it is on. A card or panel nested inside keeps its own padding, so a `.card.flush` holding a `.panel` still pads the panel by 1rem.
76
+
77
+ A panel is for sidebars, toolbars, and wells: areas that are part of the page, not objects on it. A card is a self-contained object, such as the profile card or the plan card on the settings screen.
78
+
79
+ ### Neutral cards and panels
80
+
81
+ A neutral `.card.soft` and a neutral `.panel` show no tint: they rest on the quiet background tone one step off the page, so they read as a separate area without drawing attention. With a built-in intent they take the ordinary tint. [Composing → Neutral surfaces rest untinted](./composing.md#neutral-surfaces-rest-untinted) has the details, including hover.
82
+
83
+ ### Clickable cards
104
84
 
105
- `.ghost` means two different things on these components, and both are worth knowing before you reach for it.
85
+ | Class | Effect |
86
+ | -------------- | --------------------------------------------------------------------------------------------------------- |
87
+ | `.interactive` | Pointer cursor, hover color, press, and a focus ring. The same as `.hoverable` and `.pressable` together. |
88
+ | `.hoverable` | The hover color only, with no pointer cursor. |
89
+ | `.pressable` | The press and the pointer cursor only. |
106
90
 
107
- On `.data-table` it removes the header plate along with the body tint, so `.data-table.ghost` is boundaries and type alone. The component rests at `soft`, so that is something to ask for rather than the default.
91
+ On the default look, a press scales the card down slightly (`scale(0.97)`); an aesthetic can replace that with its own press, and a reduced-motion preference turns it off.
108
92
 
109
- `.soft` rests untinted throughout -- `--color-foreground`, no intent color mixed in, for every intent, including the resting default, on the head plate and the table's own base fill alike. A table has no hover or interaction state to reveal a tint into the way `.card.soft` does on `.interactive`/`.hoverable`, so unlike a card there is no state where a `.data-table.success.soft` reveals green; only the boundary and rule lines still read the intent.
93
+ Use one half for a card that answers only one gesture. A card that holds its own button takes `.hoverable`, so that pressing the button does not press the whole card.
110
94
 
111
- On `.kbd`, `.code`, and `.pre` it is **not supported**. All three rest on `--intent-subtle`, and that ground draws the plate whatever the fill says — so `.ghost` took the fill away and changed nothing visible. Worse, the ground alone is a near-page tint: a ghost chip measured the same `#e5e5e5` for neutral and primary on the light page, and `#f5f5f5` at 1.04:1 against it for secondary. A named intent rests at `.soft` instead, which puts a real `12%` of the intent over the ground and separates it from the others; the no-named-intent case reads no differently from `.ghost` either way, so it rests at the ground alone rather than adding an unmotivated wash of its own.
95
+ ```html
96
+ <article class="card">Neutral card</article>
97
+ <article class="card success solid">Filled success card</article>
98
+ <article class="card primary ghost edged">Intent border, no fill</article>
99
+ <a class="card success soft interactive" href="/settings/billing">Billing: tinted at rest, deeper on hover</a>
100
+ <article class="card hoverable">Tinted on hover; the action is a nested button</article>
101
+ <aside class="panel">A sidebar</aside>
102
+ ```
103
+
104
+ These classes only style. Put them on a real link or button and give it an accessible name; a `<div class="card interactive">` cannot be focused or used from a keyboard.
112
105
 
113
- Use `.table-wrap` around `.data-table` when table width may exceed its container:
106
+ ## Tables
107
+
108
+ The settings screen lists API keys in a table:
114
109
 
115
110
  ```html
116
111
  <div class="table-wrap">
117
112
  <table class="data-table">
113
+ <caption class="visually-hidden">
114
+ API keys
115
+ </caption>
118
116
  <thead>
119
117
  <tr>
120
- <th>Package</th>
121
- <th>Status</th>
118
+ <th scope="col">Name</th>
119
+ <th scope="col">Created</th>
120
+ <th scope="col">Status</th>
122
121
  </tr>
123
122
  </thead>
124
123
  <tbody>
125
124
  <tr>
126
- <td>styles</td>
127
- <td>Ready</td>
125
+ <td>Deploy bot</td>
126
+ <td>3 March 2026</td>
127
+ <td>Active</td>
128
+ </tr>
129
+ <tr class="destructive">
130
+ <td>Old laptop</td>
131
+ <td>12 June 2024</td>
132
+ <td>Revoked</td>
128
133
  </tr>
129
134
  </tbody>
130
135
  </table>
131
136
  </div>
132
137
  ```
133
138
 
134
- ## Surfaces
139
+ | Class | Effect |
140
+ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
141
+ | `.data-table` | Styles a `<table>`: full width, `.text-body` text, a header background, the surface corner, cell padding, and a hover color on body rows. |
142
+ | `.table-wrap` | Scrolls a table sideways when it is wider than its container. |
143
+ | `.ruled` | On `.data-table`. Draws a line between body rows. |
144
+ | `.ruleless` | On `.data-table`. Draws no lines inside the table. |
145
+
146
+ ### Row intent
147
+
148
+ A table's rows take the table's intent, so `.data-table.success` colors its header and lines green. A row with its own intent class uses that instead, as the revoked key's `<tr class="destructive">` does. `<tr class="neutral">` sets a row back to neutral inside a colored table. On a `.solid` table, a row with its own intent keeps the table's text color so it stays readable on the table's fill, and shows its intent through its row line and hover. This is the one place an intent passes down, because rows are parts of the table, not separate components.
149
+
150
+ ### Table rules
135
151
 
136
- | Class | Purpose |
137
- | -------------- | ------------------------------------------------------------------------------------- |
138
- | `.card` | Bordered container, surface radius, padded. Rests at elevation `1`. |
139
- | `.panel` | Flush container for sidebars, toolbars, and wells. No elevation. |
140
- | `.interactive` | On `.card`. Adds pointer cursor, hover and press response, and a focus ring. |
141
- | `.hoverable` | On `.card`. The hover half of `.interactive`: hover response only, no pointer cursor. |
142
- | `.pressable` | On `.card`. The press half of `.interactive`: press response and pointer cursor. |
143
- | `.p-xs` | On `.card` or `.panel`. Reduces padding further than `.p-sm`. |
144
- | `.p-sm` | On `.card` or `.panel`. Reduces padding. |
145
- | `.p-lg` | On `.card` or `.panel`. Increases padding. |
146
- | `.flush` | On `.card` or `.panel`. Removes padding, for edge-to-edge content. |
152
+ A table draws lines under its header and above its footer. `.ruled` and `.ruleless` change them together with the lines between body rows:
147
153
 
148
- Both read intent, [presentation](./composing.md#presentation), and [material tokens](./customizing.md#material-tokens). A plain `.card` is a neutral bordered container; only an explicit presentation tints it. Resting at elevation `1` is not a visible shadow by itself — nothing draws depth until an [aesthetic](./aesthetics.md) supplies shadow geometry or `.raised`/`.floating` asks for it; see [Composing → Elevation](./composing.md#elevation).
154
+ | Class | Under the header and above the footer | Between body rows |
155
+ | ----------- | ------------------------------------- | ----------------- |
156
+ | `.ruleless` | No | No |
157
+ | _none_ | Yes | No |
158
+ | `.ruled` | Yes | Yes |
149
159
 
150
- `.card.soft` with no named intent is untinted at rest — a plain `--color-foreground` plate, no ink mixed in, marking a different container without drawing attention to it. The intent tint and a `--color-surface` ground only appear together, on `:hover`, and only on `.card.interactive`/`.card.hoverable`: a plain `.card.soft` with neither has no hover state to reveal into and stays at the quiet rest. A named intent (`.card.soft.success`, `.card.soft.destructive`, and so on) keeps its ordinary tint at rest instead, and deepens further on hover the same way any other filled surface does — only the no-intent case is untinted, since removing an intent's own color would silence it rather than quiet it. `.solid` and `.ghost` are unaffected either way.
160
+ `--ui-rule` is the token behind both classes, so a container can rule every table inside it: `style="--ui-rule: 100%"` acts like `.ruled`, and `0%` like `.ruleless`.
151
161
 
152
- `.panel` with no named intent behaves the same way, permanently rather than on hover: a plain `.panel` rests at the same untinted `--color-foreground` plate a neutral `.card.soft` does, because a panel has no hover state to reveal a tint into. `.panel.primary`, `.panel.destructive`, and every other named intent keep their ordinary tint. `.kbd`, `.code`, and `.pre` follow the same no-named-intent rule for their own fill, without moving off their `--intent-subtle` ground.
162
+ The frame around the table is separate: a table has no border by default, and `.edged` adds one. The three choices do not affect each other, so `.data-table.ruleless.edged` is a framed table with no lines inside, and `.data-table.ruled` has every row separated and no frame.
153
163
 
154
- On the base look, `.card.interactive` scales down slightly on press (`--ui-active-transform`, `scale(0.97)`); an [aesthetic](./aesthetics.md) substitutes its own press gesture, and `prefers-reduced-motion` turns it off.
164
+ ### Presentation on tables
155
165
 
156
- `.interactive` is the pair `.hoverable` (hover response only, no pointer cursor) and `.pressable` (press response and pointer cursor) applied together. Take one half for a card that answers a single gesture: a card that warms on hover but holds its own action in a nested button takes `.hoverable`, so pressing that button does not dip the whole card.
166
+ A table reads [presentation](./composing.md#presentation) on its header, its lines, and its border:
157
167
 
158
168
  ```html
159
- <article class="card">Neutral card</article>
160
- <article class="card success solid">Filled success card</article>
161
- <article class="card primary ghost edged">Intent border, no fill</article>
162
- <a class="card success soft interactive" href="/package">Success-tinted at rest; deepens on hover</a>
163
- <article class="card hoverable">Warms on hover; the action is a nested button</article>
164
- <aside class="panel">Flush panel</aside>
169
+ <table class="data-table success soft edged">
170
+ …
171
+ </table>
172
+ <table class="data-table ghost">
173
+ <!-- No header background: only lines and text -->
174
+ </table>
165
175
  ```
166
176
 
167
- `.interactive` and `.pressable` are styling only. Use a real interactive element and give it an accessible name; a `<div class="card interactive">` is not focusable or operable by keyboard.
177
+ - `.soft`, the default, gives the header the quiet background tone, `--color-foreground`, for every intent. A table has no hover state for a tint, so a `.data-table.success.soft` does not turn green; its lines and border do.
178
+ - `.ghost` removes the header background, leaving lines and text.
179
+ - `.solid` fills the header with the intent color.
180
+
181
+ ### Corners and scrolling
182
+
183
+ A table takes the surface corner, like a card beside it. The corner cells carry the corners, so a `<caption>` above the table is not cut off in any browser. A cell that spans rows down into a bottom corner leaves that corner square.
184
+
185
+ `.table-wrap` scrolls, and a scrolling element cuts off whatever is drawn outside it, including a tooltip on a cell; see [Tooltips → Where a tooltip gets cut off](./tooltips.md#where-a-tooltip-gets-cut-off).
186
+
187
+ - Under an aesthetic that draws a glow around components, such as `.cyber`, the wrapper makes room for the glow so it is not cut off. The wrapper then extends that far past its parent, which only shows when the parent touches the edge of the window.
188
+ - The wrapper can only make room for a glow from an aesthetic around it. Put the aesthetic class on `.table-wrap` or an element above it, not on the table alone.
189
+ - Shadows, such as a `.raised` table's, get no room and are cut off.
190
+
191
+ Keep the wrapper on any table that could be wider than its container; without it, a wide table widens the whole page.
192
+
193
+ ## Quotes, code, and keys
194
+
195
+ | Class | Use | Default look | Intent colors |
196
+ | --------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------ |
197
+ | `.quote` | A `<blockquote>`. A `<cite>` inside it is upright and takes the quote's color. | A bar at the start, no fill | Bar, background, text |
198
+ | `.quote-inline` | An inline `<q>` quotation. | Quotation styling only | Nothing |
199
+ | `.kbd` | A key the user presses, such as <kbd>Ctrl</kbd>. | A tinted chip with a border | Background, border, text |
200
+ | `.code` | Inline code. | A tinted chip with no border | Background, text |
201
+ | `.pre` | A block of code. It scrolls sideways when a line is too long. | A tinted block with no border | Background, text |
202
+
203
+ ```html
204
+ <p>Press <kbd class="kbd">Ctrl</kbd> + <kbd class="kbd">K</kbd> to search members.</p>
205
+ <p>Use the <code class="code">Authorization</code> header with your API key.</p>
206
+ <kbd class="kbd primary solid">Ctrl</kbd>
207
+ <kbd class="kbd primary soft edged">Shift</kbd>
208
+ ```
168
209
 
169
- ## Typography utilities
210
+ A `.kbd`, `.code`, or `.pre` rests on its intent's subtle tone, `--color-surface` for neutral, and a built-in intent class adds 12% of its color over it. `.ghost` is not supported on these three: the tinted background is what makes them chips, so they keep it and `.ghost` changes nothing. Their font is `--font-mono`; see [Theming → Fonts](./theming.md#fonts).
170
211
 
171
- All typography classes and `.selection-contrast` are `@utility` classes.
212
+ ## Next
172
213
 
173
- | Class | Purpose |
174
- | --------------------- | ------------------------------------------------------------ |
175
- | `.text-display` | Large display headings. |
176
- | `.text-title-lg` | Large section titles. |
177
- | `.text-title` | Default section titles. |
178
- | `.text-title-sm` | Smaller titles or card titles. |
179
- | `.text-label-lg` | Large label text. |
180
- | `.text-label` | Default label text. |
181
- | `.text-body` | Default body copy. |
182
- | `.selection-contrast` | Inverts `::selection` colors to primary-contrast background. |
214
+ [Accessibility](../accessibility.md) lists what the CSS does for your users and what your application still owes them.