abilian-ds 0.1.0__tar.gz
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.
- abilian_ds-0.1.0/.gitignore +19 -0
- abilian_ds-0.1.0/CHANGES.md +71 -0
- abilian_ds-0.1.0/LICENSE +202 -0
- abilian_ds-0.1.0/PKG-INFO +128 -0
- abilian_ds-0.1.0/README.md +104 -0
- abilian_ds-0.1.0/TOKENS.md +425 -0
- abilian_ds-0.1.0/pyproject.toml +61 -0
- abilian_ds-0.1.0/src/abilian_ds/__init__.py +3 -0
- abilian_ds-0.1.0/src/abilian_ds/allowlist.txt +11 -0
- abilian_ds-0.1.0/src/abilian_ds/cli.py +291 -0
- abilian_ds-0.1.0/src/abilian_ds/css/ads.css +39 -0
- abilian_ds-0.1.0/src/abilian_ds/css/base.css +89 -0
- abilian_ds-0.1.0/src/abilian_ds/css/derive.css +242 -0
- abilian_ds-0.1.0/src/abilian_ds/css/knobs.css +113 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/alert.css +25 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/button.css +103 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/card.css +123 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/content.css +515 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/forced-colors.css +62 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/form.css +340 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/indicator.css +391 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/layout.css +320 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/nav.css +249 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/overlay.css +359 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/shell.css +419 -0
- abilian_ds-0.1.0/src/abilian_ds/css/parts/table.css +116 -0
- abilian_ds-0.1.0/src/abilian_ds/lint.py +819 -0
- abilian_ds-0.1.0/src/abilian_ds/shell.js +231 -0
- abilian_ds-0.1.0/src/abilian_ds/situ.css +108 -0
- abilian_ds-0.1.0/src/abilian_ds/templates/ads/form.html +94 -0
- abilian_ds-0.1.0/src/abilian_ds/templates/ads/nav.html +52 -0
- abilian_ds-0.1.0/src/abilian_ds/templates/ads/shell.html +119 -0
- abilian_ds-0.1.0/src/abilian_ds/tokens.py +271 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.egg-info/
|
|
3
|
+
.venv/
|
|
4
|
+
node_modules/
|
|
5
|
+
.pytest_cache/
|
|
6
|
+
|
|
7
|
+
# Generated. `abilian-ds tokens` writes TOKENS.md and docs/src/reference/ — those ARE
|
|
8
|
+
# committed, because they are the menu. What is not is the built site.
|
|
9
|
+
docs/site/
|
|
10
|
+
docs/.cache/
|
|
11
|
+
|
|
12
|
+
# A 466 MB checkout of Tabler, kept locally as the calibration reference. The stylesheet
|
|
13
|
+
# the harness actually loads is poc/static/tabler.min.css, which is committed.
|
|
14
|
+
sandbox/
|
|
15
|
+
|
|
16
|
+
# Vendored into the pocs by `abilian-ds sync`. Scoped to pocs/ deliberately: a bare
|
|
17
|
+
# `templates/ads/` would also match demos/templates/ads/, which is real tracked content.
|
|
18
|
+
demos/static/css/ads/
|
|
19
|
+
demos/situ_demos/templates/ads/
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.1.0] - 2026-11-11
|
|
8
|
+
|
|
9
|
+
The first release.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **A menu button in the shell's top bar.** Wide, it folds the sidebar to a rail and back, and the reader's choice is remembered and restored before first paint. Below 48em it opens the sidebar as a panel from the start edge, closed by Escape or a click outside. `aria-expanded` holds the state. Asked for by the first outside adopter ([notes/issues/03](notes/issues/03-analytics-requests.md)), like the fixes below marked *(adopter)*.
|
|
14
|
+
- **Image logos in the brand.** A `brand_mark` holding an `<img>` or `<svg>` drops the coloured tile. *(adopter)*
|
|
15
|
+
- **Tabular numerals** in table cells and `.ads-metric`, so figures line up whatever the font. *(adopter)*
|
|
16
|
+
- **Figures:** `ads-band` (a row of headline figures divided by hairlines, items optionally `aria-pressed` buttons), `ads-change` (a toned delta with an arrow, `--up` or `--down`) and `ads-share` (a row's share as a pale fill, through `--share`). *(adopter)*
|
|
17
|
+
- **Four knobs.** `--ads-label-case` and `--ads-label-tracking` set the small labels (table headers, pretitles, nav sections and the rest) for a sentence-case brand. `--ads-font-figures` gives `.ads-metric` a separate face. `--ads-page-contrast` sets how far the page ground stands back from the surfaces on it, 0 for a flat look. *(adopter)*
|
|
18
|
+
- **Tables:** `ads-table--nowrap` keeps cells on one line, and `ads-col--secondary` and `ads-col--tertiary` drop columns when the table's wrapper is under 40rem and 30rem. A small button in a compact row no longer makes the row taller. *(adopter)*
|
|
19
|
+
- **`ads-list--columns`**, a list whose rows are subgrids of it, so cells line up across rows. *(adopter)*
|
|
20
|
+
- **Nav entries without an icon:** an entry can name an `image`. One with neither shows the label's initial in the folded rail. *(adopter)*
|
|
21
|
+
- **Documentation** for the figure components, sparklines, uptime strips, legends and the inline-SVG chart pattern, and the Python floor on the install page. *(adopter)*
|
|
22
|
+
- **`ads-split--fill`**, the inbox shape: each pane scrolls by itself and the page does not, with the shell bounding the main column whenever a page contains one. It fills only with room both ways (a container query in `rem`, so 200% text counts, and a minimum viewport height), and is an ordinary split otherwise, so reflow holds. From the first port of a real application ([notes/issues/02](notes/issues/02-a-mail-client-asks-for-three-things.md)).
|
|
23
|
+
- **`ads-media`**, a figure beside a block of text, aligned to the top and never wrapping: a mail row, a notification, a comment.
|
|
24
|
+
- **`ads-btn--mark`**, a toggle that marks the thing it sits on: a star, a flag, a pin. When pressed, it fills the outline glyph in the tone's ink, where the mode-switcher draws a box.
|
|
25
|
+
- **An install test.** `tests/test_install.py` builds the wheel and sdist, installs into a clean virtualenv, runs `sync`, renders a page on the packaged shell and lints it, on each `make check`.
|
|
26
|
+
- **`--ads-line-input`**, the edge of a control, which has to be found by eye. It is `--ads-n-500` in dark mode, and in light mode it moves from Tabler's hairline to `n-500` with `--ads-contrast`. `--ads-line` keeps the same job and value.
|
|
27
|
+
- **An application shell.** `sync` vendors `ads/shell.html` (extended in place, with navigation taken as **data**), plus `ads/nav.html` and `shell.js`, which `.ads-dropdown`, `.ads-drawer`, the theme toggle, the lightbox and the sidebar's memory need. The reference application's frame went from 308 lines to 99.
|
|
28
|
+
- **`llms.txt` and `llms-full.txt`** for agents adopting the system, generated from the documentation site's navigation so the index cannot list a page the site lacks.
|
|
29
|
+
- **`ads-split__head`**, a pane header that stays in view while the page scrolls under it.
|
|
30
|
+
- **`make help`** in all three Makefiles, plus `format`, `lint`, `types`, `test-cov`, `build` and `publish`.
|
|
31
|
+
- **Apache 2.0, a README and the packaging metadata** a first release needs.
|
|
32
|
+
- **`abilian-ds tokens --docs`** writes the documentation site's reference pages from the stylesheet, so the menu cannot drift from the system.
|
|
33
|
+
- **Five lint rules**: `modifier-without-block` (a modifier on an element without the block it modifies), `duplicate-rule` and `duplicate-token` (a selector or a custom property declared twice), `self-as-child` (an element that *is* the child its class expects to contain), and `path-missing` (a configured path that is not on disk, which used to be a traceback).
|
|
34
|
+
- **Components** found by porting applications the system did not grow around: `ads-tree` (hierarchy), `ads-viewport` (a fixed-height scrolling pane), `ads-bulkbar` (a selection bar any selection model can drive), and `--ads-tap`, the 24px pointer-target floor, which does not scale with the density knob.
|
|
35
|
+
- **Collapsible sidebar groups**, opened by the server for the current page and remembered per reader.
|
|
36
|
+
- **A documentation site** (Zensical) with a generated reference section.
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **`--ads-contrast` defaults to 1.** At Tabler's values the light theme failed WCAG AA on the system's badges, chips and muted text, so every adopter met the same audit finding. The knob also reaches further now: body ink from n-700 to n-800, the soft hairline from 12% to 18%, and a dark-mode brand ink lifted towards white. Set it to 0 for the reference's palette; the calibration frames do, and parity with Tabler still measures zero differences. *(adopter)*
|
|
41
|
+
- **Card heads share one height**, so the content of cards in a grid starts on one line; a head holding a control gives back the extra height. *(adopter)*
|
|
42
|
+
- **A segmented control stays on one line** and scrolls when short of room. Wrapped, it read as two controls. *(adopter)*
|
|
43
|
+
- **`.ads-card--status` takes its colour from `ads-tone-*`**, like every other toned component. `ads-card--status-success`, `-warning` and `-danger` are gone; write `ads-card--status ads-tone-success`. Used alone, as five demo pages did, those modifiers drew no stripe at all. *(adopter)*
|
|
44
|
+
- **The package ships the system it has.** `theme.css`, `examples/` and four Jinja macros described the Tailwind design this package used to be; `abilian-ds sync` vendored them and `TOKENS.md` documented them. All removed. `sync` now vendors the real stylesheet tree. The linter's Tailwind-CLI path is gone.
|
|
45
|
+
- **`situ.css` points at tokens that exist.** It had been aliasing `--color-*`, a namespace this package deleted.
|
|
46
|
+
- **Current-item styling keys off `aria-current`**, so the highlight cannot exist without the semantics. Same for `aria-pressed` and `aria-invalid`.
|
|
47
|
+
- **The sidebar is sticky and scrolls the overflow inside it.** Its height used to be the document's, so how far a page scrolled depended on which nav groups were open.
|
|
48
|
+
- `poc/` and `pocs/` merged into one `demos/` application.
|
|
49
|
+
- **`sync` vendors one stylesheet**, spliced from the parts in import order, so a page costs one request where it used to cost a fifteen-deep `@import` waterfall. Stale `.css` under the target is removed, so no one edits a file and wonders why nothing changes.
|
|
50
|
+
- **`ads-split` wraps on the split's width**, where it used to wrap on a viewport media query, which is why a split nested in a split kept three panes long after the third stopped being readable. The gap classes set `gap` directly. They used to set the inherited `--ads-gap`, which had been governing all the layout primitives below whatever held the class.
|
|
51
|
+
- **`unused-class` is opt-in.** It asks a question only the project owning the stylesheet can answer; a first adopter with one correct page got 224 findings. `duplicate-rule` now spans the whole sheet the way the cascade does (see [note 25](notes/25-a-check-is-a-scope.md)).
|
|
52
|
+
- **The sdist is the package**, without the rest of the repository: 604 kB to 81 kB.
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
|
|
56
|
+
- **On a phone the sidebar was the whole first screen.** Below 48em it stacked above the page, sticky and a viewport tall, so a page opened on its menu. It is now the panel the menu button opens. *(adopter)*
|
|
57
|
+
- **A folded section heading drew a 24px grey block** where a hairline belongs: the tap-target floor beat the `height`. *(adopter)*
|
|
58
|
+
- **A table in its scroll wrapper inside a card** kept 16px of margin under the last row and its first column out of line with the card's title; the card rules only matched a bare table. Header and hovered rows at a card's top or bottom also painted square corners over the round ones. *(adopter)*
|
|
59
|
+
- **`table-overflow` never ran in an adopter's `lint`.** It lived only in `check_document`, which only this repository's tests called. It now runs on all templates, except for tables inside a `{% macro %}`. `heading-skip` still needs the rendered page; the linter docs show how to run `check_document` in an application's tests.
|
|
60
|
+
- **Control edges met no contrast floor, in either theme.** Inputs, selects, textareas, the drawn checkbox and radio, the switch, the colour input and the editor all took `--ads-line`, a divider at 1.2 : 1 against WCAG 1.4.11's 3 : 1. They read `--ads-line-input` now. Reported from a questionnaire in dark mode ([notes/issues/01](notes/issues/01-dark-mode.md)), and gated by `test_control_edges_meet_the_non_text_floor_in_both_themes`, because the text sweep has no text node to read on a checkbox.
|
|
61
|
+
- **An unanswered radio group looked answered.** `:indeterminate` matches a radio whose group has nothing checked, so each such radio wore the brand fill of a tri-state checkbox. The rule is qualified with `[type="checkbox"]`.
|
|
62
|
+
- Accessibility, each found by rendering a condition no one had rendered: a keyboard trap in the rich-text field (WCAG 2.1.2), three reflow failures at 320px (1.4.10), six pages overflowing at 200% text (1.4.4), twenty-four pointer targets under 24×24 (2.5.8), ten current-item markers invisible to assistive technology, and each page load moving focus to the end of the document (2.4.3).
|
|
63
|
+
- Forced-colors mode: meaning shown by colour alone now stays visible, marked with borders. `Highlight` fills were dropped, because the text backplate can hide them.
|
|
64
|
+
- The linter's vocabulary contained 48 fragments read out of decimals and SVG data-URIs, each one a class name a template could use and pass.
|
|
65
|
+
|
|
66
|
+
### Documentation
|
|
67
|
+
|
|
68
|
+
- Guides for knobs, layout, shells, forms, data and lists, accessibility, dark mode and situ; a generated reference for knobs, tokens, components, macros and the CLI.
|
|
69
|
+
- The pre-system planning notes are archived in `notes/OLD/` with what replaced each.
|
|
70
|
+
- **One home per topic.** A dozen topics were explained on two to four pages each. The copies had drifted: the shell was still described as unpackaged, `sync` as writing two files, and the vocabulary's size disagreed across five pages. Each topic now lives on one page and the others link to it. The shells guide documents the packaged `ads/shell.html`: the blocks, navigation as data, the four layouts and `shell.js`.
|
|
71
|
+
- **The vocabulary's size is stated once**, on the About page, and `test_the_vocabulary_is_sized_once_and_correctly` holds it to the stylesheet and fails if another page states it. The generated reference pages compute the counts themselves.
|
abilian_ds-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: abilian-ds
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Abilian Design System — a closed token vocabulary for Litestar and Jinja
|
|
5
|
+
Project-URL: Homepage, https://ads.lab.abilian.com
|
|
6
|
+
Project-URL: Documentation, https://ads.lab.abilian.com
|
|
7
|
+
Project-URL: Source, https://github.com/abilian/abilian-ds
|
|
8
|
+
Project-URL: Issues, https://github.com/abilian/abilian-ds/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/abilian/abilian-ds/blob/main/CHANGES.md
|
|
10
|
+
Author-email: Stefane Fermigier <sf@abilian.com>
|
|
11
|
+
License-Expression: Apache-2.0
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: accessibility,css,design-system,design-tokens,jinja,litestar
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Web Environment
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Topic :: Software Development :: User Interfaces
|
|
20
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# Abilian Design System
|
|
26
|
+
|
|
27
|
+
This is a design system for business applications built on **Litestar and Jinja**, written in plain CSS with no front-end toolchain. A small set of knobs is the whole overridable surface; everything else is derived from them.
|
|
28
|
+
|
|
29
|
+
[Documentation](https://ads.lab.abilian.com) · [Token and class reference](https://ads.lab.abilian.com/reference/components/) · [llms.txt](https://ads.lab.abilian.com/llms.txt)
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
pip install abilian-ds # or: uv add abilian-ds
|
|
33
|
+
abilian-ds sync
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
It has no runtime dependencies and needs no build step.
|
|
37
|
+
|
|
38
|
+
## The idea
|
|
39
|
+
|
|
40
|
+
Styling goes through a **closed vocabulary**: a `--ads-*` custom property or an `ads-*` class. There is no utility layer, no arbitrary-value syntax and no `style=` attribute. `bg-gray-100`, `p-4` and `text-[13px]` generate no CSS at all, and `abilian-ds lint` rejects them before they can sit in a template looking plausible.
|
|
41
|
+
|
|
42
|
+
That closure is what makes the rest possible:
|
|
43
|
+
|
|
44
|
+
- **Knobs are the overridable surface; everything else derives.** Set `--ads-brand` and its hover, active, tint, border and foreground shades follow. Set `--ads-space-scale` and every padding, gap, margin and control height follows. One declaration on `:root` changes 361 of 501 elements on a page.
|
|
45
|
+
- **Both themes in one value.** Every colour holds light and dark through `light-dark()`. There is no `dark:` variant anywhere and so no second styling pass to forget.
|
|
46
|
+
- **State that a person can perceive is an attribute.** The current item is `aria-current`, a toggle is `aria-pressed`, an invalid field is `aria-invalid`. The stylesheet keys off those, so the look cannot exist without the meaning.
|
|
47
|
+
- **Measured parity with [Tabler](https://tabler.io).** A harness compares the two property by property and reports **0 differences**.
|
|
48
|
+
- **Accessibility with tests behind it**: contrast in both themes, reflow at 320px, 200% text-only zoom, keyboard traversal, pointer target size and Windows high contrast, swept across every route on every run.
|
|
49
|
+
|
|
50
|
+
## What `sync` gives you
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
static/css/ads/ads.css the stylesheet — one file, one request
|
|
54
|
+
static/css/ads/shell.js what the dropdowns, drawers and theme toggle need
|
|
55
|
+
static/css/ads/situ.css only if you use situ
|
|
56
|
+
templates/ads/shell.html the application frame, extended not copied
|
|
57
|
+
templates/ads/nav.html navigation rendered from data
|
|
58
|
+
templates/ads/form.html field, select, textarea, checkbox, button macros
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Paths live in `[tool.abilian-ds]` in your `pyproject.toml`, so the commands take no flags:
|
|
62
|
+
|
|
63
|
+
```toml
|
|
64
|
+
[tool.abilian-ds]
|
|
65
|
+
templates = ["templates"]
|
|
66
|
+
prefix = "ads-"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## A page
|
|
70
|
+
|
|
71
|
+
```jinja
|
|
72
|
+
{% extends "ads/shell.html" %}
|
|
73
|
+
{% block title %}Contacts · Acme{% endblock %}
|
|
74
|
+
{% block brand_name %}Acme{% endblock %}
|
|
75
|
+
{% block heading %}Contacts{% endblock %}
|
|
76
|
+
{% block actions %}<button class="ads-btn ads-btn--primary">New contact</button>{% endblock %}
|
|
77
|
+
{% block body %}
|
|
78
|
+
<div class="ads-card"><div class="ads-card__body ads-stack">
|
|
79
|
+
<div class="ads-cluster">
|
|
80
|
+
<span class="ads-avatar ads-avatar--sm">AR</span>
|
|
81
|
+
<strong class="ads-truncate">Amélie Rousseau</strong>
|
|
82
|
+
<span class="ads-badge ads-tone-success">active</span>
|
|
83
|
+
</div>
|
|
84
|
+
</div></div>
|
|
85
|
+
{% endblock %}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The navigation is data, because markup drifts:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
nav = [{"section": "Directory",
|
|
92
|
+
"items": [{"href": "/contacts", "label": "Contacts", "icon": "users"}]}]
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Configure Jinja with `undefined=StrictUndefined`. It turns a misspelt component argument into an error, where it would otherwise yield an unstyled element.
|
|
96
|
+
|
|
97
|
+
## The commands
|
|
98
|
+
|
|
99
|
+
| command | what it does |
|
|
100
|
+
|---|---|
|
|
101
|
+
| `abilian-ds sync` | vendor the stylesheet, the shell script and the macros into your project |
|
|
102
|
+
| `abilian-ds lint` | check templates against the design system |
|
|
103
|
+
| `abilian-ds tokens` | regenerate `TOKENS.md` from the stylesheet |
|
|
104
|
+
|
|
105
|
+
`lint` is the contract. Green means on-system:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
templates/page.html:1: unknown-class: bg-gray-100: not in the design system
|
|
109
|
+
templates/page.html:2: dark-variant: dark:text-white: colours carry both themes, there is no dark pass
|
|
110
|
+
templates/page.html:2: arbitrary-value: text-[13px]: bypasses the token scale
|
|
111
|
+
templates/page.html:2: inline-style: style='color: red': a decision belongs in CSS
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
It also hashes every vendored file against what the package would produce, so a local edit to `ads.css` shows up as a finding.
|
|
115
|
+
|
|
116
|
+
## What it does not do
|
|
117
|
+
|
|
118
|
+
- **No icon set.** The shell uses an `icon()` Jinja global if you register one; an icon set is a licence you cannot change once it is baked in. [How to wire one up.](https://ads.lab.abilian.com/getting-started/first-page/)
|
|
119
|
+
- **No JavaScript framework.** `shell.js` is a page of delegated event handlers with no dependencies. Components that need more (a rich data grid, a live region) are [situ](https://situ.hop3.abilian.com)'s job, and `situ.css` bridges the two palettes.
|
|
120
|
+
- **No CSS-in-JS, no theme builder UI, no component library for React.** This is Jinja and CSS.
|
|
121
|
+
|
|
122
|
+
## Status
|
|
123
|
+
|
|
124
|
+
Beta. The vocabulary, the linter and the shell are stable enough to build on; the 0.x version number covers the rest. See [CHANGES.md](CHANGES.md).
|
|
125
|
+
|
|
126
|
+
## Licence
|
|
127
|
+
|
|
128
|
+
Apache 2.0. Copyright © 2026 Abilian SAS.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Abilian Design System
|
|
2
|
+
|
|
3
|
+
This is a design system for business applications built on **Litestar and Jinja**, written in plain CSS with no front-end toolchain. A small set of knobs is the whole overridable surface; everything else is derived from them.
|
|
4
|
+
|
|
5
|
+
[Documentation](https://ads.lab.abilian.com) · [Token and class reference](https://ads.lab.abilian.com/reference/components/) · [llms.txt](https://ads.lab.abilian.com/llms.txt)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install abilian-ds # or: uv add abilian-ds
|
|
9
|
+
abilian-ds sync
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
It has no runtime dependencies and needs no build step.
|
|
13
|
+
|
|
14
|
+
## The idea
|
|
15
|
+
|
|
16
|
+
Styling goes through a **closed vocabulary**: a `--ads-*` custom property or an `ads-*` class. There is no utility layer, no arbitrary-value syntax and no `style=` attribute. `bg-gray-100`, `p-4` and `text-[13px]` generate no CSS at all, and `abilian-ds lint` rejects them before they can sit in a template looking plausible.
|
|
17
|
+
|
|
18
|
+
That closure is what makes the rest possible:
|
|
19
|
+
|
|
20
|
+
- **Knobs are the overridable surface; everything else derives.** Set `--ads-brand` and its hover, active, tint, border and foreground shades follow. Set `--ads-space-scale` and every padding, gap, margin and control height follows. One declaration on `:root` changes 361 of 501 elements on a page.
|
|
21
|
+
- **Both themes in one value.** Every colour holds light and dark through `light-dark()`. There is no `dark:` variant anywhere and so no second styling pass to forget.
|
|
22
|
+
- **State that a person can perceive is an attribute.** The current item is `aria-current`, a toggle is `aria-pressed`, an invalid field is `aria-invalid`. The stylesheet keys off those, so the look cannot exist without the meaning.
|
|
23
|
+
- **Measured parity with [Tabler](https://tabler.io).** A harness compares the two property by property and reports **0 differences**.
|
|
24
|
+
- **Accessibility with tests behind it**: contrast in both themes, reflow at 320px, 200% text-only zoom, keyboard traversal, pointer target size and Windows high contrast, swept across every route on every run.
|
|
25
|
+
|
|
26
|
+
## What `sync` gives you
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
static/css/ads/ads.css the stylesheet — one file, one request
|
|
30
|
+
static/css/ads/shell.js what the dropdowns, drawers and theme toggle need
|
|
31
|
+
static/css/ads/situ.css only if you use situ
|
|
32
|
+
templates/ads/shell.html the application frame, extended not copied
|
|
33
|
+
templates/ads/nav.html navigation rendered from data
|
|
34
|
+
templates/ads/form.html field, select, textarea, checkbox, button macros
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Paths live in `[tool.abilian-ds]` in your `pyproject.toml`, so the commands take no flags:
|
|
38
|
+
|
|
39
|
+
```toml
|
|
40
|
+
[tool.abilian-ds]
|
|
41
|
+
templates = ["templates"]
|
|
42
|
+
prefix = "ads-"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## A page
|
|
46
|
+
|
|
47
|
+
```jinja
|
|
48
|
+
{% extends "ads/shell.html" %}
|
|
49
|
+
{% block title %}Contacts · Acme{% endblock %}
|
|
50
|
+
{% block brand_name %}Acme{% endblock %}
|
|
51
|
+
{% block heading %}Contacts{% endblock %}
|
|
52
|
+
{% block actions %}<button class="ads-btn ads-btn--primary">New contact</button>{% endblock %}
|
|
53
|
+
{% block body %}
|
|
54
|
+
<div class="ads-card"><div class="ads-card__body ads-stack">
|
|
55
|
+
<div class="ads-cluster">
|
|
56
|
+
<span class="ads-avatar ads-avatar--sm">AR</span>
|
|
57
|
+
<strong class="ads-truncate">Amélie Rousseau</strong>
|
|
58
|
+
<span class="ads-badge ads-tone-success">active</span>
|
|
59
|
+
</div>
|
|
60
|
+
</div></div>
|
|
61
|
+
{% endblock %}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The navigation is data, because markup drifts:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
nav = [{"section": "Directory",
|
|
68
|
+
"items": [{"href": "/contacts", "label": "Contacts", "icon": "users"}]}]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Configure Jinja with `undefined=StrictUndefined`. It turns a misspelt component argument into an error, where it would otherwise yield an unstyled element.
|
|
72
|
+
|
|
73
|
+
## The commands
|
|
74
|
+
|
|
75
|
+
| command | what it does |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `abilian-ds sync` | vendor the stylesheet, the shell script and the macros into your project |
|
|
78
|
+
| `abilian-ds lint` | check templates against the design system |
|
|
79
|
+
| `abilian-ds tokens` | regenerate `TOKENS.md` from the stylesheet |
|
|
80
|
+
|
|
81
|
+
`lint` is the contract. Green means on-system:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
templates/page.html:1: unknown-class: bg-gray-100: not in the design system
|
|
85
|
+
templates/page.html:2: dark-variant: dark:text-white: colours carry both themes, there is no dark pass
|
|
86
|
+
templates/page.html:2: arbitrary-value: text-[13px]: bypasses the token scale
|
|
87
|
+
templates/page.html:2: inline-style: style='color: red': a decision belongs in CSS
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
It also hashes every vendored file against what the package would produce, so a local edit to `ads.css` shows up as a finding.
|
|
91
|
+
|
|
92
|
+
## What it does not do
|
|
93
|
+
|
|
94
|
+
- **No icon set.** The shell uses an `icon()` Jinja global if you register one; an icon set is a licence you cannot change once it is baked in. [How to wire one up.](https://ads.lab.abilian.com/getting-started/first-page/)
|
|
95
|
+
- **No JavaScript framework.** `shell.js` is a page of delegated event handlers with no dependencies. Components that need more (a rich data grid, a live region) are [situ](https://situ.hop3.abilian.com)'s job, and `situ.css` bridges the two palettes.
|
|
96
|
+
- **No CSS-in-JS, no theme builder UI, no component library for React.** This is Jinja and CSS.
|
|
97
|
+
|
|
98
|
+
## Status
|
|
99
|
+
|
|
100
|
+
Beta. The vocabulary, the linter and the shell are stable enough to build on; the 0.x version number covers the rest. See [CHANGES.md](CHANGES.md).
|
|
101
|
+
|
|
102
|
+
## Licence
|
|
103
|
+
|
|
104
|
+
Apache 2.0. Copyright © 2026 Abilian SAS.
|