opencode-skills-collection 3.1.0 → 3.1.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.
- package/bundled-skills/.antigravity-install-manifest.json +84 -1
- package/bundled-skills/android-ui-journey-testing/SKILL.md +191 -0
- package/bundled-skills/ask-matt/SKILL.md +92 -0
- package/bundled-skills/bugs-are-annoying/SKILL.md +137 -0
- package/bundled-skills/codebase-design/DEEPENING.md +37 -0
- package/bundled-skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
- package/bundled-skills/codebase-design/SKILL.md +145 -0
- package/bundled-skills/competitor-analysis/LICENSE.txt +21 -0
- package/bundled-skills/competitor-analysis/SKILL.md +434 -0
- package/bundled-skills/competitor-analysis/references/battle-card-subagent.md +127 -0
- package/bundled-skills/competitor-analysis/references/battle-card.md +91 -0
- package/bundled-skills/competitor-analysis/references/example-research.md +130 -0
- package/bundled-skills/competitor-analysis/references/report-template.html +127 -0
- package/bundled-skills/competitor-analysis/references/research-patterns.md +217 -0
- package/bundled-skills/competitor-analysis/references/workflow.md +434 -0
- package/bundled-skills/competitor-analysis/scripts/capture_screenshots.mjs +142 -0
- package/bundled-skills/competitor-analysis/scripts/compile_report.mjs +929 -0
- package/bundled-skills/competitor-analysis/scripts/extract_vs_names.mjs +140 -0
- package/bundled-skills/competitor-analysis/scripts/gate_candidates.mjs +194 -0
- package/bundled-skills/competitor-analysis/scripts/list_urls.mjs +90 -0
- package/bundled-skills/competitor-analysis/scripts/md_utils.mjs +50 -0
- package/bundled-skills/competitor-analysis/scripts/merge_partials.mjs +291 -0
- package/bundled-skills/competitor-analysis/scripts/package.json +6 -0
- package/bundled-skills/design-it/3d-ui/SKILL.md +259 -0
- package/bundled-skills/design-it/SKILL.md +170 -0
- package/bundled-skills/design-it/ai-native-ui/SKILL.md +295 -0
- package/bundled-skills/design-it/aurora-ui/SKILL.md +307 -0
- package/bundled-skills/design-it/bento-ui/SKILL.md +314 -0
- package/bundled-skills/design-it/brutalism/SKILL.md +270 -0
- package/bundled-skills/design-it/brutalist-typography/SKILL.md +287 -0
- package/bundled-skills/design-it/card-based-design/SKILL.md +262 -0
- package/bundled-skills/design-it/claymorphism/SKILL.md +287 -0
- package/bundled-skills/design-it/color-blocking/SKILL.md +278 -0
- package/bundled-skills/design-it/command-center-ui/SKILL.md +345 -0
- package/bundled-skills/design-it/cyber-y2k/SKILL.md +312 -0
- package/bundled-skills/design-it/cyberpunk-ui/SKILL.md +262 -0
- package/bundled-skills/design-it/dark-mode/SKILL.md +289 -0
- package/bundled-skills/design-it/dashboard-design/SKILL.md +331 -0
- package/bundled-skills/design-it/data-dense-design/SKILL.md +322 -0
- package/bundled-skills/design-it/duotone-design/SKILL.md +248 -0
- package/bundled-skills/design-it/editorial-design/SKILL.md +328 -0
- package/bundled-skills/design-it/flat-design/SKILL.md +221 -0
- package/bundled-skills/design-it/flat-design-2/SKILL.md +240 -0
- package/bundled-skills/design-it/floating-ui/SKILL.md +299 -0
- package/bundled-skills/design-it/frutiger-aero/SKILL.md +274 -0
- package/bundled-skills/design-it/glassmorphism/SKILL.md +272 -0
- package/bundled-skills/design-it/gradient-design/SKILL.md +309 -0
- package/bundled-skills/design-it/high-contrast/SKILL.md +288 -0
- package/bundled-skills/design-it/holographic-ui/SKILL.md +310 -0
- package/bundled-skills/design-it/isometric-design/SKILL.md +228 -0
- package/bundled-skills/design-it/layered-design/SKILL.md +247 -0
- package/bundled-skills/design-it/material-design/SKILL.md +275 -0
- package/bundled-skills/design-it/maximalism/SKILL.md +297 -0
- package/bundled-skills/design-it/minimalism/SKILL.md +267 -0
- package/bundled-skills/design-it/monochromatic-ui/SKILL.md +296 -0
- package/bundled-skills/design-it/neo-brutalism/SKILL.md +270 -0
- package/bundled-skills/design-it/neumorphism/SKILL.md +248 -0
- package/bundled-skills/design-it/retro-design/SKILL.md +283 -0
- package/bundled-skills/design-it/retro-futurism/SKILL.md +259 -0
- package/bundled-skills/design-it/sci-fi-interface/SKILL.md +309 -0
- package/bundled-skills/design-it/skeuomorphism/SKILL.md +280 -0
- package/bundled-skills/design-it/soft-pastel/SKILL.md +307 -0
- package/bundled-skills/design-it/spatial-computing-ui/SKILL.md +300 -0
- package/bundled-skills/design-it/spatial-design/SKILL.md +268 -0
- package/bundled-skills/design-it/swiss-design/SKILL.md +293 -0
- package/bundled-skills/design-it/synthwave/SKILL.md +257 -0
- package/bundled-skills/design-it/tile-design/SKILL.md +297 -0
- package/bundled-skills/design-it/typography-first/SKILL.md +247 -0
- package/bundled-skills/design-it/vaporwave/SKILL.md +331 -0
- package/bundled-skills/design-it/vibrant-maximalism/SKILL.md +291 -0
- package/bundled-skills/design-it/widget-based-design/SKILL.md +274 -0
- package/bundled-skills/design-it/y2k-design/SKILL.md +268 -0
- package/bundled-skills/diagnosing-bugs/SKILL.md +165 -0
- package/bundled-skills/diagnosing-bugs/scripts/hitl-loop.template.sh +41 -0
- package/bundled-skills/docs/contributors/skill-scoring.md +235 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +4 -4
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/domain-modeling/ADR-FORMAT.md +47 -0
- package/bundled-skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
- package/bundled-skills/domain-modeling/SKILL.md +105 -0
- package/bundled-skills/grill-me/SKILL.md +36 -0
- package/bundled-skills/grill-with-docs/SKILL.md +36 -0
- package/bundled-skills/grilling/SKILL.md +39 -0
- package/bundled-skills/handoff/SKILL.md +45 -0
- package/bundled-skills/image-generator/.env.example +7 -0
- package/bundled-skills/image-generator/SKILL.md +509 -0
- package/bundled-skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
- package/bundled-skills/improve-codebase-architecture/SKILL.md +97 -0
- package/bundled-skills/learn/SKILL.md +156 -0
- package/bundled-skills/lesson-generator/SKILL.md +90 -0
- package/bundled-skills/llm-council/.env.example +7 -0
- package/bundled-skills/llm-council/SKILL.md +602 -0
- package/bundled-skills/loop-library/SKILL.md +205 -0
- package/bundled-skills/loop-library/agents/openai.yaml +4 -0
- package/bundled-skills/loop-library/references/catalog.md +270 -0
- package/bundled-skills/mailtrap-managing-contacts/SKILL.md +112 -0
- package/bundled-skills/mailtrap-sending-emails/SKILL.md +167 -0
- package/bundled-skills/mailtrap-setting-up-sending-domain/SKILL.md +77 -0
- package/bundled-skills/mailtrap-testing-with-sandbox/SKILL.md +110 -0
- package/bundled-skills/prototype/LOGIC.md +79 -0
- package/bundled-skills/prototype/SKILL.md +62 -0
- package/bundled-skills/prototype/UI.md +112 -0
- package/bundled-skills/setup-matt-pocock-skills/SKILL.md +158 -0
- package/bundled-skills/setup-matt-pocock-skills/domain.md +51 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-github.md +34 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-gitlab.md +35 -0
- package/bundled-skills/setup-matt-pocock-skills/issue-tracker-local.md +19 -0
- package/bundled-skills/setup-matt-pocock-skills/triage-labels.md +15 -0
- package/bundled-skills/survey-generator/LICENSE +21 -0
- package/bundled-skills/survey-generator/SKILL.md +143 -0
- package/bundled-skills/survey-generator/build_artifact.py +208 -0
- package/bundled-skills/survey-generator/examples/agentic-engineering/research_bundle.json +1196 -0
- package/bundled-skills/survey-generator/examples/agentic-engineering/survey.html +706 -0
- package/bundled-skills/survey-generator/style_spec.json +85 -0
- package/bundled-skills/survey-generator/templates/research_bundle_template.json +69 -0
- package/bundled-skills/tdd/SKILL.md +139 -0
- package/bundled-skills/tdd/mocking.md +59 -0
- package/bundled-skills/tdd/refactoring.md +10 -0
- package/bundled-skills/tdd/tests.md +61 -0
- package/bundled-skills/teach/GLOSSARY-FORMAT.md +35 -0
- package/bundled-skills/teach/LEARNING-RECORD-FORMAT.md +46 -0
- package/bundled-skills/teach/MISSION-FORMAT.md +31 -0
- package/bundled-skills/teach/RESOURCES-FORMAT.md +32 -0
- package/bundled-skills/teach/SKILL.md +169 -0
- package/bundled-skills/to-issues/SKILL.md +115 -0
- package/bundled-skills/to-prd/SKILL.md +104 -0
- package/bundled-skills/tools-page-seo-optimizer/SKILL.md +616 -0
- package/bundled-skills/triage/AGENT-BRIEF.md +207 -0
- package/bundled-skills/triage/OUT-OF-SCOPE.md +105 -0
- package/bundled-skills/triage/SKILL.md +143 -0
- package/bundled-skills/vibecode-production-qa-validator/SKILL.md +371 -141
- package/bundled-skills/wiki-builder/SKILL.md +157 -0
- package/bundled-skills/wiki-builder/agents/openai.yaml +5 -0
- package/bundled-skills/wiki-builder/references/wiki-flavors.md +98 -0
- package/bundled-skills/wiki-builder/scripts/init_wiki.sh +105 -0
- package/bundled-skills/wiki-builder/templates/index.md +20 -0
- package/bundled-skills/wiki-builder/templates/maintenance-log.md +7 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-concept-page.md +12 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-index.md +11 -0
- package/bundled-skills/wiki-builder/templates/prompts/compile-source-page.md +12 -0
- package/bundled-skills/wiki-builder/templates/prompts/lint-wiki.md +10 -0
- package/bundled-skills/wiki-builder/templates/prompts/query-and-file.md +11 -0
- package/bundled-skills/wiki-builder/templates/sources.md +9 -0
- package/bundled-skills/wiki-builder/templates/wiki.config.md +53 -0
- package/bundled-skills/writing-great-skills/GLOSSARY.md +181 -0
- package/bundled-skills/writing-great-skills/SKILL.md +111 -0
- package/bundled-skills/yao-meta-skill/SKILL.md +86 -0
- package/bundled-skills/yao-meta-skill/agents/interface.yaml +26 -0
- package/bundled-skills/yao-meta-skill/manifest.json +24 -0
- package/bundled-skills/yao-meta-skill/references/artifact-design-doctrine.md +49 -0
- package/bundled-skills/yao-meta-skill/references/authoring-discipline.md +78 -0
- package/bundled-skills/yao-meta-skill/references/autonomous-adaptation.md +65 -0
- package/bundled-skills/yao-meta-skill/references/distribution-registry-method.md +60 -0
- package/bundled-skills/yao-meta-skill/references/eval-playbook.md +69 -0
- package/bundled-skills/yao-meta-skill/references/gate-selection.md +68 -0
- package/bundled-skills/yao-meta-skill/references/governance.md +134 -0
- package/bundled-skills/yao-meta-skill/references/human-review-template.md +54 -0
- package/bundled-skills/yao-meta-skill/references/intent-dialogue.md +138 -0
- package/bundled-skills/yao-meta-skill/references/iteration-philosophy.md +30 -0
- package/bundled-skills/yao-meta-skill/references/non-skill-decision-tree.md +39 -0
- package/bundled-skills/yao-meta-skill/references/operating-modes.md +107 -0
- package/bundled-skills/yao-meta-skill/references/output-eval-method.md +113 -0
- package/bundled-skills/yao-meta-skill/references/output-quality-risk.md +41 -0
- package/bundled-skills/yao-meta-skill/references/output-visual-quality.md +53 -0
- package/bundled-skills/yao-meta-skill/references/packaging-contracts.md +70 -0
- package/bundled-skills/yao-meta-skill/references/pattern-extraction-doctrine.md +76 -0
- package/bundled-skills/yao-meta-skill/references/platform-capability-matrix.md +49 -0
- package/bundled-skills/yao-meta-skill/references/prompt-engineering-doctrine.md +76 -0
- package/bundled-skills/yao-meta-skill/references/qa-ladder.md +57 -0
- package/bundled-skills/yao-meta-skill/references/reference-scan.md +126 -0
- package/bundled-skills/yao-meta-skill/references/regression-cause-taxonomy.md +80 -0
- package/bundled-skills/yao-meta-skill/references/resource-boundaries.md +120 -0
- package/bundled-skills/yao-meta-skill/references/review-studio-method.md +87 -0
- package/bundled-skills/yao-meta-skill/references/review-waiver-method.md +76 -0
- package/bundled-skills/yao-meta-skill/references/runtime-conformance-method.md +21 -0
- package/bundled-skills/yao-meta-skill/references/skill-archetypes.md +86 -0
- package/bundled-skills/yao-meta-skill/references/skill-atlas-method.md +35 -0
- package/bundled-skills/yao-meta-skill/references/skill-engineering-method.md +210 -0
- package/bundled-skills/yao-meta-skill/references/skill-ir-method.md +41 -0
- package/bundled-skills/yao-meta-skill/references/skillops-decision-policy.md +53 -0
- package/bundled-skills/yao-meta-skill/references/systems-thinking-doctrine.md +75 -0
- package/bundled-skills/yao-meta-skill/references/telemetry-drift-method.md +182 -0
- package/bundled-skills/yao-meta-skill/references/trust-security-method.md +79 -0
- package/bundled-skills/yao-meta-skill/references/user-memory-policy.md +35 -0
- package/bundled-skills/youtube-notetaker/SKILL.md +209 -0
- package/bundled-skills/youtube-notetaker/reference/artifact.html +269 -0
- package/bundled-skills/youtube-notetaker/scripts/contact_sheet.py +53 -0
- package/bundled-skills/youtube-notetaker/scripts/detect_slides.sh +19 -0
- package/bundled-skills/youtube-notetaker/scripts/download.sh +24 -0
- package/bundled-skills/youtube-notetaker/scripts/extract_slides.py +43 -0
- package/bundled-skills/youtube-notetaker/scripts/serve.py +173 -0
- package/bundled-skills/youtube-notetaker/scripts/setup.sh +27 -0
- package/bundled-skills/youtube-notetaker/scripts/verify.sh +31 -0
- package/bundled-skills/youtube-notetaker/scripts/vtt_to_transcript.py +59 -0
- package/bundled-skills/youtube-notetaker/scripts/write_library_item.py +69 -0
- package/package.json +1 -1
- package/skills_index.json +1956 -286
- package/bundled-skills/ai-md/SKILL.md +0 -523
- package/bundled-skills/atlas-contract/SKILL.md +0 -650
- package/bundled-skills/busybox-on-windows/SKILL.md +0 -40
- package/bundled-skills/monte-carlo-prevent/SKILL.md +0 -257
- package/bundled-skills/monte-carlo-prevent/references/TROUBLESHOOTING.md +0 -23
- package/bundled-skills/monte-carlo-prevent/references/parameters.md +0 -32
- package/bundled-skills/monte-carlo-prevent/references/workflows.md +0 -478
- package/bundled-skills/monte-carlo-push-ingestion/SKILL.md +0 -372
- package/bundled-skills/monte-carlo-push-ingestion/references/anomaly-detection.md +0 -87
- package/bundled-skills/monte-carlo-push-ingestion/references/custom-lineage.md +0 -203
- package/bundled-skills/monte-carlo-push-ingestion/references/direct-http-api.md +0 -207
- package/bundled-skills/monte-carlo-push-ingestion/references/prerequisites.md +0 -150
- package/bundled-skills/monte-carlo-push-ingestion/references/push-lineage.md +0 -160
- package/bundled-skills/monte-carlo-push-ingestion/references/push-metadata.md +0 -158
- package/bundled-skills/monte-carlo-push-ingestion/references/push-query-logs.md +0 -219
- package/bundled-skills/monte-carlo-push-ingestion/references/validation.md +0 -257
- package/bundled-skills/monte-carlo-push-ingestion/scripts/sample_verify.py +0 -357
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_lineage.py +0 -70
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_metadata.py +0 -65
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_and_push_query_logs.py +0 -70
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_lineage.py +0 -214
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_metadata.py +0 -160
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/collect_query_logs.py +0 -164
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_lineage.py +0 -198
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_metadata.py +0 -193
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery/push_query_logs.py +0 -207
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_metadata.py +0 -71
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_and_push_query_logs.py +0 -64
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_metadata.py +0 -253
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/collect_query_logs.py +0 -149
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_metadata.py +0 -190
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/bigquery-iceberg/push_query_logs.py +0 -208
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_lineage.py +0 -83
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_metadata.py +0 -77
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_and_push_query_logs.py +0 -83
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_lineage.py +0 -240
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_metadata.py +0 -212
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/collect_query_logs.py +0 -204
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_lineage.py +0 -192
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_metadata.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/databricks/push_query_logs.py +0 -200
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_lineage.py +0 -119
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_metadata.py +0 -119
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_and_push_query_logs.py +0 -117
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_lineage.py +0 -265
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_metadata.py +0 -313
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/collect_query_logs.py +0 -284
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_lineage.py +0 -309
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_metadata.py +0 -245
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/hive/push_query_logs.py +0 -255
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_lineage.py +0 -78
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_metadata.py +0 -80
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_and_push_query_logs.py +0 -88
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_lineage.py +0 -235
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_metadata.py +0 -219
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/collect_query_logs.py +0 -239
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_lineage.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_metadata.py +0 -178
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/redshift/push_query_logs.py +0 -196
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_lineage.py +0 -154
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_metadata.py +0 -137
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_and_push_query_logs.py +0 -137
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_lineage.py +0 -349
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_metadata.py +0 -329
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/collect_query_logs.py +0 -254
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_lineage.py +0 -307
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_metadata.py +0 -228
- package/bundled-skills/monte-carlo-push-ingestion/scripts/templates/snowflake/push_query_logs.py +0 -248
- package/bundled-skills/monte-carlo-push-ingestion/scripts/test_template_sdk_usage.py +0 -340
- package/bundled-skills/skill-optimizer/SKILL.md +0 -271
- package/bundled-skills/using-superpowers/SKILL.md +0 -98
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: data-dense-design
|
|
3
|
+
description: Web and App implementation guide for Data-Dense Design. Trigger when user wants professional tools, maximum information density, and expert interfaces (like Bloomberg terminals or IDEs).
|
|
4
|
+
date_added: "2026-06-17"
|
|
5
|
+
risk: safe
|
|
6
|
+
source: self
|
|
7
|
+
source_type: self
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Data-Dense Design
|
|
11
|
+
|
|
12
|
+
> "Density is a feature. For expert users, reducing clicks is more important than whitespace."
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.
|
|
17
|
+
|
|
18
|
+
## Core Principles
|
|
19
|
+
1. **Compact Layouts**: Extremely tight margins and padding (often 2px to 4px).
|
|
20
|
+
2. **Monospace & Tabular Data**: Numbers must align vertically perfectly.
|
|
21
|
+
3. **High Utility**: Every pixel serves a functional purpose. Minimal purely decorative elements.
|
|
22
|
+
|
|
23
|
+
## Visual DNA
|
|
24
|
+
- **Colors**: **Industrial Chic** (high contrast) or **Minimalist Slate**. Avoid bright backgrounds. Dark themes are heavily preferred to reduce eye strain over 8-hour sessions.
|
|
25
|
+
- **Typography**: Small base sizes (`11px` - `13px`). Strict use of monospace fonts (`Fira Code`, `JetBrains Mono`) for data.
|
|
26
|
+
- **Borders**: Thin `1px` borders (`#333` or `#e0e0e0`) are used extensively to separate tiny cells of data.
|
|
27
|
+
|
|
28
|
+
## Web Implementation
|
|
29
|
+
- Tables, CSS Grid, and Flexbox with zero gap.
|
|
30
|
+
- **CSS Example**:
|
|
31
|
+
```css
|
|
32
|
+
body {
|
|
33
|
+
background-color: #1e1e1e; /* IDE Dark */
|
|
34
|
+
color: #cccccc;
|
|
35
|
+
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
|
36
|
+
font-size: 12px; /* Very small */
|
|
37
|
+
margin: 0;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.dense-toolbar {
|
|
41
|
+
display: flex;
|
|
42
|
+
background-color: #2d2d2d;
|
|
43
|
+
border-bottom: 1px solid #3c3c3c;
|
|
44
|
+
padding: 2px 4px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.dense-btn {
|
|
48
|
+
background: transparent;
|
|
49
|
+
color: #ccc;
|
|
50
|
+
border: 1px solid transparent;
|
|
51
|
+
padding: 2px 8px;
|
|
52
|
+
border-radius: 2px;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
}
|
|
55
|
+
.dense-btn:hover {
|
|
56
|
+
background-color: #3c3c3c;
|
|
57
|
+
border-color: #555;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/* Dense Data Table */
|
|
61
|
+
.data-table {
|
|
62
|
+
width: 100%;
|
|
63
|
+
border-collapse: collapse;
|
|
64
|
+
font-family: 'JetBrains Mono', monospace;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.data-table th, .data-table td {
|
|
68
|
+
padding: 4px 8px;
|
|
69
|
+
border: 1px solid #3c3c3c;
|
|
70
|
+
text-align: right; /* Numbers align right */
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.data-table tr:nth-child(even) { background-color: #252526; }
|
|
74
|
+
.data-table tr:hover { background-color: #094771; color: #fff; } /* Selection highlight */
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## App Implementation
|
|
78
|
+
|
|
79
|
+
### SwiftUI
|
|
80
|
+
```swift
|
|
81
|
+
struct DataDenseView: View {
|
|
82
|
+
var body: some View {
|
|
83
|
+
ScrollView([.horizontal, .vertical]) {
|
|
84
|
+
Grid(horizontalSpacing: 0, verticalSpacing: 0) {
|
|
85
|
+
// Header Row
|
|
86
|
+
GridRow {
|
|
87
|
+
HeaderCell("SYM")
|
|
88
|
+
HeaderCell("BID")
|
|
89
|
+
HeaderCell("ASK")
|
|
90
|
+
HeaderCell("CHG")
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Data Rows
|
|
94
|
+
DataRow(sym: "AAPL", bid: "173.40", ask: "173.45", chg: "+0.12", isPos: true)
|
|
95
|
+
DataRow(sym: "MSFT", bid: "320.10", ask: "320.15", chg: "-0.45", isPos: false)
|
|
96
|
+
DataRow(sym: "GOOG", bid: "135.20", ask: "135.30", chg: "+0.02", isPos: true)
|
|
97
|
+
}
|
|
98
|
+
.border(Color.gray.opacity(0.3), width: 1)
|
|
99
|
+
}
|
|
100
|
+
.background(Color(white: 0.12)) // Dark IDE background
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
struct HeaderCell: View {
|
|
105
|
+
let text: String
|
|
106
|
+
init(_ text: String) { self.text = text }
|
|
107
|
+
var body: some View {
|
|
108
|
+
Text(text)
|
|
109
|
+
.font(.system(size: 11, weight: .bold, design: .monospaced))
|
|
110
|
+
.foregroundColor(.gray)
|
|
111
|
+
.padding(4)
|
|
112
|
+
.frame(minWidth: 60, alignment: .leading)
|
|
113
|
+
.border(Color.gray.opacity(0.3), width: 0.5)
|
|
114
|
+
.background(Color(white: 0.18))
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
struct DataRow: View {
|
|
119
|
+
let sym, bid, ask, chg: String
|
|
120
|
+
let isPos: Bool
|
|
121
|
+
var body: some View {
|
|
122
|
+
GridRow {
|
|
123
|
+
Cell(sym, color: .white)
|
|
124
|
+
Cell(bid, color: .white, align: .trailing)
|
|
125
|
+
Cell(ask, color: .white, align: .trailing)
|
|
126
|
+
Cell(chg, color: isPos ? .green : .red, align: .trailing)
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
struct Cell: View {
|
|
132
|
+
let text: String
|
|
133
|
+
let color: Color
|
|
134
|
+
let align: Alignment
|
|
135
|
+
init(_ text: String, color: Color, align: Alignment = .leading) {
|
|
136
|
+
self.text = text; self.color = color; self.align = align
|
|
137
|
+
}
|
|
138
|
+
var body: some View {
|
|
139
|
+
Text(text)
|
|
140
|
+
.font(.system(size: 12, design: .monospaced))
|
|
141
|
+
.foregroundColor(color)
|
|
142
|
+
.padding(4)
|
|
143
|
+
.frame(minWidth: 60, alignment: align)
|
|
144
|
+
.border(Color.gray.opacity(0.3), width: 0.5)
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
- Use `Grid` with `0` spacing.
|
|
149
|
+
- Font must be `.system(..., design: .monospaced)`.
|
|
150
|
+
- Use a `.border()` with `0.5` width on every single cell to recreate the dense spreadsheet look.
|
|
151
|
+
|
|
152
|
+
### Flutter
|
|
153
|
+
```dart
|
|
154
|
+
class DataDenseScreen extends StatelessWidget {
|
|
155
|
+
@override
|
|
156
|
+
Widget build(BuildContext context) {
|
|
157
|
+
return Scaffold(
|
|
158
|
+
backgroundColor: const Color(0xFF1E1E1E),
|
|
159
|
+
body: SingleChildScrollView(
|
|
160
|
+
scrollDirection: Axis.vertical,
|
|
161
|
+
child: SingleChildScrollView(
|
|
162
|
+
scrollDirection: Axis.horizontal,
|
|
163
|
+
child: Theme(
|
|
164
|
+
// Override theme specifically to make the table hyper-dense
|
|
165
|
+
data: Theme.of(context).copyWith(
|
|
166
|
+
dividerColor: Colors.grey[800],
|
|
167
|
+
),
|
|
168
|
+
child: DataTable(
|
|
169
|
+
headingRowHeight: 28, // Extremely dense
|
|
170
|
+
dataRowMinHeight: 24,
|
|
171
|
+
dataRowMaxHeight: 24, // Extremely dense
|
|
172
|
+
columnSpacing: 16,
|
|
173
|
+
border: TableBorder.all(color: Colors.grey[800]!, width: 1),
|
|
174
|
+
columns: const [
|
|
175
|
+
DataColumn(label: Text('SYM', style: TextStyle(color: Colors.grey, fontSize: 11, fontFamily: 'RobotoMono'))),
|
|
176
|
+
DataColumn(label: Text('BID', style: TextStyle(color: Colors.grey, fontSize: 11, fontFamily: 'RobotoMono')), numeric: true),
|
|
177
|
+
DataColumn(label: Text('ASK', style: TextStyle(color: Colors.grey, fontSize: 11, fontFamily: 'RobotoMono')), numeric: true),
|
|
178
|
+
],
|
|
179
|
+
rows: [
|
|
180
|
+
_buildRow('AAPL', '173.40', '173.45'),
|
|
181
|
+
_buildRow('MSFT', '320.10', '320.15'),
|
|
182
|
+
_buildRow('GOOG', '135.20', '135.30'),
|
|
183
|
+
],
|
|
184
|
+
),
|
|
185
|
+
),
|
|
186
|
+
),
|
|
187
|
+
),
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
DataRow _buildRow(String sym, String bid, String ask) {
|
|
192
|
+
const style = TextStyle(color: Colors.white, fontSize: 12, fontFamily: 'RobotoMono');
|
|
193
|
+
return DataRow(
|
|
194
|
+
cells: [
|
|
195
|
+
DataCell(Text(sym, style: style)),
|
|
196
|
+
DataCell(Text(bid, style: style)),
|
|
197
|
+
DataCell(Text(ask, style: style)),
|
|
198
|
+
],
|
|
199
|
+
);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
- Flutter's `DataTable` is perfect, but you must manually crush the `headingRowHeight` and `dataRowHeight` down from their Material defaults (which are huge).
|
|
204
|
+
- Wrap in dual `SingleChildScrollView` to allow panning around large data sets.
|
|
205
|
+
|
|
206
|
+
### React Native
|
|
207
|
+
```jsx
|
|
208
|
+
const DataDenseScreen = () => {
|
|
209
|
+
return (
|
|
210
|
+
<ScrollView style={{ backgroundColor: '#1E1E1E', flex: 1 }}>
|
|
211
|
+
<ScrollView horizontal>
|
|
212
|
+
<View style={{ borderWidth: 1, borderColor: '#333' }}>
|
|
213
|
+
{/* Header */}
|
|
214
|
+
<View style={{ flexDirection: 'row', backgroundColor: '#2D2D2D' }}>
|
|
215
|
+
<HeaderCell text="SYM" width={60} />
|
|
216
|
+
<HeaderCell text="BID" width={80} align="right" />
|
|
217
|
+
<HeaderCell text="ASK" width={80} align="right" />
|
|
218
|
+
<HeaderCell text="CHG" width={60} align="right" />
|
|
219
|
+
</View>
|
|
220
|
+
|
|
221
|
+
{/* Rows */}
|
|
222
|
+
<DataRow sym="AAPL" bid="173.40" ask="173.45" chg="+0.12" isPos={true} />
|
|
223
|
+
<DataRow sym="MSFT" bid="320.10" ask="320.15" chg="-0.45" isPos={false} />
|
|
224
|
+
</View>
|
|
225
|
+
</ScrollView>
|
|
226
|
+
</ScrollView>
|
|
227
|
+
);
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const HeaderCell = ({ text, width, align = 'left' }) => (
|
|
231
|
+
<View style={{ width, padding: 4, borderWidth: 0.5, borderColor: '#333' }}>
|
|
232
|
+
<Text style={{ color: '#999', fontSize: 11, fontFamily: 'monospace', textAlign: align, fontWeight: 'bold' }}>
|
|
233
|
+
{text}
|
|
234
|
+
</Text>
|
|
235
|
+
</View>
|
|
236
|
+
);
|
|
237
|
+
|
|
238
|
+
const DataRow = ({ sym, bid, ask, chg, isPos }) => (
|
|
239
|
+
<View style={{ flexDirection: 'row' }}>
|
|
240
|
+
<Cell text={sym} width={60} />
|
|
241
|
+
<Cell text={bid} width={80} align="right" />
|
|
242
|
+
<Cell text={ask} width={80} align="right" />
|
|
243
|
+
<Cell text={chg} width={60} align="right" color={isPos ? '#4CAF50' : '#F44336'} />
|
|
244
|
+
</View>
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
const Cell = ({ text, width, align = 'left', color = '#CCC' }) => (
|
|
248
|
+
<View style={{ width, padding: 4, borderWidth: 0.5, borderColor: '#333' }}>
|
|
249
|
+
<Text style={{ color, fontSize: 12, fontFamily: 'monospace', textAlign: align }}>
|
|
250
|
+
{text}
|
|
251
|
+
</Text>
|
|
252
|
+
</View>
|
|
253
|
+
);
|
|
254
|
+
```
|
|
255
|
+
- React Native doesn't have a native Table component, so you must construct a grid using `flexDirection: 'row'` and strict `width` properties on cells.
|
|
256
|
+
- Double scroll views (one vertical, one horizontal inside it) are standard for mobile data tables.
|
|
257
|
+
|
|
258
|
+
### Jetpack Compose
|
|
259
|
+
```kotlin
|
|
260
|
+
@Composable
|
|
261
|
+
fun DataDenseScreen() {
|
|
262
|
+
val scrollStateHorizontal = rememberScrollState()
|
|
263
|
+
val scrollStateVertical = rememberScrollState()
|
|
264
|
+
|
|
265
|
+
Box(
|
|
266
|
+
modifier = Modifier
|
|
267
|
+
.fillMaxSize()
|
|
268
|
+
.background(Color(0xFF1E1E1E))
|
|
269
|
+
.verticalScroll(scrollStateVertical)
|
|
270
|
+
.horizontalScroll(scrollStateHorizontal)
|
|
271
|
+
.padding(8.dp)
|
|
272
|
+
) {
|
|
273
|
+
Column(modifier = Modifier.border(1.dp, Color(0xFF333333))) {
|
|
274
|
+
// Header
|
|
275
|
+
Row(modifier = Modifier.background(Color(0xFF2D2D2D))) {
|
|
276
|
+
Cell("SYM", 60.dp, Color.Gray, true)
|
|
277
|
+
Cell("BID", 80.dp, Color.Gray, true, TextAlign.End)
|
|
278
|
+
Cell("ASK", 80.dp, Color.Gray, true, TextAlign.End)
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Rows
|
|
282
|
+
DataRow("AAPL", "173.40", "173.45")
|
|
283
|
+
DataRow("MSFT", "320.10", "320.15")
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
@Composable
|
|
289
|
+
fun DataRow(sym: String, bid: String, ask: String) {
|
|
290
|
+
Row {
|
|
291
|
+
Cell(sym, 60.dp, Color.White, false)
|
|
292
|
+
Cell(bid, 80.dp, Color.White, false, TextAlign.End)
|
|
293
|
+
Cell(ask, 80.dp, Color.White, false, TextAlign.End)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
@Composable
|
|
298
|
+
fun Cell(text: String, width: Dp, color: Color, isHeader: Boolean, align: TextAlign = TextAlign.Start) {
|
|
299
|
+
Text(
|
|
300
|
+
text = text,
|
|
301
|
+
color = color,
|
|
302
|
+
fontSize = if (isHeader) 11.sp else 12.sp,
|
|
303
|
+
fontWeight = if (isHeader) FontWeight.Bold else FontWeight.Normal,
|
|
304
|
+
fontFamily = FontFamily.Monospace,
|
|
305
|
+
textAlign = align,
|
|
306
|
+
modifier = Modifier
|
|
307
|
+
.width(width)
|
|
308
|
+
.border(0.5.dp, Color(0xFF333333))
|
|
309
|
+
.padding(4.dp)
|
|
310
|
+
)
|
|
311
|
+
}
|
|
312
|
+
```
|
|
313
|
+
- Chain `.verticalScroll()` and `.horizontalScroll()` on the root `Box`.
|
|
314
|
+
- Compose allows `.border()` directly on `Text` modifiers, making spreadsheet grids very clean to implement without wrapping everything in `Box`es.
|
|
315
|
+
|
|
316
|
+
## Do's and Don'ts
|
|
317
|
+
- **DO**: Use color coding (red/green) for data deltas, but keep the saturation muted to prevent eye fatigue.
|
|
318
|
+
- **DON'T**: Use large padding or giant H1 headers. Expert users already know what screen they are on.
|
|
319
|
+
|
|
320
|
+
## Limitations
|
|
321
|
+
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
|
|
322
|
+
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: duotone-design
|
|
3
|
+
description: Web and App implementation guide for Duotone Design. Trigger when user wants two-color schemes, striking imagery, and Spotify-like playlist aesthetics.
|
|
4
|
+
date_added: "2026-06-17"
|
|
5
|
+
risk: safe
|
|
6
|
+
source: self
|
|
7
|
+
source_type: self
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Duotone Design
|
|
11
|
+
|
|
12
|
+
> "Striking contrast. Photography and UI stripped down to exactly two clashing or complementary colors."
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
Use this sub-style when the user's request matches the aesthetic described above. This is a child reference of the `design-it` skill and is not meant to be triggered directly.
|
|
17
|
+
|
|
18
|
+
## Core Principles
|
|
19
|
+
1. **Two Colors Only**: The entire design is mapped to a dark color (replacing blacks/shadows) and a light color (replacing whites/highlights).
|
|
20
|
+
2. **Treated Imagery**: All photos MUST be processed into the duotone palette.
|
|
21
|
+
3. **Bold, Flat Typography**: Text is usually massive, solid, and uses one of the two colors.
|
|
22
|
+
|
|
23
|
+
## Visual DNA
|
|
24
|
+
- **Colors**: Very high contrast pairs. Navy and Peach, Deep Purple and Neon Green, Crimson and Cream. Look at **Industrial Chic** for inspiration.
|
|
25
|
+
- **Typography**: Heavy, condensed sans-serifs (e.g., `League Gothic`, `Oswald`).
|
|
26
|
+
- **Imagery**: High-contrast, gritty photography works best when mapped to duotone.
|
|
27
|
+
|
|
28
|
+
## Web Implementation
|
|
29
|
+
- Modern CSS can achieve image duotone effects without Photoshop, using `mix-blend-mode` and filters.
|
|
30
|
+
- **CSS Example**:
|
|
31
|
+
```css
|
|
32
|
+
:root {
|
|
33
|
+
--duo-dark: #1E0045; /* Deep Purple */
|
|
34
|
+
--duo-light: #CCFF00; /* Neon Lime */
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
body {
|
|
38
|
+
background-color: var(--duo-dark);
|
|
39
|
+
color: var(--duo-light);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* CSS Duotone Image Effect */
|
|
43
|
+
.duotone-container {
|
|
44
|
+
position: relative;
|
|
45
|
+
width: 100%;
|
|
46
|
+
height: 400px;
|
|
47
|
+
background-color: var(--duo-light); /* Base color */
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.duotone-container img {
|
|
51
|
+
width: 100%;
|
|
52
|
+
height: 100%;
|
|
53
|
+
object-fit: cover;
|
|
54
|
+
/* Convert image to grayscale, increase contrast */
|
|
55
|
+
filter: grayscale(100%) contrast(1.5);
|
|
56
|
+
/* Multiply the grayscale image against the light background */
|
|
57
|
+
mix-blend-mode: multiply;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.duotone-container::after {
|
|
61
|
+
/* Overlay the dark color using screen/lighten */
|
|
62
|
+
content: '';
|
|
63
|
+
position: absolute;
|
|
64
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
65
|
+
background-color: var(--duo-dark);
|
|
66
|
+
mix-blend-mode: screen;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.duotone-btn {
|
|
70
|
+
background: var(--duo-light);
|
|
71
|
+
color: var(--duo-dark);
|
|
72
|
+
border: none;
|
|
73
|
+
font-weight: 900;
|
|
74
|
+
text-transform: uppercase;
|
|
75
|
+
padding: 16px 32px;
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## App Implementation
|
|
80
|
+
|
|
81
|
+
### SwiftUI
|
|
82
|
+
```swift
|
|
83
|
+
struct DuotoneImage: View {
|
|
84
|
+
let duoDark = Color(red: 0.12, green: 0.0, blue: 0.27) // #1E0045
|
|
85
|
+
let duoLight = Color(red: 0.8, green: 1.0, blue: 0.0) // #CCFF00
|
|
86
|
+
|
|
87
|
+
var body: some View {
|
|
88
|
+
ZStack {
|
|
89
|
+
// Background base color
|
|
90
|
+
duoLight.ignoresSafeArea()
|
|
91
|
+
|
|
92
|
+
// Image processing
|
|
93
|
+
Image("sample_photo")
|
|
94
|
+
.resizable()
|
|
95
|
+
.scaledToFill()
|
|
96
|
+
.grayscale(1.0)
|
|
97
|
+
.contrast(1.5)
|
|
98
|
+
.colorMultiply(duoLight) // Multiplies the light color into the grays
|
|
99
|
+
|
|
100
|
+
// Dark color overlay
|
|
101
|
+
duoDark
|
|
102
|
+
.blendMode(.screen) // Equivalent to CSS screen blend mode
|
|
103
|
+
.allowsHitTesting(false)
|
|
104
|
+
}
|
|
105
|
+
.frame(height: 400)
|
|
106
|
+
.clipped()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
- Real-time image processing is easy in SwiftUI.
|
|
111
|
+
- Convert to `.grayscale()`, boost `.contrast()`, then use `.colorMultiply()` and `.blendMode(.screen)` layers to map the two colors exactly like CSS `mix-blend-mode`.
|
|
112
|
+
|
|
113
|
+
### Flutter
|
|
114
|
+
```dart
|
|
115
|
+
class DuotoneImage extends StatelessWidget {
|
|
116
|
+
final Color duoDark = const Color(0xFF1E0045);
|
|
117
|
+
final Color duoLight = const Color(0xFFCCFF00);
|
|
118
|
+
|
|
119
|
+
@override
|
|
120
|
+
Widget build(BuildContext context) {
|
|
121
|
+
return Container(
|
|
122
|
+
height: 400,
|
|
123
|
+
width: double.infinity,
|
|
124
|
+
color: duoLight,
|
|
125
|
+
child: Stack(
|
|
126
|
+
fit: StackFit.expand,
|
|
127
|
+
children: [
|
|
128
|
+
// 1. Grayscale & Contrast (using ColorFilter matrix)
|
|
129
|
+
// 2. Light Color Multiply
|
|
130
|
+
ColorFiltered(
|
|
131
|
+
colorFilter: ColorFilter.mode(duoLight, BlendMode.multiply),
|
|
132
|
+
child: ColorFiltered(
|
|
133
|
+
// Simple grayscale matrix
|
|
134
|
+
colorFilter: const ColorFilter.matrix([
|
|
135
|
+
0.2126, 0.7152, 0.0722, 0, 0,
|
|
136
|
+
0.2126, 0.7152, 0.0722, 0, 0,
|
|
137
|
+
0.2126, 0.7152, 0.0722, 0, 0,
|
|
138
|
+
0, 0, 0, 1, 0,
|
|
139
|
+
]),
|
|
140
|
+
child: Image.asset('assets/sample_photo.jpg', fit: BoxFit.cover),
|
|
141
|
+
),
|
|
142
|
+
),
|
|
143
|
+
// 3. Dark Color Screen Overlay
|
|
144
|
+
ColorFiltered(
|
|
145
|
+
colorFilter: ColorFilter.mode(duoDark, BlendMode.screen),
|
|
146
|
+
child: Container(color: Colors.transparent), // Applies filter to stack below
|
|
147
|
+
),
|
|
148
|
+
],
|
|
149
|
+
),
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
- Flutter requires stacking `ColorFiltered` widgets.
|
|
155
|
+
- Use a `ColorFilter.matrix` to convert the image to grayscale first.
|
|
156
|
+
- Apply `BlendMode.multiply` with the light color, then overlay the dark color using `BlendMode.screen`.
|
|
157
|
+
|
|
158
|
+
### React Native
|
|
159
|
+
```jsx
|
|
160
|
+
// Real-time CSS-like blend modes do NOT exist natively in React Native.
|
|
161
|
+
// You must use react-native-skia or pre-process images.
|
|
162
|
+
|
|
163
|
+
import { Canvas, Image, useImage, ColorMatrix } from "@shopify/react-native-skia";
|
|
164
|
+
|
|
165
|
+
const DuotoneImage = () => {
|
|
166
|
+
const image = useImage(require('./sample_photo.jpg'));
|
|
167
|
+
|
|
168
|
+
if (!image) return null;
|
|
169
|
+
|
|
170
|
+
// Skia allows custom SVG/CSS style color matrices.
|
|
171
|
+
// Building a true duotone matrix requires math mapping black to duoDark
|
|
172
|
+
// and white to duoLight.
|
|
173
|
+
|
|
174
|
+
return (
|
|
175
|
+
<View style={{ height: 400, backgroundColor: '#CCFF00' }}>
|
|
176
|
+
<Canvas style={{ flex: 1 }}>
|
|
177
|
+
<Image image={image} x={0} y={0} width={400} height={400} fit="cover">
|
|
178
|
+
{/* Note: In production, you would construct a specific
|
|
179
|
+
ColorMatrix to map the luminance to the two hex colors. */}
|
|
180
|
+
<ColorMatrix
|
|
181
|
+
matrix={[
|
|
182
|
+
-1, 0, 0, 0, 255,
|
|
183
|
+
0, -1, 0, 0, 255,
|
|
184
|
+
0, 0, -1, 0, 255,
|
|
185
|
+
0, 0, 0, 1, 0,
|
|
186
|
+
]}
|
|
187
|
+
/>
|
|
188
|
+
</Image>
|
|
189
|
+
</Canvas>
|
|
190
|
+
</View>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
- **Critical Limitation**: Standard React Native `<Image>` cannot do duotone blending.
|
|
195
|
+
- **Solution 1**: Use `@shopify/react-native-skia` to apply low-level color matrices and blend modes.
|
|
196
|
+
- **Solution 2**: Pre-process all imagery in Photoshop/Figma before importing into the app. This is the safest and most performant route.
|
|
197
|
+
|
|
198
|
+
### Jetpack Compose
|
|
199
|
+
```kotlin
|
|
200
|
+
@Composable
|
|
201
|
+
fun DuotoneImage() {
|
|
202
|
+
val duoDark = Color(0xFF1E0045)
|
|
203
|
+
val duoLight = Color(0xFFCCFF00)
|
|
204
|
+
|
|
205
|
+
// A ColorMatrix to map luminance to the two colors is required for true duotone.
|
|
206
|
+
// For simplicity, we use BlendModes here to approximate the CSS multiply/screen effect.
|
|
207
|
+
Box(modifier = Modifier
|
|
208
|
+
.fillMaxWidth()
|
|
209
|
+
.height(400.dp)
|
|
210
|
+
.background(duoLight)
|
|
211
|
+
) {
|
|
212
|
+
Image(
|
|
213
|
+
painter = painterResource(id = R.drawable.sample_photo),
|
|
214
|
+
contentDescription = null,
|
|
215
|
+
contentScale = ContentScale.Crop,
|
|
216
|
+
modifier = Modifier.matchParentSize(),
|
|
217
|
+
colorFilter = ColorFilter.colorMatrix(ColorMatrix().apply {
|
|
218
|
+
setToSaturation(0f) // Grayscale
|
|
219
|
+
})
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
// Multiply light color
|
|
223
|
+
Spacer(modifier = Modifier
|
|
224
|
+
.matchParentSize()
|
|
225
|
+
.background(duoLight)
|
|
226
|
+
.graphicsLayer { blendMode = BlendMode.Multiply }
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
// Screen dark color
|
|
230
|
+
Spacer(modifier = Modifier
|
|
231
|
+
.matchParentSize()
|
|
232
|
+
.background(duoDark)
|
|
233
|
+
.graphicsLayer { blendMode = BlendMode.Screen }
|
|
234
|
+
)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
```
|
|
238
|
+
- Use `ColorFilter.colorMatrix` with `setToSaturation(0f)` to make the image grayscale.
|
|
239
|
+
- Use `Spacer` overlays with `Modifier.graphicsLayer { blendMode = BlendMode... }` to apply the dual color mapping.
|
|
240
|
+
- Similar to Flutter, layer `Multiply` (light) and `Screen` (dark) to achieve the effect.
|
|
241
|
+
|
|
242
|
+
## Do's and Don'ts
|
|
243
|
+
- **DO**: Ensure the dark color is dark enough to be legible when used as text against the light color.
|
|
244
|
+
- **DON'T**: Add a third color. It instantly ruins the aesthetic.
|
|
245
|
+
|
|
246
|
+
## Limitations
|
|
247
|
+
- This is a styling reference and does not replace environment-specific validation, accessibility testing, or expert review.
|
|
248
|
+
- Ensure appropriate contrast ratios and responsive behaviors are verified separately.
|