@antadesign/anta 0.1.1-dev.1 → 0.1.1-dev.4
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/LICENSE.md +21 -0
- package/NOTICES.md +279 -0
- package/README.md +112 -24
- package/dist/anta_helpers.d.ts +8 -0
- package/dist/anta_helpers.js +3 -0
- package/dist/components/Icon.d.ts +40 -0
- package/dist/components/Icon.js +18 -0
- package/dist/components/Progress.d.ts +33 -4
- package/dist/components/Progress.js +5 -0
- package/dist/components/Text.d.ts +42 -0
- package/dist/components/Text.js +22 -0
- package/dist/components/Text.module.css +6 -0
- package/dist/elements/a-icon.css +18 -0
- package/dist/elements/a-icon.d.ts +12 -0
- package/dist/elements/a-icon.js +13 -0
- package/dist/elements/a-icon.shapes.css +365 -0
- package/dist/elements/a-icon.shapes.d.ts +97 -0
- package/dist/elements/a-icon.shapes.js +184 -0
- package/dist/elements/a-progress.css +69 -64
- package/dist/elements/a-progress.d.ts +2 -1
- package/dist/elements/a-progress.js +3 -1
- package/dist/elements/a-text.css +77 -0
- package/dist/elements/a-text.d.ts +10 -0
- package/dist/elements/a-text.js +143 -0
- package/dist/elements/index.d.ts +5 -0
- package/dist/elements/index.js +14 -1
- package/dist/general_types.d.ts +74 -0
- package/dist/generate-icons.mjs +193 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.js +7 -0
- package/dist/jsx-runtime.d.ts +17 -1
- package/dist/reset.css +115 -0
- package/dist/tokens.css +281 -0
- package/package.json +15 -5
package/dist/general_types.d.ts
CHANGED
|
@@ -1,16 +1,90 @@
|
|
|
1
|
+
/** Common props for JSX component wrappers. */
|
|
1
2
|
export interface BaseProps {
|
|
3
|
+
/** CSS class name. Merged with any internal classes by the component. */
|
|
2
4
|
className?: string;
|
|
5
|
+
/** Inline styles applied to the root element. */
|
|
3
6
|
style?: React.CSSProperties;
|
|
7
|
+
/** Child elements. When provided, replaces the component's default label/content. */
|
|
4
8
|
children?: React.ReactNode;
|
|
5
9
|
}
|
|
10
|
+
/** Attributes for intrinsic custom elements (`<a-*>` tags) in JSX. */
|
|
6
11
|
export interface BaseAttributes {
|
|
12
|
+
/** HTML `class` attribute (standard DOM). */
|
|
7
13
|
class?: string;
|
|
14
|
+
/** React/Preact-style class name. Alias for `class`. */
|
|
8
15
|
className?: string;
|
|
16
|
+
/** Inline styles applied to the element. */
|
|
9
17
|
style?: React.CSSProperties;
|
|
10
18
|
children?: React.ReactNode;
|
|
19
|
+
/** Tab order. Set to `0` to make the element keyboard-focusable. */
|
|
20
|
+
tabIndex?: number;
|
|
21
|
+
/** ARIA role override. */
|
|
22
|
+
role?: string;
|
|
23
|
+
/** Keydown handler — used for keyboard-driven interactions. */
|
|
24
|
+
onKeyDown?: (e: any) => void;
|
|
25
|
+
/** Click handler — used for mouse / tap activation. */
|
|
26
|
+
onClick?: (e: any) => void;
|
|
11
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Attributes for the `<a-progress>` custom element.
|
|
30
|
+
*
|
|
31
|
+
* These are the low-level web component attributes. For the JSX wrapper with
|
|
32
|
+
* typed props and computed labels, use `Progress` from `@antadesign/anta`.
|
|
33
|
+
*/
|
|
12
34
|
export interface AProgressAttributes extends BaseAttributes {
|
|
35
|
+
/** Current progress value. */
|
|
13
36
|
value?: number | string;
|
|
37
|
+
/** Maximum value. Defaults to 100. */
|
|
14
38
|
max?: number | string;
|
|
39
|
+
/** Color variant. `'neutral'` is the default gray; `'info'` is blue. */
|
|
15
40
|
tone?: 'neutral' | 'info';
|
|
41
|
+
/** ARIA role — the JSX wrapper sets this to `'progressbar'`. */
|
|
42
|
+
role?: string;
|
|
43
|
+
/** ARIA value-now (current). */
|
|
44
|
+
'aria-valuenow'?: number | string;
|
|
45
|
+
/** ARIA value-max. */
|
|
46
|
+
'aria-valuemax'?: number | string;
|
|
47
|
+
/** ARIA value-min (defaults to 0). */
|
|
48
|
+
'aria-valuemin'?: number | string;
|
|
49
|
+
/** ARIA accessible name. */
|
|
50
|
+
'aria-label'?: string;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Attributes for the `<a-text>` custom element.
|
|
54
|
+
*
|
|
55
|
+
* Low-level web component attributes; for the JSX wrapper use `Text`
|
|
56
|
+
* from `@antadesign/anta`.
|
|
57
|
+
*/
|
|
58
|
+
export interface ATextAttributes extends BaseAttributes {
|
|
59
|
+
/** Visual priority. Maps to text-1..text-5. */
|
|
60
|
+
priority?: 'primary' | 'secondary' | 'tertiary' | 'quaternary' | 'quinary';
|
|
61
|
+
/** Color tint. Applies the matching `--text-{N}-{tone}` palette. */
|
|
62
|
+
tone?: 'brand' | 'success' | 'critical' | 'warning' | 'info';
|
|
63
|
+
/** Render as inline-block instead of the default block. */
|
|
64
|
+
inline?: boolean | string;
|
|
65
|
+
/** Truncate to N lines with a trailing ellipsis. The attribute value
|
|
66
|
+
* carries the line count (e.g. `"1"`, `"3"`); the count is also
|
|
67
|
+
* available via the `--line-clamp` CSS custom property set inline. */
|
|
68
|
+
truncate?: boolean | string | number;
|
|
69
|
+
/** Marks the host as expandable when paired with `truncate`. Adds
|
|
70
|
+
* the fade-out mask; the JSX wrapper renders the chevron and owns
|
|
71
|
+
* the click/keyboard expansion logic. */
|
|
72
|
+
expandable?: boolean | string;
|
|
73
|
+
/** ARIA disclosure state, mirrors the JSX wrapper's `expanded` flag. */
|
|
74
|
+
'aria-expanded'?: boolean | 'true' | 'false';
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Attributes for the `<a-icon>` custom element. The `shape` attribute
|
|
78
|
+
* value is typed as `string` here so the element accepts any consumer's
|
|
79
|
+
* generated shapes. The JSX wrapper (`Icon`) narrows it to `IconShape`.
|
|
80
|
+
*/
|
|
81
|
+
export interface AIconAttributes extends BaseAttributes {
|
|
82
|
+
/** Which icon to render. */
|
|
83
|
+
shape?: string;
|
|
84
|
+
/** ARIA role — the JSX wrapper sets `'img'` when a label is provided. */
|
|
85
|
+
role?: string;
|
|
86
|
+
/** ARIA accessible name when the icon carries meaning. */
|
|
87
|
+
'aria-label'?: string;
|
|
88
|
+
/** Hides decorative icons from screen readers. */
|
|
89
|
+
'aria-hidden'?: 'true' | 'false' | boolean;
|
|
16
90
|
}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* generate-icons.mjs — read a folder of SVGs, emit a CSS file with one
|
|
4
|
+
* `a-icon[shape="…"]` rule per icon and a `.d.ts` file that augments
|
|
5
|
+
* Anta's `IconShapes` interface so the new shapes flow into `IconShape`.
|
|
6
|
+
*
|
|
7
|
+
* Run from CLI:
|
|
8
|
+
* node scripts/generate-icons.mjs --input <svg-folder> --output <out-folder> --name <basename>
|
|
9
|
+
*
|
|
10
|
+
* Or import programmatically:
|
|
11
|
+
* import { generate } from '@antadesign/anta/generate-icons.mjs'
|
|
12
|
+
* await generate({ input, output, name, builtInShapes })
|
|
13
|
+
*
|
|
14
|
+
* Defaults:
|
|
15
|
+
* --name = "a-icon.shapes"
|
|
16
|
+
* --output = "."
|
|
17
|
+
* --input is required
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import fs from 'node:fs'
|
|
21
|
+
import path from 'node:path'
|
|
22
|
+
import { fileURLToPath } from 'node:url'
|
|
23
|
+
|
|
24
|
+
// SVGs whose names match these get a "collision" warning so consumers
|
|
25
|
+
// know they're shadowing a built-in. Anta passes its own list when
|
|
26
|
+
// generating its own shapes; for consumers, we include the canonical
|
|
27
|
+
// built-in names so generating a same-named shape is flagged.
|
|
28
|
+
const DEFAULT_BUILT_IN = [
|
|
29
|
+
'chevron-down', 'chevron-up', 'chevron-left', 'chevron-right',
|
|
30
|
+
'check', 'x', 'info', 'warning-triangle', 'plus', 'minus', 'menu', 'copy',
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
function encodeSvg(svg) {
|
|
34
|
+
return svg
|
|
35
|
+
.replace(/"/g, "'")
|
|
36
|
+
.replace(/[\r\n%#()<>?[\\\]^`{|}]/g, encodeURIComponent)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Removes `width=…` and `height=…` only from the root <svg> opening tag.
|
|
40
|
+
// Child elements (e.g. <rect width="14"…>) are intentionally untouched.
|
|
41
|
+
// Handles double-quoted, single-quoted, and unquoted attribute values.
|
|
42
|
+
function stripDimensions(svg) {
|
|
43
|
+
return svg.replace(/<svg\b[^>]*>/i, (m) =>
|
|
44
|
+
m.replace(/\s(?:width|height)\s*=\s*("[^"]*"|'[^']*'|[^\s>]+)/g, '')
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export async function generate({ input, output = '.', name = 'a-icon.shapes', internal = false } = {}) {
|
|
49
|
+
if (!input) throw new Error('generate-icons: --input is required')
|
|
50
|
+
const inDir = path.resolve(input)
|
|
51
|
+
const outDir = path.resolve(output)
|
|
52
|
+
if (!fs.existsSync(inDir)) throw new Error(`generate-icons: input folder not found: ${inDir}`)
|
|
53
|
+
fs.mkdirSync(outDir, { recursive: true })
|
|
54
|
+
|
|
55
|
+
const files = fs.readdirSync(inDir).filter((f) => f.endsWith('.svg')).sort()
|
|
56
|
+
if (files.length === 0) {
|
|
57
|
+
console.warn(`generate-icons: no .svg files in ${inDir}`)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const shapes = []
|
|
61
|
+
// Anta's per-element CSS lives in `@layer anta`. Consumer-generated
|
|
62
|
+
// icon sets default to the same so they sort alongside Anta's
|
|
63
|
+
// built-ins; consumers who want their icons unlayered can post-
|
|
64
|
+
// process the output.
|
|
65
|
+
const cssLines = [
|
|
66
|
+
'/* Auto-generated by scripts/generate-icons.mjs. Do not edit by hand. */',
|
|
67
|
+
'',
|
|
68
|
+
'@layer anta {',
|
|
69
|
+
'',
|
|
70
|
+
]
|
|
71
|
+
// Built-in collision detection is for consumer runs only. Anta's own
|
|
72
|
+
// build passes --internal so it doesn't warn about every one of its
|
|
73
|
+
// own shapes "colliding" with itself.
|
|
74
|
+
const builtInSet = internal ? new Set() : new Set(DEFAULT_BUILT_IN)
|
|
75
|
+
const collisions = []
|
|
76
|
+
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const shape = path.parse(file).name
|
|
79
|
+
if (shapes.includes(shape)) {
|
|
80
|
+
console.warn(`generate-icons: duplicate shape name "${shape}" — skipping`)
|
|
81
|
+
continue
|
|
82
|
+
}
|
|
83
|
+
if (builtInSet.has(shape)) collisions.push(shape)
|
|
84
|
+
const raw = fs.readFileSync(path.join(inDir, file), 'utf8')
|
|
85
|
+
const encoded = encodeSvg(stripDimensions(raw)).trim()
|
|
86
|
+
cssLines.push(` a-icon[shape="${shape}"] {`)
|
|
87
|
+
cssLines.push(` --icon: url("data:image/svg+xml,${encoded}");`)
|
|
88
|
+
cssLines.push(' }')
|
|
89
|
+
cssLines.push('')
|
|
90
|
+
shapes.push(shape)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (collisions.length > 0) {
|
|
94
|
+
console.warn(
|
|
95
|
+
`generate-icons: ${collisions.length} shape name(s) collide with Anta's built-in icons: ` +
|
|
96
|
+
`${collisions.join(', ')}. ` +
|
|
97
|
+
`The runtime CSS loaded last wins; import yours after \`@antadesign/anta/elements\` to override.`
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Optional synonyms — extra search keywords per shape. Read from
|
|
102
|
+
// `<input>/synonyms.json` if present; consumers/maintainers extend
|
|
103
|
+
// the list as their icon set grows. Format: { "shape-name": ["alt", "term"] }.
|
|
104
|
+
const synFile = path.join(inDir, 'synonyms.json')
|
|
105
|
+
/** @type {Record<string, string[]>} */
|
|
106
|
+
let synonyms = {}
|
|
107
|
+
if (fs.existsSync(synFile)) {
|
|
108
|
+
try {
|
|
109
|
+
const parsed = JSON.parse(fs.readFileSync(synFile, 'utf8'))
|
|
110
|
+
for (const [shape, list] of Object.entries(parsed)) {
|
|
111
|
+
if (!shapes.includes(shape)) {
|
|
112
|
+
console.warn(`generate-icons: synonyms.json references unknown shape "${shape}" — skipping`)
|
|
113
|
+
continue
|
|
114
|
+
}
|
|
115
|
+
if (!Array.isArray(list) || !list.every((v) => typeof v === 'string')) {
|
|
116
|
+
console.warn(`generate-icons: synonyms.json entry for "${shape}" is not a string array — skipping`)
|
|
117
|
+
continue
|
|
118
|
+
}
|
|
119
|
+
synonyms[shape] = list
|
|
120
|
+
}
|
|
121
|
+
} catch (e) {
|
|
122
|
+
console.warn(`generate-icons: failed to parse ${synFile}: ${e.message}`)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Close the `@layer anta {` block opened at the top of cssLines.
|
|
127
|
+
cssLines.push('}')
|
|
128
|
+
|
|
129
|
+
const cssPath = path.join(outDir, `${name}.css`)
|
|
130
|
+
const tsPath = path.join(outDir, `${name}.ts`)
|
|
131
|
+
fs.writeFileSync(cssPath, cssLines.join('\n'))
|
|
132
|
+
|
|
133
|
+
const synonymsEntries = Object.entries(synonyms)
|
|
134
|
+
const tsLines = [
|
|
135
|
+
'/* Auto-generated by scripts/generate-icons.mjs. Do not edit by hand. */',
|
|
136
|
+
'',
|
|
137
|
+
'export const ICON_SHAPES = [',
|
|
138
|
+
...shapes.map((s) => ` '${s}',`),
|
|
139
|
+
"] as const",
|
|
140
|
+
'',
|
|
141
|
+
'export const ICON_SYNONYMS: Readonly<Record<string, readonly string[]>> = {',
|
|
142
|
+
...synonymsEntries.map(([shape, list]) =>
|
|
143
|
+
` '${shape}': [${list.map((v) => `'${v.replace(/'/g, "\\'")}'`).join(', ')}],`
|
|
144
|
+
),
|
|
145
|
+
'}',
|
|
146
|
+
'',
|
|
147
|
+
"declare module '@antadesign/anta' {",
|
|
148
|
+
' interface IconShapes {',
|
|
149
|
+
...shapes.map((s) => ` '${s}': true`),
|
|
150
|
+
' }',
|
|
151
|
+
'}',
|
|
152
|
+
'',
|
|
153
|
+
"export type IconShape = keyof import('@antadesign/anta').IconShapes",
|
|
154
|
+
'',
|
|
155
|
+
]
|
|
156
|
+
fs.writeFileSync(tsPath, tsLines.join('\n'))
|
|
157
|
+
|
|
158
|
+
console.log(`generate-icons: wrote ${shapes.length} shape${shapes.length === 1 ? '' : 's'} to ${cssPath} and ${tsPath}`)
|
|
159
|
+
return { shapes, cssPath, tsPath }
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function parseArgs(argv) {
|
|
163
|
+
const out = {}
|
|
164
|
+
for (let i = 0; i < argv.length; i++) {
|
|
165
|
+
const arg = argv[i]
|
|
166
|
+
if (arg.startsWith('--')) {
|
|
167
|
+
const key = arg.slice(2)
|
|
168
|
+
const next = argv[i + 1]
|
|
169
|
+
if (next && !next.startsWith('--')) {
|
|
170
|
+
out[key] = next
|
|
171
|
+
i++
|
|
172
|
+
} else {
|
|
173
|
+
out[key] = true
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return out
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const isMain = import.meta.url === `file://${process.argv[1]}` ||
|
|
181
|
+
import.meta.url === fileURLToPath(import.meta.url + '')
|
|
182
|
+
if (isMain || process.argv[1]?.endsWith('generate-icons.mjs')) {
|
|
183
|
+
const args = parseArgs(process.argv.slice(2))
|
|
184
|
+
generate({
|
|
185
|
+
input: args.input,
|
|
186
|
+
output: args.output,
|
|
187
|
+
name: args.name,
|
|
188
|
+
internal: args.internal === true,
|
|
189
|
+
}).catch((e) => {
|
|
190
|
+
console.error(e.message)
|
|
191
|
+
process.exit(1)
|
|
192
|
+
})
|
|
193
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @antadesign/anta — Antithesis Design System
|
|
3
|
+
*
|
|
4
|
+
* Portable UI components with web component internals and JSX wrappers.
|
|
5
|
+
* Works with React, Preact (via compat or `configure()`), or any custom JSX runtime.
|
|
6
|
+
*
|
|
7
|
+
* Import components from this entry point:
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Progress } from '@antadesign/anta'
|
|
10
|
+
* ```
|
|
11
|
+
*
|
|
12
|
+
* Register custom elements (client-side only):
|
|
13
|
+
* ```ts
|
|
14
|
+
* import '@antadesign/anta/elements'
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
1
19
|
export { Progress } from './components/Progress';
|
|
20
|
+
export type { ProgressProps } from './components/Progress';
|
|
21
|
+
export { Text } from './components/Text';
|
|
22
|
+
export type { TextProps } from './components/Text';
|
|
23
|
+
export { Icon } from './components/Icon';
|
|
24
|
+
export type { IconProps } from './components/Icon';
|
|
25
|
+
export { ICON_SHAPES, ICON_SYNONYMS } from './elements/a-icon.shapes';
|
|
26
|
+
export type { BaseProps, BaseAttributes } from './general_types';
|
|
2
27
|
export { configure } from './jsx-runtime';
|
|
28
|
+
/**
|
|
29
|
+
* Seed interface for the icon shape registry. The generated
|
|
30
|
+
* `a-icon.shapes.d.ts` augments this interface with one key per
|
|
31
|
+
* available shape; consumers can do the same with their own generated
|
|
32
|
+
* .d.ts files (TypeScript merges them by interface name).
|
|
33
|
+
*/
|
|
34
|
+
export interface IconShapes {
|
|
35
|
+
}
|
|
36
|
+
export type IconShape = keyof IconShapes;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Progress } from "./components/Progress";
|
|
2
|
+
import { Text } from "./components/Text";
|
|
3
|
+
import { Icon } from "./components/Icon";
|
|
4
|
+
import { ICON_SHAPES, ICON_SYNONYMS } from "./elements/a-icon.shapes";
|
|
2
5
|
import { configure } from "./jsx-runtime";
|
|
3
6
|
export {
|
|
7
|
+
ICON_SHAPES,
|
|
8
|
+
ICON_SYNONYMS,
|
|
9
|
+
Icon,
|
|
4
10
|
Progress,
|
|
11
|
+
Text,
|
|
5
12
|
configure
|
|
6
13
|
};
|
package/dist/jsx-runtime.d.ts
CHANGED
|
@@ -4,11 +4,25 @@ type JsxFunction = {
|
|
|
4
4
|
h(type: ComponentType, props: Record<string, unknown> | null, ...children: unknown[]): unknown;
|
|
5
5
|
}['h'];
|
|
6
6
|
declare let _Fragment: ComponentType;
|
|
7
|
+
/**
|
|
8
|
+
* Swap the underlying JSX factory used by all anta components.
|
|
9
|
+
*
|
|
10
|
+
* Not needed for React or Preact-with-compat — those work automatically.
|
|
11
|
+
* Call this before rendering any anta components when using Preact without
|
|
12
|
+
* compat aliasing, or a custom JSX runtime.
|
|
13
|
+
*
|
|
14
|
+
* @example Preact without compat
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { configure } from '@antadesign/anta'
|
|
17
|
+
* import { h, Fragment } from 'preact'
|
|
18
|
+
* configure(h, Fragment)
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
7
21
|
export declare function configure(jsx: JsxFunction, Fragment?: ComponentType): void;
|
|
8
22
|
export declare function jsx(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
9
23
|
export declare function jsxs(type: ComponentType, props: Record<string, unknown> | null, key?: string | number): unknown;
|
|
10
24
|
export { _Fragment as Fragment };
|
|
11
|
-
import type { AProgressAttributes, BaseAttributes } from './general_types';
|
|
25
|
+
import type { AProgressAttributes, ATextAttributes, AIconAttributes, BaseAttributes } from './general_types';
|
|
12
26
|
export declare namespace JSX {
|
|
13
27
|
type IntrinsicElements = React.JSX.IntrinsicElements & {
|
|
14
28
|
'a-progress': AProgressAttributes;
|
|
@@ -16,5 +30,7 @@ export declare namespace JSX {
|
|
|
16
30
|
'a-progress-number': BaseAttributes;
|
|
17
31
|
'a-progress-text': BaseAttributes;
|
|
18
32
|
'a-progress-hint': BaseAttributes;
|
|
33
|
+
'a-text': ATextAttributes;
|
|
34
|
+
'a-icon': AIconAttributes;
|
|
19
35
|
};
|
|
20
36
|
}
|
package/dist/reset.css
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/* Anta's reset + typography defaults. All rules live in `@layer anta`
|
|
2
|
+
so consumer-owned components (in `@layer components`) and utility
|
|
3
|
+
frameworks (in `@layer utilities`) can override on demand. The
|
|
4
|
+
layer-order declaration in `tokens.css` (`@layer base, anta,
|
|
5
|
+
components, utilities;`) keeps Anta above any preflight resets in
|
|
6
|
+
`@layer base` so a Tailwind import doesn't wipe Anta's typography. */
|
|
7
|
+
|
|
8
|
+
@layer anta {
|
|
9
|
+
/* ───── Structural reset ─────────────────────────────────────── */
|
|
10
|
+
|
|
11
|
+
/* Modern box-sizing — pads and borders count inside the declared
|
|
12
|
+
width/height. Universal selectors so `::before` / `::after`
|
|
13
|
+
pseudo-elements follow the host. */
|
|
14
|
+
*, *::before, *::after {
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* Zero out browser-default margins on every element. Apps build
|
|
19
|
+
up their own spacing from explicit values rather than fighting
|
|
20
|
+
the user-agent stylesheet. */
|
|
21
|
+
* {
|
|
22
|
+
margin: 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Replaced elements as block-level by default + cap to their
|
|
26
|
+
container so a misplaced large image doesn't blow out the
|
|
27
|
+
layout. Consumers re-inline them with `display: inline-block`
|
|
28
|
+
where needed. */
|
|
29
|
+
img, picture, video, canvas, svg {
|
|
30
|
+
display: block;
|
|
31
|
+
max-width: 100%;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Inherit typography into form controls — by default browsers
|
|
35
|
+
reset font on these. */
|
|
36
|
+
input, button, textarea, select {
|
|
37
|
+
font: inherit;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Wrap long words rather than overflow; `text-wrap: pretty`
|
|
41
|
+
balances widows on paragraphs, `text-wrap: balance` evens
|
|
42
|
+
headlines across lines. */
|
|
43
|
+
p, h1, h2, h3, h4, h5, h6 {
|
|
44
|
+
overflow-wrap: break-word;
|
|
45
|
+
}
|
|
46
|
+
p {
|
|
47
|
+
text-wrap: pretty;
|
|
48
|
+
}
|
|
49
|
+
h1, h2, h3, h4, h5, h6 {
|
|
50
|
+
text-wrap: balance;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* ───── Typography defaults — Anta opinion ───────────────────── */
|
|
54
|
+
|
|
55
|
+
h1, h2, h3, h4, h5, h6 {
|
|
56
|
+
font-weight: 600;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
strong {
|
|
60
|
+
font-weight: 600;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Prose lists (ul, ol) get a tight 3ch left padding so markers
|
|
64
|
+
hug the text, and items get a small bottom margin so
|
|
65
|
+
consecutive ones breathe. Markers are toned all the way down
|
|
66
|
+
to --text-5 since they are visual scaffolding, not content. */
|
|
67
|
+
ul, ol {
|
|
68
|
+
padding-left: 3ch;
|
|
69
|
+
}
|
|
70
|
+
:is(ul, ol) > li {
|
|
71
|
+
margin-bottom: 0.5em;
|
|
72
|
+
}
|
|
73
|
+
:is(ul, ol) > li::marker {
|
|
74
|
+
color: var(--text-5);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* `<menu>` is for command/option lists, not prose. By default
|
|
78
|
+
browsers render it like a `<ul>` (disc markers, 40px padding);
|
|
79
|
+
strip all of that so it's a clean semantic container ready to
|
|
80
|
+
be styled. */
|
|
81
|
+
menu {
|
|
82
|
+
list-style: none;
|
|
83
|
+
padding: 0;
|
|
84
|
+
margin: 0;
|
|
85
|
+
}
|
|
86
|
+
menu > li {
|
|
87
|
+
margin: 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Global link defaults. Hairline underline at 75% alpha;
|
|
91
|
+
underline goes to currentColor (100%) and 1px on hover. Color
|
|
92
|
+
comes from --link-color tokens, which auto-flip in dark mode.
|
|
93
|
+
Components or specific contexts (nav, headings, buttons)
|
|
94
|
+
should override as needed. */
|
|
95
|
+
a, a:link, a:visited {
|
|
96
|
+
color: var(--link-color);
|
|
97
|
+
text-decoration: underline;
|
|
98
|
+
text-decoration-style: solid;
|
|
99
|
+
text-decoration-color: color-mix(in oklch, currentColor 75%, transparent);
|
|
100
|
+
text-decoration-thickness: 0.5px;
|
|
101
|
+
text-underline-offset: 3px;
|
|
102
|
+
}
|
|
103
|
+
a:hover {
|
|
104
|
+
color: var(--link-color-hover);
|
|
105
|
+
/* Underline color set to the hover token directly (rather than
|
|
106
|
+
`currentColor`) so it repaints in lockstep with `color` — a
|
|
107
|
+
few browsers latch onto the old currentColor value
|
|
108
|
+
otherwise. */
|
|
109
|
+
text-decoration-color: var(--link-color-hover);
|
|
110
|
+
text-decoration-thickness: 1px;
|
|
111
|
+
}
|
|
112
|
+
a:active {
|
|
113
|
+
text-decoration-color: color-mix(in oklch, currentColor 75%, transparent);
|
|
114
|
+
}
|
|
115
|
+
}
|