@softize/opus 12.2.1 → 12.4.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.
- package/CHANGELOG.md +42 -0
- package/bin/cli.mjs +2 -2
- package/bin/lib/copy.mjs +4 -0
- package/docs/elevation-scale.md +2 -0
- package/docs/radius-scale.md +1 -0
- package/docs/relative-unit-scale.md +55 -0
- package/docs/releasing.md +2 -2
- package/package.json +3 -3
- package/registry/skills/build-opus-ui/SKILL.md +8 -4
- package/registry/skills/build-opus-ui/references/ui-patterns.md +2 -0
- package/registry/templates/app/package.json +1 -1
- package/src/ui/components/patterns/dock.tsx +182 -0
- package/src/ui/components/patterns/shell-nav.tsx +1 -0
- package/src/ui/components/patterns/sidebar.tsx +56 -13
- package/src/ui/components/primitives/accordion.tsx +1 -1
- package/src/ui/components/primitives/button.tsx +4 -4
- package/src/ui/components/primitives/calendar.tsx +2 -2
- package/src/ui/components/primitives/chat.tsx +1 -1
- package/src/ui/components/primitives/checkbox.tsx +1 -1
- package/src/ui/components/primitives/command.tsx +1 -1
- package/src/ui/components/primitives/dialog.tsx +1 -1
- package/src/ui/components/primitives/dot.tsx +39 -0
- package/src/ui/components/primitives/input-group.tsx +4 -4
- package/src/ui/components/primitives/input-otp.tsx +1 -1
- package/src/ui/components/primitives/input.tsx +4 -5
- package/src/ui/components/primitives/item.tsx +1 -1
- package/src/ui/components/primitives/radio-group.tsx +1 -1
- package/src/ui/components/primitives/scroll-area.tsx +1 -1
- package/src/ui/components/primitives/select.tsx +7 -4
- package/src/ui/components/primitives/switch.tsx +1 -1
- package/src/ui/components/primitives/table.tsx +14 -4
- package/src/ui/components/primitives/tabs.tsx +3 -3
- package/src/ui/components/primitives/textarea.tsx +1 -1
- package/src/ui/components/primitives/toggle.tsx +1 -1
- package/src/ui/components/primitives/tooltip.tsx +1 -1
- package/src/ui/components/primitives/truncate.tsx +9 -20
- package/src/ui/docs/DocBrowser.tsx +1 -1
- package/src/ui/docs/content/button.md +2 -2
- package/src/ui/docs/content/customization.md +5 -0
- package/src/ui/docs/content/dock.md +69 -0
- package/src/ui/docs/content/dot.md +17 -0
- package/src/ui/docs/content/select.md +1 -0
- package/src/ui/docs/content/sidebar.md +21 -0
- package/src/ui/docs/content/table.md +25 -24
- package/src/ui/docs/content/tabs.md +1 -1
- package/src/ui/docs/content/tokens.md +9 -9
- package/src/ui/docs/content/truncate.md +26 -0
- package/src/ui/docs/doc.tsx +1 -1
- package/src/ui/docs/registry.tsx +4 -0
- package/src/ui/lib/overflow.ts +34 -0
- package/src/ui/meta.ts +16 -4
- package/src/ui/react.tsx +12 -1
- package/src/ui/theme.css +27 -24
|
@@ -101,11 +101,11 @@ render(
|
|
|
101
101
|
)
|
|
102
102
|
```
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Escala relativa
|
|
105
105
|
|
|
106
|
-
>
|
|
107
|
-
>
|
|
108
|
-
>
|
|
106
|
+
> O Opus não define a fonte raiz. Cada `rem` acompanha o documento, portanto o navegador e a
|
|
107
|
+
> aplicação continuam responsáveis pela densidade. Uma aplicação pode ajustar `font-size` em
|
|
108
|
+
> `html`; texto, espaçamento, radius, foco e elevação acompanham a mesma decisão.
|
|
109
109
|
|
|
110
110
|
## Radius
|
|
111
111
|
|
|
@@ -118,12 +118,12 @@ render(
|
|
|
118
118
|
render(
|
|
119
119
|
<div className="flex flex-wrap gap-4">
|
|
120
120
|
{[
|
|
121
|
-
['rounded-xs', 'radius −
|
|
122
|
-
['rounded-sm', 'radius −
|
|
123
|
-
['rounded-md', 'radius −
|
|
121
|
+
['rounded-xs', 'radius − 0.375rem'],
|
|
122
|
+
['rounded-sm', 'radius − 0.25rem'],
|
|
123
|
+
['rounded-md', 'radius − 0.125rem'],
|
|
124
124
|
['rounded-lg', 'radius (0.75rem)'],
|
|
125
|
-
['rounded-xl', 'radius +
|
|
126
|
-
['rounded-2xl', 'radius +
|
|
125
|
+
['rounded-xl', 'radius + 0.25rem'],
|
|
126
|
+
['rounded-2xl', 'radius + 0.5rem'],
|
|
127
127
|
].map(([cls, calc]) => (
|
|
128
128
|
<div key={cls} className="flex items-center gap-3">
|
|
129
129
|
<div className={'h-12 w-12 border-2 border-foreground/30 bg-muted ' + cls} />
|
|
@@ -20,6 +20,32 @@ O mesmo componente, com espaço de sobra: sem tooltip, sem atributo, só o texto
|
|
|
20
20
|
</div>
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
## Corte por esmaecimento
|
|
24
|
+
|
|
25
|
+
`fade` troca as reticências por um gradiente: o texto segue até a borda da caixa e desaparece
|
|
26
|
+
ali. A medição é a mesma, então o esmaecimento e a dica aparecem juntos, só quando há texto
|
|
27
|
+
escondido.
|
|
28
|
+
|
|
29
|
+
```tsx preview
|
|
30
|
+
<div className="w-48 rounded-md border p-2">
|
|
31
|
+
<Truncate fade>relatorio-consolidado-vendas-pos-vendas-2026-julho-final-v3.xlsx</Truncate>
|
|
32
|
+
</div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Uma composição que precisa do esmaecimento sem o tooltip aplica a utilitária `truncate-fade`,
|
|
36
|
+
que cobre o último `1.5rem` da caixa, e decide quando ligá-la com o hook `useOverflowing` — a
|
|
37
|
+
mesma medição que este componente usa. A máscara pressupõe corte real: em texto que cabe
|
|
38
|
+
inteiro, ela esmaeceria o fim de uma palavra visível. É assim que o rótulo do `SidebarItem`
|
|
39
|
+
funciona.
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
const { ref, overflowing } = useOverflowing<HTMLSpanElement>(label)
|
|
43
|
+
|
|
44
|
+
<span ref={ref} className={cn('overflow-hidden whitespace-nowrap', overflowing && 'truncate-fade')}>
|
|
45
|
+
{label}
|
|
46
|
+
</span>
|
|
47
|
+
```
|
|
48
|
+
|
|
23
49
|
## Conteúdo da dica
|
|
24
50
|
|
|
25
51
|
`tooltip` sobrepõe o conteúdo mostrado no hover (default: os próprios children) — útil
|
package/src/ui/docs/doc.tsx
CHANGED
|
@@ -30,7 +30,7 @@ function InlineMd({ text }: { text: string }): React.ReactElement {
|
|
|
30
30
|
{parts.map((part, i) =>
|
|
31
31
|
i % 2 === 1 ? (
|
|
32
32
|
// eslint-disable-next-line react/no-array-index-key
|
|
33
|
-
<code key={i} className="rounded-[calc(var(--radius)-
|
|
33
|
+
<code key={i} className="rounded-[calc(var(--radius)-0.25rem)] bg-muted px-1.5 py-0.5 font-mono text-[0.85em]">
|
|
34
34
|
{part}
|
|
35
35
|
</code>
|
|
36
36
|
) : (
|
package/src/ui/docs/registry.tsx
CHANGED
|
@@ -50,6 +50,8 @@ import confirmMd from './content/confirm.md?raw'
|
|
|
50
50
|
import aspectRatioMd from './content/aspect-ratio.md?raw'
|
|
51
51
|
import avatarMd from './content/avatar.md?raw'
|
|
52
52
|
import badgeMd from './content/badge.md?raw'
|
|
53
|
+
import dotMd from './content/dot.md?raw'
|
|
54
|
+
import dockMd from './content/dock.md?raw'
|
|
53
55
|
import breadcrumbMd from './content/breadcrumb.md?raw'
|
|
54
56
|
import buttonMd from './content/button.md?raw'
|
|
55
57
|
import buttonGroupMd from './content/button-group.md?raw'
|
|
@@ -357,6 +359,8 @@ export const UI_SECTIONS: DocSection[] = [
|
|
|
357
359
|
pages: [
|
|
358
360
|
{ slug: 'avatar', title: 'Avatar', render: comp('Avatar', 'avatar', avatarMd) },
|
|
359
361
|
{ slug: 'badge', title: 'Badge', render: comp('Badge', 'badge', badgeMd) },
|
|
362
|
+
{ slug: 'dot', title: 'Dot', render: comp('Dot', 'dot', dotMd) },
|
|
363
|
+
{ slug: 'dock', title: 'Dock', render: comp('Dock', 'dock', dockMd) },
|
|
360
364
|
{ slug: 'carousel', title: 'Carousel', render: comp('Carousel', 'carousel', carouselMd) },
|
|
361
365
|
{ slug: 'copyable', title: 'Copyable', render: comp('Copyable', 'copyable', copyableMd) },
|
|
362
366
|
{ slug: 'item', title: 'Item', render: comp('Item', 'item', itemMd) },
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Diz se uma linha única de texto não cabe na própria caixa (`scrollWidth > clientWidth`).
|
|
5
|
+
* A medida é refeita quando a caixa muda de tamanho e quando o conteúdo passado em `content`
|
|
6
|
+
* muda — o ResizeObserver enxerga a CAIXA, não o texto que entra nela.
|
|
7
|
+
*
|
|
8
|
+
* É o que separa o corte real do corte suposto: quem consome liga o sinal de truncamento
|
|
9
|
+
* (reticências, esmaecimento, tooltip) só quando existe texto escondido.
|
|
10
|
+
*/
|
|
11
|
+
export function useOverflowing<T extends HTMLElement>(content?: React.ReactNode): {
|
|
12
|
+
ref: React.RefObject<T | null>
|
|
13
|
+
overflowing: boolean
|
|
14
|
+
} {
|
|
15
|
+
const ref = React.useRef<T>(null)
|
|
16
|
+
const [overflowing, setOverflowing] = React.useState(false)
|
|
17
|
+
|
|
18
|
+
const measure = React.useCallback(() => {
|
|
19
|
+
const el = ref.current
|
|
20
|
+
if (el === null) return
|
|
21
|
+
setOverflowing(el.scrollWidth > el.clientWidth)
|
|
22
|
+
}, [])
|
|
23
|
+
|
|
24
|
+
React.useLayoutEffect(() => {
|
|
25
|
+
measure()
|
|
26
|
+
const el = ref.current
|
|
27
|
+
if (el === null || typeof ResizeObserver === 'undefined') return
|
|
28
|
+
const ro = new ResizeObserver(measure)
|
|
29
|
+
ro.observe(el)
|
|
30
|
+
return () => ro.disconnect()
|
|
31
|
+
}, [measure, content])
|
|
32
|
+
|
|
33
|
+
return { ref, overflowing }
|
|
34
|
+
}
|
package/src/ui/meta.ts
CHANGED
|
@@ -29,11 +29,23 @@ export const componentMeta = {
|
|
|
29
29
|
whenToUse:
|
|
30
30
|
'Rótulo curto de status/categoria. `variant` pra intenção (default/secondary/destructive/outline) ou tom de status (success/warning/info, fill tingido). Não-interativo — pra clique, use Button ou `asChild` num <a>.',
|
|
31
31
|
},
|
|
32
|
+
'dot': {
|
|
33
|
+
name: 'dot',
|
|
34
|
+
ancestry: 'opus',
|
|
35
|
+
whenToUse:
|
|
36
|
+
'Sinal compacto de estado quando o contexto ou o nome acessível já explica o significado. `variant` segue a intenção semântica (default/secondary/destructive/outline/success/warning/info). Passe `label` quando a cor comunicar informação; sem label, o ponto é decorativo. Para texto visível, use Badge.',
|
|
37
|
+
},
|
|
38
|
+
'dock': {
|
|
39
|
+
name: 'dock',
|
|
40
|
+
ancestry: 'opus',
|
|
41
|
+
whenToUse:
|
|
42
|
+
'Barra de ferramentas ancorada a uma superfície de trabalho — canvas, editor, preview —, quando um cabeçalho empilharia mais uma faixa de chrome sobre a trilha. Compõe Dock > DockGroup > DockAction; o estado da superfície (salvamento, versão) fica no SurfaceStatus, que flutua num canto e não pertence à barra. `position` escolhe a aresta; a divisória entre grupos é do componente. Requer TooltipProvider na raiz. Para ações de uma PÁGINA, use as `actions` do Page; para um conjunto de toggles exclusivos, ToggleGroup.',
|
|
43
|
+
},
|
|
32
44
|
'button': {
|
|
33
45
|
name: 'button',
|
|
34
46
|
ancestry: 'shadcn',
|
|
35
47
|
whenToUse:
|
|
36
|
-
'Ação clicável. `variant` define intenção (default/secondary/outline/ghost/destructive/link), `size` define altura (default/sm/lg · icon/icon-sm/icon-xs
|
|
48
|
+
'Ação clicável. `variant` define intenção (default/secondary/outline/ghost/destructive/link), `size` define altura (default/sm/lg · icon/icon-sm/icon-xs para os casos só-ícone, 2.25/2/1.5rem) e `shape="pill"` troca somente a geometria, sem alterar cor ou hierarquia. `busy` mostra spinner e desabilita. `asChild` renderiza como outro elemento.',
|
|
37
49
|
},
|
|
38
50
|
'card': {
|
|
39
51
|
name: 'card',
|
|
@@ -116,7 +128,7 @@ export const componentMeta = {
|
|
|
116
128
|
name: 'select',
|
|
117
129
|
ancestry: 'opus',
|
|
118
130
|
whenToUse:
|
|
119
|
-
'
|
|
131
|
+
'Seletor para escolhas em lista. Recebe `options` no formato { value, label, hint?, content?, group? }, sem JSX por item. Os modos são definidos por `searchable`, `multiple`, `onSearch` e `native`. `variant="default"` funciona como campo de formulário; `outline` envolve o conteúdo com borda; `ghost` o envolve sem borda. `size` segue a régua inline (default 2.25rem/sm 2rem), e `shape="pill"` altera somente a geometria. Também aceita `icon`, `trailing`, `triggerLabel` e `clearable`.',
|
|
120
132
|
},
|
|
121
133
|
'separator': {
|
|
122
134
|
name: 'separator',
|
|
@@ -137,7 +149,7 @@ export const componentMeta = {
|
|
|
137
149
|
name: 'table',
|
|
138
150
|
ancestry: 'shadcn',
|
|
139
151
|
whenToUse:
|
|
140
|
-
'Tabela de dados. Compõe Table > (TableHeader > TableRow > TableHead, TableBody > TableRow > TableCell).
|
|
152
|
+
'Tabela de dados. Compõe Table > (TableHeader > TableRow > TableHead, TableBody > TableRow > TableCell). `variant="plain"` vem sem borda externa; `variant="framed"` aplica a moldura canônica, recorta o scroll e destaca o cabeçalho. Pra listagem tabular — pro pattern de search use ActionList.',
|
|
141
153
|
},
|
|
142
154
|
'tabs': {
|
|
143
155
|
name: 'tabs',
|
|
@@ -167,7 +179,7 @@ export const componentMeta = {
|
|
|
167
179
|
name: 'truncate',
|
|
168
180
|
ancestry: 'opus',
|
|
169
181
|
whenToUse:
|
|
170
|
-
'Texto truncado com tooltip SÓ quando transborda (medição do overflow, re-medida em resize) — substitui a composição `block truncate` + `title` sempre presente, que mostra dica até em texto que não corta. `tooltip` sobrepõe o conteúdo da dica (default: os children). Requer TooltipProvider na raiz. Pra célula de tabela, nome de arquivo, URL — qualquer linha única que pode estourar.',
|
|
182
|
+
'Texto truncado com tooltip SÓ quando transborda (medição do overflow, re-medida em resize) — substitui a composição `block truncate` + `title` sempre presente, que mostra dica até em texto que não corta. `tooltip` sobrepõe o conteúdo da dica (default: os children); `fade` troca as reticências por um esmaecimento até a borda, ligado pela mesma medição. Requer TooltipProvider na raiz. Pra célula de tabela, nome de arquivo, URL — qualquer linha única que pode estourar.',
|
|
171
183
|
},
|
|
172
184
|
'accordion': {
|
|
173
185
|
name: 'accordion',
|
package/src/ui/react.tsx
CHANGED
|
@@ -135,6 +135,7 @@ export {
|
|
|
135
135
|
TableCell,
|
|
136
136
|
TableCaption,
|
|
137
137
|
} from './components/primitives/table.tsx'
|
|
138
|
+
export type { TableProps } from './components/primitives/table.tsx'
|
|
138
139
|
|
|
139
140
|
// UM seletor: `native` (menu do SO), `searchable` (busca), `multiple` (chips) e
|
|
140
141
|
// `variant="ghost"` (barra de composer) são PROPS, não componentes. Ver select.tsx.
|
|
@@ -172,6 +173,10 @@ export { ToggleGroup, ToggleGroupItem } from './components/primitives/toggle-gro
|
|
|
172
173
|
export { Truncate } from './components/primitives/truncate.tsx'
|
|
173
174
|
export type { TruncateProps } from './components/primitives/truncate.tsx'
|
|
174
175
|
|
|
176
|
+
// A medição de transbordo por trás do Truncate, exposta para composições que precisam
|
|
177
|
+
// do sinal de corte sem o tooltip — por exemplo, esmaecer um rótulo com `truncate-fade`.
|
|
178
|
+
export { useOverflowing } from './lib/overflow.ts'
|
|
179
|
+
|
|
175
180
|
// Patterns (renderizam actions a partir do spec)
|
|
176
181
|
export { ActionForm, ActionFormField, useActionFormContext } from './components/patterns/form.tsx'
|
|
177
182
|
export type { ActionFormProps, ActionFormFieldProps, ActionFormContextValue } from './components/patterns/form.tsx'
|
|
@@ -209,8 +214,12 @@ export type { PageProps } from './components/patterns/page.tsx'
|
|
|
209
214
|
export { Split, Pane } from './components/patterns/split.tsx'
|
|
210
215
|
export type { SplitProps, PaneProps, PaneSize, SplitLayout, SplitLayoutChange } from './components/patterns/split.tsx'
|
|
211
216
|
|
|
217
|
+
// A barra de ferramentas que flutua sobre uma superfície de trabalho (canvas, editor, preview).
|
|
218
|
+
export { Dock, DockGroup, DockAction, SurfaceStatus } from './components/patterns/dock.tsx'
|
|
219
|
+
export type { DockProps, DockActionProps, SurfaceStatusProps } from './components/patterns/dock.tsx'
|
|
220
|
+
|
|
212
221
|
// Barra lateral composicional: header/conteúdo/footer e navegação, sem possuir o layout.
|
|
213
|
-
export { PaneHeader, PaneContent, PaneFooter, Sidebar, SidebarItem, SidebarNav } from './components/patterns/sidebar.tsx'
|
|
222
|
+
export { PaneHeader, PaneContent, PaneFooter, Sidebar, SidebarItem, SidebarGroupLabel, SidebarNav } from './components/patterns/sidebar.tsx'
|
|
214
223
|
export type { SidebarProps, SidebarItemProps, SidebarNavGroup, SidebarNavSubgroup, SidebarNavItem } from './components/patterns/sidebar.tsx'
|
|
215
224
|
|
|
216
225
|
// O menu como primitivo pivotável: recolhe quando composto dentro de Sidebar.
|
|
@@ -221,3 +230,5 @@ export type { ShellNavProps, ShellNavGroup, ShellNavItem, ShellNavHeadingProps }
|
|
|
221
230
|
// reativa da URL + navigate — sem tabela de rotas. Ver src/ui/router.ts.
|
|
222
231
|
export { navigate, usePathname, useSegments, useSearchParams } from './router.ts'
|
|
223
232
|
export type { NavigateOptions } from './router.ts'
|
|
233
|
+
export { Dot, dotVariants } from './components/primitives/dot.tsx'
|
|
234
|
+
export type { DotProps } from './components/primitives/dot.tsx'
|
package/src/ui/theme.css
CHANGED
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
--destructive-foreground: hsl(0 0% 98%);
|
|
50
50
|
--border: hsl(0 0% 92.5%);
|
|
51
51
|
--input: hsl(0 0% 92.5%);
|
|
52
|
-
/* Ring de foco LEVE (pedido da casa): aro sutil, não um halo. Com ring-[
|
|
52
|
+
/* Ring de foco LEVE (pedido da casa): aro sutil, não um halo. Com ring-[0.1875rem] + /50,
|
|
53
53
|
~86% encosta na borda (89.8%) — um sussurro de foco. */
|
|
54
54
|
--ring: hsl(0 0% 86%);
|
|
55
55
|
--radius: 0.75rem;
|
|
@@ -134,23 +134,23 @@
|
|
|
134
134
|
--color-input: var(--input);
|
|
135
135
|
--color-ring: var(--ring);
|
|
136
136
|
|
|
137
|
-
--radius-xs: calc(var(--radius) -
|
|
138
|
-
--radius-sm: calc(var(--radius) -
|
|
139
|
-
--radius-md: calc(var(--radius) -
|
|
137
|
+
--radius-xs: calc(var(--radius) - 0.375rem);
|
|
138
|
+
--radius-sm: calc(var(--radius) - 0.25rem);
|
|
139
|
+
--radius-md: calc(var(--radius) - 0.125rem);
|
|
140
140
|
--radius-lg: var(--radius);
|
|
141
|
-
--radius-xl: calc(var(--radius) +
|
|
142
|
-
--radius-2xl: calc(var(--radius) +
|
|
141
|
+
--radius-xl: calc(var(--radius) + 0.25rem);
|
|
142
|
+
--radius-2xl: calc(var(--radius) + 0.5rem);
|
|
143
143
|
|
|
144
144
|
/* Escala Tailwind, com receita direta para o compilador preservar modifiers `/opacity`.
|
|
145
145
|
`light-dark()` mantém o peso adequado em cada tema sem uma variável intermediária. */
|
|
146
|
-
--shadow-2xs: 0
|
|
147
|
-
--shadow-xs: 0
|
|
148
|
-
--shadow-sm: 0
|
|
149
|
-
--shadow: 0
|
|
150
|
-
--shadow-md: 0
|
|
151
|
-
--shadow-lg: 0
|
|
152
|
-
--shadow-xl: 0
|
|
153
|
-
--shadow-2xl: 0
|
|
146
|
+
--shadow-2xs: 0 0.0625rem 0.125rem -0.0625rem light-dark(rgb(15 15 15 / 0.03), rgb(0 0 0 / 0.12));
|
|
147
|
+
--shadow-xs: 0 0.0625rem 0.125rem -0.0625rem light-dark(rgb(15 15 15 / 0.025), rgb(0 0 0 / 0.12)), 0 0.125rem 0.25rem -0.125rem light-dark(rgb(15 15 15 / 0.035), rgb(0 0 0 / 0.18));
|
|
148
|
+
--shadow-sm: 0 0.125rem 0.25rem -0.125rem light-dark(rgb(15 15 15 / 0.025), rgb(0 0 0 / 0.16)), 0 0.25rem 0.5rem -0.25rem light-dark(rgb(15 15 15 / 0.04), rgb(0 0 0 / 0.28));
|
|
149
|
+
--shadow: 0 0.125rem 0.375rem -0.125rem light-dark(rgb(15 15 15 / 0.03), rgb(0 0 0 / 0.16)), 0 0.375rem 0.875rem -0.375rem light-dark(rgb(15 15 15 / 0.05), rgb(0 0 0 / 0.29));
|
|
150
|
+
--shadow-md: 0 0.25rem 0.5rem -0.25rem light-dark(rgb(15 15 15 / 0.03), rgb(0 0 0 / 0.16)), 0 0.625rem 1.75rem -0.5rem light-dark(rgb(15 15 15 / 0.065), rgb(0 0 0 / 0.3));
|
|
151
|
+
--shadow-lg: 0 0.375rem 1rem -0.375rem light-dark(rgb(15 15 15 / 0.03), rgb(0 0 0 / 0.18)), 0 1.125rem 3rem -0.75rem light-dark(rgb(15 15 15 / 0.07), rgb(0 0 0 / 0.3));
|
|
152
|
+
--shadow-xl: 0 0.5rem 1.5rem -0.625rem light-dark(rgb(15 15 15 / 0.04), rgb(0 0 0 / 0.2)), 0 1.5rem 4rem -1.125rem light-dark(rgb(15 15 15 / 0.08), rgb(0 0 0 / 0.34));
|
|
153
|
+
--shadow-2xl: 0 0.75rem 2rem -0.875rem light-dark(rgb(15 15 15 / 0.05), rgb(0 0 0 / 0.22)), 0 2rem 5.5rem -1.5rem light-dark(rgb(15 15 15 / 0.1), rgb(0 0 0 / 0.38));
|
|
154
154
|
}
|
|
155
155
|
|
|
156
156
|
/* Base canônica do consumidor — vem DAQUI, não do entry de cada app. Tailwind v4
|
|
@@ -160,15 +160,6 @@
|
|
|
160
160
|
* {
|
|
161
161
|
border-color: var(--border);
|
|
162
162
|
}
|
|
163
|
-
/* Base 15px: o rem da casa — TODA a escala rem (texto, spacing, radius) deriva daqui,
|
|
164
|
-
então a UI densifica ~6% vs o default do browser (16px). Histórico (conferido no git):
|
|
165
|
-
até a 2.31.4 o pacote NÃO fixava rem (valia o 16px do browser); a 2.31.5 introduziu
|
|
166
|
-
14px; a 2.35.0 assenta em 15px — valor INÉDITO, não é revert. O 15px veio da prática:
|
|
167
|
-
a Empresa X escolheu 15px por conta própria em DOIS apps, e a exceção reincidente
|
|
168
|
-
virou default. Quem quiser mais denso sobrescreve o `html` no próprio entry. */
|
|
169
|
-
html {
|
|
170
|
-
font-size: 15px;
|
|
171
|
-
}
|
|
172
163
|
/* Canvas da casa: quase-branco vem do BODY — o shell é transparente e as
|
|
173
164
|
superfícies (cards, miolo flush) pintam bg-background por cima. Tinte de 25%
|
|
174
165
|
de muted: separa a superfície do canvas sem virar cinza; segue o tema. */
|
|
@@ -177,6 +168,18 @@
|
|
|
177
168
|
}
|
|
178
169
|
}
|
|
179
170
|
|
|
171
|
+
/* Truncamento por esmaecimento: a linha continua em direção à borda e desaparece num
|
|
172
|
+
* gradiente, em vez de terminar em reticências. A máscara ocupa o último 1.5rem da caixa,
|
|
173
|
+
* então só deve ser aplicada quando o texto REALMENTE corta — em texto que cabe, ela
|
|
174
|
+
* esmaeceria o fim de uma palavra inteira. `Truncate fade` e o rótulo do `SidebarItem`
|
|
175
|
+
* medem o transbordo antes de ligá-la. */
|
|
176
|
+
@utility truncate-fade {
|
|
177
|
+
overflow: hidden;
|
|
178
|
+
white-space: nowrap;
|
|
179
|
+
text-overflow: clip;
|
|
180
|
+
mask-image: linear-gradient(to right, #000 calc(100% - 1.5rem), transparent);
|
|
181
|
+
}
|
|
182
|
+
|
|
180
183
|
/* Scrollbar nativa da casa: todo scroller do documento compartilha o mesmo acabamento,
|
|
181
184
|
* inclusive conteúdo renderizado por portal. Isso elimina a variação do macOS entre raiz,
|
|
182
185
|
* elementos aninhados, mouse e trackpad sem trocar o mecanismo nativo nem adicionar trabalho
|
|
@@ -241,7 +244,7 @@
|
|
|
241
244
|
* regra custom vaza pra dentro do not-prose (o CodeBlock ganhava uma SEGUNDA
|
|
242
245
|
* borda no <pre>, colada na do contêiner — a "borda duplicada"). */
|
|
243
246
|
.prose :where(code):not(:where(pre code, [class~='not-prose'], [class~='not-prose'] *)) {
|
|
244
|
-
border-radius: calc(var(--radius) -
|
|
247
|
+
border-radius: calc(var(--radius) - 0.25rem);
|
|
245
248
|
background: var(--muted);
|
|
246
249
|
padding: 0.125rem 0.375rem;
|
|
247
250
|
font-weight: 400;
|