@codenhub/styles 0.6.0 → 0.8.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 (151) hide show
  1. package/NOTICE +18 -16
  2. package/README.es.md +62 -0
  3. package/README.md +28 -22
  4. package/README.pt-BR.md +62 -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/cli.js +189 -0
  13. package/dist/components.css +2 -2
  14. package/dist/index.css +2 -2
  15. package/dist/index.d.ts +1 -0
  16. package/dist/native.css +2 -2
  17. package/dist/palette.css +1 -1
  18. package/dist/theme.css +2 -2
  19. package/docs/accessibility.md +108 -60
  20. package/docs/changelog/0.1.1.md +1 -0
  21. package/docs/changelog/0.2.0.md +1 -0
  22. package/docs/changelog/0.3.0.md +1 -0
  23. package/docs/changelog/0.4.0.md +1 -0
  24. package/docs/changelog/0.5.0.md +8 -3
  25. package/docs/changelog/0.6.0.md +2 -1
  26. package/docs/changelog/0.7.0.md +50 -0
  27. package/docs/changelog/0.8.0.md +70 -0
  28. package/docs/changelog/index.md +2 -0
  29. package/docs/concepts.md +188 -46
  30. package/docs/es/accessibility.md +169 -0
  31. package/docs/es/concepts.md +212 -0
  32. package/docs/es/index.md +105 -0
  33. package/docs/es/integrating/astro.md +35 -0
  34. package/docs/es/integrating/index.md +75 -0
  35. package/docs/es/integrating/nextjs.md +67 -0
  36. package/docs/es/integrating/svelte.md +45 -0
  37. package/docs/es/integrating/tailwind.md +148 -0
  38. package/docs/es/integrating/vue.md +31 -0
  39. package/docs/es/integrating/without-a-bundler.md +238 -0
  40. package/docs/es/setup.md +188 -0
  41. package/docs/es/usage/aesthetics.md +282 -0
  42. package/docs/es/usage/buttons.md +135 -0
  43. package/docs/es/usage/composing.md +168 -0
  44. package/docs/es/usage/content-and-layout.md +219 -0
  45. package/docs/es/usage/customizing.md +304 -0
  46. package/docs/es/usage/feedback.md +157 -0
  47. package/docs/es/usage/forms.md +256 -0
  48. package/docs/es/usage/index.md +33 -0
  49. package/docs/es/usage/presets.md +92 -0
  50. package/docs/es/usage/solo.md +86 -0
  51. package/docs/es/usage/theming.md +309 -0
  52. package/docs/es/usage/tooltips.md +127 -0
  53. package/docs/index.md +86 -26
  54. package/docs/integrating/astro.md +3 -4
  55. package/docs/integrating/index.md +46 -13
  56. package/docs/integrating/nextjs.md +3 -4
  57. package/docs/integrating/svelte.md +5 -4
  58. package/docs/integrating/tailwind.md +89 -6
  59. package/docs/integrating/vue.md +3 -4
  60. package/docs/integrating/without-a-bundler.md +237 -0
  61. package/docs/pt-BR/accessibility.md +169 -0
  62. package/docs/pt-BR/concepts.md +212 -0
  63. package/docs/pt-BR/index.md +105 -0
  64. package/docs/pt-BR/integrating/astro.md +35 -0
  65. package/docs/pt-BR/integrating/index.md +75 -0
  66. package/docs/pt-BR/integrating/nextjs.md +67 -0
  67. package/docs/pt-BR/integrating/svelte.md +45 -0
  68. package/docs/pt-BR/integrating/tailwind.md +148 -0
  69. package/docs/pt-BR/integrating/vue.md +31 -0
  70. package/docs/pt-BR/integrating/without-a-bundler.md +238 -0
  71. package/docs/pt-BR/setup.md +188 -0
  72. package/docs/pt-BR/usage/aesthetics.md +282 -0
  73. package/docs/pt-BR/usage/buttons.md +135 -0
  74. package/docs/pt-BR/usage/composing.md +168 -0
  75. package/docs/pt-BR/usage/content-and-layout.md +219 -0
  76. package/docs/pt-BR/usage/customizing.md +304 -0
  77. package/docs/pt-BR/usage/feedback.md +157 -0
  78. package/docs/pt-BR/usage/forms.md +256 -0
  79. package/docs/pt-BR/usage/index.md +33 -0
  80. package/docs/pt-BR/usage/presets.md +92 -0
  81. package/docs/pt-BR/usage/solo.md +86 -0
  82. package/docs/pt-BR/usage/theming.md +309 -0
  83. package/docs/pt-BR/usage/tooltips.md +127 -0
  84. package/docs/setup.md +142 -91
  85. package/docs/usage/aesthetics.md +89 -73
  86. package/docs/usage/buttons.md +112 -40
  87. package/docs/usage/composing.md +109 -92
  88. package/docs/usage/content-and-layout.md +160 -125
  89. package/docs/usage/customizing.md +117 -41
  90. package/docs/usage/feedback.md +138 -71
  91. package/docs/usage/forms.md +201 -107
  92. package/docs/usage/index.md +22 -14
  93. package/docs/usage/presets.md +91 -0
  94. package/docs/usage/solo.md +85 -0
  95. package/docs/usage/theming.md +273 -118
  96. package/docs/usage/tooltips.md +90 -49
  97. package/llms-full.txt +2820 -1298
  98. package/llms.txt +24 -22
  99. package/package.json +134 -91
  100. package/{dist/tw → tw}/aesthetics/chunky-tile.css +107 -29
  101. package/{dist/tw → tw}/aesthetics/cyber.css +88 -40
  102. package/{dist/tw → tw}/aesthetics/glass.css +257 -61
  103. package/{dist/tw → tw}/aesthetics/neobrutalism.css +113 -20
  104. package/{dist/tw → tw}/aesthetics/pixel.css +93 -8
  105. package/tw/aesthetics/sketch.css +417 -0
  106. package/{dist/tw → tw}/box.css +105 -9
  107. package/tw/components/button.css +11 -0
  108. package/tw/components/button.rules.css +187 -0
  109. package/tw/components/feedback.css +11 -0
  110. package/{dist/tw/components/feedback.css → tw/components/feedback.rules.css} +136 -32
  111. package/tw/components/form.css +11 -0
  112. package/{dist/tw/components/form.css → tw/components/form.rules.css} +577 -125
  113. package/tw/components/index.css +16 -0
  114. package/tw/components/rules.css +41 -0
  115. package/tw/components/surface.css +11 -0
  116. package/tw/components/surface.rules.css +222 -0
  117. package/tw/components/tooltip.css +11 -0
  118. package/{dist/tw/components/tooltip.css → tw/components/tooltip.rules.css} +43 -27
  119. package/{dist/tw → tw}/corner.css +18 -12
  120. package/{dist/tw → tw}/elevation.css +23 -17
  121. package/{dist/tw → tw}/index.css +12 -10
  122. package/tw/index.d.ts +1 -0
  123. package/tw/intent.css +312 -0
  124. package/tw/modifiers.css +127 -0
  125. package/tw/native.css +320 -0
  126. package/tw/presentation.css +139 -0
  127. package/tw/reset.css +10 -0
  128. package/{dist/tw/reset.css → tw/reset.rules.css} +21 -22
  129. package/tw/size.css +34 -0
  130. package/tw/surface.css +9 -0
  131. package/tw/surface.rules.css +212 -0
  132. package/{dist/tw → tw}/theme.css +121 -45
  133. package/tw/typography.css +8 -0
  134. package/{dist/tw/typography.css → tw/typography.rules.css} +0 -3
  135. package/{dist/tw → tw}/utilities/content.css +212 -50
  136. package/tw/utilities/index.css +11 -0
  137. package/tw/utilities/layout.css +208 -0
  138. package/tw/utilities/rules.css +8 -0
  139. package/dist/tw/aesthetics/sketch.css +0 -333
  140. package/dist/tw/components/button.css +0 -139
  141. package/dist/tw/components/index.css +0 -36
  142. package/dist/tw/components/loader.css +0 -116
  143. package/dist/tw/components/surface.css +0 -175
  144. package/dist/tw/intent.css +0 -228
  145. package/dist/tw/native.css +0 -203
  146. package/dist/tw/palette.css +0 -460
  147. package/dist/tw/presentation.css +0 -68
  148. package/dist/tw/surface.css +0 -61
  149. package/dist/tw/utilities/index.css +0 -6
  150. package/dist/tw/utilities/layout.css +0 -130
  151. /package/{dist/tw → tw}/aesthetics/index.css +0 -0
@@ -1,183 +1,218 @@
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
- - `.section` adds responsive block padding and an inline gutter.
18
- - `.section-content` centers content at `--container-max`; `.narrow` and `.wide` select the corresponding container tokens.
19
- - `.divider` is horizontal; `.vertical` makes it self-stretch vertically. It takes intent, but presentation classes do not affect it.
20
- - `.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`.
21
-
22
- ## Content
23
-
24
- | Class | Purpose | Intent affects |
25
- | --------------- | ---------------------------------------------------------------------------------------- | ---------------------- |
26
- | `.table-wrap` | Full-width horizontal overflow wrapper for wide tables. | Nothing. |
27
- | `.data-table` | Rounded nested table styling for captions, heads, footers, cells, and rows. | Head, border, hover. |
28
- | `.ruled` | On `.data-table`. Draws a rule between body rows. | Rule color. |
29
- | `.ruleless` | On `.data-table`. Draws no lines inside the table at all. | Nothing. |
30
- | `.kbd` | Inline keyboard-input styling. | Surface, border, text. |
31
- | `.quote` | Block quote styling; a nested `cite` is set upright and takes the quotation's own color. | Bar, surface, text. |
32
- | `.quote-inline` | Inline quotation styling. | Nothing. |
33
- | `.code` | Inline code formatting. | Surface. |
34
- | `.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.
35
14
 
36
- ### 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 |
37
25
 
38
- 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.
39
27
 
40
- | Class | Head and foot boundaries | Rules between body rows |
41
- | ----------- | ------------------------ | ----------------------- |
42
- | `.ruleless` | No | No |
43
- | _no class_ | Yes | No |
44
- | `.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).
45
29
 
46
- ```html
47
- <table class="data-table">
48
- <!-- Head and foot boundaries only -->
49
- </table>
50
- <table class="data-table ruled">
51
- <!-- Every row separated -->
52
- </table>
53
- <table class="data-table ruleless">
54
- <!-- No lines inside the table at all -->
55
- </table>
56
- ```
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.
57
31
 
58
- 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 are asked for by `.ruled` or `--ui-rule`, never by the edge axis, so whether you get them depends on your markup and not on a default you cannot see.
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.
59
33
 
60
- `--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
61
35
 
62
- ```html
63
- <section style="--ui-rule: 100%">
64
- <table class="data-table">
65
- <!-- Ruled by the region -->
66
- </table>
67
- </section>
68
- ```
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 |
69
45
 
70
- 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.
71
47
 
72
- 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. `/native` is the exception: it sets `.text-body` on `body`, so there it is the page text, and paragraphs and list items inherit it from whatever they sit in. See [Classless HTML](../setup.md#classless-html).
73
49
 
74
- ```html
75
- <table class="data-table success">
76
- <tbody>
77
- <tr>
78
- <td>Inherits the table intent</td>
79
- </tr>
80
- <tr class="destructive">
81
- <td>Overrides it for this row</td>
82
- </tr>
83
- </tbody>
84
- </table>
85
- ```
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.
51
+
52
+ ## Surfaces
86
53
 
87
- This is the one place intent cascades, because a table's rows are parts of the table rather than independent components.
54
+ `.card` and `.panel` are the two containers. Both take intent, [presentation](./composing.md#presentation), and [material tokens](./customizing.md#material-tokens).
88
55
 
89
- `.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:
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
84
+
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. |
90
+
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 under a reduced-motion preference it still happens, at once.
92
+
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.
90
94
 
91
95
  ```html
92
- <table class="data-table success soft edged">
93
- <!-- ... -->
94
- </table>
95
- <table class="data-table ghost">
96
- <!-- A ghost table: rules and type, no header plate -->
97
- </table>
98
- <kbd class="kbd primary solid">Ctrl</kbd>
99
- <kbd class="kbd primary soft edged">Shift</kbd>
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>
100
102
  ```
101
103
 
102
- `.ghost` means two different things on these components, and both are worth knowing before you reach for it.
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.
103
105
 
104
- 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.
106
+ A disabled `.interactive` or `.pressable` card shows the not-allowed cursor instead of the pointer, whether it is a `<button>` with `disabled`, or carries `.disabled`, `aria-disabled="true"`, or `data-disabled`.
105
107
 
106
- `.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.
108
+ ## Tables
107
109
 
108
- 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.
109
-
110
- Use `.table-wrap` around `.data-table` when table width may exceed its container:
110
+ The settings screen lists API keys in a table:
111
111
 
112
112
  ```html
113
113
  <div class="table-wrap">
114
114
  <table class="data-table">
115
+ <caption class="visually-hidden">
116
+ API keys
117
+ </caption>
115
118
  <thead>
116
119
  <tr>
117
- <th>Package</th>
118
- <th>Status</th>
120
+ <th scope="col">Name</th>
121
+ <th scope="col">Created</th>
122
+ <th scope="col">Status</th>
119
123
  </tr>
120
124
  </thead>
121
125
  <tbody>
122
126
  <tr>
123
- <td>styles</td>
124
- <td>Ready</td>
127
+ <td>Deploy bot</td>
128
+ <td>3 March 2026</td>
129
+ <td>Active</td>
130
+ </tr>
131
+ <tr class="destructive">
132
+ <td>Old laptop</td>
133
+ <td>12 June 2024</td>
134
+ <td>Revoked</td>
125
135
  </tr>
126
136
  </tbody>
127
137
  </table>
128
138
  </div>
129
139
  ```
130
140
 
131
- A table takes the surface corner, like a card beside it. Nothing clips it: the four corner cells take the corners, so a `<caption>` sits above the table untouched in every engine. A cell that spans rows down into a bottom corner leaves that corner square.
141
+ | Class | Effect |
142
+ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
143
+ | `.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. |
144
+ | `.table-wrap` | Scrolls a table sideways when it is wider than its container. |
145
+ | `.ruled` | On `.data-table`. Draws a line between body rows. |
146
+ | `.ruleless` | On `.data-table`. Draws no lines inside the table. |
132
147
 
133
- `.table-wrap` scrolls, and a scroll container clips whatever paints outside it. Under an aesthetic that draws a halo -- cyber's glow -- the wrapper pads itself by the halo's reach and pulls itself out by the same amount, so the glow fits inside it and the table stays where it would be. The wrapper then reaches that far past its parent, which only shows when the parent is flush with the viewport. Depth shadows, such as a `.raised` table's, are not given room and are still cut. The wrapper can only make room for a halo it is inside, so put the aesthetic class on `.table-wrap` or an ancestor rather than on a wrapped table alone: `<table class="data-table cyber">` inside a plain wrapper glows, and the wrapper cuts the glow. Leave the wrapper off a table that can never outgrow its container; keep it wherever one can, or a wide table widens the whole page.
148
+ ### Row intent
134
149
 
135
- ## Surfaces
150
+ 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.
151
+
152
+ Only the six built-in intents and `.neutral` recolor a body row. A row with an intent you defined yourself, such as `<tr class="beta">`, looks like the rest of the table: its text, line, and hover come from the table's intent. To mark such a row, write a built-in intent class on the row and retheme that intent's color family on the row, as [Theming → Your own intent](./theming.md#your-own-intent) describes, or paint the row with your own utilities.
153
+
154
+ ### Table rules
136
155
 
137
- | Class | Purpose |
138
- | -------------- | ------------------------------------------------------------------------------------- |
139
- | `.card` | Bordered container, surface radius, padded. Rests at elevation `1`. |
140
- | `.panel` | Flush container for sidebars, toolbars, and wells. No elevation. |
141
- | `.interactive` | On `.card`. Adds pointer cursor, hover and press response, and a focus ring. |
142
- | `.hoverable` | On `.card`. The hover half of `.interactive`: hover response only, no pointer cursor. |
143
- | `.pressable` | On `.card`. The press half of `.interactive`: press response and pointer cursor. |
144
- | `.p-xs` | On `.card` or `.panel`. Reduces padding further than `.p-sm`. |
145
- | `.p-sm` | On `.card` or `.panel`. Reduces padding. |
146
- | `.p-lg` | On `.card` or `.panel`. Increases padding. |
147
- | `.flush` | On `.card` or `.panel`. Removes padding, for edge-to-edge content. |
156
+ A table draws lines under its header and above its footer. `.ruled` and `.ruleless` change them together with the lines between body rows:
148
157
 
149
- 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).
158
+ | Class | Under the header and above the footer | Between body rows |
159
+ | ----------- | ------------------------------------- | ----------------- |
160
+ | `.ruleless` | No | No |
161
+ | _none_ | Yes | No |
162
+ | `.ruled` | Yes | Yes |
150
163
 
151
- `.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.
164
+ `--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`.
152
165
 
153
- `.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.
166
+ 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.
154
167
 
155
- 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.
168
+ ### Presentation on tables
156
169
 
157
- `.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.
170
+ A table reads [presentation](./composing.md#presentation) on its header, its lines, and its border:
158
171
 
159
172
  ```html
160
- <article class="card">Neutral card</article>
161
- <article class="card success solid">Filled success card</article>
162
- <article class="card primary ghost edged">Intent border, no fill</article>
163
- <a class="card success soft interactive" href="/package">Success-tinted at rest; deepens on hover</a>
164
- <article class="card hoverable">Warms on hover; the action is a nested button</article>
165
- <aside class="panel">Flush panel</aside>
173
+ <table class="data-table success soft edged">
174
+ …
175
+ </table>
176
+ <table class="data-table ghost">
177
+ <!-- No header background: only lines and text -->
178
+ </table>
166
179
  ```
167
180
 
168
- `.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.
181
+ - `.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.
182
+ - `.ghost` removes the header background, leaving lines and text.
183
+ - `.solid` fills the header with the intent color.
184
+
185
+ ### Corners and scrolling
186
+
187
+ 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.
188
+
189
+ `.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).
190
+
191
+ - 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.
192
+ - 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.
193
+ - Shadows, such as a `.raised` table's, get no room and are cut off.
194
+
195
+ Keep the wrapper on any table that could be wider than its container; without it, a wide table widens the whole page.
196
+
197
+ ## Quotes, code, and keys
198
+
199
+ | Class | Use | Default look | Intent colors |
200
+ | --------------- | ------------------------------------------------------------------------------ | ----------------------------- | ------------------------ |
201
+ | `.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 |
202
+ | `.quote-inline` | An inline `<q>` quotation. | Quotation styling only | Nothing |
203
+ | `.kbd` | A key the user presses, such as <kbd>Ctrl</kbd>. | A tinted chip with a border | Background, border, text |
204
+ | `.code` | Inline code. | A tinted chip with no border | Background, text |
205
+ | `.pre` | A block of code. It scrolls sideways when a line is too long. | A tinted block with no border | Background, text |
206
+
207
+ ```html
208
+ <p>Press <kbd class="kbd">Ctrl</kbd> + <kbd class="kbd">K</kbd> to search members.</p>
209
+ <p>Use the <code class="code">Authorization</code> header with your API key.</p>
210
+ <kbd class="kbd primary solid">Ctrl</kbd>
211
+ <kbd class="kbd primary soft edged">Shift</kbd>
212
+ ```
169
213
 
170
- ## Typography utilities
214
+ 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).
171
215
 
172
- All typography classes and `.selection-contrast` are `@utility` classes.
216
+ ## Next
173
217
 
174
- | Class | Purpose |
175
- | --------------------- | ------------------------------------------------------------ |
176
- | `.text-display` | Large display headings. |
177
- | `.text-title-lg` | Large section titles. |
178
- | `.text-title` | Default section titles. |
179
- | `.text-title-sm` | Smaller titles or card titles. |
180
- | `.text-label-lg` | Large label text. |
181
- | `.text-label` | Default label text. |
182
- | `.text-body` | Default body copy. |
183
- | `.selection-contrast` | Inverts `::selection` colors to primary-contrast background. |
218
+ [Presets](./presets.md) shows how to set a look once instead of on every element. [Accessibility](../accessibility.md) lists what the CSS does for your users and what your application still owes them.