@inglorious/ui 9.7.3 → 9.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/package.json +5 -5
  2. package/src/controls/button/style.css +0 -2
  3. package/src/controls/button/template.js +2 -3
  4. package/src/controls/checkbox/style.css +0 -1
  5. package/src/controls/checkbox/template.js +0 -2
  6. package/src/controls/combobox/style.css +0 -14
  7. package/src/controls/combobox/template.js +0 -13
  8. package/src/controls/file-upload/template.js +1 -1
  9. package/src/controls/image-cropper/helpers.js +0 -2
  10. package/src/controls/image-cropper/image.js +0 -2
  11. package/src/controls/image-cropper/style.css +0 -6
  12. package/src/controls/image-cropper/template.js +3 -5
  13. package/src/controls/input/style.css +0 -1
  14. package/src/controls/radio-group/style.css +0 -2
  15. package/src/controls/rating/style.css +0 -3
  16. package/src/controls/select/style.css +0 -6
  17. package/src/controls/slider/style.css +0 -5
  18. package/src/controls/slider/template.js +0 -1
  19. package/src/controls/switch/style.css +0 -1
  20. package/src/controls/switch/template.js +0 -2
  21. package/src/controls/textarea/style.css +0 -2
  22. package/src/data-display/before-after/style.css +0 -4
  23. package/src/data-display/before-after/template.js +3 -3
  24. package/src/data-display/carousel/carousel.stories.js +0 -2
  25. package/src/data-display/carousel/handlers.js +0 -2
  26. package/src/data-display/carousel/style.css +0 -18
  27. package/src/data-display/carousel/template.js +0 -15
  28. package/src/data-display/chat/index.js +0 -1
  29. package/src/data-display/chat/style.css +0 -2
  30. package/src/data-display/chat/template.js +0 -1
  31. package/src/data-display/chip/template.js +0 -1
  32. package/src/data-display/data-grid/base.css +0 -2
  33. package/src/data-display/data-grid/handlers.js +1 -8
  34. package/src/data-display/data-grid/helpers.js +0 -5
  35. package/src/data-display/data-grid/template.js +0 -1
  36. package/src/data-display/data-grid/theme.css +0 -1
  37. package/src/data-display/icon/style.css +0 -7
  38. package/src/data-display/icon/template.js +2 -2
  39. package/src/data-display/table/style.css +0 -2
  40. package/src/data-display/tooltip/style.css +0 -3
  41. package/src/data-display/virtual-list/handlers.js +0 -2
  42. package/src/data-display/virtual-list/template.js +2 -4
  43. package/src/examples/dashboard/before-after-data.js +0 -3
  44. package/src/examples/dashboard/data.js +0 -1
  45. package/src/examples/dashboard/primitive-content.js +0 -2
  46. package/src/examples/dashboard/style.css +0 -3
  47. package/src/feedback/alert/style.css +0 -1
  48. package/src/feedback/dialog/dialog.stories.js +7 -2
  49. package/src/feedback/dialog/style.css +31 -18
  50. package/src/feedback/dialog/template.js +16 -16
  51. package/src/feedback/progress/style.css +0 -6
  52. package/src/feedback/progress/template.js +0 -3
  53. package/src/feedback/snackbar/snackbar.stories.js +0 -1
  54. package/src/feedback/snackbar/style.css +0 -10
  55. package/src/layout/flex/style.css +0 -2
  56. package/src/navigation/bottom-navigation/style.css +0 -7
  57. package/src/navigation/drawer/style.css +0 -21
  58. package/src/navigation/drawer/template.js +10 -9
  59. package/src/navigation/menu/menu.stories.js +0 -2
  60. package/src/navigation/menu/style.css +0 -4
  61. package/src/navigation/menu/template.js +0 -3
  62. package/src/navigation/speed-dial/style.css +0 -4
  63. package/src/navigation/speed-dial/template.js +0 -5
  64. package/src/navigation/tabs/template.js +0 -2
  65. package/src/navigation/view-transitions/index.js +0 -13
  66. package/src/navigation/view-transitions/style.css +0 -2
  67. package/src/shared/icons.js +0 -4
  68. package/src/styles/themes/bootstrap.css +0 -40
  69. package/src/styles/themes/inglorious.css +0 -21
  70. package/src/styles/themes/ios-18.css +0 -47
  71. package/src/styles/themes/ios-26.css +0 -55
  72. package/src/styles/themes/material-3.css +0 -52
  73. package/src/styles/themes/material-ui.css +0 -43
  74. package/src/styles/tokens.css +0 -40
  75. package/src/surfaces/accordion/style.css +0 -2
  76. package/src/surfaces/accordion/template.js +0 -4
  77. package/src/surfaces/app-bar/style.css +0 -3
  78. package/src/surfaces/card/style.css +0 -3
  79. package/types/controls/button-group.d.ts +5 -3
  80. package/types/controls/button.d.ts +3 -1
  81. package/types/controls/combobox.d.ts +13 -0
  82. package/types/controls/fab.d.ts +1 -1
  83. package/types/controls/icon-button.d.ts +7 -21
  84. package/types/controls/input.d.ts +2 -2
  85. package/types/data-display/avatar.d.ts +1 -1
  86. package/types/data-display/badge.d.ts +4 -2
  87. package/types/data-display/chip.d.ts +5 -3
  88. package/types/data-display/icon.d.ts +4 -2
  89. package/types/data-display/tooltip.d.ts +4 -2
  90. package/types/data-display/typography.d.ts +3 -1
  91. package/types/feedback/alert.d.ts +3 -1
  92. package/types/feedback/backdrop.d.ts +4 -2
  93. package/types/feedback/dialog.d.ts +11 -1
  94. package/types/index.d.ts +1 -0
  95. package/types/layout/container.d.ts +3 -1
  96. package/types/layout/flex.d.ts +9 -11
  97. package/types/layout/grid.d.ts +4 -2
  98. package/types/navigation/breadcrumbs.d.ts +1 -1
  99. package/types/navigation/drawer.d.ts +9 -1
  100. package/types/navigation/link.d.ts +4 -2
  101. package/types/shared/renderable.d.ts +12 -0
  102. package/types/surfaces/app-bar.d.ts +3 -1
  103. package/types/surfaces/card.d.ts +4 -2
  104. package/types/surfaces/paper.d.ts +3 -1
@@ -167,7 +167,6 @@ export const Chat = {
167
167
  isFullWidth: true,
168
168
  onChange: (value) => props.onDraftChange?.(value),
169
169
  onKeyDown: (event) => {
170
- // Enter sends, unless it closes a character being composed.
171
170
  if (event.key !== "Enter" || event.shiftKey || event.isComposing) {
172
171
  return
173
172
  }
@@ -38,7 +38,6 @@ export function render(props) {
38
38
  () => html`<span class="iw-chip-icon" aria-hidden="true">${icon}</span>`,
39
39
  )} <span class="iw-chip-label">${children}</span>`
40
40
 
41
- // A chip that can be picked is a toggle button, pressed while selected.
42
41
  if (isSelected !== undefined) {
43
42
  return html`<button
44
43
  type="button"
@@ -35,8 +35,6 @@
35
35
  gap: var(--iw-space-2);
36
36
  }
37
37
 
38
- /* The two ends of a range share the column; native date and number
39
- fields would otherwise keep a width of their own and spill out. */
40
38
  .iw-data-grid-filter-range > .iw-input {
41
39
  flex: 1 1 0;
42
40
  min-width: 0;
@@ -37,16 +37,13 @@ export function sortChange(entity, columnId) {
37
37
  const existingIndex = entity.sorts.findIndex((s) => s.column === columnId)
38
38
 
39
39
  if (existingIndex !== -1) {
40
- // Toggle direction
41
40
  const existing = entity.sorts[existingIndex]
42
41
  if (existing.direction === "asc") {
43
42
  existing.direction = "desc"
44
43
  } else {
45
- // Remove from sort if going from desc back to nothing
46
44
  entity.sorts.splice(existingIndex, 1)
47
45
  }
48
46
  } else {
49
- // Add new sort
50
47
  entity.sorts.push({ column: columnId, direction: "asc" })
51
48
  }
52
49
 
@@ -201,7 +198,7 @@ export function rowToggle(entity, rowId) {
201
198
 
202
199
  if (index === -1) {
203
200
  if (!entity.isMultiSelect) {
204
- entity.selection = [rowId] // Replace entirely
201
+ entity.selection = [rowId]
205
202
  } else {
206
203
  entity.selection.push(rowId)
207
204
  }
@@ -251,14 +248,12 @@ export function rowsToggleAll(entity) {
251
248
  )
252
249
 
253
250
  if (allSelected) {
254
- // Deselect all visible
255
251
  rows.forEach((row) => {
256
252
  const rowId = getRowKeyValue(entity, row)
257
253
  const index = entity.selection.indexOf(rowId)
258
254
  if (index !== -1) entity.selection.splice(index, 1)
259
255
  })
260
256
  } else {
261
- // Select all visible
262
257
  rows.forEach((row) => {
263
258
  const rowId = getRowKeyValue(entity, row)
264
259
  if (!entity.selection.includes(rowId)) {
@@ -398,7 +393,6 @@ function initDataGrid(entity) {
398
393
  entity.rows ??= []
399
394
  entity.rowId ??= "id"
400
395
 
401
- // Auto-generate columns from first data item if not provided
402
396
  if (!entity.columns && entity.rows.length) {
403
397
  const [firstRow] = entity.rows
404
398
 
@@ -427,7 +421,6 @@ function initDataGrid(entity) {
427
421
  })
428
422
  }
429
423
 
430
- // State
431
424
  entity.sorts ??= []
432
425
  entity.filters ??= {}
433
426
  entity.search ??= null
@@ -196,12 +196,10 @@ function applyFilters(entity, rows) {
196
196
  const column = entity.columns.find((c) => c.id === columnId)
197
197
  if (!column) return true
198
198
 
199
- // Custom filter function
200
199
  if (column.filterFn) {
201
200
  return column.filterFn(row, filterValue)
202
201
  }
203
202
 
204
- // Default filters by type
205
203
  const value = row[columnId]
206
204
 
207
205
  if (["range", "date", "time", "datetime"].includes(column.filter.type)) {
@@ -215,7 +213,6 @@ function applyFilters(entity, rows) {
215
213
  return value === filterValue
216
214
  }
217
215
 
218
- // String filtering (case-insensitive contains)
219
216
  return String(value)
220
217
  .toLowerCase()
221
218
  .includes(String(filterValue).toLowerCase())
@@ -262,7 +259,6 @@ function applySorts(entity, rows) {
262
259
  let aVal = a[columnId]
263
260
  let bVal = b[columnId]
264
261
 
265
- // Custom sort function
266
262
  if (column?.sortFn) {
267
263
  const result =
268
264
  direction === "asc" ? column.sortFn(a, b) : column.sortFn(b, a)
@@ -270,7 +266,6 @@ function applySorts(entity, rows) {
270
266
  continue
271
267
  }
272
268
 
273
- // Default sorting
274
269
  if (aVal === bVal) continue
275
270
  if (aVal == null) return 1
276
271
  if (bVal == null) return -1
@@ -264,7 +264,6 @@ export const DataGrid = {
264
264
  const column = props.columns[index]
265
265
  const isEditable = Boolean(column.isEditable && row)
266
266
 
267
- // Typing in a cell's editor is not picking its row.
268
267
  return html`<div
269
268
  class="iw-data-grid-cell ${classMap({
270
269
  "iw-data-grid-cell-number": column.type === "number",
@@ -146,7 +146,6 @@
146
146
  }
147
147
  }
148
148
 
149
- /* An editor fills its cell, which keeps less padding around it. */
150
149
  .iw-data-grid-cell-editable {
151
150
  padding: var(--iw-space-2);
152
151
  }
@@ -1,7 +1,3 @@
1
- /* The size is a floor, not a fixed box. A glyph or an `icon` takes the size's
2
- font-size and fits it exactly, an SVG being drawn at 1em; content that sizes
3
- itself (an SVG with its own width, a button) grows the box instead of
4
- overflowing it or being squeezed into it. */
5
1
  .iw-icon {
6
2
  display: inline-flex;
7
3
  align-items: center;
@@ -26,9 +22,6 @@
26
22
  font-size: var(--iw-font-size-2xl);
27
23
  }
28
24
 
29
- /* An icon that points along the line, in right-to-left text. `scale`
30
- rather than `transform`, so it adds to a rotation set elsewhere instead
31
- of replacing it. */
32
25
  &.iw-icon-rtl {
33
26
  scale: -1 1;
34
27
  }
@@ -4,7 +4,7 @@
4
4
  * @typedef {import('@inglorious/web').TemplateResult} TemplateResult
5
5
  */
6
6
 
7
- import { html } from "@inglorious/web"
7
+ import { html, nothing } from "@inglorious/web"
8
8
  import { classMap } from "@inglorious/web/directives/class-map"
9
9
  import { ref } from "@inglorious/web/directives/ref"
10
10
  import { unsafeSVG } from "@inglorious/web/directives/unsafe-svg"
@@ -53,7 +53,7 @@ export function render({
53
53
  "iw-icon-rtl": direction === "rtl",
54
54
  ...extraClasses,
55
55
  })}
56
- style=${color !== "current" ? `color: ${color};` : ""}
56
+ style=${color !== "current" ? `color: ${color};` : nothing}
57
57
  @click=${onClick}
58
58
  ${ref((el) =>
59
59
  applyElementProps(el, {
@@ -18,8 +18,6 @@
18
18
  &.iw-table-wrapping {
19
19
  min-width: 0;
20
20
 
21
- /* Wrap between words; break a word only when it cannot fit alone, so
22
- short values such as percentages stay whole. */
23
21
  .iw-table-header-cell,
24
22
  .iw-table-cell {
25
23
  overflow-wrap: break-word;
@@ -1,6 +1,3 @@
1
- /* The bubble is anchored to the trigger by CSS: the browser places it on the
2
- requested side and flips it to the opposite one when it would leave the
3
- viewport. Fixed, so a container that clips its overflow does not cut it. */
4
1
  .iw-tooltip {
5
2
  anchor-scope: --iw-tooltip;
6
3
  display: inline-flex;
@@ -45,8 +45,6 @@ export function scroll(entity, containerEl) {
45
45
  */
46
46
  export function mount(entity, containerEl) {
47
47
  const firstItem = containerEl.querySelector("[data-index]")
48
- // A list not laid out yet, such as one rendered into a detached element,
49
- // measures 0: keep the estimate, and measure again on a later render.
50
48
  if (!firstItem?.offsetHeight) return
51
49
 
52
50
  entity.itemHeight = firstItem.offsetHeight
@@ -4,15 +4,13 @@
4
4
  * @typedef {import('@inglorious/web').Api} Api
5
5
  */
6
6
 
7
- import { html } from "@inglorious/web"
7
+ import { html, nothing } from "@inglorious/web"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
  import { repeat } from "@inglorious/web/directives/repeat"
10
10
  import { styleMap } from "@inglorious/web/directives/style-map"
11
11
 
12
12
  const PRETTY_INDEX = 1
13
13
 
14
- // The list elements already being measured. Every update re-renders, and
15
- // measuring is an update, so measuring on each render would loop forever.
16
14
  const measured = new WeakSet()
17
15
 
18
16
  /**
@@ -49,7 +47,7 @@ export function render(entity, api) {
49
47
 
50
48
  return html`
51
49
  <div
52
- class=${className ?? ""}
50
+ class=${className ?? nothing}
53
51
  style=${styleMap({ height: `${viewportHeight}px`, overflow: "auto" })}
54
52
  @scroll=${(e) => api.notify(`#${entity.id}:scroll`, e.currentTarget)}
55
53
  ${ref((el) => {
@@ -9,9 +9,6 @@ export const beforeAfterImages = {
9
9
  },
10
10
  }
11
11
 
12
- // Self-contained demo images for the Before/After control, so the dashboard
13
- // renders the comparison without any network requests.
14
-
15
12
  function svg(label, from, to) {
16
13
  return (
17
14
  "data:image/svg+xml," +
@@ -94,7 +94,6 @@ export const trafficSummary = [
94
94
  progress: 80,
95
95
  color: "error",
96
96
  },
97
- // { label: "Bounce Rate", value: "40.15%", progress: 40, color: "primary" },
98
97
  ]
99
98
 
100
99
  export const socialCards = [
@@ -1525,8 +1525,6 @@ function toTitleCase(slug) {
1525
1525
  function livePreview(types, entity) {
1526
1526
  if (!livePreviews.has(entity.id)) {
1527
1527
  const container = document.createElement("div")
1528
- // The mount needs an element, but it must not become a box of its own:
1529
- // as a flex item it would shrink and take the primitive down with it.
1530
1528
  container.style.display = "contents"
1531
1529
 
1532
1530
  const store = createStore({ types, entities: { [entity.id]: entity } })
@@ -57,7 +57,6 @@
57
57
  width: 100%;
58
58
  }
59
59
 
60
- /* Outside the app bar, so it pads itself to line up with it. */
61
60
  .iw-dashboard-breadcrumbs {
62
61
  min-height: var(--iw-space-12);
63
62
  padding-inline: var(--iw-space-4);
@@ -261,8 +260,6 @@
261
260
  inset: 0;
262
261
  }
263
262
 
264
- /* Shown in place (isModal: false), so it can sit in the preview's flow
265
- rather than where the browser positions a non-modal dialog. */
266
263
  .iw-primitive-preview .iw-dialog {
267
264
  position: static;
268
265
  min-width: 0;
@@ -81,7 +81,6 @@
81
81
  --iw-alert-color: var(--iw-color-error, #d14343);
82
82
  }
83
83
 
84
- /* A plain note: no tone of its own, just the text colour. */
85
84
  .iw-alert-neutral {
86
85
  --iw-alert-color: var(--iw-color-text-secondary, var(--iw-color-text));
87
86
  }
@@ -10,14 +10,15 @@ export default {
10
10
  argTypes: {
11
11
  isOpen: { control: "boolean" },
12
12
  isModal: { control: "boolean" },
13
+ variant: { control: "select", options: ["dialog", "sheet"] },
13
14
  size: { control: "select", options: ["sm", "md", "lg"] },
14
15
  title: { control: "text" },
15
16
  description: { control: "text" },
17
+ closeLabel: { control: "text" },
16
18
  onClose: { action: "onClose" },
17
19
  },
18
20
  }
19
21
 
20
- // In place, so the docs page that shows every story stays usable.
21
22
  export const Open = {
22
23
  args: {
23
24
  isOpen: true,
@@ -51,8 +52,12 @@ export const Large = {
51
52
  },
52
53
  }
53
54
 
54
- // Modal takes over the page, so it is left out of the docs page.
55
55
  export const Modal = {
56
56
  tags: ["!autodocs"],
57
57
  args: { ...Open.args, isModal: true },
58
58
  }
59
+
60
+ export const Sheet = {
61
+ tags: ["!autodocs"],
62
+ args: { ...Open.args, isModal: true, variant: "sheet" },
63
+ }
@@ -1,7 +1,3 @@
1
- /* A native <dialog>, so the browser's own box is reset: the surface inside
2
- carries the padding, which leaves the dialog element itself reachable only
3
- through the backdrop. Modal dialogs sit in the top layer, above any
4
- z-index, and the browser centres them. */
5
1
  .iw-dialog {
6
2
  background: var(--iw-color-surface);
7
3
  color: var(--iw-color-text);
@@ -48,20 +44,7 @@
48
44
  }
49
45
 
50
46
  .iw-dialog-close {
51
- border: 0 none;
52
- background: transparent;
53
- width: 1.75rem;
54
- height: 1.75rem;
55
- border-radius: var(--iw-radius-sm);
56
- display: inline-flex;
57
- align-items: center;
58
- justify-content: center;
59
- cursor: pointer;
60
- color: inherit;
61
- }
62
-
63
- .iw-dialog-close:hover {
64
- background-color: color-mix(in srgb, currentColor 12%, transparent);
47
+ flex-shrink: 0;
65
48
  }
66
49
 
67
50
  .iw-dialog-description {
@@ -80,3 +63,33 @@
80
63
  flex-wrap: wrap;
81
64
  gap: var(--iw-space-2);
82
65
  }
66
+
67
+ @media (width < 48rem) {
68
+ dialog.iw-dialog.iw-dialog-sheet {
69
+ inset: auto 0 0;
70
+ margin: 0;
71
+ width: 100%;
72
+ min-width: 0;
73
+ max-width: 100%;
74
+ max-height: 85dvh;
75
+ padding-bottom: var(--safe-area-bottom, 0px);
76
+ border-end-start-radius: 0;
77
+ border-end-end-radius: 0;
78
+ }
79
+
80
+ dialog.iw-dialog.iw-dialog-sheet[open] {
81
+ animation: iw-dialog-sheet-in 0.32s cubic-bezier(0.22, 1, 0.36, 1);
82
+ }
83
+ }
84
+
85
+ @keyframes iw-dialog-sheet-in {
86
+ from {
87
+ transform: translateY(100%);
88
+ }
89
+ }
90
+
91
+ @media (prefers-reduced-motion: reduce) {
92
+ dialog.iw-dialog.iw-dialog-sheet[open] {
93
+ animation: none;
94
+ }
95
+ }
@@ -8,6 +8,9 @@ import { classMap } from "@inglorious/web/directives/class-map"
8
8
  import { ref } from "@inglorious/web/directives/ref"
9
9
  import { when } from "@inglorious/web/directives/when"
10
10
 
11
+ import { IconButton } from "../../controls/icon-button/index.js"
12
+ import { Icon } from "../../data-display/icon/index.js"
13
+ import { close } from "../../shared/icons.js"
11
14
  import { syncDialog } from "../../shared/top-layer.js"
12
15
 
13
16
  /**
@@ -29,12 +32,14 @@ export function render(props) {
29
32
  id,
30
33
  isOpen = false,
31
34
  isModal = true,
35
+ variant = "dialog",
32
36
  size = "md",
33
37
  title,
34
38
  description,
35
39
  children,
36
40
  actions,
37
41
  className = "",
42
+ closeLabel = "Close",
38
43
  onClose,
39
44
  onBackdropClick,
40
45
  } = props
@@ -50,15 +55,12 @@ export function render(props) {
50
55
  const descriptionId = id && description ? `${id}-description` : ""
51
56
  const onBackdrop = onBackdropClick ?? onClose
52
57
 
53
- // The surface fills the dialog box, so a click that lands on the dialog
54
- // itself can only have come from the backdrop around it. The press has to
55
- // start there too: a drag from inside the surface that ends on the backdrop
56
- // also clicks the dialog, and must not close it.
57
58
  return html`<dialog
58
59
  id=${id || nothing}
59
60
  class=${classMap({
60
61
  "iw-dialog": true,
61
62
  [`iw-dialog-${size}`]: true,
63
+ "iw-dialog-sheet": variant === "sheet",
62
64
  ...extraClasses,
63
65
  })}
64
66
  aria-labelledby=${titleId || nothing}
@@ -77,7 +79,6 @@ export function render(props) {
77
79
  }
78
80
  }}
79
81
  @cancel=${(event) => {
80
- // Without onClose nothing would take isOpen down, so Esc is refused.
81
82
  if (!onClose) event.preventDefault()
82
83
  }}
83
84
  ${ref((element) => syncDialog(element, { isOpen, isModal, onClose }))}
@@ -94,17 +95,16 @@ export function render(props) {
94
95
  ${title}
95
96
  </div>`,
96
97
  )}
97
- ${when(
98
- onClose,
99
- () =>
100
- html`<button
101
- type="button"
102
- class="iw-dialog-close"
103
- aria-label="Close"
104
- @click=${onClose}
105
- >
106
- ×
107
- </button>`,
98
+ ${when(onClose, () =>
99
+ IconButton.render({
100
+ icon: Icon.render({ icon: close, size: "lg" }),
101
+ ariaLabel: closeLabel,
102
+ variant: "ghost",
103
+ color: "secondary",
104
+ shape: "round",
105
+ className: "iw-dialog-close",
106
+ onClick: onClose,
107
+ }),
108
108
  )}
109
109
  </div>`,
110
110
  )}
@@ -24,10 +24,6 @@
24
24
  }
25
25
  }
26
26
 
27
- /* A native <progress>, restyled. Browsers draw its value through their own
28
- pseudo-elements, so the look is set once here: the bar takes `color`, like
29
- the color variants above, and an app adjusts the rest through
30
- --iw-progress-height, --iw-progress-radius and --iw-progress-track-color. */
31
27
  .iw-progress-linear {
32
28
  --iw-progress-bar: linear-gradient(
33
29
  90deg,
@@ -63,8 +59,6 @@
63
59
  border-radius: var(--iw-progress-radius, var(--iw-radius-sm));
64
60
  }
65
61
 
66
- /* Indeterminate: no value to draw, so a sliver of the bar sweeps across
67
- the track, painted on the element itself. */
68
62
  &:indeterminate {
69
63
  background:
70
64
  var(--iw-progress-bar) no-repeat 0 0 / 30% 100%,
@@ -77,9 +77,6 @@ export function render(props) {
77
77
 
78
78
  const progress = value == null ? null : clamp(value)
79
79
 
80
- // An attribute, not a property: removing it is the only way back to
81
- // indeterminate, which `:indeterminate` styles and assistive tech announces
82
- // as busy.
83
80
  return html`<progress
84
81
  class=${classMap({
85
82
  "iw-progress": true,
@@ -31,7 +31,6 @@ export const Default = {
31
31
  },
32
32
  }
33
33
 
34
- // A phone app keeps a bar at the bottom: the snackbar rises above it.
35
34
  export const AboveBottomNavigation = {
36
35
  args: {
37
36
  isOpen: true,
@@ -1,8 +1,3 @@
1
- /* Fixed to the viewport, clear of the system bars. A bottom snackbar also
2
- clears whatever bar the app keeps at the bottom: the app sets
3
- --iw-snackbar-offset-bottom to that bar's height while it shows, and the
4
- offset then stands in for the safe area, which the bar already covers.
5
- Only the app knows when its bar is on screen, so nothing is guessed here. */
6
1
  .iw-snackbar {
7
2
  --iw-snackbar-gap: var(--iw-space-4);
8
3
  position: fixed;
@@ -10,9 +5,6 @@
10
5
  max-width: calc(100vw - 2 * var(--iw-snackbar-gap));
11
6
  }
12
7
 
13
- /* A manual popover in the top layer. The browser centres a popover in the
14
- viewport as a bordered box, so its insets and box are reset, with no
15
- specificity so the positions below still set their own sides. */
16
8
  :where(.iw-snackbar) {
17
9
  inset: auto;
18
10
  margin: 0;
@@ -48,8 +40,6 @@
48
40
  right: var(--iw-snackbar-gap);
49
41
  }
50
42
 
51
- /* Both insets and auto margins: the snackbar is as wide as its content, up
52
- to the gutters, and centered within them. */
53
43
  .iw-snackbar-bottom-center,
54
44
  .iw-snackbar-top-center {
55
45
  inset-inline: var(--iw-snackbar-gap);
@@ -129,8 +129,6 @@
129
129
  padding: var(--iw-space-8);
130
130
  }
131
131
 
132
- /* A flex item needs both minimum dimensions released before either axis can
133
- overflow instead of expanding its parent. */
134
132
  &.iw-flex-overflow-auto,
135
133
  &.iw-flex-overflow-scroll,
136
134
  &.iw-flex-overflow-hidden,
@@ -19,8 +19,6 @@
19
19
  align-items: center;
20
20
  justify-content: center;
21
21
  gap: var(--iw-space-1);
22
- /* Narrow sides: a tab is a quarter or a fifth of a phone, and its label
23
- needs every pixel of it. */
24
22
  padding: var(--iw-space-2) var(--iw-space-1);
25
23
  cursor: pointer;
26
24
  }
@@ -29,13 +27,8 @@
29
27
  color: var(--iw-color-primary);
30
28
  }
31
29
 
32
- /* 12px, as Material sizes navigation labels: at 14px, "Applications" or
33
- "Candidatures" does not fit a quarter of a 360px phone. */
34
30
  .iw-bottom-navigation-label {
35
31
  font-size: var(--iw-font-size-xs);
36
- /* One line, like its neighbours: a label too long for its tab is cut short
37
- rather than wrapping, which in languages that break between any two
38
- characters (Japanese, Chinese) splits a word and makes the bar taller. */
39
32
  max-width: 100%;
40
33
  overflow: hidden;
41
34
  text-overflow: ellipsis;
@@ -1,7 +1,3 @@
1
- /* While it overlays the page the drawer is a popover in the top layer. The
2
- browser styles every popover as a centred, bordered box hidden until it
3
- opens, so those defaults are reset here: the drawer stays displayed while
4
- closed, off-screen or docked, and slides rather than appears. */
5
1
  .iw-drawer {
6
2
  display: flex;
7
3
  flex-direction: column;
@@ -24,8 +20,6 @@
24
20
  inset-block: 0;
25
21
  z-index: var(--iw-z-modal, 1050);
26
22
 
27
- /* As tall as an app bar, so the line under a drawer and the app bar beside
28
- it runs straight across. */
29
23
  .iw-drawer-header {
30
24
  min-height: var(--iw-space-16);
31
25
  border-bottom: 1px solid var(--iw-color-border);
@@ -52,8 +46,6 @@
52
46
  transition: transform var(--iw-transition-fast);
53
47
  }
54
48
 
55
- /* The toggle points at the edge the drawer sits on, which a right-to-left
56
- page mirrors. `scale`, so the collapsed state's rotation still applies. */
57
49
  .iw-drawer-toggler > span:dir(rtl) {
58
50
  scale: -1 1;
59
51
  }
@@ -84,15 +76,10 @@
84
76
  opacity: 0;
85
77
  }
86
78
 
87
- /* The header keeps only what fits the rail, such as a brand mark, so
88
- it centres it. */
89
79
  .iw-drawer-header {
90
80
  justify-content: center;
91
81
  }
92
82
 
93
- /* Only the icon is left, centred in the rail. The label also has to
94
- leave the row: faded out, it still took its width and pushed the
95
- icon off centre, as did the icon's side margin. */
96
83
  .iw-list-item > .iw-flex {
97
84
  justify-content: center;
98
85
  }
@@ -112,8 +99,6 @@
112
99
  }
113
100
  }
114
101
 
115
- /* `left` and `right` are the start and end of the line: the left drawer
116
- sits on the right in a right-to-left page, and slides off that way. */
117
102
  .iw-drawer-left {
118
103
  inset-inline: 0 auto;
119
104
  border-inline-end: 1px solid var(--iw-color-border);
@@ -136,9 +121,6 @@
136
121
  backdrop-filter: none;
137
122
  }
138
123
 
139
- /* Overlaying: a temporary drawer at every width, a responsive one below
140
- 64rem. Off-screen until open, raised, closed from its header. The collapse
141
- toggle only makes sense for a rail, so the footer goes. */
142
124
  .iw-drawer {
143
125
  box-shadow: var(--iw-shadow-lg);
144
126
 
@@ -151,9 +133,6 @@
151
133
  }
152
134
  }
153
135
 
154
- /* Docked: a permanent drawer at every width, a responsive one from 64rem
155
- (keep in step with DOCKED_QUERY in template.js). In place, flat, and
156
- hidden only on request. */
157
136
  .iw-drawer-permanent {
158
137
  transform: none;
159
138
  box-shadow: none;