houseaccount 0.14.2 → 0.16.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +51 -0
- data/README.md +91 -151
- data/art/index.html.erb +37 -111
- data/config/locales/houseaccount.en.yml +0 -11
- data/lib/houseaccount/helpers/flows.rb +7 -39
- data/lib/houseaccount/helpers.rb +7 -5
- data/lib/houseaccount/version.rb +1 -1
- data/lib/houseaccount.rb +12 -4
- data/public/css/houseaccount.css +1 -1
- data/public/index.html +49 -117
- data/public/js/houseaccount.js +4 -4
- data/public/theme/bootstrap.css +2 -3
- data/public/{v0.14.2 → v0.16.0}/css/houseaccount.css +1 -1
- data/public/{v0.14.2 → v0.16.0}/js/houseaccount.js +4 -4
- data/public/{v0.14.2 → v0.16.0}/theme/bootstrap.css +2 -3
- metadata +33 -29
- data/lib/houseaccount/form_builder/comboboxes.rb +0 -38
- data/lib/houseaccount/form_builder/controls.rb +0 -67
- data/lib/houseaccount/form_builder/pins.rb +0 -30
- data/lib/houseaccount/form_builder.rb +0 -96
- data/lib/houseaccount/helpers/chats/asides.rb +0 -49
- data/lib/houseaccount/helpers/chats/asks.rb +0 -41
- data/lib/houseaccount/helpers/chats.rb +0 -42
- data/lib/houseaccount/helpers/dialogs.rb +0 -47
- data/lib/houseaccount/helpers/notices.rb +0 -55
- data/lib/houseaccount/message.rb +0 -11
- /data/public/{v0.14.2 → v0.16.0}/font/bootstrap-icons-FRBPO3H7.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-latin-QHYSRFVK.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-latin-ext-QZ4PXVHB.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-latin-ext.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-latin.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-vietnamese-RRA5CUQB.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/font/quicksand-500-vietnamese.woff2 +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/dawn.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/dracula.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/gruvbox.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/monokai.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/nord.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/one_dark.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/solarized.css +0 -0
- /data/public/{v0.14.2 → v0.16.0}/theme/tokyo_night.css +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1b6c8ab985a0b86c7f687ccdaf099b99c8fe8f8149ceb81f29e30407d8d4bf32
|
|
4
|
+
data.tar.gz: f796c8ea89ee0cf82724941342af9341a57ad1fc8826562046d7d4617bf0ca02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8cbb39eb69b849914d2c37e2da1688e91c9f7b551a267e76edab0956a8d1f52aad4abd200e48d4e215cd21fa033aff48b53e452cc1d25301cad483a5c3454ba2
|
|
7
|
+
data.tar.gz: fe457ead3c577b750f990bd5c3f7d32d36b5267f385aabb08080f6d2a7a54b4c0a245cd55e8e50361fc55cbafc1b4b1e7a2ef0366d54864978c135d898bca5f2
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,57 @@ For more information about changelogs, check [Keep a Changelog](http://keepachan
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## 0.16.0 - 2026-09-18
|
|
11
|
+
|
|
12
|
+
* [FEATURE] bh 6.5, which carries a picture in a bubble and a note over a thread
|
|
13
|
+
|
|
14
|
+
`Bh::Message` takes `photos`, drawn under the words in the same bubble, and `chat_with`
|
|
15
|
+
takes a `note:` that holds the top while the thread scrolls under it.
|
|
16
|
+
|
|
17
|
+
* [FIX] The shell fills the screen in whole pixels
|
|
18
|
+
|
|
19
|
+
`100dvh` computes to a fraction on a scaled display, and the tenths over are a scrollbar
|
|
20
|
+
the page cannot use beside the one its content already has.
|
|
21
|
+
|
|
22
|
+
## 0.15.0 - 2026-09-18
|
|
23
|
+
|
|
24
|
+
* [Breaking change] The nine palettes move to bh as well
|
|
25
|
+
|
|
26
|
+
`dracula`, `nord`, `solarized` and the rest are editor colour schemes restating Bootstrap's
|
|
27
|
+
own families — nothing in them is this house's, which is the test that moved everything
|
|
28
|
+
else. They are bh's now, and the build copies them out of the gem to `public/theme/`, so
|
|
29
|
+
every URL a host has ever linked answers exactly as before.
|
|
30
|
+
|
|
31
|
+
* [Breaking change] Bootstrap 6 moves to the `bh` gem, which this one now depends on
|
|
32
|
+
|
|
33
|
+
Most of what had grown here was not the house's: a combobox, a 6-digit code, a dialog, a
|
|
34
|
+
toast, a thread of messages and twenty-two Stimulus controllers are Bootstrap 6 with the
|
|
35
|
+
markup written once, and are worth the same to any Rails app. They live in `bh` now, along
|
|
36
|
+
with the form builder, nine stylesheets and Bootstrap itself. This gem depends on it and
|
|
37
|
+
bundles it, so `css/houseaccount.css` and `js/houseaccount.js` still carry everything they
|
|
38
|
+
carried before and a host changes nothing.
|
|
39
|
+
|
|
40
|
+
What a host does have to change is where it reaches for a name. `HouseAccount::Message` is
|
|
41
|
+
`Bh::Message` and `HouseAccount::FormBuilder` is `Bh::FormBuilder` — both kept under the
|
|
42
|
+
house's names, so neither breaks — but the locale keys moved: `houseaccount.all`,
|
|
43
|
+
`.ask`, `.clear`, `.close`, `.more`, `.no_results`, `.okay`, `.search`, `.send`, `.typing`
|
|
44
|
+
and `.ago` are now `bh.*`, and a host that overrode one overrides it there. The meta that
|
|
45
|
+
words a confirmation's other button is `bh-cancel` rather than `houseaccount-cancel`.
|
|
46
|
+
|
|
47
|
+
* [Breaking change] `flow` takes what the page stands on rather than assuming it
|
|
48
|
+
|
|
49
|
+
bh's `flow` knows nothing of a lockup or a wall. The house's still draws both — `flow logo:`
|
|
50
|
+
is unchanged — but every other option is now the column's, so a page standing on something
|
|
51
|
+
of its own names the controller that paints it.
|
|
52
|
+
|
|
53
|
+
* [Breaking change] The npm package ships the built tree alone
|
|
54
|
+
|
|
55
|
+
It used to export `app/javascript` and `app/stylesheets` for a host that would rather
|
|
56
|
+
bundle the sources itself. Those sources now reach for bh, which is a gem and cannot be
|
|
57
|
+
resolved from `node_modules` — there is no npm package of bh and there will not be one —
|
|
58
|
+
so the exports go and the package is `public/css`, `public/js`, `public/font` and
|
|
59
|
+
`public/theme`: exactly what the CDN links in the README serve.
|
|
60
|
+
|
|
10
61
|
## 0.14.2 - 2026-09-18
|
|
11
62
|
|
|
12
63
|
* [Fix] A conversation reads at the house's own size wherever it is drawn
|
data/README.md
CHANGED
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
# HouseAccount design
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
What makes a page look like HouseAccount's: the marks every app is known by, the lockup they
|
|
4
|
+
sit in, the wall a signup flow stands on, the palettes, the pages an app shows when it is down
|
|
5
|
+
or lost, and the one stylesheet and one script that carry all of it.
|
|
6
|
+
|
|
7
|
+
The Bootstrap 6 underneath is [`bh`](https://claudiob.github.io/bh/), which this gem depends on
|
|
8
|
+
and bundles. **The components are documented there, not here** — the form builder, the combobox,
|
|
9
|
+
the 6-digit code, the phone field, the dialog, the toasts, the thread of messages and the
|
|
10
|
+
twenty-two Stimulus controllers are Bootstrap with the markup written once, and are worth the
|
|
11
|
+
same to any Rails app. This gem is only what is the house's.
|
|
6
12
|
|
|
7
13
|
Published three ways from this repo:
|
|
8
14
|
|
|
9
15
|
| Surface | Where | What it is for |
|
|
10
16
|
| --- | --- | --- |
|
|
11
|
-
| Site | https://design.houseaccount.com (staging: https://design.houseparty.dev) | A stable URL for every asset, and a showcase of
|
|
17
|
+
| Site | https://design.houseaccount.com (staging: https://design.houseparty.dev) | A stable URL for every asset, and a showcase of them |
|
|
12
18
|
| Gem | `houseaccount` on RubyGems | A Rails engine: serves the same tree from the gem, and the helpers |
|
|
13
|
-
| npm | `houseaccount` | The
|
|
19
|
+
| npm | `houseaccount` | The same built stylesheet and script, for any CDN that carries it |
|
|
14
20
|
|
|
15
21
|
## How to install
|
|
16
22
|
|
|
@@ -22,44 +28,13 @@ gem install houseaccount
|
|
|
22
28
|
|
|
23
29
|
```ruby
|
|
24
30
|
# Gemfile
|
|
25
|
-
gem 'houseaccount', '~> 0.
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
`~> 0.14.0` stops short of `0.15`, since below 1.0 a minor release may break whatever it likes.
|
|
29
|
-
Rails 8.1 and Ruby 3.2 are the minimum.
|
|
30
|
-
|
|
31
|
-
### From npm
|
|
32
|
-
|
|
33
|
-
For a host that bundles the sources itself rather than serving the gem's built tree.
|
|
34
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npm install houseaccount
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
```js
|
|
40
|
-
import 'houseaccount'
|
|
41
|
-
import 'houseaccount/houseaccount.css'
|
|
31
|
+
gem 'houseaccount', '~> 0.15.0'
|
|
42
32
|
```
|
|
43
33
|
|
|
44
|
-
|
|
45
|
-
controller the house's markup names, and hands Turbo the dialog it draws for a confirmation.
|
|
46
|
-
|
|
47
|
-
Bootstrap 6 is not on npm, so the bundle ships inside this package and a bundler has to send the
|
|
48
|
-
bare `bootstrap` specifier there:
|
|
34
|
+
bh comes with it; nothing else has to be named.
|
|
49
35
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
alias: { bootstrap: 'houseaccount/bootstrap' }
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
A single controller comes from `houseaccount/controllers`, for a host registering its own
|
|
56
|
-
Stimulus application rather than taking the house's:
|
|
57
|
-
|
|
58
|
-
```js
|
|
59
|
-
import WallController from 'houseaccount/controllers/wall_controller.js'
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
Pin as a Gemfile does, and for the same reason: `"houseaccount": "~0.14.0"` stops short of `0.15`.
|
|
36
|
+
`~> 0.15.0` stops short of `0.16`, since below 1.0 a minor release may break whatever it likes.
|
|
37
|
+
Rails 8.1 and Ruby 3.2 are the minimum.
|
|
63
38
|
|
|
64
39
|
A page takes the gem's layout, and wears the same head:
|
|
65
40
|
|
|
@@ -95,84 +70,68 @@ which Pages redirects away from.
|
|
|
95
70
|
|
|
96
71
|
With the gem in the bundle an app serves `/css/houseaccount.css`, `/js/houseaccount.js`,
|
|
97
72
|
`/theme/*`, `/font/*`, `/logo/*` and `/favicon/*` itself — and its own version's copy under
|
|
98
|
-
`/v0.
|
|
99
|
-
with the house's own page, and
|
|
73
|
+
`/v0.15.0/`, which is what the head helper links, cached for a year — answers a 400, 404, 406,
|
|
74
|
+
422 or 500 with the house's own page, and answers `/down.html` with this app's.
|
|
75
|
+
|
|
76
|
+
## Which app this is
|
|
77
|
+
|
|
78
|
+
Read off the Rails application's own name, the `Goldrush` of `Goldrush::Application`. That is
|
|
79
|
+
what its tab wears, what `houseaccount_head_tags` links without an argument, and whose page the
|
|
80
|
+
engine answers `/down.html` with — the app's mark in the middle and the house's at the foot. An
|
|
81
|
+
app the family has no mark for wears the cube.
|
|
82
|
+
|
|
83
|
+
## The helpers
|
|
100
84
|
|
|
101
85
|
```erb
|
|
102
|
-
<%# In the <head>: the viewport, color-scheme and Turbo refresh metas, the stylesheet, the
|
|
103
|
-
and the icons a tab, a phone and a manifest ask for — this app's, by its name. %>
|
|
86
|
+
<%# In the <head>: the viewport, color-scheme and Turbo refresh metas, the stylesheet, the
|
|
87
|
+
script, and the icons a tab, a phone and a manifest ask for — this app's, by its name. %>
|
|
104
88
|
<%= houseaccount_head_tags %>
|
|
105
89
|
|
|
106
90
|
<%# The icons alone, for a head of the host's own: this app's unless another of the family is
|
|
107
|
-
named, the way a page for
|
|
108
|
-
recourse needs no call at all — the gem answers recourse's `recourses/head` with them
|
|
109
|
-
admin's tab wears the app's cube the moment the gem is in the bundle. %>
|
|
91
|
+
named, the way a page for customers wears the house's cube rather than the app's. A host of
|
|
92
|
+
recourse needs no call at all — the gem answers recourse's `recourses/head` with them. %>
|
|
110
93
|
<%= houseaccount_icons :houseaccount %>
|
|
111
94
|
|
|
112
|
-
<%# A mark beside its name, as one word and one link.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
link. Under the cursor the whole logo turns the mark's blue. %>
|
|
95
|
+
<%# A mark beside its name, as one word and one link. Each drawing fills its 512 grid
|
|
96
|
+
differently, so equal sizes never align: every mark is rendered at a box of its own and
|
|
97
|
+
pushed down by its own nudge, and its ink then stands on the baseline. %>
|
|
116
98
|
<%= houseaccount_logo %>
|
|
117
99
|
<%= houseaccount_logo app: :fountain, href: root_path, class: 'fs-3' %>
|
|
118
100
|
|
|
119
|
-
<%# A thread of messages, newest at the foot, and — where `url` is given — the field that
|
|
120
|
-
posts the next one there, suggesting `hints` one at a time in its placeholder. %>
|
|
121
|
-
<%= chat_with url: chat_question_path, hints: Provider::Chat::HINTS, messages: messages %>
|
|
122
|
-
|
|
123
|
-
<%# What the flash says, as toasts at the bottom right: green for a notice, red for an alert,
|
|
124
|
-
neutral for any other key; visible at first paint, gone after a moment or a click, held
|
|
125
|
-
while read. A value in the flash that is not words is left alone. %>
|
|
126
|
-
<%= notices %>
|
|
127
|
-
|
|
128
|
-
<%# A link and the dialog it opens: headed, with an X, holding the block, and closed by an
|
|
129
|
-
`Okay` too (`okay:` words it otherwise, `okay: false` leaves it out). The two share an id
|
|
130
|
-
made from the link's words; any other option is an attribute of the link. %>
|
|
131
|
-
<%= dialog 'I’m not on Google Business', title: 'Not a problem' do %>
|
|
132
|
-
We will look your business up ourselves and match it by hand.
|
|
133
|
-
<% end %>
|
|
134
|
-
|
|
135
|
-
<%# The house's form, from `builder: HouseAccount::FormBuilder` or a controller's
|
|
136
|
-
`default_form_builder`: `fieldset` a one-column grid with a legend where given, a label a
|
|
137
|
-
form-label, a text or phone field a large control — the phone one shaped by the `phone`
|
|
138
|
-
controller — a submit or a button the solid pill, a `type: :button` one the outlined pill, a
|
|
139
|
-
disabled one given a `title` saying why on hover, and
|
|
140
|
-
`pin_field` the six slots a code is typed into, one real field offered by the phone from the
|
|
141
|
-
text that brought it. %>
|
|
142
|
-
<%= form.fieldset do %>
|
|
143
|
-
<%= form.label :pin_confirmation, '6-digit code' %>
|
|
144
|
-
<%= form.pin_field :pin_confirmation, required: true %>
|
|
145
|
-
<%= form.submit 'Confirm' %>
|
|
146
|
-
<% end %>
|
|
147
|
-
|
|
148
101
|
<%# An asset on the design site, for a page this app does not serve — a mail, say. %>
|
|
149
102
|
<%= image_tag houseaccount_url('logo/fountain.png') %>
|
|
150
103
|
```
|
|
151
104
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
105
|
+
## The layout
|
|
106
|
+
|
|
107
|
+
A page takes the gem's layout and wears the same head:
|
|
108
|
+
|
|
109
|
+
```ruby
|
|
110
|
+
class Unauthenticated::AgentsController < ApplicationController
|
|
111
|
+
layout 'houseaccount'
|
|
112
|
+
end
|
|
113
|
+
```
|
|
155
114
|
|
|
156
115
|
```erb
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
116
|
+
<% content_for :title, 'Authenticating as admin' %>
|
|
117
|
+
<% content_for :head, tag.meta(name: 'robots', content: 'noindex') %>
|
|
118
|
+
<h1>Authenticating as admin</h1>
|
|
160
119
|
```
|
|
161
120
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
121
|
+
<p>
|
|
122
|
+
<img src='screenshot/layout-light.png' width='49%' alt='The page in light mode'>
|
|
123
|
+
<img src='screenshot/layout-dark.png' width='49%' alt='The page in dark mode'>
|
|
124
|
+
</p>
|
|
125
|
+
|
|
126
|
+
It is the charset, the title, the CSRF and CSP metas, `houseaccount_head_tags`, `yield :head`,
|
|
127
|
+
then `yield` inside a `main.container-fluid`, and `notices` after it — and nothing else. A host
|
|
128
|
+
wanting more copies it into its own `app/views/layouts/`, which wins on being earlier in the
|
|
129
|
+
view paths.
|
|
166
130
|
|
|
167
|
-
|
|
168
|
-
draws on the first ask: the first line of the message is the question, the rest are
|
|
169
|
-
paragraphs, and the answer wears the words of the button that asked. A host in another
|
|
170
|
-
language names the other word in `<meta name='houseaccount-cancel'>`.
|
|
131
|
+
## The flow, and the wall it stands on
|
|
171
132
|
|
|
172
|
-
`flow`
|
|
173
|
-
|
|
174
|
-
nests on the gem's layout, giving the page as `content_for :content` and rendering the gem's
|
|
175
|
-
as a template:
|
|
133
|
+
`flow` is bh's page-of-a-signup-flow with the house's two things added: the lockup in its header
|
|
134
|
+
and the cyanotype behind the card. A layout of the app's own calls it and nests on the gem's:
|
|
176
135
|
|
|
177
136
|
```erb
|
|
178
137
|
<% content_for :logo, 'houseaccount' %>
|
|
@@ -186,49 +145,23 @@ as a template:
|
|
|
186
145
|
<%= render template: 'layouts/houseaccount' %>
|
|
187
146
|
```
|
|
188
147
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
words it says before a pick. Everything else in the fieldset keeps the whole row, and
|
|
195
|
-
the card is what is measured rather than the window, so a narrow one stays in one column.
|
|
196
|
-
|
|
197
|
-
`content_for :logo` is which of the family's marks the tab wears, for a page a customer reads
|
|
198
|
-
rather than the app's own people: unsaid, it is this app's, by its name.
|
|
199
|
-
|
|
200
|
-
The words are the view's, said in `content_for`: `:title` is the `h1`, `:subtitle` the line
|
|
201
|
-
under it, drawn only where there is one, and `:width` how wide the card is, a CSS length that
|
|
202
|
-
is `75rem` unless said — a page asking one question, a sign-in say, says `30rem`. What the layout knows goes in the call:
|
|
203
|
-
`footer:` is the pieces of the foot, joined by a middot, none drawing no foot, and `logo:`
|
|
204
|
-
where the mark links, the house's front door unless said.
|
|
205
|
-
|
|
206
|
-
The wall alone is one attribute, `data-controller='wall'`, on any element that should
|
|
207
|
-
stand on it.
|
|
208
|
-
|
|
209
|
-
A message is anything answering six methods, and `HouseAccount::Message` is one for a host
|
|
210
|
-
that has the facts and no model to hang them on:
|
|
211
|
-
|
|
212
|
-
| Method | What it says |
|
|
213
|
-
| --- | --- |
|
|
214
|
-
| `side` | `:left` for the other party's bubble, `:right` for the reader's |
|
|
215
|
-
| `text` | what was said — a string, or markup the host rendered; nil draws the typing dots |
|
|
216
|
-
| `sender` | who said it, shown small above the bubble; nil shows nobody |
|
|
217
|
-
| `at` | when, as `3 minutes ago` with the moment itself in a tooltip; nil shows no time |
|
|
218
|
-
| `delivery` | `:delivered`, `:sent`, `:failed` or `:undelivered`, a ✓ or ✕ in its tone; nil for none |
|
|
219
|
-
| `cost` | dollars the message cost, shown as `· $0.0123`; nil for none |
|
|
148
|
+
`logo:` is where the mark links, the house's front door unless said; `footer:` the pieces of the
|
|
149
|
+
foot, joined by a middot, none drawing no foot. Everything else — `:title`, `:subtitle`,
|
|
150
|
+
`:width`, how the card lays its fields out — is bh's, and is
|
|
151
|
+
[documented there](https://claudiob.github.io/bh/). `content_for :logo` is which of the family's
|
|
152
|
+
marks the tab wears, for a page a customer reads rather than the app's own people.
|
|
220
153
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
154
|
+
The wall alone is one attribute, `data-controller='wall'`, on any element that should stand on
|
|
155
|
+
it: fourteen trade tools and the family's five marks drifting up in seven columns, on blueprint
|
|
156
|
+
blues of its own so it reads the same whatever the primary is. Under `prefers-reduced-motion`
|
|
157
|
+
the columns stand still.
|
|
158
|
+
|
|
159
|
+
## A code sent to a phone
|
|
225
160
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
The host is the application's default one unless `host:` says otherwise, and the words are
|
|
231
|
-
the gem's `config/locales` entry.
|
|
161
|
+
The same words from every app, in each voice they are said in. `written` is the sentence a
|
|
162
|
+
person reads and, under it, the `@host #code` line that offers the code above the keyboard on
|
|
163
|
+
the phone it arrived on; `spoken` is the sentence alone, its digits one at a time so a listener
|
|
164
|
+
can write them down.
|
|
232
165
|
|
|
233
166
|
```ruby
|
|
234
167
|
HouseAccount.one_time_code(contact.pin).written
|
|
@@ -237,6 +170,8 @@ HouseAccount.one_time_code(contact.pin).spoken
|
|
|
237
170
|
# => "Enter this 6-digit code to proceed: 4, 8, 2, 9, 1, 3"
|
|
238
171
|
```
|
|
239
172
|
|
|
173
|
+
## Off the gem
|
|
174
|
+
|
|
240
175
|
A page not on the gem links the two files from the site, and nothing else:
|
|
241
176
|
|
|
242
177
|
```html
|
|
@@ -248,19 +183,19 @@ Those follow the latest release. Every release is also kept whole under its own
|
|
|
248
183
|
forever and cached for a year, for a page that would rather move on its own terms:
|
|
249
184
|
|
|
250
185
|
```html
|
|
251
|
-
<link rel='stylesheet' href='https://design.houseaccount.com/v0.
|
|
252
|
-
<script type='module' src='https://design.houseaccount.com/v0.
|
|
186
|
+
<link rel='stylesheet' href='https://design.houseaccount.com/v0.15.0/css/houseaccount.css'>
|
|
187
|
+
<script type='module' src='https://design.houseaccount.com/v0.15.0/js/houseaccount.js'></script>
|
|
253
188
|
```
|
|
254
189
|
|
|
255
190
|
The same two files come from any CDN that carries the npm package, for a page that would
|
|
256
191
|
rather not depend on the site at all:
|
|
257
192
|
|
|
258
193
|
```html
|
|
259
|
-
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/houseaccount@0.
|
|
260
|
-
<script type='module' src='https://cdn.jsdelivr.net/npm/houseaccount@0.
|
|
194
|
+
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/houseaccount@0.15.0/public/css/houseaccount.css'>
|
|
195
|
+
<script type='module' src='https://cdn.jsdelivr.net/npm/houseaccount@0.15.0/public/js/houseaccount.js'></script>
|
|
261
196
|
```
|
|
262
197
|
|
|
263
|
-
The palettes are beside them, at `public/theme/nord.css` and the rest. A published version is never
|
|
198
|
+
The palettes are beside them, at `public/theme/nord.css` and the rest — bh's nine, copied out of the gem at build time to the path hosts have always linked. A published version is never
|
|
264
199
|
written again, so that URL is owed its bytes for as long as npm stands.
|
|
265
200
|
|
|
266
201
|
A host with a Content Security Policy allows whichever origin it names for `style-src`,
|
|
@@ -268,13 +203,14 @@ A host with a Content Security Policy allows whichever origin it names for `styl
|
|
|
268
203
|
|
|
269
204
|
## What is in the bundle
|
|
270
205
|
|
|
271
|
-
`css/houseaccount.css` is Bootstrap 6 alpha as upstream ships it,
|
|
272
|
-
the glyphs `art/icons.txt` names
|
|
273
|
-
and
|
|
274
|
-
lockup's face, is served from `/font` too; nothing on a page reaches
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
206
|
+
`css/houseaccount.css` is bh's stylesheet — Bootstrap 6 alpha as upstream ships it, then bh's
|
|
207
|
+
own rules — followed by Bootstrap Icons cut down to the glyphs `art/icons.txt` names (the ones
|
|
208
|
+
`unicon` maps and the few written out by name) and the house's three: the page, the lockup and
|
|
209
|
+
the wall. Quicksand, the lockup's face, is served from `/font` too; nothing on a page reaches
|
|
210
|
+
another origin. `js/houseaccount.js` is bh's script — Turbo (with the cable element
|
|
211
|
+
`turbo-rails` signs its streams for), Bootstrap, and a Stimulus application holding every
|
|
212
|
+
controller bh's markup names, started once under `window.Stimulus` — and then `wall`, the one
|
|
213
|
+
controller that is the house's own. Everything is drawn for light and dark alike: every color is a Bootstrap
|
|
278
214
|
token or a `light-dark()` pair, and `data-bs-theme` on `<html>` forces either. A phone is
|
|
279
215
|
formatted in the browser: the server hands over ten digits and
|
|
280
216
|
`data-controller='phone'`, and the controller decides `555-555-5555`.
|
|
@@ -289,6 +225,10 @@ rake icons # after editing art/icons.txt, the glyphs the icon fon
|
|
|
289
225
|
cd test/dummy && bin/rails server
|
|
290
226
|
```
|
|
291
227
|
|
|
228
|
+
The build reads bh's sources out of the gem — `bundle info bh --path` — rather than out of
|
|
229
|
+
`node_modules`, so the Gemfile is the one place bh's version is pinned. An edit to bh shows in
|
|
230
|
+
this bundle on the next `rake assets`.
|
|
231
|
+
|
|
292
232
|
The built `public/css`, `public/js`, `public/font` and `public/theme` are committed: the gem
|
|
293
233
|
serves them, and `spec.files` is `git ls-files`. `rake assets` rebuilds and fails until the
|
|
294
234
|
result is committed, so a source edit cannot ship without its build.
|
data/art/index.html.erb
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
<body class='text-center'>
|
|
35
35
|
<header class='container-fluid px-3 py-3 border-bottom d-flex flex-wrap justify-content-center align-items-baseline gap-3'>
|
|
36
36
|
<a class='lockup quicksand' href='#'><svg aria-hidden='true' style='width: 1.0515em; height: 1.0515em; top: 0.18625em' viewBox='0 0 512 512'><g fill='none' stroke='#3b8ae8' stroke-width='28' stroke-linecap='round' stroke-linejoin='round' transform='rotate(45 256 256)'><path d='M196 60 L316 60 L316 372 L196 372 Z'/><path d='M196 120 L316 120'/><path d='M196 372 L256 470 L316 372'/><path d='M232 431 L256 470 L280 431 Z' fill='#1B5288'/></g></svg>design</a>
|
|
37
|
-
<nav class='fg-2'>the <a href='#
|
|
37
|
+
<nav class='fg-2'>the <a href='#lockup'>lockups</a>, <a href='#theme'>themes</a>, <a href='#page'>pages</a>, <a href='#favicon'>icons</a> shared by <a href='https://pro.houseaccount.com/bookings' title='Fountain'><img class='design-mark' src='logo/fountain.svg' alt='Fountain'></a> <a href='https://gold.houseaccount.com/specialty_matches' title='Goldrush'><img class='design-mark' src='logo/goldrush.svg' alt='Goldrush'></a> <a href='https://providers.houseaccount.com/providers' title='Houston'><img class='design-mark' src='logo/houston.svg' alt='Houston'></a> <a href='https://checkout.houseaccount.com/providers' title='Autopilot'><img class='design-mark' src='logo/autopilot.svg' alt='Autopilot'></a></nav>
|
|
38
38
|
</header>
|
|
39
39
|
|
|
40
40
|
<main class='container-fluid px-3'>
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
<div class='card p-3'>
|
|
46
46
|
<strong>Stylesheet</strong>
|
|
47
47
|
<a class='design-url' href='css/houseaccount.css'><span class='d-none sm:d-inline'>https://design.houseaccount.com/</span>css/houseaccount.css</a>
|
|
48
|
-
<span class='small fg-2 mt-1'>Bootstrap 6
|
|
48
|
+
<span class='small fg-2 mt-1'>bh's Bootstrap 6, then the icon subset and the brand</span>
|
|
49
49
|
</div>
|
|
50
50
|
</div>
|
|
51
51
|
<div class='col-12 md:col-6'>
|
|
52
52
|
<div class='card p-3'>
|
|
53
53
|
<strong>Script</strong>
|
|
54
54
|
<a class='design-url' href='js/houseaccount.js'><span class='d-none sm:d-inline'>https://design.houseaccount.com/</span>js/houseaccount.js</a>
|
|
55
|
-
<span class='small fg-2 mt-1'>
|
|
55
|
+
<span class='small fg-2 mt-1'>bh's bundle, and the controller that paints the wall</span>
|
|
56
56
|
</div>
|
|
57
57
|
</div>
|
|
58
58
|
<div class='col-12'>
|
|
@@ -74,117 +74,34 @@
|
|
|
74
74
|
</button>
|
|
75
75
|
</section>
|
|
76
76
|
|
|
77
|
-
<section class='design-section' id='
|
|
78
|
-
<h2>
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
</div>
|
|
88
|
-
|
|
89
|
-
<h3 class='h5 design-subsection'>Breadcrumb</h3>
|
|
90
|
-
<nav aria-label='Breadcrumb'><ol class='breadcrumb m-0 justify-content-center'>
|
|
91
|
-
<li class='breadcrumb-item'><a class='breadcrumb-link' href='#'><i class='bi bi-geo'></i> States</a></li>
|
|
92
|
-
<li class='breadcrumb-item'><span class='breadcrumb-link active'>California</span></li>
|
|
93
|
-
</ol></nav>
|
|
94
|
-
|
|
95
|
-
<h3 class='h5 design-subsection' id='table'>Tables</h3>
|
|
96
|
-
<div class='table-responsive' style='container-type: inline-size'>
|
|
97
|
-
<table class='table table-hover sm:table-stacked'>
|
|
98
|
-
<thead><tr>
|
|
99
|
-
<th scope='col'><i class='bi bi-bookmark' role='img' data-controller='tooltip' data-bs-placement='top' data-bs-title='Kept'></i></th>
|
|
100
|
-
<th scope='col'><a href='#'>Name <i class='bi bi-sort-down'></i></a></th>
|
|
101
|
-
<th scope='col'><a href='#'>Phone</a></th>
|
|
102
|
-
<th scope='col'><a href='#'>Status</a></th>
|
|
103
|
-
<th scope='col' class='recourse-counter'><i class='bi bi-briefcase' role='img' data-controller='tooltip' data-bs-placement='top' data-bs-title='Jobs'></i></th>
|
|
104
|
-
</tr></thead>
|
|
105
|
-
<tbody>
|
|
106
|
-
<tr class='recourse-kept'><td class='recourse-bookmark'><i class='bi bi-bookmark-fill'></i></td><td data-cell='Name'>Blue Crew</td><td data-cell='Phone'><span data-controller='phone'>4155550000</span></td><td data-cell='Status'><span class='badge'>active</span></td><td class='recourse-counter'><a href='#' data-cell='Jobs'><span class='recourse-counter-figure'>21</span><span class='recourse-counter-word'>21 jobs</span></a></td></tr>
|
|
107
|
-
<tr class='recourse-written'><td class='recourse-bookmark'><i class='bi bi-bookmark'></i></td><td data-cell='Name'>Nashville Plumbing</td><td data-cell='Phone'><span data-controller='phone'>6155550123</span></td><td data-cell='Status'><span class='badge'>draft</span></td><td class='recourse-counter'><a href='#' data-cell='Jobs'><span class='recourse-counter-figure'>3</span><span class='recourse-counter-word'>3 jobs</span></a></td></tr>
|
|
108
|
-
<tr><td class='recourse-bookmark'><i class='bi bi-bookmark'></i></td><td data-cell='Name'>Golden Gate Electric</td><td data-cell='Phone'><span data-controller='phone'>4155559876</span></td><td data-cell='Status'><span class='badge'>active</span></td><td class='recourse-counter'><a href='#' data-cell='Jobs'><span class='recourse-counter-figure'>38,405</span><span class='recourse-counter-word'>38,405 jobs</span></a></td></tr>
|
|
109
|
-
</tbody>
|
|
110
|
-
</table>
|
|
111
|
-
</div>
|
|
112
|
-
|
|
113
|
-
<h3 class='h5 design-subsection'>PIN</h3>
|
|
114
|
-
<form class='mx-auto' onsubmit='return false' style='max-width: 22rem'>
|
|
115
|
-
<div class='otp otp-lg' data-controller='otp' data-bs-otp='true'>
|
|
116
|
-
<input class='otp-input' inputmode='numeric' pattern='[0-9]{6}' minlength='6' maxlength='6' autocomplete='one-time-code' required type='text' name='pin' id='pin' aria-label='6-digit code'>
|
|
117
|
-
</div>
|
|
118
|
-
</form>
|
|
119
|
-
|
|
120
|
-
<h3 class='h5 design-subsection'>Combobox</h3>
|
|
121
|
-
<div class='d-flex flex-wrap justify-content-center gap-3 align-items-start'>
|
|
122
|
-
<div style='width: 16rem'>
|
|
123
|
-
<label class='form-label' for='team'>Team</label>
|
|
124
|
-
<select class='form-select' id='team' name='team' data-controller='combobox' data-combobox-placeholder-value='Select…' data-search='Search…' data-clear='Clear search' data-no-results='No results found'>
|
|
125
|
-
<option value=''>None</option>
|
|
126
|
-
<option value='1'>Blue Crew</option>
|
|
127
|
-
<option value='2' selected>Golden Gate Electric</option>
|
|
128
|
-
<option value='3'>Nashville Plumbing</option>
|
|
129
|
-
</select>
|
|
130
|
-
</div>
|
|
131
|
-
<div style='width: 16rem'>
|
|
132
|
-
<label class='form-label' for='markets'>Markets</label>
|
|
133
|
-
<select class='form-select form-select-sm' id='markets' name='markets[]' multiple data-controller='combobox' data-combobox-placeholder-value='Market' data-combobox-all-value='All markets' data-combobox-more-value='%{first} + %{count} more' data-search='Search…' data-clear='Clear search' data-no-results='No results found'>
|
|
134
|
-
<option value='1' data-count='38,405' selected>San Francisco</option>
|
|
135
|
-
<option value='2' data-count='21' selected>Nashville</option>
|
|
136
|
-
<option value='3' data-count='3'>Austin</option>
|
|
137
|
-
<option value='4' data-count='0' data-hidden>Boise</option>
|
|
138
|
-
</select>
|
|
139
|
-
</div>
|
|
77
|
+
<section class='design-section' id='lockup'>
|
|
78
|
+
<h2>Lockups</h2>
|
|
79
|
+
<p class='fg-2'>A mark beside its name, as one word and one link. Each drawing fills its 512 grid
|
|
80
|
+
differently, so equal sizes never align: every mark is rendered at a box of its own and pushed
|
|
81
|
+
down by its own nudge, and its ink then stands on the baseline and reaches Quicksand's ascender.
|
|
82
|
+
The two blues are the mark's rather than the theme's, so a lockup reads the same in every app.</p>
|
|
83
|
+
<div class='d-flex flex-wrap justify-content-center align-items-baseline gap-4 mt-3'>
|
|
84
|
+
<%- mark.each_key do |app| -%>
|
|
85
|
+
<a class='lockup quicksand' href='logo/<%= app %>.svg'><%= mark[app] %><%- if app == :houseaccount -%><span class='house'>house</span>account<%- else -%><%= app %><%- end -%></a>
|
|
86
|
+
<%- end -%>
|
|
140
87
|
</div>
|
|
141
|
-
|
|
142
|
-
<
|
|
143
|
-
|
|
144
|
-
<a class='
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
<h3 class='h5 design-subsection'>Tooltip and relative time</h3>
|
|
148
|
-
<p>Hover the icon and the time: <i class='bi bi-telephone' role='img' data-controller='tooltip' data-bs-placement='top' data-bs-title='Phone'></i> ·
|
|
149
|
-
<time datetime='2026-09-13T12:00:00-04:00' data-controller='relative-time tooltip' data-bs-placement='left' data-bs-title='a moment ago'>Sep 13 at 12:00pm EDT</time></p>
|
|
150
|
-
|
|
151
|
-
<h3 class='h5 design-subsection'>Phone</h3>
|
|
152
|
-
<p>Phone: <span data-controller='phone'>4155550000</span></p>
|
|
153
|
-
<div class='mx-auto' style='max-width: 20rem'>
|
|
154
|
-
<label class='form-label' for='phone'>Phone</label>
|
|
155
|
-
<input class='form-control' type='tel' id='phone' data-controller='phone' data-action='keydown->phone#down input->phone#input' value='4155550000'>
|
|
156
|
-
</div>
|
|
157
|
-
|
|
158
|
-
<h3 class='h5 design-subsection'>Mask</h3>
|
|
159
|
-
<div class='form-control-plaintext d-flex justify-content-center gap-2 align-items-end' data-controller='reveal' data-reveal-plain-value='SEC-0000'>
|
|
160
|
-
<span data-reveal-target='mask'>********</span>
|
|
161
|
-
<button type='button' class='btn btn-link btn-sm p-0' data-action='reveal#show' data-reveal-target='button'>Show</button>
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
<h3 class='h5 design-subsection'>Toast</h3>
|
|
165
|
-
<div class='toast show mx-auto' role='status' aria-live='polite' style='position: static'>
|
|
166
|
-
<div class='toast-body d-flex align-items-center gap-2'><i class='bi bi-check-circle-fill fg-success'></i> Blue Crew was updated.</div>
|
|
88
|
+
<p class='fg-2 mt-4 mb-0'>At three sizes, to show the seating holds:</p>
|
|
89
|
+
<div class='d-flex flex-wrap justify-content-center align-items-baseline gap-4 mt-2'>
|
|
90
|
+
<a class='lockup quicksand' href='#lockup' style='font-size: 14px'><%= mark[:fountain] %>fountain</a>
|
|
91
|
+
<a class='lockup quicksand' href='#lockup'><%= mark[:fountain] %>fountain</a>
|
|
92
|
+
<a class='lockup quicksand' href='#lockup' style='font-size: 34px'><%= mark[:fountain] %>fountain</a>
|
|
167
93
|
</div>
|
|
94
|
+
</section>
|
|
168
95
|
|
|
169
|
-
|
|
170
|
-
<
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
<p class='chat-bubble chat-in chat-typing' aria-label='Typing'><span></span><span></span><span></span></p>
|
|
179
|
-
</div>
|
|
180
|
-
<form class='d-flex align-items-center' data-controller='require' action='#' onsubmit='return false'>
|
|
181
|
-
<label for='ask' class='visually-hidden'>Ask a question</label>
|
|
182
|
-
<input type='text' name='ask' id='ask' required autocomplete='off' class='form-control rounded-4 flex-grow-1 chat-ask'
|
|
183
|
-
placeholder='How much did I bill last month?' data-thread-target='field' data-controller='placeholder'
|
|
184
|
-
data-placeholder-questions-value='["How much did I bill last month?","Which ZIP codes book me most?","Which customers have booked me more than once?"]'>
|
|
185
|
-
<input type='submit' value='Send' class='btn btn-solid rounded-3 theme-primary ms-3'>
|
|
186
|
-
</form>
|
|
187
|
-
</div>
|
|
96
|
+
<section class='design-section' id='component'>
|
|
97
|
+
<h2>Components</h2>
|
|
98
|
+
<p class='fg-2'>They are not this gem's. The form that dresses every field, the combobox, the
|
|
99
|
+
6-digit code, the phone field, the dialog, the toasts, the thread of messages and the
|
|
100
|
+
twenty-two Stimulus controllers all live in <strong>bh</strong>, which is Bootstrap 6 for any
|
|
101
|
+
Rails app and has no opinion about this house. This gem depends on it and bundles it, so the
|
|
102
|
+
stylesheet and the script above already carry every one of them — and bh's own page draws each
|
|
103
|
+
beside the line of Ruby that produces it.</p>
|
|
104
|
+
<p class='mt-3'><a href='https://claudiob.github.io/bh/'>Bootstrap Helpers</a></p>
|
|
188
105
|
</section>
|
|
189
106
|
|
|
190
107
|
<section class='design-section' id='page'>
|
|
@@ -196,6 +113,15 @@
|
|
|
196
113
|
<li><a href='page/422'>422 Unprocessable</a></li>
|
|
197
114
|
<li><a href='page/500'>500 Server error</a></li>
|
|
198
115
|
</ul>
|
|
116
|
+
<h3 class='h5 design-subsection'>Down</h3>
|
|
117
|
+
<p class='fg-2'>What an app shows while it is down — its own mark in the middle, the house's at
|
|
118
|
+
the foot. The engine answers <code>/down.html</code> with the right one, and Heroku's
|
|
119
|
+
<code>MAINTENANCE_PAGE_URL</code> points here, where the app is not.</p>
|
|
120
|
+
<ul class='list-unstyled d-flex flex-wrap justify-content-center gap-3'>
|
|
121
|
+
<%- mark.each_key do |app| -%>
|
|
122
|
+
<li><a href='down/<%= app %>'><%= app %></a></li>
|
|
123
|
+
<%- end -%>
|
|
124
|
+
</ul>
|
|
199
125
|
</section>
|
|
200
126
|
|
|
201
127
|
<section class='design-section' id='favicon'>
|